]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-2.6.37/core' of git://git.kernel.dk/linux-2.6-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 00:00:32 +0000 (17:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 00:00:32 +0000 (17:00 -0700)
* 'for-2.6.37/core' of git://git.kernel.dk/linux-2.6-block: (39 commits)
  cfq-iosched: Fix a gcc 4.5 warning and put some comments
  block: Turn bvec_k{un,}map_irq() into static inline functions
  block: fix accounting bug on cross partition merges
  block: Make the integrity mapped property a bio flag
  block: Fix double free in blk_integrity_unregister
  block: Ensure physical block size is unsigned int
  blkio-throttle: Fix possible multiplication overflow in iops calculations
  blkio-throttle: limit max iops value to UINT_MAX
  blkio-throttle: There is no need to convert jiffies to milli seconds
  blkio-throttle: Fix link failure failure on i386
  blkio: Recalculate the throttled bio dispatch time upon throttle limit change
  blkio: Add root group to td->tg_list
  blkio: deletion of a cgroup was causes oops
  blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n
  block: set the bounce_pfn to the actual DMA limit rather than to max memory
  block: revert bad fix for memory hotplug causing bounces
  Fix compile error in blk-exec.c for !CONFIG_DETECT_HUNG_TASK
  block: set the bounce_pfn to the actual DMA limit rather than to max memory
  block: Prevent hang_check firing during long I/O
  cfq: improve fsync performance for small files
  ...

Fix up trivial conflicts due to __rcu sparse annotation in include/linux/genhd.h

3705 files changed:
CREDITS
Documentation/ABI/testing/sysfs-ata [new file with mode: 0644]
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-power
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/drm.tmpl
Documentation/DocBook/genericirq.tmpl
Documentation/DocBook/kernel-api.tmpl
Documentation/DocBook/kernel-locking.tmpl
Documentation/DocBook/tracepoint.tmpl
Documentation/RCU/checklist.txt
Documentation/RCU/stallwarn.txt
Documentation/RCU/trace.txt
Documentation/arm/00-INDEX
Documentation/arm/msm/gpiomux.txt [new file with mode: 0644]
Documentation/block/cfq-iosched.txt [new file with mode: 0644]
Documentation/cgroups/blkio-controller.txt
Documentation/cputopology.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/ocfs2.txt
Documentation/gpio.txt
Documentation/hwmon/sysfs-interface
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/kernel-parameters.txt
Documentation/kprobes.txt
Documentation/lguest/Makefile
Documentation/lguest/lguest.c
Documentation/mutex-design.txt
Documentation/networking/e1000.txt
Documentation/networking/e1000e.txt [new file with mode: 0644]
Documentation/networking/ixgbevf.txt [changed mode: 0755->0644]
Documentation/pcmcia/driver-changes.txt
Documentation/power/00-INDEX
Documentation/power/interface.txt
Documentation/power/opp.txt [new file with mode: 0644]
Documentation/power/regulator/overview.txt
Documentation/power/runtime_pm.txt
Documentation/power/s2ram.txt
Documentation/power/swsusp.txt
Documentation/powerpc/dts-bindings/fsl/spi.txt
Documentation/sound/alsa/HD-Audio-Models.txt
Documentation/vm/page-types.c
Documentation/workqueue.txt [new file with mode: 0644]
Documentation/x86/x86_64/kernel-stacks
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/include/asm/cache.h
arch/alpha/include/asm/cacheflush.h
arch/alpha/include/asm/irqflags.h [new file with mode: 0644]
arch/alpha/include/asm/perf_event.h
arch/alpha/include/asm/system.h
arch/alpha/include/asm/unistd.h
arch/alpha/kernel/entry.S
arch/alpha/kernel/err_ev6.c
arch/alpha/kernel/err_marvel.c
arch/alpha/kernel/err_titan.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/pci-sysfs.c
arch/alpha/kernel/perf_event.c
arch/alpha/kernel/process.c
arch/alpha/kernel/proto.h
arch/alpha/kernel/signal.c
arch/alpha/kernel/srm_env.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/systbls.S
arch/alpha/kernel/time.c
arch/alpha/kernel/traps.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/common/gic.c
arch/arm/common/it8152.c
arch/arm/common/pl330.c
arch/arm/common/sa1111.c
arch/arm/configs/at91sam9g20ek_defconfig
arch/arm/configs/kirkwood_defconfig
arch/arm/configs/mx27_defconfig
arch/arm/configs/mx31pdk_defconfig [deleted file]
arch/arm/configs/mx3_defconfig
arch/arm/configs/mx51_defconfig
arch/arm/configs/omap_4430sdp_defconfig
arch/arm/configs/realview-smp_defconfig
arch/arm/configs/realview_defconfig
arch/arm/configs/s5p64x0_defconfig [moved from arch/arm/configs/s5p6440_defconfig with 97% similarity]
arch/arm/configs/u300_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/cachetype.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/elf.h
arch/arm/include/asm/ftrace.h
arch/arm/include/asm/hardware/coresight.h
arch/arm/include/asm/hw_breakpoint.h [new file with mode: 0644]
arch/arm/include/asm/hw_irq.h
arch/arm/include/asm/io.h
arch/arm/include/asm/irqflags.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/module.h
arch/arm/include/asm/perf_event.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/seccomp.h [new file with mode: 0644]
arch/arm/include/asm/smp_mpidr.h [new file with mode: 0644]
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/system.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/Makefile
arch/arm/kernel/armksyms.c
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/calls.S
arch/arm/kernel/debug.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/etm.c
arch/arm/kernel/ftrace.c
arch/arm/kernel/head-common.S
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c [new file with mode: 0644]
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-decode.c
arch/arm/kernel/module.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/unwind.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-aaec2000/aaed2000.c
arch/arm/mach-aaec2000/include/mach/debug-macro.S
arch/arm/mach-aaec2000/include/mach/vmalloc.h
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-at572d940hf_ek.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-cap9adk.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-dk.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-ek.c
arch/arm/mach-at91/board-flexibity.c [new file with mode: 0644]
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c [deleted file]
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a9260.c
arch/arm/mach-at91/board-usb-a9263.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/at91x40.h
arch/arm/mach-at91/include/mach/debug-macro.S
arch/arm/mach-at91/include/mach/system.h
arch/arm/mach-bcmring/arch.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-bcmring/include/mach/vmalloc.h
arch/arm/mach-bcmring/irq.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/include/mach/debug-macro.S
arch/arm/mach-clps711x/include/mach/vmalloc.h
arch/arm/mach-clps711x/p720t.c
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-cns3xxx/include/mach/debug-macro.S
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-neuros-osd2.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/board-tnetv107x-evm.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/include/mach/debug-macro.S
arch/arm/mach-dove/dove-db-setup.c
arch/arm/mach-dove/include/mach/debug-macro.S
arch/arm/mach-dove/include/mach/io.h
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ebsa110/include/mach/debug-macro.S
arch/arm/mach-ebsa110/include/mach/vmalloc.h
arch/arm/mach-ep93xx/adssphere.c
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/dma-m2p.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/gesbc9312.c
arch/arm/mach-ep93xx/include/mach/debug-macro.S
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-footbridge/cats-hw.c
arch/arm/mach-footbridge/ebsa285.c
arch/arm/mach-footbridge/include/mach/debug-macro.S
arch/arm/mach-footbridge/include/mach/vmalloc.h
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-gemini/include/mach/debug-macro.S
arch/arm/mach-h720x/h7201-eval.c
arch/arm/mach-h720x/h7202-eval.c
arch/arm/mach-h720x/include/mach/debug-macro.S
arch/arm/mach-h720x/include/mach/vmalloc.h
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clock-imx1.c
arch/arm/mach-imx/clock-imx21.c
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-imx/devices-imx1.h
arch/arm/mach-imx/devices-imx21.h
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/devices.c
arch/arm/mach-imx/devices.h
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c [new file with mode: 0644]
arch/arm/mach-imx/mach-imx27lite.c
arch/arm/mach-imx/mach-mx1ads.c
arch/arm/mach-imx/mach-mx21ads.c
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx27ads.c
arch/arm/mach-imx/mach-mxt_td60.c
arch/arm/mach-imx/mach-pca100.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-imx/mach-scb9328.c
arch/arm/mach-imx/pcm970-baseboard.c
arch/arm/mach-integrator/include/mach/debug-macro.S
arch/arm/mach-integrator/include/mach/vmalloc.h
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/include/mach/debug-macro.S
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop13xx/msi.c
arch/arm/mach-iop32x/em7210.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/include/mach/debug-macro.S
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/include/mach/debug-macro.S
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-ixp2000/enp2611.c
arch/arm/mach-ixp2000/include/mach/debug-macro.S
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/include/mach/debug-macro.S
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-setup.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/coyote-setup.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-ixp4xx/gateway7001-setup.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/arm/mach-ixp4xx/include/mach/debug-macro.S
arch/arm/mach-ixp4xx/include/mach/hardware.h
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-ixp4xx/wg302v2-setup.c
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/Makefile
arch/arm/mach-kirkwood/d2net_v2-setup.c [new file with mode: 0644]
arch/arm/mach-kirkwood/db88f6281-bp-setup.c
arch/arm/mach-kirkwood/dockstar-setup.c [new file with mode: 0644]
arch/arm/mach-kirkwood/guruplug-setup.c
arch/arm/mach-kirkwood/include/mach/debug-macro.S
arch/arm/mach-kirkwood/include/mach/kirkwood.h
arch/arm/mach-kirkwood/include/mach/leds-netxbig.h [new file with mode: 0644]
arch/arm/mach-kirkwood/lacie_v2-common.c [new file with mode: 0644]
arch/arm/mach-kirkwood/lacie_v2-common.h [new file with mode: 0644]
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/pcie.c
arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
arch/arm/mach-kirkwood/rd88f6281-setup.c
arch/arm/mach-kirkwood/sheevaplug-setup.c
arch/arm/mach-kirkwood/t5325-setup.c
arch/arm/mach-kirkwood/ts219-setup.c
arch/arm/mach-kirkwood/ts41x-setup.c
arch/arm/mach-ks8695/board-acs5k.c
arch/arm/mach-ks8695/board-dsm320.c
arch/arm/mach-ks8695/board-micrel.c
arch/arm/mach-ks8695/include/mach/debug-macro.S
arch/arm/mach-l7200/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-lh7a40x/arch-kev7a400.c
arch/arm/mach-lh7a40x/arch-lpd7a40x.c
arch/arm/mach-lh7a40x/include/mach/debug-macro.S
arch/arm/mach-loki/include/mach/debug-macro.S
arch/arm/mach-loki/lb88rc8480-setup.c
arch/arm/mach-lpc32xx/include/mach/debug-macro.S
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-mmp/Kconfig
arch/arm/mach-mmp/Makefile
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/avengers_lite.c
arch/arm/mach-mmp/common.c
arch/arm/mach-mmp/flint.c
arch/arm/mach-mmp/include/mach/cputype.h
arch/arm/mach-mmp/include/mach/debug-macro.S
arch/arm/mach-mmp/include/mach/irqs.h
arch/arm/mach-mmp/include/mach/mfp-pxa168.h
arch/arm/mach-mmp/include/mach/pxa168.h
arch/arm/mach-mmp/include/mach/regs-apmu.h
arch/arm/mach-mmp/include/mach/system.h
arch/arm/mach-mmp/include/mach/teton_bga.h [new file with mode: 0644]
arch/arm/mach-mmp/jasper.c
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/tavorevb.c
arch/arm/mach-mmp/teton_bga.c [new file with mode: 0644]
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-msm/Kconfig
arch/arm/mach-msm/Makefile
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-msm8x60.c [new file with mode: 0644]
arch/arm/mach-msm/board-qsd8x50.c
arch/arm/mach-msm/board-sapphire.c
arch/arm/mach-msm/board-trout.c
arch/arm/mach-msm/clock-dummy.c [new file with mode: 0644]
arch/arm/mach-msm/devices-msm7x30.c
arch/arm/mach-msm/devices-msm8x60-iommu.c [new file with mode: 0644]
arch/arm/mach-msm/devices-qsd8x50.c
arch/arm/mach-msm/gpio.c
arch/arm/mach-msm/gpio_hw.h [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-7x30.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-8x50.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-8x60.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-v1.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-v1.h [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-v2.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux-v2.h [new file with mode: 0644]
arch/arm/mach-msm/gpiomux.c [new file with mode: 0644]
arch/arm/mach-msm/gpiomux.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/board.h
arch/arm/mach-msm/include/mach/debug-macro.S
arch/arm/mach-msm/include/mach/dma.h
arch/arm/mach-msm/include/mach/entry-macro-qgic.S [new file with mode: 0644]
arch/arm/mach-msm/include/mach/entry-macro-vic.S [new file with mode: 0644]
arch/arm/mach-msm/include/mach/entry-macro.S
arch/arm/mach-msm/include/mach/gpio.h
arch/arm/mach-msm/include/mach/io.h
arch/arm/mach-msm/include/mach/iommu.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/irqs-8x60.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/irqs.h
arch/arm/mach-msm/include/mach/memory.h
arch/arm/mach-msm/include/mach/msm_iomap-8x60.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/msm_iomap.h
arch/arm/mach-msm/include/mach/smp.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/vmalloc.h
arch/arm/mach-msm/io.c
arch/arm/mach-msm/iommu.c [new file with mode: 0644]
arch/arm/mach-msm/iommu_dev.c [new file with mode: 0644]
arch/arm/mach-msm/last_radio_log.c
arch/arm/mach-msm/smd_debug.c
arch/arm/mach-msm/timer.c
arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
arch/arm/mach-mv78xx0/db78x00-bp-setup.c
arch/arm/mach-mv78xx0/include/mach/debug-macro.S
arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
arch/arm/mach-mx25/Kconfig
arch/arm/mach-mx25/clock.c
arch/arm/mach-mx25/devices-imx25.h
arch/arm/mach-mx25/devices.c
arch/arm/mach-mx25/devices.h
arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
arch/arm/mach-mx25/mach-cpuimx25.c
arch/arm/mach-mx25/mach-mx25_3ds.c
arch/arm/mach-mx3/Kconfig
arch/arm/mach-mx3/Makefile
arch/arm/mach-mx3/clock-imx31.c
arch/arm/mach-mx3/clock-imx35.c
arch/arm/mach-mx3/cpu.c
arch/arm/mach-mx3/devices-imx31.h
arch/arm/mach-mx3/devices-imx35.h
arch/arm/mach-mx3/devices.c
arch/arm/mach-mx3/devices.h
arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
arch/arm/mach-mx3/mach-armadillo5x0.c
arch/arm/mach-mx3/mach-cpuimx35.c
arch/arm/mach-mx3/mach-kzm_arm11_01.c
arch/arm/mach-mx3/mach-mx31_3ds.c
arch/arm/mach-mx3/mach-mx31ads.c
arch/arm/mach-mx3/mach-mx31lilly.c
arch/arm/mach-mx3/mach-mx31lite.c
arch/arm/mach-mx3/mach-mx31moboard.c
arch/arm/mach-mx3/mach-mx35_3ds.c
arch/arm/mach-mx3/mach-pcm037.c
arch/arm/mach-mx3/mach-pcm037_eet.c
arch/arm/mach-mx3/mach-pcm043.c
arch/arm/mach-mx3/mach-qong.c
arch/arm/mach-mx3/mm.c
arch/arm/mach-mx5/Kconfig
arch/arm/mach-mx5/Makefile
arch/arm/mach-mx5/board-cpuimx51.c
arch/arm/mach-mx5/board-cpuimx51sd.c [new file with mode: 0644]
arch/arm/mach-mx5/board-mx51_3ds.c
arch/arm/mach-mx5/board-mx51_babbage.c
arch/arm/mach-mx5/board-mx51_efikamx.c [new file with mode: 0644]
arch/arm/mach-mx5/clock-mx51.c
arch/arm/mach-mx5/cpu.c
arch/arm/mach-mx5/devices-imx51.h [new file with mode: 0644]
arch/arm/mach-mx5/devices.c
arch/arm/mach-mx5/devices.h
arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c [new file with mode: 0644]
arch/arm/mach-mxc91231/magx-zn5.c
arch/arm/mach-netx/include/mach/debug-macro.S
arch/arm/mach-netx/include/mach/vmalloc.h
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-nomadik/include/mach/debug-macro.S
arch/arm/mach-ns9xxx/include/mach/debug-macro.S
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/include/mach/debug-macro.S
arch/arm/mach-omap1/include/mach/vmalloc.h
arch/arm/mach-omap2/Makefile
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-am3517evm.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.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-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-rx51.c
arch/arm/mach-omap2/board-zoom2.c
arch/arm/mach-omap2/board-zoom3.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/debug-macro.S
arch/arm/mach-omap2/include/mach/entry-macro.S
arch/arm/mach-omap2/include/mach/vmalloc.h
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/pm34xx.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/include/mach/debug-macro.S
arch/arm/mach-orion5x/kurobox_pro-setup.c
arch/arm/mach-orion5x/ls_hgl-setup.c
arch/arm/mach-orion5x/lsmini-setup.c
arch/arm/mach-orion5x/mss2-setup.c
arch/arm/mach-orion5x/mv2120-setup.c
arch/arm/mach-orion5x/net2big-setup.c
arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
arch/arm/mach-orion5x/terastation_pro2-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-orion5x/ts409-setup.c
arch/arm/mach-orion5x/ts78xx-setup.c
arch/arm/mach-orion5x/wnr854t-setup.c
arch/arm/mach-orion5x/wrt350n-v2-setup.c
arch/arm/mach-pnx4008/core.c
arch/arm/mach-pnx4008/include/mach/debug-macro.S
arch/arm/mach-pnx4008/include/mach/vmalloc.h
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/cpufreq-pxa2xx.c
arch/arm/mach-pxa/cpufreq-pxa3xx.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/devices.h
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/include/mach/balloon3.h
arch/arm/mach-pxa/include/mach/debug-macro.S
arch/arm/mach-pxa/include/mach/eseries-irq.h
arch/arm/mach-pxa/include/mach/hardware.h
arch/arm/mach-pxa/include/mach/hx4700.h
arch/arm/mach-pxa/include/mach/io.h
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/include/mach/littleton.h
arch/arm/mach-pxa/include/mach/lpd270.h
arch/arm/mach-pxa/include/mach/lubbock.h
arch/arm/mach-pxa/include/mach/magician.h
arch/arm/mach-pxa/include/mach/mainstone.h
arch/arm/mach-pxa/include/mach/mfp-pxa300.h
arch/arm/mach-pxa/include/mach/mfp-pxa930.h
arch/arm/mach-pxa/include/mach/pcm027.h
arch/arm/mach-pxa/include/mach/poodle.h
arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h [new file with mode: 0644]
arch/arm/mach-pxa/include/mach/tosa.h
arch/arm/mach-pxa/include/mach/zeus.h
arch/arm/mach-pxa/include/mach/zylonite.h
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palm27x.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pcm027.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa3xx-ulpi.c [new file with mode: 0644]
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa930.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/tavorevb3.c [new file with mode: 0644]
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-realview/core.c
arch/arm/mach-realview/include/mach/debug-macro.S
arch/arm/mach-realview/include/mach/smp.h
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-realview/realview_pba8.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mach-rpc/include/mach/debug-macro.S
arch/arm/mach-rpc/include/mach/vmalloc.h
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-s3c2410/include/mach/debug-macro.S
arch/arm/mach-s3c2410/include/mach/vmalloc.h
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-s3c24a0/include/mach/debug-macro.S
arch/arm/mach-s3c64xx/dev-spi.c
arch/arm/mach-s3c64xx/include/mach/debug-macro.S
arch/arm/mach-s3c64xx/include/mach/vmalloc.h
arch/arm/mach-s3c64xx/mach-anw6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-ncp.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s3c64xx/mach-smartq.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-s5p6440/Kconfig [deleted file]
arch/arm/mach-s5p6440/Makefile [deleted file]
arch/arm/mach-s5p6440/clock.c [deleted file]
arch/arm/mach-s5p6440/cpu.c [deleted file]
arch/arm/mach-s5p6440/dev-audio.c [deleted file]
arch/arm/mach-s5p6440/dev-spi.c [deleted file]
arch/arm/mach-s5p6440/include/mach/debug-macro.S [deleted file]
arch/arm/mach-s5p6440/include/mach/gpio.h [deleted file]
arch/arm/mach-s5p6440/include/mach/io.h [deleted file]
arch/arm/mach-s5p6440/include/mach/map.h [deleted file]
arch/arm/mach-s5p6440/include/mach/regs-clock.h [deleted file]
arch/arm/mach-s5p6440/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5p6440/include/mach/uncompress.h [deleted file]
arch/arm/mach-s5p6440/init.c [deleted file]
arch/arm/mach-s5p6442/cpu.c
arch/arm/mach-s5p6442/include/mach/debug-macro.S
arch/arm/mach-s5p6442/include/mach/map.h
arch/arm/mach-s5p6442/include/mach/vmalloc.h
arch/arm/mach-s5p6442/mach-smdk6442.c
arch/arm/mach-s5p64x0/Kconfig [new file with mode: 0644]
arch/arm/mach-s5p64x0/Makefile [new file with mode: 0644]
arch/arm/mach-s5p64x0/Makefile.boot [moved from arch/arm/mach-s5p6440/Makefile.boot with 100% similarity]
arch/arm/mach-s5p64x0/clock-s5p6440.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/clock-s5p6450.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/clock.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/cpu.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/dev-audio.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/dev-spi.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/dma.c [moved from arch/arm/mach-s5p6440/dma.c with 55% similarity]
arch/arm/mach-s5p64x0/gpio.c [moved from arch/arm/mach-s5p6440/gpio.c with 74% similarity]
arch/arm/mach-s5p64x0/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/dma.h [moved from arch/arm/mach-s5p6440/include/mach/dma.h with 100% similarity]
arch/arm/mach-s5p64x0/include/mach/entry-macro.S [moved from arch/arm/mach-s5p6440/include/mach/entry-macro.S with 58% similarity]
arch/arm/mach-s5p64x0/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/hardware.h [moved from arch/arm/mach-s5p6440/include/mach/hardware.h with 67% similarity]
arch/arm/mach-s5p64x0/include/mach/i2c.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/irqs.h [moved from arch/arm/mach-s5p6440/include/mach/irqs.h with 71% similarity]
arch/arm/mach-s5p64x0/include/mach/map.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/memory.h [moved from arch/arm/mach-s5p6440/include/mach/memory.h with 55% similarity]
arch/arm/mach-s5p64x0/include/mach/pwm-clock.h [moved from arch/arm/mach-s5p6440/include/mach/pwm-clock.h with 86% similarity]
arch/arm/mach-s5p64x0/include/mach/regs-clock.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/regs-gpio.h [moved from arch/arm/mach-s5p6440/include/mach/regs-gpio.h with 79% similarity]
arch/arm/mach-s5p64x0/include/mach/regs-irq.h [moved from arch/arm/mach-s5p6440/include/mach/regs-irq.h with 66% similarity]
arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/spi-clocks.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/system.h [moved from arch/arm/mach-s5p6440/include/mach/system.h with 69% similarity]
arch/arm/mach-s5p64x0/include/mach/tick.h [moved from arch/arm/mach-s5p6440/include/mach/tick.h with 60% similarity]
arch/arm/mach-s5p64x0/include/mach/timex.h [moved from arch/arm/mach-s5p6440/include/mach/timex.h with 80% similarity]
arch/arm/mach-s5p64x0/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/vmalloc.h [moved from arch/arm/mach-s5p6440/include/mach/vmalloc.h with 68% similarity]
arch/arm/mach-s5p64x0/init.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/mach-smdk6440.c [moved from arch/arm/mach-s5p6440/mach-smdk6440.c with 67% similarity]
arch/arm/mach-s5p64x0/mach-smdk6450.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/setup-i2c0.c [moved from arch/arm/mach-s5p6440/setup-i2c0.c with 52% similarity]
arch/arm/mach-s5p64x0/setup-i2c1.c [moved from arch/arm/mach-s5p6440/setup-i2c1.c with 55% similarity]
arch/arm/mach-s5pc100/cpu.c
arch/arm/mach-s5pc100/include/mach/debug-macro.S
arch/arm/mach-s5pc100/include/mach/map.h
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/Makefile
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/cpu.c
arch/arm/mach-s5pv210/include/mach/debug-macro.S
arch/arm/mach-s5pv210/include/mach/map.h
arch/arm/mach-s5pv210/include/mach/vmalloc.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-s5pv310/clock.c
arch/arm/mach-s5pv310/cpu.c
arch/arm/mach-s5pv310/include/mach/debug-macro.S
arch/arm/mach-s5pv310/include/mach/irqs.h
arch/arm/mach-s5pv310/include/mach/map.h
arch/arm/mach-s5pv310/include/mach/regs-clock.h
arch/arm/mach-s5pv310/include/mach/smp.h
arch/arm/mach-s5pv310/include/mach/vmalloc.h
arch/arm/mach-s5pv310/mach-smdkv310.c
arch/arm/mach-s5pv310/mach-universal_c210.c
arch/arm/mach-s5pv310/platsmp.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/badge4.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/h3100.c
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/hackkit.c
arch/arm/mach-sa1100/include/mach/debug-macro.S
arch/arm/mach-sa1100/jornada720.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-sa1100/shannon.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mach-shark/core.c
arch/arm/mach-shark/include/mach/debug-macro.S
arch/arm/mach-shark/include/mach/vmalloc.h
arch/arm/mach-shmobile/Makefile
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/clock-sh7372.c
arch/arm/mach-shmobile/clock.c
arch/arm/mach-shmobile/pm_runtime.c [new file with mode: 0644]
arch/arm/mach-stmp378x/stmp378x_devb.c
arch/arm/mach-stmp37xx/stmp37xx_devb.c
arch/arm/mach-tcc8k/Kconfig [new file with mode: 0644]
arch/arm/mach-tcc8k/Makefile [new file with mode: 0644]
arch/arm/mach-tcc8k/Makefile.boot [new file with mode: 0644]
arch/arm/mach-tcc8k/board-tcc8000-sdk.c [new file with mode: 0644]
arch/arm/mach-tcc8k/clock.c [new file with mode: 0644]
arch/arm/mach-tcc8k/common.h [new file with mode: 0644]
arch/arm/mach-tcc8k/devices.c [new file with mode: 0644]
arch/arm/mach-tcc8k/io.c [new file with mode: 0644]
arch/arm/mach-tcc8k/irq.c [new file with mode: 0644]
arch/arm/mach-tcc8k/time.c [new file with mode: 0644]
arch/arm/mach-tegra/board-harmony.c
arch/arm/mach-tegra/include/mach/debug-macro.S
arch/arm/mach-tegra/include/mach/smp.h
arch/arm/mach-tegra/include/mach/vmalloc.h
arch/arm/mach-u300/dummyspichip.c
arch/arm/mach-u300/include/mach/debug-macro.S
arch/arm/mach-u300/include/mach/gpio.h
arch/arm/mach-u300/spi.c
arch/arm/mach-u300/u300.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/board-mop500-regulators.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500-sdi.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h [new file with mode: 0644]
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-ux500/cpu-db5500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/hotplug.c [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/db5500-regs.h
arch/arm/mach-ux500/include/mach/db8500-regs.h
arch/arm/mach-ux500/include/mach/debug-macro.S
arch/arm/mach-ux500/include/mach/devices.h
arch/arm/mach-ux500/include/mach/hardware.h
arch/arm/mach-ux500/include/mach/irqs-db5500.h
arch/arm/mach-ux500/include/mach/irqs.h
arch/arm/mach-ux500/include/mach/mbox.h [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/prcmu-regs.h [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/prcmu.h [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/setup.h
arch/arm/mach-ux500/include/mach/smp.h
arch/arm/mach-ux500/mbox.c [new file with mode: 0644]
arch/arm/mach-ux500/modem_irq.c [new file with mode: 0644]
arch/arm/mach-ux500/pins-db5500.h [new file with mode: 0644]
arch/arm/mach-ux500/pins-db8500.h
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-ux500/prcmu.c [new file with mode: 0644]
arch/arm/mach-ux500/ste-dma40-db5500.h [new file with mode: 0644]
arch/arm/mach-ux500/ste-dma40-db8500.h
arch/arm/mach-versatile/include/mach/debug-macro.S
arch/arm/mach-versatile/include/mach/vmalloc.h
arch/arm/mach-versatile/versatile_ab.c
arch/arm/mach-versatile/versatile_pb.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/include/mach/debug-macro.S
arch/arm/mach-vexpress/include/mach/smp.h
arch/arm/mach-vexpress/v2m.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/Kconfig
arch/arm/mm/alignment.c
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v6.c
arch/arm/mm/copypage-xscale.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/init.c
arch/arm/mm/ioremap.c
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm6_7.S
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-arm740.S
arch/arm/mm/proc-arm7tdmi.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-arm9tdmi.S
arch/arm/mm/proc-fa526.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/mm/tlb-v7.S
arch/arm/oprofile/Makefile
arch/arm/oprofile/common.c
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/Makefile
arch/arm/plat-mxc/audmux-v2.c
arch/arm/plat-mxc/devices/Kconfig
arch/arm/plat-mxc/devices/Makefile
arch/arm/plat-mxc/devices/platform-esdhc.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-fec.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-imx-dma.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-imx-i2c.c
arch/arm/plat-mxc/devices/platform-imx-ssi.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-imx-uart.c
arch/arm/plat-mxc/devices/platform-mxc_nand.c
arch/arm/plat-mxc/devices/platform-spi_imx.c
arch/arm/plat-mxc/ehci.c
arch/arm/plat-mxc/epit.c [new file with mode: 0644]
arch/arm/plat-mxc/gpio.c
arch/arm/plat-mxc/include/mach/board-mx31ads.h [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/include/mach/debug-macro.S
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/esdhc.h [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
arch/arm/plat-mxc/include/mach/iomux-mx51.h
arch/arm/plat-mxc/include/mach/iram.h [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/mx21.h
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-mxc/include/mach/mx27.h
arch/arm/plat-mxc/include/mach/mx31.h
arch/arm/plat-mxc/include/mach/mx35.h
arch/arm/plat-mxc/include/mach/mx3x.h
arch/arm/plat-mxc/include/mach/mx51.h
arch/arm/plat-mxc/include/mach/system.h
arch/arm/plat-mxc/include/mach/uncompress.h
arch/arm/plat-mxc/iram_alloc.c [new file with mode: 0644]
arch/arm/plat-mxc/tzic.c
arch/arm/plat-nomadik/gpio.c
arch/arm/plat-nomadik/include/plat/gpio.h
arch/arm/plat-nomadik/include/plat/pincfg.h
arch/arm/plat-nomadik/timer.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/include/plat/smp.h
arch/arm/plat-omap/iommu-debug.c
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/sram.c
arch/arm/plat-pxa/include/plat/pxa27x_keypad.h [moved from arch/arm/mach-pxa/include/mach/pxa27x_keypad.h with 83% similarity]
arch/arm/plat-pxa/pwm.c
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/clock.c
arch/arm/plat-s5p/cpu.c
arch/arm/plat-s5p/dev-fimc0.c
arch/arm/plat-s5p/dev-fimc1.c
arch/arm/plat-s5p/dev-fimc2.c
arch/arm/plat-s5p/dev-onenand.c [moved from arch/arm/mach-s5pv210/dev-onenand.c with 59% similarity]
arch/arm/plat-s5p/dev-uart.c
arch/arm/plat-s5p/include/plat/map-s5p.h
arch/arm/plat-s5p/include/plat/pll.h
arch/arm/plat-s5p/include/plat/s5p-clock.h
arch/arm/plat-s5p/include/plat/s5p6440.h
arch/arm/plat-s5p/include/plat/s5p6450.h [new file with mode: 0644]
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/clock.c
arch/arm/plat-samsung/gpio-config.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/gpio-cfg.h
arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
arch/arm/plat-spear/include/plat/debug-macro.S
arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
arch/arm/plat-tcc/Kconfig [new file with mode: 0644]
arch/arm/plat-tcc/Makefile [new file with mode: 0644]
arch/arm/plat-tcc/clock.c [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/clock.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/hardware.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/io.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/irqs.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/memory.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/system.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/tcc8k-regs.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/timex.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/plat-tcc/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/plat-tcc/system.c [new file with mode: 0644]
arch/arm/tools/mach-types
arch/avr32/Kconfig
arch/avr32/boards/mimc200/fram.c
arch/avr32/include/asm/irqflags.h
arch/avr32/kernel/module.c
arch/blackfin/include/asm/bfin5xx_spi.h
arch/blackfin/include/asm/bfin_sport.h
arch/blackfin/include/asm/bitops.h
arch/blackfin/include/asm/ipipe.h
arch/blackfin/include/asm/irqflags.h
arch/blackfin/include/asm/mmu_context.h
arch/blackfin/include/asm/system.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-mpu/cplbmgr.c
arch/blackfin/kernel/ipipe.c
arch/blackfin/kernel/kgdb_test.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/trace.c
arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
arch/blackfin/mach-bf518/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
arch/blackfin/mach-bf527/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/ip0x.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/include/mach/cdefBF532.h
arch/blackfin/mach-bf533/include/mach/defBF532.h
arch/blackfin/mach-bf533/include/mach/fio_flag.h [new file with mode: 0644]
arch/blackfin/mach-bf533/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf537/include/mach/cdefBF534.h
arch/blackfin/mach-bf537/include/mach/defBF534.h
arch/blackfin/mach-bf537/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf538/include/mach/cdefBF538.h
arch/blackfin/mach-bf538/include/mach/defBF539.h
arch/blackfin/mach-bf538/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
arch/blackfin/mach-bf548/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-bf561/coreb.c
arch/blackfin/mach-bf561/include/mach/cdefBF561.h
arch/blackfin/mach-bf561/include/mach/defBF561.h
arch/blackfin/mach-bf561/include/mach/pll.h [new file with mode: 0644]
arch/blackfin/mach-common/cpufreq.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/pm.c
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/gpio.c
arch/cris/arch-v10/drivers/i2c.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/drivers/sync_serial.c
arch/cris/arch-v32/drivers/cryptocop.c
arch/cris/arch-v32/drivers/i2c.c
arch/cris/arch-v32/drivers/mach-a3/gpio.c
arch/cris/arch-v32/drivers/mach-fs/gpio.c
arch/cris/arch-v32/drivers/pcf8563.c
arch/cris/arch-v32/drivers/sync_serial.c
arch/cris/include/arch-v10/arch/irqflags.h [new file with mode: 0644]
arch/cris/include/arch-v10/arch/system.h
arch/cris/include/arch-v32/arch/irqflags.h [new file with mode: 0644]
arch/cris/include/arch-v32/arch/system.h
arch/cris/include/asm/irqflags.h [new file with mode: 0644]
arch/cris/include/asm/system.h
arch/cris/kernel/profile.c
arch/frv/Kconfig
arch/frv/include/asm/irqflags.h [new file with mode: 0644]
arch/frv/include/asm/system.h
arch/frv/kernel/signal.c
arch/frv/lib/Makefile
arch/h8300/include/asm/atomic.h
arch/h8300/include/asm/irqflags.h [new file with mode: 0644]
arch/h8300/include/asm/system.h
arch/h8300/kernel/module.c
arch/h8300/kernel/sys_h8300.c
arch/h8300/kernel/traps.c
arch/ia64/Kconfig
arch/ia64/hp/sim/simserial.c
arch/ia64/include/asm/compat.h [deleted file]
arch/ia64/include/asm/hardirq.h
arch/ia64/include/asm/iommu_table.h [new file with mode: 0644]
arch/ia64/include/asm/irqflags.h [new file with mode: 0644]
arch/ia64/include/asm/system.h
arch/ia64/kernel/Makefile
arch/ia64/kernel/cyclone.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/msi_ia64.c
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/stacktrace.c [new file with mode: 0644]
arch/ia64/kernel/unwind.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/ia64/xen/xen_pv_ops.c
arch/m32r/include/asm/elf.h
arch/m32r/include/asm/irqflags.h [new file with mode: 0644]
arch/m32r/include/asm/signal.h
arch/m32r/include/asm/system.h
arch/m32r/include/asm/unistd.h
arch/m32r/kernel/.gitignore [new file with mode: 0644]
arch/m32r/kernel/entry.S
arch/m32r/kernel/irq.c
arch/m32r/kernel/ptrace.c
arch/m32r/kernel/signal.c
arch/m32r/platforms/m32104ut/setup.c
arch/m32r/platforms/m32700ut/setup.c
arch/m32r/platforms/mappi/setup.c
arch/m32r/platforms/mappi2/setup.c
arch/m32r/platforms/mappi3/setup.c
arch/m32r/platforms/oaks32r/setup.c
arch/m32r/platforms/opsput/setup.c
arch/m32r/platforms/usrv/setup.c
arch/m68k/bvme6000/rtc.c
arch/m68k/include/asm/entry_no.h
arch/m68k/include/asm/irqflags.h [new file with mode: 0644]
arch/m68k/include/asm/system_mm.h
arch/m68k/include/asm/system_no.h
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/entry.S
arch/m68k/mac/macboing.c
arch/m68k/mvme16x/rtc.c
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/syscalltable.S
arch/m68knommu/kernel/vmlinux.lds.S
arch/m68knommu/platform/coldfire/head.S
arch/microblaze/include/asm/irqflags.h
arch/microblaze/include/asm/memblock.h
arch/microblaze/mm/init.c
arch/mips/Kbuild
arch/mips/Kconfig
arch/mips/alchemy/common/prom.c
arch/mips/alchemy/devboards/bcsr.c
arch/mips/ar7/irq.c
arch/mips/bcm63xx/irq.c
arch/mips/boot/compressed/Makefile
arch/mips/cavium-octeon/Kconfig
arch/mips/cavium-octeon/cpu.c
arch/mips/cavium-octeon/executive/Makefile
arch/mips/cavium-octeon/serial.c
arch/mips/dec/Platform
arch/mips/dec/setup.c
arch/mips/include/asm/atomic.h
arch/mips/include/asm/compat.h
arch/mips/include/asm/cop2.h
arch/mips/include/asm/fcntl.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/mach-loongson/loongson.h
arch/mips/include/asm/mach-tx49xx/kmalloc.h
arch/mips/include/asm/mips-boards/maltaint.h
arch/mips/include/asm/page.h
arch/mips/include/asm/siginfo.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/unistd.h
arch/mips/jazz/irq.c
arch/mips/jz4740/Platform
arch/mips/kernel/branch.c
arch/mips/kernel/cevt-bcm1480.c
arch/mips/kernel/cevt-ds1287.c
arch/mips/kernel/cevt-gt641xx.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cevt-sb1250.c
arch/mips/kernel/cevt-smtc.c
arch/mips/kernel/cevt-txx9.c
arch/mips/kernel/i8253.c
arch/mips/kernel/i8259.c
arch/mips/kernel/irq-gic.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/irq_txx9.c
arch/mips/kernel/kgdb.c
arch/mips/kernel/kspd.c
arch/mips/kernel/linux32.c
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/rtlx.c
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/mips/kernel/signal.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smtc.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vpe.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-rm7k.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-platform.c
arch/mips/pci/ops-tx3927.c
arch/mips/pci/ops-tx4927.c
arch/mips/pci/pci-rc32434.c
arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
arch/mips/pnx8550/common/reset.c
arch/mips/pnx8550/common/setup.c
arch/mips/powertv/asic/irq_asic.c
arch/mips/rb532/serial.c
arch/mips/sibyte/common/sb_tbprof.c
arch/mips/sni/a20r.c
arch/mips/sni/pcimt.c
arch/mips/sni/pcit.c
arch/mips/sni/rm200.c
arch/mips/sni/time.c
arch/mips/txx9/generic/irq_tx4927.c
arch/mips/txx9/generic/irq_tx4938.c
arch/mips/txx9/generic/irq_tx4939.c
arch/mips/txx9/generic/setup.c
arch/mips/txx9/jmr3927/irq.c
arch/mips/txx9/rbtx4927/irq.c
arch/mips/txx9/rbtx4938/irq.c
arch/mips/txx9/rbtx4939/irq.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/common/siu.c
arch/mn10300/Kconfig
arch/mn10300/Kconfig.debug
arch/mn10300/include/asm/bitops.h
arch/mn10300/include/asm/irqflags.h [new file with mode: 0644]
arch/mn10300/include/asm/signal.h
arch/mn10300/include/asm/system.h
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/module.c
arch/mn10300/kernel/signal.c
arch/mn10300/mm/Makefile
arch/mn10300/mm/cache-disabled.c [moved from arch/frv/lib/perf_event.c with 53% similarity]
arch/mn10300/mm/cache.c
arch/mn10300/mm/dma-alloc.c
arch/parisc/Kconfig
arch/parisc/include/asm/compat.h
arch/parisc/include/asm/irqflags.h [new file with mode: 0644]
arch/parisc/include/asm/perf_event.h
arch/parisc/include/asm/system.h
arch/parisc/kernel/module.c
arch/parisc/kernel/perf.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/addnote.c
arch/powerpc/boot/dts/bluestone.dts [new file with mode: 0644]
arch/powerpc/boot/dts/canyonlands.dts
arch/powerpc/boot/dts/mpc8308_p1m.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8536ds.dts
arch/powerpc/boot/dts/p1022ds.dts
arch/powerpc/boot/dts/p4080ds.dts
arch/powerpc/configs/44x/bluestone_defconfig [new file with mode: 0644]
arch/powerpc/configs/e55xx_smp_defconfig [new file with mode: 0644]
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/include/asm/checksum.h
arch/powerpc/include/asm/compat.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/fsl_85xx_cache_sram.h [new file with mode: 0644]
arch/powerpc/include/asm/fsldma.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/include/asm/irqflags.h
arch/powerpc/include/asm/kexec.h
arch/powerpc/include/asm/kvm_fpu.h
arch/powerpc/include/asm/lppaca.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/memblock.h
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/ppc-pci.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/pte-common.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/rwsem.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/system.h
arch/powerpc/include/asm/time.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/align.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_44x.S
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fpu.S
arch/powerpc/kernel/head_40x.S
arch/powerpc/kernel/head_44x.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/machine_kexec_32.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/module.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_of_scan.c
arch/powerpc/kernel/perf_callchain.c
arch/powerpc/kernel/perf_event.c
arch/powerpc/kernel/perf_event_fsl_emb.c
arch/powerpc/kernel/ppc970-pmu.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/rtasd.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso32/Makefile
arch/powerpc/kernel/vdso64/Makefile
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/book3s_paired_singles.c
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/fpu.S
arch/powerpc/lib/Makefile
arch/powerpc/lib/checksum_64.S
arch/powerpc/lib/checksum_wrappers_64.c [new file with mode: 0644]
arch/powerpc/lib/copy_32.S
arch/powerpc/lib/ldstfp.S
arch/powerpc/lib/locks.c
arch/powerpc/lib/sstep.c
arch/powerpc/math-emu/Makefile
arch/powerpc/mm/40x_mmu.c
arch/powerpc/mm/44x_mmu.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/fault.c
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/mm/tlb_nohash_low.S
arch/powerpc/oprofile/Makefile
arch/powerpc/oprofile/backtrace.c
arch/powerpc/oprofile/op_model_fsl_emb.c
arch/powerpc/platforms/44x/Kconfig
arch/powerpc/platforms/44x/ppc44x_simple.c
arch/powerpc/platforms/512x/clock.c
arch/powerpc/platforms/52xx/efika.c
arch/powerpc/platforms/52xx/mpc52xx_common.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/mpc830x_rdb.c
arch/powerpc/platforms/83xx/mpc837x_mds.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p3041_ds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/p5020_ds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/ras.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/chrp/nvram.c
arch/powerpc/platforms/embedded6xx/wii.c
arch/powerpc/platforms/iseries/Makefile
arch/powerpc/platforms/iseries/dt.c
arch/powerpc/platforms/iseries/iommu.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/iseries/smp.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/mobility.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/scanlog.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h [new file with mode: 0644]
arch/powerpc/sysdev/fsl_85xx_cache_sram.c [new file with mode: 0644]
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c [new file with mode: 0644]
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_pci.h
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/mpc8xxx_gpio.c
arch/powerpc/sysdev/mpic_pasemi_msi.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/pmi.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/xmon/Makefile
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/crypto/prng.c
arch/s390/hypfs/hypfs_diag.c
arch/s390/hypfs/hypfs_vm.c
arch/s390/hypfs/inode.c
arch/s390/include/asm/compat.h
arch/s390/include/asm/hardirq.h
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/irqflags.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/system.h
arch/s390/include/asm/tlb.h
arch/s390/include/asm/tlbflush.h
arch/s390/include/asm/topology.h
arch/s390/kernel/debug.c
arch/s390/kernel/entry.h
arch/s390/kernel/mem_detect.c
arch/s390/kernel/module.c
arch/s390/kernel/smp.c
arch/s390/kernel/topology.c
arch/s390/mm/init.c
arch/s390/mm/maccess.c
arch/score/include/asm/irqflags.h
arch/sh/Kconfig
arch/sh/boards/mach-landisk/gio.c
arch/sh/include/asm/irqflags.h
arch/sh/include/asm/memblock.h
arch/sh/include/asm/perf_event.h
arch/sh/include/asm/syscalls_32.h
arch/sh/kernel/irq.c
arch/sh/kernel/irq_32.c
arch/sh/kernel/module.c
arch/sh/kernel/perf_callchain.c
arch/sh/kernel/perf_event.c
arch/sh/mm/init.c
arch/sh/oprofile/Makefile
arch/sh/oprofile/common.c
arch/sh/oprofile/op_impl.h [deleted file]
arch/sparc/Kconfig
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/backoff.h
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/irqflags_32.h
arch/sparc/include/asm/irqflags_64.h
arch/sparc/include/asm/jump_label.h [new file with mode: 0644]
arch/sparc/include/asm/memblock.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/include/asm/perf_event.h
arch/sparc/include/asm/rwsem-const.h [deleted file]
arch/sparc/include/asm/rwsem.h
arch/sparc/include/asm/system_64.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/apc.c
arch/sparc/kernel/irq_32.c
arch/sparc/kernel/jump_label.c [new file with mode: 0644]
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/module.c
arch/sparc/kernel/pci_msi.c
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sys_sparc_32.c
arch/sparc/kernel/unaligned_32.c
arch/sparc/kernel/windows.c
arch/sparc/lib/Makefile
arch/sparc/lib/atomic_64.S
arch/sparc/lib/bitops.S
arch/sparc/lib/rwsem_64.S [deleted file]
arch/sparc/mm/init_64.c
arch/sparc/prom/cif.S
arch/sparc/prom/console_64.c
arch/sparc/prom/devops_64.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/p1275.c
arch/sparc/prom/tree_64.c
arch/tile/include/arch/chip_tile64.h
arch/tile/include/arch/chip_tilepro.h
arch/tile/include/asm/bitops.h
arch/tile/include/asm/compat.h
arch/tile/include/asm/io.h
arch/tile/include/asm/irqflags.h
arch/tile/include/asm/processor.h
arch/tile/include/asm/ptrace.h
arch/tile/include/asm/sigcontext.h
arch/tile/include/asm/signal.h
arch/tile/include/asm/syscalls.h
arch/tile/kernel/hardwall.c
arch/tile/kernel/intvec_32.S
arch/tile/kernel/irq.c
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/tile/kernel/stack.c
arch/um/drivers/harddog_kern.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/random.c
arch/um/drivers/ubd_kern.c
arch/um/kernel/exec.c
arch/um/kernel/internal.h
arch/um/kernel/irq.c
arch/um/kernel/syscall.c
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/Makefile
arch/x86/boot/early_serial_console.c
arch/x86/ia32/ia32_aout.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/alternative.h
arch/x86/include/asm/amd_iommu.h
arch/x86/include/asm/amd_iommu_proto.h
arch/x86/include/asm/amd_iommu_types.h
arch/x86/include/asm/amd_nb.h [moved from arch/x86/include/asm/k8.h with 61% similarity]
arch/x86/include/asm/apb_timer.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/apicdef.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/calgary.h
arch/x86/include/asm/compat.h
arch/x86/include/asm/cpu.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/dwarf2.h
arch/x86/include/asm/e820.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/entry_arch.h
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/gart.h
arch/x86/include/asm/hardirq.h
arch/x86/include/asm/hpet.h
arch/x86/include/asm/hw_breakpoint.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/i387.h
arch/x86/include/asm/i8259.h
arch/x86/include/asm/io.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/iomap.h
arch/x86/include/asm/iommu_table.h [new file with mode: 0644]
arch/x86/include/asm/irq.h
arch/x86/include/asm/irq_remapping.h
arch/x86/include/asm/irq_vectors.h
arch/x86/include/asm/irqflags.h
arch/x86/include/asm/jump_label.h [new file with mode: 0644]
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/memblock.h [new file with mode: 0644]
arch/x86/include/asm/module.h
arch/x86/include/asm/mrst.h
arch/x86/include/asm/mwait.h [new file with mode: 0644]
arch/x86/include/asm/olpc_ofw.h
arch/x86/include/asm/page_32_types.h
arch/x86/include/asm/page_types.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/perf_event_p4.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/setup.h
arch/x86/include/asm/swiotlb.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/vmi.h [deleted file]
arch/x86/include/asm/vmi_time.h [deleted file]
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/alternative.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/amd_nb.c [moved from arch/x86/kernel/k8.c with 66% similarity]
arch/x86/kernel/apb_timer.c
arch/x86/kernel/aperture_64.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/nmi.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/check.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu.h
arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/mcheck/mce-severity.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mtrr/cleanup.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/crash_dump_64.c
arch/x86/kernel/e820.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/early_printk.c
arch/x86/kernel/early_printk_mrst.c [new file with mode: 0644]
arch/x86/kernel/efi.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/ftrace.c
arch/x86/kernel/head.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/hpet.c
arch/x86/kernel/hw_breakpoint.c
arch/x86/kernel/i387.c
arch/x86/kernel/i8259.c
arch/x86/kernel/irq.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/irq_work.c [new file with mode: 0644]
arch/x86/kernel/irqinit.c
arch/x86/kernel/jump_label.c [new file with mode: 0644]
arch/x86/kernel/kdebugfs.c
arch/x86/kernel/kprobes.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/microcode_core.c
arch/x86/kernel/module.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/olpc-xo1.c [new file with mode: 0644]
arch/x86/kernel/olpc.c
arch/x86/kernel/olpc_ofw.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/pci-iommu_table.c [new file with mode: 0644]
arch/x86/kernel/pci-swiotlb.c
arch/x86/kernel/pmtimer_64.c [deleted file]
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/sfi.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/sys_i386_32.c
arch/x86/kernel/tlb_uv.c
arch/x86/kernel/trampoline.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uv_irq.c
arch/x86/kernel/visws_quirks.c
arch/x86/kernel/vmi_32.c [deleted file]
arch/x86/kernel/vmiclock_32.c [deleted file]
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/emulate.c
arch/x86/kvm/i8259.c
arch/x86/kvm/irq.h
arch/x86/kvm/lapic.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/lib/memcpy_32.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.c
arch/x86/mm/Makefile
arch/x86/mm/fault.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/iomap_32.c
arch/x86/mm/ioremap.c
arch/x86/mm/k8topology_64.c
arch/x86/mm/kmemcheck/kmemcheck.c
arch/x86/mm/kmemcheck/opcode.c
arch/x86/mm/memblock.c [new file with mode: 0644]
arch/x86/mm/memtest.c
arch/x86/mm/numa_32.c
arch/x86/mm/numa_64.c
arch/x86/mm/pgtable.c
arch/x86/mm/srat_32.c
arch/x86/mm/srat_64.c
arch/x86/mm/tlb.c
arch/x86/oprofile/backtrace.c
arch/x86/oprofile/nmi_int.c
arch/x86/oprofile/op_model_amd.c
arch/x86/pci/olpc.c
arch/x86/power/cpu.c
arch/x86/xen/debugfs.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/pci-swiotlb-xen.c
arch/x86/xen/platform-pci-unplug.c
arch/x86/xen/setup.c
arch/x86/xen/spinlock.c
arch/x86/xen/time.c
arch/xtensa/include/asm/irqflags.h [new file with mode: 0644]
arch/xtensa/include/asm/system.h
arch/xtensa/kernel/irq.c
block/blk-cgroup.c
block/blk-core.c
block/blk-map.c
block/blk-merge.c
block/blk-sysfs.c
block/blk.h
block/bsg.c
block/cfq-iosched.c
block/elevator.c
crypto/Kconfig
crypto/ahash.c
crypto/algboss.c
crypto/des_generic.c
crypto/testmgr.c
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/acpi_pad.c
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/exutils.c
drivers/acpi/acpica/rsutils.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/einj.c
drivers/acpi/apei/erst-dbg.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/ghes.c
drivers/acpi/apei/hest.c
drivers/acpi/atomicio.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/bus.c
drivers/acpi/debugfs.c
drivers/acpi/ec_sys.c
drivers/acpi/event.c
drivers/acpi/fan.c
drivers/acpi/pci_root.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_perflib.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/video_detect.c
drivers/amba/bus.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_platform.c
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata-transport.c [new file with mode: 0644]
drivers/ata/libata-transport.h [new file with mode: 0644]
drivers/ata/libata.h
drivers/ata/pata_artop.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_cmd640.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_legacy.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_samsung_cf.c
drivers/ata/pata_scc.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_via.c
drivers/ata/pata_winbond.c [deleted file]
drivers/ata/sata_dwc_460ex.c
drivers/ata/sata_fsl.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_sil24.c
drivers/ata/sata_via.c
drivers/atm/iphase.c
drivers/atm/iphase.h
drivers/atm/solos-pci.c
drivers/base/firmware_class.c
drivers/base/power/Makefile
drivers/base/power/generic_ops.c
drivers/base/power/main.c
drivers/base/power/opp.c [new file with mode: 0644]
drivers/base/power/power.h
drivers/base/power/runtime.c
drivers/base/power/sysfs.c
drivers/base/power/trace.c
drivers/base/power/wakeup.c
drivers/base/topology.c
drivers/block/DAC960.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/block/amiflop.c
drivers/block/aoe/aoeblk.c
drivers/block/aoe/aoechr.c
drivers/block/ataflop.c
drivers/block/brd.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/block/drbd/drbd_main.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mg_disk.c
drivers/block/nbd.c
drivers/block/paride/pcd.c
drivers/block/paride/pd.c
drivers/block/paride/pf.c
drivers/block/paride/pg.c
drivers/block/paride/pt.c
drivers/block/pktcdvd.c
drivers/block/ps3disk.c
drivers/block/rbd.c [new file with mode: 0644]
drivers/block/rbd_types.h [new file with mode: 0644]
drivers/block/swim.c
drivers/block/swim3.c
drivers/block/ub.c
drivers/block/viodasd.c
drivers/block/virtio_blk.c
drivers/block/xd.c
drivers/block/xen-blkfront.c
drivers/block/xsysace.c
drivers/block/z2ram.c
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btmrvl_debugfs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_vhci.c
drivers/cdrom/gdrom.c
drivers/cdrom/viocd.c
drivers/char/agp/Kconfig
drivers/char/agp/amd64-agp.c
drivers/char/agp/generic.c
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-agp.h
drivers/char/agp/intel-gtt.c
drivers/char/apm-emulation.c
drivers/char/applicom.c
drivers/char/bfin-otp.c
drivers/char/briq_panel.c
drivers/char/bsr.c
drivers/char/cs5535_gpio.c
drivers/char/ds1302.c
drivers/char/ds1620.c
drivers/char/dsp56k.c
drivers/char/dtlk.c
drivers/char/generic_nvram.c
drivers/char/genrtc.c
drivers/char/hangcheck-timer.c
drivers/char/hpet.c
drivers/char/hvc_console.c
drivers/char/hvsi.c
drivers/char/hw_random/core.c
drivers/char/hw_random/n2-drv.c
drivers/char/i8k.c
drivers/char/ip2/ip2main.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/istallion.c
drivers/char/lp.c
drivers/char/mbcs.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/mmtimer.c
drivers/char/mspec.c
drivers/char/mwave/mwavedd.c
drivers/char/nvram.c
drivers/char/nwbutton.c
drivers/char/nwflash.c
drivers/char/pc8736x_gpio.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/main.c
drivers/char/pcmcia/ipwireless/main.h
drivers/char/pcmcia/ipwireless/tty.h
drivers/char/pcmcia/synclink_cs.c
drivers/char/ppdev.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/rio/rio_linux.c
drivers/char/rocket.c
drivers/char/scx200_gpio.c
drivers/char/snsc.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/char/synclink_gt.c
drivers/char/sysrq.c
drivers/char/tb0219.c
drivers/char/tlclk.c
drivers/char/toshiba.c
drivers/char/tpm/tpm.c
drivers/char/tty_io.c
drivers/char/uv_mmtimer.c
drivers/char/viotape.c
drivers/char/virtio_console.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/cpuidle/governors/menu.c
drivers/dca/dca-core.c
drivers/dma/coh901318.c
drivers/dma/ioat/dma_v2.c
drivers/dma/mv_xor.c
drivers/dma/shdma.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/amd64_edac_dbg.c
drivers/edac/edac_device_sysfs.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_mce_amd.c [deleted file]
drivers/edac/edac_module.c
drivers/edac/edac_module.h
drivers/edac/edac_pci_sysfs.c
drivers/edac/edac_stub.c
drivers/edac/i7core_edac.c
drivers/edac/mce_amd.c [new file with mode: 0644]
drivers/edac/mce_amd.h [moved from drivers/edac/edac_mce_amd.h with 65% similarity]
drivers/edac/mce_amd_inj.c [new file with mode: 0644]
drivers/firewire/core-transaction.c
drivers/firewire/net.c
drivers/firewire/nosy.c
drivers/firewire/ohci.c
drivers/firewire/ohci.h
drivers/firewire/sbp2.c
drivers/firmware/Kconfig
drivers/gpio/sx150x.c
drivers/gpio/tc35892-gpio.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_buffer.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_lock.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i830/i830_dma.c
drivers/gpu/drm/i830/i830_drv.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c
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_crt.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_dvo.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/mga/mga_drv.c
drivers/gpu/drm/mga/mga_state.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv17_tv.c
drivers/gpu/drm/nouveau/nv50_instmem.c
drivers/gpu/drm/nouveau/nvc0_instmem.c
drivers/gpu/drm/r128/r128_drv.c
drivers/gpu/drm/r128/r128_state.c
drivers/gpu/drm/radeon/atombios.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_blit_shaders.h
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_atombios.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_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_object.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_state.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/savage/savage_bci.c
drivers/gpu/drm/savage/savage_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/sis/sis_mm.c
drivers/gpu/drm/tdfx/tdfx_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/via/via_dma.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/vga/vgaarb.c
drivers/hid/hid-cando.c
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-ids.h
drivers/hid/hid-mosart.c
drivers/hid/hid-roccat.c
drivers/hid/hid-topseed.c
drivers/hid/hidraw.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hid/usbhid/usbhid.h
drivers/hwmon/Kconfig
drivers/hwmon/adm1031.c
drivers/hwmon/ads7871.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/emc1403.c
drivers/hwmon/f71882fg.c
drivers/hwmon/f75375s.c
drivers/hwmon/fschmd.c
drivers/hwmon/hp_accel.c
drivers/hwmon/k8temp.c
drivers/hwmon/lis3lv02d.c
drivers/hwmon/lis3lv02d_i2c.c
drivers/hwmon/lis3lv02d_spi.c
drivers/hwmon/lm95241.c
drivers/hwmon/pkgtemp.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83793.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-octeon.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/i2c-core.c
drivers/ide/ide-cd.c
drivers/ide/ide-cs.c
drivers/ide/ide-disk_ioctl.c
drivers/ide/ide-floppy_ioctl.c
drivers/ide/ide-gd.c
drivers/ide/ide-probe.c
drivers/ide/ide-tape.c
drivers/idle/i7300_idle.c
drivers/idle/intel_idle.c [changed mode: 0755->0644]
drivers/ieee1394/ohci1394.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/ipath/ipath_diag.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/qib/qib_diag.c
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/uinput.c
drivers/input/mouse/bcm5974.c
drivers/input/mousedev.c
drivers/input/serio/hil_mlc.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/i8042.c
drivers/input/serio/serio_raw.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/isdn/act2000/act2000.h
drivers/isdn/hardware/avm/Kconfig
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/hisax.h
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/mISDN/timerdev.c
drivers/isdn/sc/interrupt.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-netxbig.c [new file with mode: 0644]
drivers/leds/leds-ns2.c
drivers/lguest/lguest_user.c
drivers/macintosh/adb.c
drivers/macintosh/ans-lcd.c
drivers/macintosh/smu.c
drivers/macintosh/via-pmu-led.c
drivers/macintosh/via-pmu.c
drivers/md/.gitignore [deleted file]
drivers/md/bitmap.c
drivers/md/dm-ioctl.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/media/IR/imon.c
drivers/media/IR/ir-keytable.c
drivers/media/IR/ir-lirc-codec.c
drivers/media/IR/ir-raw-event.c
drivers/media/IR/ir-sysfs.c
drivers/media/IR/keymaps/rc-rc6-mce.c
drivers/media/IR/lirc_dev.c
drivers/media/IR/mceusb.c
drivers/media/Kconfig
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/opera1.c
drivers/media/dvb/firewire/firedtv-ci.c
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib7000p.h
drivers/media/dvb/mantis/Kconfig
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/video/cx231xx/Makefile
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/Kconfig
drivers/media/video/dabusb.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/sn9c20x.c
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/mem2mem_testdev.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9v022.c
drivers/media/video/mx2_camera.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7164/saa7164-buffer.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/videobuf-dma-contig.c
drivers/media/video/videobuf-dma-sg.c
drivers/memstick/core/mspro_block.c
drivers/message/fusion/mptctl.c
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_config.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab8500-spi.c
drivers/mfd/max8925-core.c
drivers/mfd/twl4030-irq.c
drivers/mfd/wm831x-irq.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/bh1780gli.c
drivers/misc/hpilo.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/misc/iwmc3200top/debugfs.c
drivers/misc/lkdtm.c
drivers/misc/phantom.c
drivers/misc/sgi-gru/grufile.c
drivers/misc/vmw_balloon.c [moved from drivers/misc/vmware_balloon.c with 100% similarity]
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/debugfs.c
drivers/mmc/core/sdio.c
drivers/mmc/host/at91_mci.c
drivers/mmc/host/imxmmc.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mmci.h
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/s3cmci.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdricoh_cs.c
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/tmio_mmc.h
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdchar.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/onenand/samsung.c
drivers/mtd/ubi/Kconfig
drivers/mtd/ubi/Kconfig.debug
drivers/mtd/ubi/build.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c
drivers/mtd/ubi/wl.c
drivers/net/3c527.c
drivers/net/3c59x.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/appletalk/Kconfig
drivers/net/atlx/atl1.c
drivers/net/b44.c
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_ethtool.c
drivers/net/benet/be_hw.h
drivers/net/benet/be_main.c
drivers/net/bfin_mac.c
drivers/net/bnx2x/bnx2x.h
drivers/net/bnx2x/bnx2x_main.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/caif/Kconfig
drivers/net/caif/caif_spi.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb4/cxgb4_main.c
drivers/net/e1000e/82571.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/hw.h
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/lib.c
drivers/net/e1000e/netdev.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/ehea/ehea_qmr.h
drivers/net/eql.c
drivers/net/fec.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/debug.c
drivers/net/ibmveth.c
drivers/net/irda/sir_dev.c
drivers/net/ks8851.c
drivers/net/ll_temac_main.c
drivers/net/ll_temac_mdio.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/niu.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy_device.c
drivers/net/ppp_async.c
drivers/net/ppp_generic.c
drivers/net/pxa168_eth.c [new file with mode: 0644]
drivers/net/qlcnic/qlcnic_init.c
drivers/net/qlcnic/qlcnic_main.c
drivers/net/qlge/qlge_main.c
drivers/net/r8169.c
drivers/net/rionet.c
drivers/net/sgiseeq.c
drivers/net/sh_eth.c
drivers/net/skge.c
drivers/net/smc91x.c
drivers/net/smsc911x.c
drivers/net/stmmac/stmmac_main.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tulip/de2104x.c
drivers/net/usb/hso.c
drivers/net/usb/ipheth.c
drivers/net/via-velocity.c
drivers/net/wan/cosa.c
drivers/net/wimax/i2400m/debugfs.c
drivers/net/wimax/i2400m/rx.c
drivers/net/wireless/adm8211.c
drivers/net/wireless/airo.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/debug.c
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/regd.h
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/b43/debugfs.c
drivers/net/wireless/b43/pcmcia.c
drivers/net/wireless/b43legacy/debugfs.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-3945-rs.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/debugfs.c
drivers/net/wireless/iwmc3200wifi/sdio.c
drivers/net/wireless/libertas/debugfs.c
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/p54/eeprom.c
drivers/net/wireless/p54/fwio.c
drivers/net/wireless/p54/led.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/txrx.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/ray_cs.h
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rtl818x/rtl8180_dev.c
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
drivers/net/wireless/wl12xx/wl1251_debugfs.c
drivers/net/wireless/wl12xx/wl1271_debugfs.c
drivers/net/wireless/wl3501_cs.c
drivers/oprofile/buffer_sync.c
drivers/oprofile/cpu_buffer.c
drivers/oprofile/oprof.c
drivers/oprofile/oprof.h
drivers/oprofile/oprofile_files.c
drivers/oprofile/oprofile_perf.c [new file with mode: 0644]
drivers/oprofile/oprofilefs.c
drivers/parport/parport_cs.c
drivers/parport/share.c
drivers/pci/dmar.c
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/cpqphp_sysfs.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_acpi.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/htirq.c
drivers/pci/intel-iommu.c
drivers/pci/intr_remapping.c
drivers/pci/iov.c
drivers/pci/msi.c
drivers/pci/pci.h
drivers/pci/pcie/Makefile
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/pme.c [moved from drivers/pci/pcie/pme/pcie_pme.c with 83% similarity]
drivers/pci/pcie/pme/Makefile [deleted file]
drivers/pci/pcie/pme/pcie_pme.h [deleted file]
drivers/pci/pcie/pme/pcie_pme_acpi.c [deleted file]
drivers/pci/pcie/portdrv.h
drivers/pci/pcie/portdrv_acpi.c [new file with mode: 0644]
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/quirks.c
drivers/pci/slot.c
drivers/pcmcia/au1000_generic.c
drivers/pcmcia/au1000_generic.h
drivers/pcmcia/au1000_pb1x00.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/o2micro.h
drivers/pcmcia/pcmcia_cis.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/rsrc_iodyn.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/sa1100_generic.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/vrc4173_cardu.c
drivers/pcmcia/xxs1500_ss.c
drivers/pcmcia/yenta_socket.c
drivers/platform/x86/Kconfig
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_rar_register.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/isapnp/proc.c
drivers/power/apm_power.c
drivers/power/intel_mid_battery.c
drivers/regulator/88pm8607.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/core.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/max1586.c
drivers/regulator/max8649.c
drivers/regulator/max8998.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/rtc/rtc-ab3100.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-s3c.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eer.c
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dcssblk.c
drivers/s390/char/ctrlchar.c
drivers/s390/char/fs3270.c
drivers/s390/char/keyboard.c
drivers/s390/char/monreader.c
drivers/s390/char/monwriter.c
drivers/s390/char/sclp.c
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/vmcp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/char/vmwatchdog.c
drivers/s390/char/zcore.c
drivers/s390/cio/chsc_sch.c
drivers/s390/cio/css.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/net/ctcm_main.c
drivers/s390/scsi/zfcp_cfdc.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/envctrl.c
drivers/sbus/char/jsflash.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/aacraid/linit.c
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/ch.c
drivers/scsi/constants.c
drivers/scsi/dpt_i2o.c
drivers/scsi/gdth.c
drivers/scsi/hpsa.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mm.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/osst.c
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_tgt_if.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/scsi/sym53c8xx_2/sym_hipd.c
drivers/serial/68328serial.c
drivers/serial/8250_early.c
drivers/serial/Kconfig
drivers/serial/amba-pl010.c
drivers/serial/bfin_sport_uart.c
drivers/serial/ioc3_serial.c
drivers/serial/mfd.c
drivers/serial/mpc52xx_uart.c
drivers/serial/mrst_max3110.c
drivers/serial/samsung.c
drivers/serial/serial_cs.c
drivers/serial/sn_console.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/amba-pl022.c
drivers/spi/atmel_spi.c
drivers/spi/dw_spi.c
drivers/spi/omap2_mcspi.c
drivers/spi/orion_spi.c
drivers/spi/spi.c
drivers/spi/spi_bfin5xx.c
drivers/spi/spi_fsl_espi.c [new file with mode: 0644]
drivers/spi/spi_fsl_lib.c [new file with mode: 0644]
drivers/spi/spi_fsl_lib.h [new file with mode: 0644]
drivers/spi/spi_fsl_spi.c [moved from drivers/spi/spi_mpc8xxx.c with 63% similarity]
drivers/spi/spi_gpio.c
drivers/spi/spi_imx.c
drivers/spi/spi_s3c64xx.c
drivers/spi/spi_topcliff_pch.c [new file with mode: 0644]
drivers/spi/spidev.c
drivers/ssb/main.c
drivers/ssb/pcmcia.c
drivers/ssb/scan.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/batman-adv/bat_sysfs.c
drivers/staging/batman-adv/hard-interface.c
drivers/staging/batman-adv/icmp_socket.c
drivers/staging/batman-adv/main.c
drivers/staging/batman-adv/originator.c
drivers/staging/batman-adv/routing.c
drivers/staging/batman-adv/send.c
drivers/staging/batman-adv/types.h
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/das08_cs.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/quatech_daqp_cs.c
drivers/staging/crystalhd/crystalhd_lnx.c
drivers/staging/cx25821/Kconfig
drivers/staging/dream/camera/msm_camera.c
drivers/staging/dream/pmem.c
drivers/staging/dream/qdsp5/adsp_driver.c
drivers/staging/dream/qdsp5/audio_aac.c
drivers/staging/dream/qdsp5/audio_amrnb.c
drivers/staging/dream/qdsp5/audio_evrc.c
drivers/staging/dream/qdsp5/audio_in.c
drivers/staging/dream/qdsp5/audio_mp3.c
drivers/staging/dream/qdsp5/audio_out.c
drivers/staging/dream/qdsp5/audio_qcelp.c
drivers/staging/dream/qdsp5/evlog.h
drivers/staging/dream/qdsp5/snd.c
drivers/staging/easycap/Kconfig
drivers/staging/frontier/alphatrack.c
drivers/staging/frontier/tranzport.c
drivers/staging/go7007/Kconfig
drivers/staging/hv/blkvsc_drv.c
drivers/staging/hv/netvsc_drv.c
drivers/staging/hv/ring_buffer.c
drivers/staging/hv/storvsc_api.h
drivers/staging/hv/storvsc_drv.c
drivers/staging/iio/industrialio-core.c
drivers/staging/iio/industrialio-ring.c
drivers/staging/lirc/lirc_imon.c
drivers/staging/lirc/lirc_it87.c
drivers/staging/lirc/lirc_sasem.c
drivers/staging/lirc/lirc_serial.c
drivers/staging/lirc/lirc_sir.c
drivers/staging/memrar/memrar_handler.c
drivers/staging/octeon/Kconfig
drivers/staging/panel/panel.c
drivers/staging/rt2860/usb_main_dev.c
drivers/staging/sep/Kconfig [deleted file]
drivers/staging/sep/Makefile [deleted file]
drivers/staging/sep/TODO [deleted file]
drivers/staging/sep/sep_dev.h [deleted file]
drivers/staging/sep/sep_driver.c [deleted file]
drivers/staging/sep/sep_driver_api.h [deleted file]
drivers/staging/sep/sep_driver_config.h [deleted file]
drivers/staging/sep/sep_driver_hw_defs.h [deleted file]
drivers/staging/spectra/Kconfig
drivers/staging/spectra/ffsport.c
drivers/staging/spectra/flash.c
drivers/staging/ti-st/st.h
drivers/staging/ti-st/st_core.c
drivers/staging/ti-st/st_core.h
drivers/staging/ti-st/st_kim.c
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/staging/tm6000/Kconfig
drivers/staging/tm6000/tm6000-input.c
drivers/staging/usbip/Kconfig
drivers/staging/vt6655/wpactl.c
drivers/staging/wlags49_h2/wl_cs.c
drivers/staging/wlags49_h2/wl_internal.h
drivers/staging/wlags49_h2/wl_main.c
drivers/staging/wlan-ng/cfg80211.c
drivers/staging/zram/zram_drv.c
drivers/telephony/ixj.c
drivers/telephony/ixj_pcmcia.c
drivers/telephony/phonedev.c
drivers/uio/uio.c
drivers/usb/atm/cxacru.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/class/usblp.c
drivers/usb/class/usbtmc.c
drivers/usb/core/Kconfig
drivers/usb/core/file.c
drivers/usb/core/message.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_hid.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/rndis.h
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/uvc_v4l2.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-ppc-of.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/sl811_cs.c
drivers/usb/host/xhci-ring.c
drivers/usb/image/mdc800.c
drivers/usb/misc/adutux.c
drivers/usb/misc/idmouse.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/rio500.c
drivers/usb/misc/usblcd.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/musb_debugfs.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget.h
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_host.c
drivers/usb/otg/twl4030-usb.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/generic.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/navman.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/ssu100.c
drivers/usb/serial/usb-serial.c
drivers/usb/usb-skeleton.c
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/console/fbcon.c
drivers/video/efifb.c
drivers/video/fbmem.c
drivers/video/mbx/mbxdebugfs.c
drivers/video/omap2/vram.c
drivers/video/pxa168fb.c
drivers/video/sis/sis_main.c
drivers/video/via/ioctl.c
drivers/vlynq/vlynq.c
drivers/watchdog/Kconfig
drivers/watchdog/ar7_wdt.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/cpwd.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/octeon-wdt-main.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/ts72xx_wdt.c
drivers/xen/events.c
drivers/xen/evtchn.c
drivers/xen/manage.c
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenfs/super.c
drivers/xen/xenfs/xenbus.c
firmware/Makefile
fs/9p/fid.c
fs/9p/vfs_dir.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/Kconfig
fs/adfs/Kconfig
fs/adfs/super.c
fs/affs/super.c
fs/afs/flock.c
fs/afs/mntpt.c
fs/afs/super.c
fs/aio.c
fs/autofs/Kconfig
fs/autofs/root.c
fs/autofs4/dev-ioctl.c
fs/autofs4/root.c
fs/bfs/inode.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_misc.c
fs/bio-integrity.c
fs/btrfs/super.c
fs/cachefiles/daemon.c
fs/ceph/Kconfig
fs/ceph/Makefile
fs/ceph/README [deleted file]
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/ceph_frag.c
fs/ceph/debugfs.c
fs/ceph/dir.c
fs/ceph/export.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/ioctl.c
fs/ceph/ioctl.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mdsmap.c
fs/ceph/pagelist.c [deleted file]
fs/ceph/snap.c
fs/ceph/strings.c [moved from fs/ceph/ceph_strings.c with 59% similarity]
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/char_dev.c
fs/cifs/cifs_unicode.h
fs/cifs/cifs_uniupr.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/netmisc.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/coda/psdev.c
fs/compat.c
fs/compat_ioctl.c
fs/debugfs/file.c
fs/direct-io.c
fs/dlm/debug_fs.c
fs/dlm/plock.c
fs/dlm/user.c
fs/ecryptfs/crypto.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/kthread.c
fs/ecryptfs/messaging.c
fs/ecryptfs/miscdev.c
fs/eventfd.c
fs/eventpoll.c
fs/exec.c
fs/exofs/inode.c
fs/ext2/super.c
fs/ext3/super.c
fs/ext4/super.c
fs/fat/inode.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fcntl.c
fs/fifo.c
fs/freevxfs/vxfs_lookup.c
fs/freevxfs/vxfs_super.c
fs/fs-writeback.c
fs/fuse/control.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/gfs2/Kconfig
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/bmap.h
fs/gfs2/dentry.c
fs/gfs2/dir.c
fs/gfs2/dir.h
fs/gfs2/export.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/lock_dlm.c
fs/gfs2/log.c
fs/gfs2/main.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
fs/gfs2/quota.c
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h
fs/gfs2/super.c
fs/gfs2/sys.c
fs/gfs2/trace_gfs2.h
fs/gfs2/trans.h
fs/gfs2/xattr.c
fs/hfs/bfind.c
fs/hfs/btree.c
fs/hfs/btree.h
fs/hfs/super.c
fs/hfsplus/bfind.c
fs/hfsplus/bitmap.c
fs/hfsplus/brec.c
fs/hfsplus/btree.c
fs/hfsplus/catalog.c
fs/hfsplus/dir.c
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/hfsplus_raw.h
fs/hfsplus/inode.c
fs/hfsplus/ioctl.c
fs/hfsplus/options.c
fs/hfsplus/part_tbl.c
fs/hfsplus/super.c
fs/hfsplus/unicode.c
fs/hfsplus/wrapper.c
fs/hpfs/Kconfig
fs/hpfs/super.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/isofs/dir.c
fs/isofs/inode.c
fs/isofs/isofs.h
fs/isofs/namei.c
fs/isofs/rock.c
fs/jbd2/journal.c
fs/jffs2/fs.c
fs/jffs2/super.c
fs/jfs/super.c
fs/libfs.c
fs/locks.c
fs/logfs/dir.c
fs/minix/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/ncplib_kernel.c
fs/ncpfs/ncplib_kernel.h
fs/ncpfs/ncpsign_kernel.c
fs/ncpfs/sock.c
fs/nfs/Kconfig
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/file.c
fs/nfs/nfs4state.c
fs/nfs/super.c
fs/nfsd/Kconfig
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.h
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/nilfs2/ioctl.c
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c
fs/no-block.c
fs/notify/Kconfig
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/notify/inotify/inotify_user.c
fs/ntfs/super.c
fs/ocfs2/acl.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/blockcheck.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/heartbeat.h
fs/ocfs2/cluster/masklog.h
fs/ocfs2/cluster/nodemanager.c
fs/ocfs2/cluster/ocfs2_nodemanager.h
fs/ocfs2/cluster/tcp.c
fs/ocfs2/dcache.c
fs/ocfs2/dcache.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdebug.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/mmap.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/ocfs2_ioctl.h
fs/ocfs2/refcounttree.c
fs/ocfs2/refcounttree.h
fs/ocfs2/reservations.c
fs/ocfs2/slot_map.c
fs/ocfs2/stack_o2cb.c
fs/ocfs2/stack_user.c
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/super.c
fs/ocfs2/symlink.c
fs/ocfs2/sysfile.c
fs/ocfs2/xattr.c
fs/proc/base.c
fs/proc/page.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/proc/task_mmu.c
fs/proc/vmcore.c
fs/qnx4/dir.c
fs/qnx4/inode.c
fs/qnx4/namei.c
fs/read_write.c
fs/reiserfs/ioctl.c
fs/romfs/super.c
fs/signalfd.c
fs/smbfs/Kconfig
fs/smbfs/inode.c
fs/squashfs/dir.c
fs/squashfs/super.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/timerfd.c
fs/ubifs/commit.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/file.c
fs/ubifs/gc.c
fs/ubifs/io.c
fs/ubifs/journal.c
fs/ubifs/key.h
fs/ubifs/log.c
fs/ubifs/lpt.c
fs/ubifs/lpt_commit.c
fs/ubifs/master.c
fs/ubifs/misc.h
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/scan.c
fs/ubifs/shrinker.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/ubifs.h
fs/udf/Kconfig
fs/udf/super.c
fs/ufs/Kconfig
fs/ufs/super.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_fs.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_fsops.h
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans_priv.h
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/asm-generic/atomic.h
include/asm-generic/bitops/find.h
include/asm-generic/cmpxchg-local.h
include/asm-generic/fcntl.h
include/asm-generic/gpio.h
include/asm-generic/hardirq.h
include/asm-generic/io.h
include/asm-generic/irqflags.h
include/asm-generic/kdebug.h
include/asm-generic/percpu.h
include/asm-generic/pgtable.h
include/asm-generic/system.h
include/asm-generic/vmlinux.lds.h
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/drm_pciids.h
include/drm/i830_drm.h
include/drm/i915_drm.h
include/drm/mga_drm.h
include/drm/nouveau_drm.h
include/drm/radeon_drm.h
include/drm/savage_drm.h
include/drm/ttm/ttm_bo_api.h
include/linux/Kbuild
include/linux/acpi.h
include/linux/acpi_pmtmr.h
include/linux/amba/bus.h
include/linux/amba/mmci.h
include/linux/amba/pl022.h
include/linux/amba/serial.h
include/linux/ata.h
include/linux/bitops.h
include/linux/ceph/auth.h [moved from fs/ceph/auth.h with 97% similarity]
include/linux/ceph/buffer.h [moved from fs/ceph/buffer.h with 100% similarity]
include/linux/ceph/ceph_debug.h [moved from fs/ceph/ceph_debug.h with 86% similarity]
include/linux/ceph/ceph_frag.h [moved from fs/ceph/ceph_frag.h with 100% similarity]
include/linux/ceph/ceph_fs.h [moved from fs/ceph/ceph_fs.h with 99% similarity]
include/linux/ceph/ceph_hash.h [moved from fs/ceph/ceph_hash.h with 100% similarity]
include/linux/ceph/debugfs.h [new file with mode: 0644]
include/linux/ceph/decode.h [moved from fs/ceph/decode.h with 96% similarity]
include/linux/ceph/libceph.h [new file with mode: 0644]
include/linux/ceph/mdsmap.h [moved from fs/ceph/mdsmap.h with 100% similarity]
include/linux/ceph/messenger.h [moved from fs/ceph/messenger.h with 95% similarity]
include/linux/ceph/mon_client.h [moved from fs/ceph/mon_client.h with 99% similarity]
include/linux/ceph/msgpool.h [moved from fs/ceph/msgpool.h with 100% similarity]
include/linux/ceph/msgr.h [moved from fs/ceph/msgr.h with 100% similarity]
include/linux/ceph/osd_client.h [moved from fs/ceph/osd_client.h with 76% similarity]
include/linux/ceph/osdmap.h [moved from fs/ceph/osdmap.h with 97% similarity]
include/linux/ceph/pagelist.h [moved from fs/ceph/pagelist.h with 62% similarity]
include/linux/ceph/rados.h [moved from fs/ceph/rados.h with 100% similarity]
include/linux/ceph/types.h [moved from fs/ceph/types.h with 100% similarity]
include/linux/cgroup.h
include/linux/compat.h
include/linux/compiler.h
include/linux/coredump.h
include/linux/cpuidle.h
include/linux/cred.h
include/linux/crush/crush.h [moved from fs/ceph/crush/crush.h with 100% similarity]
include/linux/crush/hash.h [moved from fs/ceph/crush/hash.h with 100% similarity]
include/linux/crush/mapper.h [moved from fs/ceph/crush/mapper.h with 100% similarity]
include/linux/debug_locks.h
include/linux/dma-mapping.h
include/linux/dmaengine.h
include/linux/dmar.h
include/linux/dynamic_debug.h
include/linux/early_res.h [deleted file]
include/linux/edac.h
include/linux/elevator.h
include/linux/fanotify.h
include/linux/fdtable.h
include/linux/fs.h
include/linux/fsnotify_backend.h
include/linux/ftrace_event.h
include/linux/genhd.h
include/linux/gpio.h
include/linux/hardirq.h
include/linux/htirq.h
include/linux/i2c/sx150x.h
include/linux/idr.h
include/linux/if_ether.h
include/linux/if_fddi.h
include/linux/if_hippi.h
include/linux/if_pppox.h
include/linux/init_task.h
include/linux/input.h
include/linux/intel-gtt.h [new file with mode: 0644]
include/linux/interrupt.h
include/linux/io-mapping.h
include/linux/iocontext.h
include/linux/ipv6.h
include/linux/irq.h
include/linux/irq_work.h [new file with mode: 0644]
include/linux/irqdesc.h [new file with mode: 0644]
include/linux/irqflags.h
include/linux/irqnr.h
include/linux/jump_label.h [new file with mode: 0644]
include/linux/jump_label_ref.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/key.h
include/linux/kfifo.h
include/linux/kobject.h
include/linux/kobject_ns.h [new file with mode: 0644]
include/linux/ksm.h
include/linux/kvm_host.h
include/linux/lglock.h
include/linux/libata.h
include/linux/list.h
include/linux/lockdep.h
include/linux/memblock.h
include/linux/mfd/tc35892.h
include/linux/miscdevice.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmc/sdio.h
include/linux/mmzone.h
include/linux/module.h
include/linux/msi.h
include/linux/mutex.h
include/linux/nbd.h
include/linux/ncp.h
include/linux/ncp_fs.h
include/linux/ncp_fs_sb.h
include/linux/netfilter/nfnetlink_conntrack.h
include/linux/netfilter/xt_IDLETIMER.h
include/linux/netfilter/xt_SECMARK.h
include/linux/netfilter/xt_ipvs.h
include/linux/netlink.h
include/linux/netpoll.h
include/linux/nfs_fs.h
include/linux/notifier.h
include/linux/opp.h [new file with mode: 0644]
include/linux/oprofile.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu-defs.h
include/linux/percpu.h
include/linux/perf_event.h
include/linux/phonet.h
include/linux/pm.h
include/linux/pm_runtime.h
include/linux/pm_wakeup.h
include/linux/pxa168_eth.h [new file with mode: 0644]
include/linux/quotaops.h
include/linux/radix-tree.h
include/linux/rculist.h
include/linux/rculist_nulls.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/resume-trace.h
include/linux/rfkill.h
include/linux/sched.h
include/linux/security.h
include/linux/selinux.h
include/linux/semaphore.h
include/linux/serial.h
include/linux/serial_core.h
include/linux/smp_lock.h
include/linux/socket.h
include/linux/spi/dw_spi.h
include/linux/spinlock.h
include/linux/srcu.h
include/linux/stop_machine.h
include/linux/sunrpc/auth_gss.h
include/linux/sunrpc/clnt.h
include/linux/suspend.h
include/linux/swap.h
include/linux/sysfs.h
include/linux/sysrq.h
include/linux/thread_info.h
include/linux/topology.h
include/linux/tracepoint.h
include/linux/types.h
include/linux/uinput.h
include/linux/usb/composite.h
include/linux/usb/serial.h
include/linux/vgaarb.h
include/linux/vmstat.h
include/linux/wait.h
include/linux/workqueue.h
include/media/videobuf-dma-sg.h
include/net/addrconf.h
include/net/bluetooth/bluetooth.h
include/net/cls_cgroup.h
include/net/dst.h
include/net/ip_vs.h
include/net/netfilter/nf_conntrack.h
include/net/route.h
include/net/sock.h
include/net/tcp.h
include/net/udp.h
include/net/xfrm.h
include/pcmcia/cs.h [deleted file]
include/pcmcia/ds.h
include/pcmcia/ss.h
include/trace/events/irq.h
include/trace/events/napi.h
include/trace/events/net.h [new file with mode: 0644]
include/trace/events/power.h
include/trace/events/sched.h
include/trace/events/skb.h
include/trace/events/timer.h
include/xen/platform_pci.h
init/Kconfig
init/main.c
ipc/mqueue.c
ipc/sem.c
ipc/shm.c
kernel/Makefile
kernel/cgroup.c
kernel/compat.c
kernel/configs.c
kernel/cpuset.c
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_bp.c
kernel/debug/kdb/kdb_main.c
kernel/early_res.c [deleted file]
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/futex_compat.c
kernel/gcov/fs.c
kernel/groups.c
kernel/hrtimer.c
kernel/hung_task.c
kernel/hw_breakpoint.c
kernel/irq/Kconfig [new file with mode: 0644]
kernel/irq/Makefile
kernel/irq/autoprobe.c
kernel/irq/chip.c
kernel/irq/dummychip.c [new file with mode: 0644]
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/irqdesc.c [new file with mode: 0644]
kernel/irq/manage.c
kernel/irq/migration.c
kernel/irq/numa_migrate.c [deleted file]
kernel/irq/proc.c
kernel/irq/resend.c
kernel/irq/spurious.c
kernel/irq_work.c [new file with mode: 0644]
kernel/jump_label.c [new file with mode: 0644]
kernel/kfifo.c
kernel/kprobes.c
kernel/lockdep.c
kernel/module.c
kernel/mutex.c
kernel/perf_event.c
kernel/pid.c
kernel/pm_qos_params.c
kernel/power/Kconfig
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/power.h
kernel/power/poweroff.c
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/swap.c
kernel/printk.c
kernel/profile.c
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/rtmutex-tester.c
kernel/sched.c
kernel/sched_fair.c
kernel/sched_features.h
kernel/sched_rt.c
kernel/sched_stoptask.c [new file with mode: 0644]
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/srcu.c
kernel/stop_machine.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl.c
kernel/sysctl_check.c
kernel/test_kprobes.c
kernel/time/ntp.c
kernel/timer.c
kernel/trace/Kconfig
kernel/trace/blktrace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_stack.c
kernel/trace/trace_workqueue.c
kernel/tracepoint.c
kernel/watchdog.c
kernel/workqueue.c
lib/Kconfig.debug
lib/bug.c
lib/dma-debug.c
lib/dynamic_debug.c
lib/kobject_uevent.c
lib/list_sort.c
lib/radix-tree.c
lib/raid6/.gitignore [new file with mode: 0644]
lib/scatterlist.c
lib/swiotlb.c
mm/Kconfig
mm/backing-dev.c
mm/bootmem.c
mm/bounce.c
mm/compaction.c
mm/fremap.c
mm/hugetlb.c
mm/ksm.c
mm/memblock.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mlock.c
mm/mmap.c
mm/mmzone.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/percpu.c
mm/percpu_up.c
mm/rmap.c
mm/sparse-vmemmap.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/9p/client.c
net/9p/trans_rdma.c
net/9p/trans_virtio.c
net/Kconfig
net/Makefile
net/atm/br2684.c
net/atm/mpc.c
net/atm/proc.c
net/ax25/ax25_ds_timer.c
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/sock.c
net/bridge/br_netfilter.c
net/caif/caif_socket.c
net/caif/cfrfml.c
net/ceph/Kconfig [new file with mode: 0644]
net/ceph/Makefile [new file with mode: 0644]
net/ceph/armor.c [moved from fs/ceph/armor.c with 100% similarity]
net/ceph/auth.c [moved from fs/ceph/auth.c with 97% similarity]
net/ceph/auth_none.c [moved from fs/ceph/auth_none.c with 96% similarity]
net/ceph/auth_none.h [moved from fs/ceph/auth_none.h with 94% similarity]
net/ceph/auth_x.c [moved from fs/ceph/auth_x.c with 98% similarity]
net/ceph/auth_x.h [moved from fs/ceph/auth_x.h with 96% similarity]
net/ceph/auth_x_protocol.h [moved from fs/ceph/auth_x_protocol.h with 100% similarity]
net/ceph/buffer.c [moved from fs/ceph/buffer.c with 86% similarity]
net/ceph/ceph_common.c [new file with mode: 0644]
net/ceph/ceph_fs.c [moved from fs/ceph/ceph_fs.c with 92% similarity]
net/ceph/ceph_hash.c [moved from fs/ceph/ceph_hash.c with 98% similarity]
net/ceph/ceph_strings.c [new file with mode: 0644]
net/ceph/crush/crush.c [moved from fs/ceph/crush/crush.c with 99% similarity]
net/ceph/crush/hash.c [moved from fs/ceph/crush/hash.c with 99% similarity]
net/ceph/crush/mapper.c [moved from fs/ceph/crush/mapper.c with 99% similarity]
net/ceph/crypto.c [moved from fs/ceph/crypto.c with 99% similarity]
net/ceph/crypto.h [moved from fs/ceph/crypto.h with 95% similarity]
net/ceph/debugfs.c [new file with mode: 0644]
net/ceph/messenger.c [moved from fs/ceph/messenger.c with 89% similarity]
net/ceph/mon_client.c [moved from fs/ceph/mon_client.c with 94% similarity]
net/ceph/msgpool.c [moved from fs/ceph/msgpool.c with 95% similarity]
net/ceph/osd_client.c [moved from fs/ceph/osd_client.c with 84% similarity]
net/ceph/osdmap.c [moved from fs/ceph/osdmap.c with 97% similarity]
net/ceph/pagelist.c [new file with mode: 0644]
net/ceph/pagevec.c [new file with mode: 0644]
net/core/datagram.c
net/core/dev.c
net/core/ethtool.c
net/core/gen_estimator.c
net/core/iovec.c
net/core/net-traces.c
net/core/skbuff.c
net/core/sock.c
net/core/stream.c
net/dccp/probe.c
net/ipv4/Kconfig
net/ipv4/datagram.c
net/ipv4/fib_frontend.c
net/ipv4/fib_trie.c
net/ipv4/igmp.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv4/netfilter/nf_nat_core.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_probe.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/xfrm4_policy.c
net/ipv4/xfrm4_state.c
net/ipv6/addrconf.c
net/ipv6/addrlabel.c
net/ipv6/datagram.c
net/ipv6/ip6_output.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/udp.c
net/ipv6/xfrm6_state.c
net/ipx/Kconfig
net/irda/af_irda.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_eth.c
net/l2tp/l2tp_eth.c
net/llc/af_llc.c
net/llc/llc_station.c
net/mac80211/agg-tx.c
net/mac80211/debugfs.c
net/mac80211/debugfs_key.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/main.c
net/mac80211/rate.c
net/mac80211/rc80211_minstrel_debugfs.c
net/mac80211/rc80211_minstrel_ht_debugfs.c
net/mac80211/rc80211_pid_debugfs.c
net/mac80211/rx.c
net/mac80211/status.c
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ftp.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_extend.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_log.c
net/netfilter/nf_queue.c
net/netfilter/nf_tproxy_core.c
net/netfilter/xt_CT.c
net/netfilter/xt_SECMARK.c
net/netfilter/xt_recent.c
net/netlink/af_netlink.c
net/nonet.c
net/phonet/pep.c
net/rds/page.c
net/rds/recv.c
net/rds/tcp_connect.c
net/rds/tcp_listen.c
net/rds/tcp_recv.c
net/rds/tcp_send.c
net/rfkill/core.c
net/rose/af_rose.c
net/sched/act_police.c
net/sched/cls_cgroup.c
net/sched/cls_u32.c
net/sched/sch_atm.c
net/sched/sch_hfsc.c
net/sctp/auth.c
net/sctp/output.c
net/sctp/probe.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/xprtsock.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/debugfs.c
net/wireless/wext-compat.c
net/wireless/wext-core.c
net/wireless/wext-priv.c
net/x25/Kconfig
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
samples/kfifo/bytestream-example.c
samples/kfifo/dma-example.c
samples/kfifo/inttype-example.c
samples/kfifo/record-example.c
samples/tracepoints/tracepoint-sample.c
scripts/Makefile
scripts/Makefile.build
scripts/Makefile.lib
scripts/basic/Makefile
scripts/basic/docproc.c
scripts/basic/hash.c [deleted file]
scripts/gcc-goto.sh [new file with mode: 0644]
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/expr.h
scripts/kconfig/menu.c
scripts/kconfig/symbol.c
scripts/kernel-doc
scripts/mkmakefile
scripts/recordmcount.c [new file with mode: 0644]
scripts/recordmcount.h [new file with mode: 0644]
scripts/recordmcount.pl
scripts/setlocalversion
security/apparmor/.gitignore
security/apparmor/apparmorfs.c
security/apparmor/include/resource.h
security/apparmor/lib.c
security/apparmor/lsm.c
security/apparmor/path.c
security/apparmor/policy.c
security/apparmor/resource.c
security/capability.c
security/commoncap.c
security/inode.c
security/integrity/ima/ima.h
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_main.c
security/keys/keyctl.c
security/security.c
security/selinux/Makefile
security/selinux/exports.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/Makefile [deleted file]
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/conditional.c
security/selinux/ss/conditional.h
security/selinux/ss/ebitmap.c
security/selinux/ss/ebitmap.h
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c
security/selinux/ss/status.c [new file with mode: 0644]
security/smack/smack_lsm.c
security/smack/smackfs.c
security/tomoyo/common.c
security/tomoyo/common.h
sound/core/control.c
sound/core/pcm.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/seq/oss/seq_oss.c
sound/core/seq/oss/seq_oss_init.c
sound/core/sound.c
sound/i2c/other/ak4xxx-adda.c
sound/isa/msnd/msnd_pinnacle.c
sound/oss/msnd_pinnacle.c
sound/oss/sound_timer.c
sound/oss/soundcard.c
sound/pci/asihpi/hpi6205.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_intelhdmi.c
sound/pci/hda/patch_nvhdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/intel8x0.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/xonar_wm87x6.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pcmcia/pdaudiocf/pdaudiocf.c
sound/pcmcia/pdaudiocf/pdaudiocf.h
sound/pcmcia/vx/vxpocket.c
sound/pcmcia/vx/vxpocket.h
sound/ppc/snd_ps3.c
sound/soc/imx/imx-ssi.c
sound/soc/s3c24xx/s3c-dma.c
sound/soc/sh/migor.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/sound_core.c
sound/usb/card.c
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/mixer.c
sound/usb/pcm.c
tools/perf/Documentation/perf-annotate.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-report.c
tools/perf/feature-tests.mak
tools/perf/perf.h
tools/perf/scripts/python/bin/netdev-times-record [new file with mode: 0644]
tools/perf/scripts/python/bin/netdev-times-report [new file with mode: 0644]
tools/perf/scripts/python/netdev-times.py [new file with mode: 0644]
tools/perf/util/cache.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/hist.c
tools/perf/util/path.c
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/sort.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/trace-event-scripting.c
tools/perf/util/ui/browser.c
tools/perf/util/ui/browser.h
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/hists.c
tools/perf/util/ui/browsers/map.c
tools/perf/util/ui/util.c
tools/perf/util/util.h
virt/kvm/eventfd.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 72b487869788c14cd40e9535b700f4be166aa12b..41d8e63d5165b5b786db6ab7d8c14fbc49fc0107 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -3554,12 +3554,12 @@ E: cvance@nai.com
 D: portions of the Linux Security Module (LSM) framework and security modules
 
 N: Petr Vandrovec
-E: vandrove@vc.cvut.cz
+E: petr@vandrovec.name
 D: Small contributions to ncpfs
 D: Matrox framebuffer driver
-S: Chudenicka 8
-S: 10200 Prague 10, Hostivar
-S: Czech Republic
+S: 21513 Conradia Ct
+S: Cupertino, CA 95014
+S: USA
 
 N: Thibaut Varene
 E: T-Bone@parisc-linux.org
diff --git a/Documentation/ABI/testing/sysfs-ata b/Documentation/ABI/testing/sysfs-ata
new file mode 100644 (file)
index 0000000..0a93215
--- /dev/null
@@ -0,0 +1,99 @@
+What:          /sys/class/ata_...
+Date:          August 2008
+Contact:       Gwendal Grignou<gwendal@google.com>
+Description:
+
+Provide a place in sysfs for storing the ATA topology of the system.  This allows
+retrieving various information about ATA objects.
+
+Files under /sys/class/ata_port
+-------------------------------
+
+       For each port, a directory ataX is created where X is the ata_port_id of
+       the port. The device parent is the ata host device.
+
+idle_irq (read)
+
+       Number of IRQ received by the port while idle [some ata HBA only].
+
+nr_pmp_links (read)
+
+       If a SATA Port Multiplier (PM) is connected, number of link behind it.
+
+Files under /sys/class/ata_link
+-------------------------------
+
+       Behind each port, there is a ata_link. If there is a SATA PM in the
+       topology, 15 ata_link objects are created.
+
+       If a link is behind a port, the directory name is linkX, where X is
+       ata_port_id of the port.
+       If a link is behind a PM, its name is linkX.Y where X is ata_port_id
+       of the parent port and Y the PM port.
+
+hw_sata_spd_limit
+
+       Maximum speed supported by the connected SATA device.
+
+sata_spd_limit
+
+       Maximum speed imposed by libata.
+
+sata_spd
+
+       Current speed of the link [1.5, 3Gps,...].
+
+Files under /sys/class/ata_device
+---------------------------------
+
+       Behind each link, up to two ata device are created.
+       The name of the directory is devX[.Y].Z where:
+       - X is ata_port_id of the port where the device is connected,
+       - Y the port of the PM if any, and
+       - Z the device id: for PATA, there is usually 2 devices [0,1],
+       only 1 for SATA.
+
+class
+       Device class. Can be "ata" for disk, "atapi" for packet device,
+       "pmp" for PM, or "none" if no device was found behind the link.
+
+dma_mode
+
+       Transfer modes supported by the device when in DMA mode.
+       Mostly used by PATA device.
+
+pio_mode
+
+       Transfer modes supported by the device when in PIO mode.
+       Mostly used by PATA device.
+
+xfer_mode
+
+       Current transfer mode.
+
+id
+
+       Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
+       Only valid if the device is not a PM.
+
+gscr
+
+       Cached result of the dump of PM GSCR register.
+       Valid registers are:
+       0:      SATA_PMP_GSCR_PROD_ID,
+       1:      SATA_PMP_GSCR_REV,
+       2:      SATA_PMP_GSCR_PORT_INFO,
+       32:     SATA_PMP_GSCR_ERROR,
+       33:     SATA_PMP_GSCR_ERROR_EN,
+       64:     SATA_PMP_GSCR_FEAT,
+       96:     SATA_PMP_GSCR_FEAT_EN,
+       130:    SATA_PMP_GSCR_SII_GPIO
+       Only valid if the device is a PM.
+
+spdn_cnt
+
+       Number of time libata decided to lower the speed of link due to errors.
+
+ering
+
+       Formatted output of the error ring of the device.
index 6123c523bfd7961c8cdc235aee2b96367062faf5..7628cd1bc36a5e8080a646da492736c3e43b917d 100644 (file)
@@ -77,3 +77,91 @@ Description:
                devices this attribute is set to "enabled" by bus type code or
                device drivers and in that cases it should be safe to leave the
                default value.
+
+What:          /sys/devices/.../power/wakeup_count
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_count attribute contains the number
+               of signaled wakeup events associated with the device.  This
+               attribute is read-only.  If the device is not enabled to wake up
+               the system from sleep states, this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_active_count
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_active_count attribute contains the
+               number of times the processing of wakeup events associated with
+               the device was completed (at the kernel level).  This attribute
+               is read-only.  If the device is not enabled to wake up the
+               system from sleep states, this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_hit_count
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_hit_count attribute contains the
+               number of times the processing of a wakeup event associated with
+               the device might prevent the system from entering a sleep state.
+               This attribute is read-only.  If the device is not enabled to
+               wake up the system from sleep states, this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_active
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_active attribute contains either 1,
+               or 0, depending on whether or not a wakeup event associated with
+               the device is being processed (1).  This attribute is read-only.
+               If the device is not enabled to wake up the system from sleep
+               states, this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_total_time_ms
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_total_time_ms attribute contains
+               the total time of processing wakeup events associated with the
+               device, in milliseconds.  This attribute is read-only.  If the
+               device is not enabled to wake up the system from sleep states,
+               this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_max_time_ms
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_max_time_ms attribute contains
+               the maximum time of processing a single wakeup event associated
+               with the device, in milliseconds.  This attribute is read-only.
+               If the device is not enabled to wake up the system from sleep
+               states, this attribute is empty.
+
+What:          /sys/devices/.../power/wakeup_last_time_ms
+Date:          September 2010
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../wakeup_last_time_ms attribute contains
+               the value of the monotonic clock corresponding to the time of
+               signaling the last wakeup event associated with the device, in
+               milliseconds.  This attribute is read-only.  If the device is
+               not enabled to wake up the system from sleep states, this
+               attribute is empty.
+
+What:          /sys/devices/.../power/autosuspend_delay_ms
+Date:          September 2010
+Contact:       Alan Stern <stern@rowland.harvard.edu>
+Description:
+               The /sys/devices/.../power/autosuspend_delay_ms attribute
+               contains the autosuspend delay value (in milliseconds).  Some
+               drivers do not want their device to suspend as soon as it
+               becomes idle at run time; they want the device to remain
+               inactive for a certain minimum period of time first.  That
+               period is called the autosuspend delay.  Negative values will
+               prevent the device from being suspended at run time (similar
+               to writing "on" to the power/control attribute).  Values >=
+               1000 will cause the autosuspend timer expiration to be rounded
+               up to the nearest second.
+
+               Not all drivers support this attribute.  If it isn't supported,
+               attempts to read or write it will yield I/O errors.
index 2875f1f74a0792c48402cdc8f33e3e545e0df5ad..194ca446ac287692333040ca76235503af8738a9 100644 (file)
@@ -99,9 +99,38 @@ Description:
 
                dmesg -s 1000000 | grep 'hash matches'
 
+               If you do not get any matches (or they appear to be false
+               positives), it is possible that the last PM event point
+               referred to a device created by a loadable kernel module.  In
+               this case cat /sys/power/pm_trace_dev_match (see below) after
+               your system is started up and the kernel modules are loaded.
+
                CAUTION: Using it will cause your machine's real-time (CMOS)
                clock to be set to a random invalid time after a resume.
 
+What;          /sys/power/pm_trace_dev_match
+Date:          October 2010
+Contact:       James Hogan <james@albanarts.com>
+Description:
+               The /sys/power/pm_trace_dev_match file contains the name of the
+               device associated with the last PM event point saved in the RTC
+               across reboots when pm_trace has been used.  More precisely it
+               contains the list of current devices (including those
+               registered by loadable kernel modules since boot) which match
+               the device hash in the RTC at boot, with a newline after each
+               one.
+
+               The advantage of this file over the hash matches printed to the
+               kernel log (see /sys/power/pm_trace), is that it includes
+               devices created after boot by loadable kernel modules.
+
+               Due to the small hash size necessary to fit in the RTC, it is
+               possible that more than one device matches the hash, in which
+               case further investigation is required to determine which
+               device is causing the problem.  Note that genuine RTC clock
+               values (such as when pm_trace has not been used), can still
+               match a device and output it's name here.
+
 What:          /sys/power/pm_async
 Date:          January 2009
 Contact:       Rafael J. Wysocki <rjw@sisk.pl>
index ecd35e9d4410a2b8c28241331f4f96f5197b6c3a..feca0758391e145a8fb76e5a7059ce7f057e79ab 100644 (file)
@@ -46,7 +46,6 @@
 
      <sect1><title>Atomic and pointer manipulation</title>
 !Iarch/x86/include/asm/atomic.h
-!Iarch/x86/include/asm/unaligned.h
      </sect1>
 
      <sect1><title>Delaying, scheduling, and timer routines</title>
index 910c923a9b86fe5bbd4e38abd6ad2eb593a25e2b..2861055afd7af0dfee9243556baff6559f4d652b 100644 (file)
 #ifdef CONFIG_COMPAT
                .compat_ioctl = i915_compat_ioctl,
 #endif
+               .llseek = noop_llseek,
                },
        .pci_driver = {
                .name = DRIVER_NAME,
index 1448b33fd22272e457e150234a877a54e5082571..fb10fd08c05cd00a49a4276f06842299e092b4a7 100644 (file)
@@ -28,7 +28,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2005-2006</year>
+   <year>2005-2010</year>
    <holder>Thomas Gleixner</holder>
   </copyright>
   <copyright>
          <listitem><para>Edge type</para></listitem>
          <listitem><para>Simple type</para></listitem>
        </itemizedlist>
+       During the implementation we identified another type:
+       <itemizedlist>
+         <listitem><para>Fast EOI type</para></listitem>
+       </itemizedlist>
        In the SMP world of the __do_IRQ() super-handler another type
        was identified:
        <itemizedlist>
        is still available. This leads to a kind of duality for the time
        being. Over time the new model should be used in more and more
        architectures, as it enables smaller and cleaner IRQ subsystems.
+       It's deprecated for three years now and about to be removed.
        </para>
   </chapter>
   <chapter id="bugs">
          <itemizedlist>
          <listitem><para>handle_level_irq</para></listitem>
          <listitem><para>handle_edge_irq</para></listitem>
+         <listitem><para>handle_fasteoi_irq</para></listitem>
          <listitem><para>handle_simple_irq</para></listitem>
          <listitem><para>handle_percpu_irq</para></listitem>
          </itemizedlist>
                are used by the default flow implementations.
                The following helper functions are implemented (simplified excerpt):
                <programlisting>
-default_enable(irq)
+default_enable(struct irq_data *data)
 {
-       desc->chip->unmask(irq);
+       desc->chip->irq_unmask(data);
 }
 
-default_disable(irq)
+default_disable(struct irq_data *data)
 {
-       if (!delay_disable(irq))
-               desc->chip->mask(irq);
+       if (!delay_disable(data))
+               desc->chip->irq_mask(data);
 }
 
-default_ack(irq)
+default_ack(struct irq_data *data)
 {
-       chip->ack(irq);
+       chip->irq_ack(data);
 }
 
-default_mask_ack(irq)
+default_mask_ack(struct irq_data *data)
 {
-       if (chip->mask_ack) {
-               chip->mask_ack(irq);
+       if (chip->irq_mask_ack) {
+               chip->irq_mask_ack(data);
        } else {
-               chip->mask(irq);
-               chip->ack(irq);
+               chip->irq_mask(data);
+               chip->irq_ack(data);
        }
 }
 
-noop(irq)
+noop(struct irq_data *data))
 {
 }
 
@@ -278,12 +284,27 @@ noop(irq)
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-desc->chip->start();
+desc->chip->irq_mask();
 handle_IRQ_event(desc->action);
-desc->chip->end();
+desc->chip->irq_unmask();
                </programlisting>
                </para>
-           </sect3>
+           </sect3>
+           <sect3 id="Default_FASTEOI_IRQ_flow_handler">
+               <title>Default Fast EOI IRQ flow handler</title>
+               <para>
+               handle_fasteoi_irq provides a generic implementation
+               for interrupts, which only need an EOI at the end of
+               the handler
+               </para>
+               <para>
+               The following control flow is implemented (simplified excerpt):
+               <programlisting>
+handle_IRQ_event(desc->action);
+desc->chip->irq_eoi();
+               </programlisting>
+               </para>
+           </sect3>
            <sect3 id="Default_Edge_IRQ_flow_handler">
                <title>Default Edge IRQ flow handler</title>
                <para>
@@ -294,20 +315,19 @@ desc->chip->end();
                The following control flow is implemented (simplified excerpt):
                <programlisting>
 if (desc->status &amp; running) {
-       desc->chip->hold();
+       desc->chip->irq_mask();
        desc->status |= pending | masked;
        return;
 }
-desc->chip->start();
+desc->chip->irq_ack();
 desc->status |= running;
 do {
        if (desc->status &amp; masked)
-               desc->chip->enable();
+               desc->chip->irq_unmask();
        desc->status &amp;= ~pending;
        handle_IRQ_event(desc->action);
 } while (status &amp; pending);
 desc->status &amp;= ~running;
-desc->chip->end();
                </programlisting>
                </para>
            </sect3>
@@ -342,9 +362,9 @@ handle_IRQ_event(desc->action);
                <para>
                The following control flow is implemented (simplified excerpt):
                <programlisting>
-desc->chip->start();
 handle_IRQ_event(desc->action);
-desc->chip->end();
+if (desc->chip->irq_eoi)
+        desc->chip->irq_eoi();
                </programlisting>
                </para>
            </sect3>
@@ -375,8 +395,7 @@ desc->chip->end();
        mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when
        you want to use the delayed interrupt disable feature and your
        hardware is not capable of retriggering an interrupt.)
-       The delayed interrupt disable can be runtime enabled, per interrupt,
-       by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field.
+       The delayed interrupt disable is not configurable.
        </para>
        </sect2>
     </sect1>
@@ -387,13 +406,13 @@ desc->chip->end();
        contains all the direct chip relevant functions, which
        can be utilized by the irq flow implementations.
          <itemizedlist>
-         <listitem><para>ack()</para></listitem>
-         <listitem><para>mask_ack() - Optional, recommended for performance</para></listitem>
-         <listitem><para>mask()</para></listitem>
-         <listitem><para>unmask()</para></listitem>
-         <listitem><para>retrigger() - Optional</para></listitem>
-         <listitem><para>set_type() - Optional</para></listitem>
-         <listitem><para>set_wake() - Optional</para></listitem>
+         <listitem><para>irq_ack()</para></listitem>
+         <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
+         <listitem><para>irq_mask()</para></listitem>
+         <listitem><para>irq_unmask()</para></listitem>
+         <listitem><para>irq_retrigger() - Optional</para></listitem>
+         <listitem><para>irq_set_type() - Optional</para></listitem>
+         <listitem><para>irq_set_wake() - Optional</para></listitem>
          </itemizedlist>
        These primitives are strictly intended to mean what they say: ack means
        ACK, masking means masking of an IRQ line, etc. It is up to the flow
@@ -458,6 +477,7 @@ desc->chip->end();
      <para>
      This chapter contains the autogenerated documentation of the internal functions.
      </para>
+!Ikernel/irq/irqdesc.c
 !Ikernel/irq/handle.c
 !Ikernel/irq/chip.c
   </chapter>
index a20c6f6fffc32aabb214c24ff9f53d477a265f69..6899f471fb152ebe7b405bcf48e4ff0b3f3aef93 100644 (file)
@@ -57,7 +57,6 @@
      </para>
 
      <sect1><title>String Conversions</title>
-!Ilib/vsprintf.c
 !Elib/vsprintf.c
      </sect1>
      <sect1><title>String Manipulation</title>
index 0b1a3f97f285361a4075c8e267d42b2053747d9a..f66f4df186908f5d6ba79171e303949683107a1e 100644 (file)
@@ -1645,7 +1645,9 @@ the amount of locking which needs to be done.
       all the readers who were traversing the list when we deleted the
       element are finished.  We use <function>call_rcu()</function> to
       register a callback which will actually destroy the object once
-      the readers are finished.
+      all pre-existing readers are finished.  Alternatively,
+      <function>synchronize_rcu()</function> may be used to block until
+      all pre-existing are finished.
     </para>
     <para>
       But how does Read Copy Update know when the readers are
@@ -1714,7 +1716,7 @@ the amount of locking which needs to be done.
 -        object_put(obj);
 +        list_del_rcu(&amp;obj-&gt;list);
          cache_num--;
-+        call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu, obj);
++        call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu);
  }
 
  /* Must be holding cache_lock */
@@ -1725,14 +1727,6 @@ the amount of locking which needs to be done.
          if (++cache_num > MAX_CACHE_SIZE) {
                  struct object *i, *outcast = NULL;
                  list_for_each_entry(i, &amp;cache, list) {
-@@ -85,6 +94,7 @@
-         obj-&gt;popularity = 0;
-         atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
-         spin_lock_init(&amp;obj-&gt;lock);
-+        INIT_RCU_HEAD(&amp;obj-&gt;rcu);
-
-         spin_lock_irqsave(&amp;cache_lock, flags);
-         __cache_add(obj);
 @@ -104,12 +114,11 @@
  struct object *cache_find(int id)
  {
@@ -1961,6 +1955,12 @@ machines due to caching.
    </sect1>
   </chapter>
 
+  <chapter id="apiref">
+   <title>Mutex API reference</title>
+!Iinclude/linux/mutex.h
+!Ekernel/mutex.c
+  </chapter>
+
   <chapter id="references">
    <title>Further reading</title>
 
index e8473eae2a2064ecef2afadf2e92551dc327bea3..b57a9ede32249bf51b69988740e455da06b7687c 100644 (file)
    <title>Block IO</title>
 !Iinclude/trace/events/block.h
   </chapter>
+
+  <chapter id="workqueue">
+   <title>Workqueue</title>
+!Iinclude/trace/events/workqueue.h
+  </chapter>
 </book>
index 790d1a8123760211bdcb6427b75c1b4abf2b7210..0c134f8afc6f60b1316b9551577179f1b6dc3961 100644 (file)
@@ -218,13 +218,22 @@ over a rather long period of time, but improvements are always welcome!
        include:
 
        a.      Keeping a count of the number of data-structure elements
-               used by the RCU-protected data structure, including those
-               waiting for a grace period to elapse.  Enforce a limit
-               on this number, stalling updates as needed to allow
-               previously deferred frees to complete.
-
-               Alternatively, limit only the number awaiting deferred
-               free rather than the total number of elements.
+               used by the RCU-protected data structure, including
+               those waiting for a grace period to elapse.  Enforce a
+               limit on this number, stalling updates as needed to allow
+               previously deferred frees to complete.  Alternatively,
+               limit only the number awaiting deferred free rather than
+               the total number of elements.
+
+               One way to stall the updates is to acquire the update-side
+               mutex.  (Don't try this with a spinlock -- other CPUs
+               spinning on the lock could prevent the grace period
+               from ever ending.)  Another way to stall the updates
+               is for the updates to use a wrapper function around
+               the memory allocator, so that this wrapper function
+               simulates OOM when there is too much memory awaiting an
+               RCU grace period.  There are of course many other
+               variations on this theme.
 
        b.      Limiting update rate.  For example, if updates occur only
                once per hour, then no explicit rate limiting is required,
@@ -365,3 +374,26 @@ over a rather long period of time, but improvements are always welcome!
        and the compiler to freely reorder code into and out of RCU
        read-side critical sections.  It is the responsibility of the
        RCU update-side primitives to deal with this.
+
+17.    Use CONFIG_PROVE_RCU, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and
+       the __rcu sparse checks to validate your RCU code.  These
+       can help find problems as follows:
+
+       CONFIG_PROVE_RCU: check that accesses to RCU-protected data
+               structures are carried out under the proper RCU
+               read-side critical section, while holding the right
+               combination of locks, or whatever other conditions
+               are appropriate.
+
+       CONFIG_DEBUG_OBJECTS_RCU_HEAD: check that you don't pass the
+               same object to call_rcu() (or friends) before an RCU
+               grace period has elapsed since the last time that you
+               passed that same object to call_rcu() (or friends).
+
+       __rcu sparse checks: tag the pointer to the RCU-protected data
+               structure with __rcu, and sparse will warn you if you
+               access that pointer without the services of one of the
+               variants of rcu_dereference().
+
+       These debugging aids can help you find problems that are
+       otherwise extremely difficult to spot.
index 44c6dcc93d6dad8e9cee2cadb9f49fa992c5eb00..862c08ef1fde4436ddac8010ba4a1aae40328719 100644 (file)
@@ -80,6 +80,24 @@ o    A CPU looping with bottom halves disabled.  This condition can
 o      For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
        without invoking schedule().
 
+o      A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
+       happen to preempt a low-priority task in the middle of an RCU
+       read-side critical section.   This is especially damaging if
+       that low-priority task is not permitted to run on any other CPU,
+       in which case the next RCU grace period can never complete, which
+       will eventually cause the system to run out of memory and hang.
+       While the system is in the process of running itself out of
+       memory, you might see stall-warning messages.
+
+o      A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
+       is running at a higher priority than the RCU softirq threads.
+       This will prevent RCU callbacks from ever being invoked,
+       and in a CONFIG_TREE_PREEMPT_RCU kernel will further prevent
+       RCU grace periods from ever completing.  Either way, the
+       system will eventually run out of memory and hang.  In the
+       CONFIG_TREE_PREEMPT_RCU case, you might see stall-warning
+       messages.
+
 o      A bug in the RCU implementation.
 
 o      A hardware failure.  This is quite unlikely, but has occurred
index efd8cc95c06b1470db165a74a0d99fd33ee17dea..a851118775d84c7a1d2356ba6a6c8e6208292887 100644 (file)
@@ -125,6 +125,17 @@ o  "b" is the batch limit for this CPU.  If more than this number
        of RCU callbacks is ready to invoke, then the remainder will
        be deferred.
 
+o      "ci" is the number of RCU callbacks that have been invoked for
+       this CPU.  Note that ci+ql is the number of callbacks that have
+       been registered in absence of CPU-hotplug activity.
+
+o      "co" is the number of RCU callbacks that have been orphaned due to
+       this CPU going offline.
+
+o      "ca" is the number of RCU callbacks that have been adopted due to
+       other CPUs going offline.  Note that ci+co-ca+ql is the number of
+       RCU callbacks registered on this CPU.
+
 There is also an rcu/rcudata.csv file with the same information in
 comma-separated-variable spreadsheet format.
 
@@ -180,7 +191,7 @@ o   "s" is the "signaled" state that drives force_quiescent_state()'s
 
 o      "jfq" is the number of jiffies remaining for this grace period
        before force_quiescent_state() is invoked to help push things
-       along.  Note that CPUs in dyntick-idle mode thoughout the grace
+       along.  Note that CPUs in dyntick-idle mode throughout the grace
        period will not report on their own, but rather must be check by
        some other CPU via force_quiescent_state().
 
index 7f5fc3ba9c912daf7824d96621b52121e6cae873..ecf7d04bca2601d79e8239b08a777c207198b451 100644 (file)
@@ -6,6 +6,8 @@ Interrupts
        - ARM Interrupt subsystem documentation
 IXP2000
        - Release Notes for Linux on Intel's IXP2000 Network Processor
+msm
+       - MSM specific documentation
 Netwinder
        - Netwinder specific documentation
 Porting
diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt
new file mode 100644 (file)
index 0000000..67a8162
--- /dev/null
@@ -0,0 +1,176 @@
+This document provides an overview of the msm_gpiomux interface, which
+is used to provide gpio pin multiplexing and configuration on mach-msm
+targets.
+
+History
+=======
+
+The first-generation API for gpio configuration & multiplexing on msm
+is the function gpio_tlmm_config().  This function has a few notable
+shortcomings, which led to its deprecation and replacement by gpiomux:
+
+The 'disable' parameter:  Setting the second parameter to
+gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
+processor in charge of the subsystem to perform a look-up into a
+low-power table and apply the low-power/sleep setting for the pin.
+As the msm family evolved this became problematic. Not all pins
+have sleep settings, not all peripheral processors will accept requests
+to apply said sleep settings, and not all msm targets have their gpio
+subsystems managed by a peripheral processor. In order to get consistent
+behavior on all targets, drivers are forced to ignore this parameter,
+rendering it useless.
+
+The 'direction' flag: for all mux-settings other than raw-gpio (0),
+the output-enable bit of a gpio is hard-wired to a known
+input (usually VDD or ground).  For those settings, the direction flag
+is meaningless at best, and deceptive at worst.  In addition, using the
+direction flag to change output-enable (OE) directly can cause trouble in
+gpiolib, which has no visibility into gpio direction changes made
+in this way.  Direction control in gpio mode should be made through gpiolib.
+
+Key Features of gpiomux
+=======================
+
+- A consistent interface across all generations of msm.  Drivers can expect
+the same results on every target.
+- gpiomux plays nicely with gpiolib.  Functions that should belong to gpiolib
+are left to gpiolib and not duplicated here.  gpiomux is written with the
+intent that gpio_chips will call gpiomux reference-counting methods
+from their request() and free() hooks, providing full integration.
+- Tabular configuration.  Instead of having to call gpio_tlmm_config
+hundreds of times, gpio configuration is placed in a single table.
+- Per-gpio sleep.  Each gpio is individually reference counted, allowing only
+those lines which are in use to be put in high-power states.
+- 0 means 'do nothing': all flags are designed so that the default memset-zero
+equates to a sensible default of 'no configuration', preventing users
+from having to provide hundreds of 'no-op' configs for unused or
+unwanted lines.
+
+Usage
+=====
+
+To use gpiomux, provide configuration information for relevant gpio lines
+in the msm_gpiomux_configs table.  Since a 0 equates to "unconfigured",
+only those lines to be managed by gpiomux need to be specified.  Here
+is a completely fictional example:
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+       [12] = {
+               .active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
+               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+       },
+       [34] = {
+               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+       },
+};
+
+To indicate that a gpio is in use, call msm_gpiomux_get() to increase
+its reference count.  To decrease the reference count, call msm_gpiomux_put().
+
+The effect of this configuration is as follows:
+
+When the system boots, gpios 12 and 34 will be initialized with their
+'suspended' configurations.  All other gpios, which were left unconfigured,
+will not be touched.
+
+When msm_gpiomux_get() is called on gpio 12 to raise its reference count
+above 0, its active configuration will be applied.  Since no other gpio
+line has a valid active configuration, msm_gpiomux_get() will have no
+effect on any other line.
+
+When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
+count to 0, their suspended configurations will be applied.
+Since no other gpio line has a valid suspended configuration, no other
+gpio line will be effected by msm_gpiomux_put().  Since gpio 34 has no valid
+active configuration, this is effectively a no-op for gpio 34 as well,
+with one small caveat, see the section "About Output-Enable Settings".
+
+All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
+they address some important issues.  As unused entries (all those
+except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
+the used fields from the unused.  In addition, the all-zero pattern
+is a valid configuration!  Therefore, gpiomux defines an additional bit
+which is used to indicate when a field is used.  This has the pleasant
+side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
+that a value should not be changed:
+
+  msm_gpiomux_write(0, GPIOMUX_VALID, 0);
+
+replaces the active configuration of gpio 0 with an all-zero configuration,
+but leaves the suspended configuration as it was.
+
+Static Configurations
+=====================
+
+To install a static configuration, which is applied at boot and does
+not change after that, install a configuration with a suspended component
+but no active component, as in the previous example:
+
+       [34] = {
+               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+       },
+
+The suspended setting is applied during boot, and the lack of any valid
+active setting prevents any other setting from being applied at runtime.
+If other subsystems attempting to access the line is a concern, one could
+*really* anchor the configuration down by calling msm_gpiomux_get on the
+line at initialization to move the line into active mode.  With the line
+held, it will never be re-suspended, and with no valid active configuration,
+no new configurations will be applied.
+
+But then, if having other subsystems grabbing for the line is truly a concern,
+it should be reserved with gpio_request instead, which carries an implicit
+msm_gpiomux_get.
+
+gpiomux and gpiolib
+===================
+
+It is expected that msm gpio_chips will call msm_gpiomux_get() and
+msm_gpiomux_put() from their request and free hooks, like this fictional
+example:
+
+static int request(struct gpio_chip *chip, unsigned offset)
+{
+        return msm_gpiomux_get(chip->base + offset);
+}
+
+static void free(struct gpio_chip *chip, unsigned offset)
+{
+        msm_gpiomux_put(chip->base + offset);
+}
+
+       ...somewhere in a gpio_chip declaration...
+       .request = request,
+       .free    = free,
+
+This provides important functionality:
+- It guarantees that a gpio line will have its 'active' config applied
+  when the line is requested, and will not be suspended while the line
+  remains requested; and
+- It guarantees that gpio-direction settings from gpiolib behave sensibly.
+  See "About Output-Enable Settings."
+
+This mechanism allows for "auto-request" of gpiomux lines via gpiolib
+when it is suitable.  Drivers wishing more exact control are, of course,
+free to also use msm_gpiomux_set and msm_gpiomux_get.
+
+About Output-Enable Settings
+============================
+
+Some msm targets do not have the ability to query the current gpio
+configuration setting.  This means that changes made to the output-enable
+(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
+Therefore, when gpiomux applies a configuration setting, any direction
+settings which may have been applied by gpiolib are lost and the default
+input settings are re-applied.
+
+For this reason, drivers should not assume that gpio direction settings
+continue to hold if they free and then re-request a gpio.  This seems like
+common sense - after all, anybody could have obtained the line in the
+meantime - but it needs saying.
+
+This also means that calls to msm_gpiomux_write will reset the OE bit,
+which means that if the gpio line is held by a client of gpiolib and
+msm_gpiomux_write is called, the direction setting has been lost and
+gpiolib's internal state has been broken.
+Release gpio lines before reconfiguring them.
diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt
new file mode 100644 (file)
index 0000000..e578fee
--- /dev/null
@@ -0,0 +1,45 @@
+CFQ ioscheduler tunables
+========================
+
+slice_idle
+----------
+This specifies how long CFQ should idle for next request on certain cfq queues
+(for sequential workloads) and service trees (for random workloads) before
+queue is expired and CFQ selects next queue to dispatch from.
+
+By default slice_idle is a non-zero value. That means by default we idle on
+queues/service trees. This can be very helpful on highly seeky media like
+single spindle SATA/SAS disks where we can cut down on overall number of
+seeks and see improved throughput.
+
+Setting slice_idle to 0 will remove all the idling on queues/service tree
+level and one should see an overall improved throughput on faster storage
+devices like multiple SATA/SAS disks in hardware RAID configuration. The down
+side is that isolation provided from WRITES also goes down and notion of
+IO priority becomes weaker.
+
+So depending on storage and workload, it might be useful to set slice_idle=0.
+In general I think for SATA/SAS disks and software RAID of SATA/SAS disks
+keeping slice_idle enabled should be useful. For any configurations where
+there are multiple spindles behind single LUN (Host based hardware RAID
+controller or for storage arrays), setting slice_idle=0 might end up in better
+throughput and acceptable latencies.
+
+CFQ IOPS Mode for group scheduling
+===================================
+Basic CFQ design is to provide priority based time slices. Higher priority
+process gets bigger time slice and lower priority process gets smaller time
+slice. Measuring time becomes harder if storage is fast and supports NCQ and
+it would be better to dispatch multiple requests from multiple cfq queues in
+request queue at a time. In such scenario, it is not possible to measure time
+consumed by single queue accurately.
+
+What is possible though is to measure number of requests dispatched from a
+single queue and also allow dispatch from multiple cfq queue at the same time.
+This effectively becomes the fairness in terms of IOPS (IO operations per
+second).
+
+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.
index 2f5613fbe680417dd5001993d2f8e6840a8a05fd..d6da611f8f6338c66cf59e9b8df21eeaa4df500d 100644 (file)
@@ -317,6 +317,7 @@ Common files among various policies
 CFQ sysfs tunable
 =================
 /sys/block/<disk>/queue/iosched/group_isolation
+-----------------------------------------------
 
 If group_isolation=1, it provides stronger isolation between groups at the
 expense of throughput. By default group_isolation is 0. In general that
@@ -343,6 +344,33 @@ By default one should run with group_isolation=0. If that is not sufficient
 and one wants stronger isolation between groups, then set group_isolation=1
 but this will come at cost of reduced throughput.
 
+/sys/block/<disk>/queue/iosched/slice_idle
+------------------------------------------
+On a faster hardware CFQ can be slow, especially with sequential workload.
+This happens because CFQ idles on a single queue and single queue might not
+drive deeper request queue depths to keep the storage busy. In such scenarios
+one can try setting slice_idle=0 and that would switch CFQ to IOPS
+(IO operations per second) mode on NCQ supporting hardware.
+
+That means CFQ will not idle between cfq queues of a cfq group and hence be
+able to driver higher queue depth and achieve better throughput. That also
+means that cfq provides fairness among groups in terms of IOPS and not in
+terms of disk time.
+
+/sys/block/<disk>/queue/iosched/group_idle
+------------------------------------------
+If one disables idling on individual cfq queues and cfq service trees by
+setting slice_idle=0, group_idle kicks in. That means CFQ will still idle
+on the group in an attempt to provide fairness among groups.
+
+By default group_idle is same as slice_idle and does not do anything if
+slice_idle is enabled.
+
+One can experience an overall throughput drop if you have created multiple
+groups and put applications in that group which are not driving enough
+IO to keep disk busy. In that case set group_idle=0, and CFQ will not idle
+on individual groups and throughput should improve.
+
 What works
 ==========
 - Currently only sync IO queues are support. All the buffered writes are
index f1c5c4bccd3e8ed6674903eedbc59db3cf76ff9e..902d3151f527919ab190d8f30ff9253e3da2c8d0 100644 (file)
@@ -14,25 +14,39 @@ to /proc/cpuinfo.
        identifier (rather than the kernel's).  The actual value is
        architecture and platform dependent.
 
-3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
+3) /sys/devices/system/cpu/cpuX/topology/book_id:
+
+       the book ID of cpuX. Typically it is the hardware platform's
+       identifier (rather than the kernel's).  The actual value is
+       architecture and platform dependent.
+
+4) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
 
        internel kernel map of cpuX's hardware threads within the same
        core as cpuX
 
-4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
+5) /sys/devices/system/cpu/cpuX/topology/core_siblings:
 
        internal kernel map of cpuX's hardware threads within the same
        physical_package_id.
 
+6) /sys/devices/system/cpu/cpuX/topology/book_siblings:
+
+       internal kernel map of cpuX's hardware threads within the same
+       book_id.
+
 To implement it in an architecture-neutral way, a new source file,
-drivers/base/topology.c, is to export the 4 attributes.
+drivers/base/topology.c, is to export the 4 or 6 attributes. The two book
+related sysfs files will only be created if CONFIG_SCHED_BOOK is selected.
 
 For an architecture to support this feature, it must define some of
 these macros in include/asm-XXX/topology.h:
 #define topology_physical_package_id(cpu)
 #define topology_core_id(cpu)
+#define topology_book_id(cpu)
 #define topology_thread_cpumask(cpu)
 #define topology_core_cpumask(cpu)
+#define topology_book_cpumask(cpu)
 
 The type of **_id is int.
 The type of siblings is (const) struct cpumask *.
@@ -45,6 +59,9 @@ not defined by include/asm-XXX/topology.h:
 3) thread_siblings: just the given CPU
 4) core_siblings: just the given CPU
 
+For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
+default definitions for topology_book_id() and topology_book_cpumask().
+
 Additionally, CPU topology information is provided under
 /sys/devices/system/cpu and includes these files.  The internal
 source for the output is in brackets ("[]").
index 842aa9de84a603298f74f9f4b8c036e0104001cf..5e2bc4ab897a1df72aa03849809747afa68ec142 100644 (file)
@@ -386,34 +386,6 @@ Who:       Tejun Heo <tj@kernel.org>
 
 ----------------------------
 
-What:  Support for VMware's guest paravirtuliazation technique [VMI] will be
-       dropped.
-When:  2.6.37 or earlier.
-Why:   With the recent innovations in CPU hardware acceleration technologies
-       from Intel and AMD, VMware ran a few experiments to compare these
-       techniques to guest paravirtualization technique on VMware's platform.
-       These hardware assisted virtualization techniques have outperformed the
-       performance benefits provided by VMI in most of the workloads. VMware
-       expects that these hardware features will be ubiquitous in a couple of
-       years, as a result, VMware has started a phased retirement of this
-       feature from the hypervisor. We will be removing this feature from the
-       Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
-       technical reasons (read opportunity to remove major chunk of pvops)
-       arise.
-
-       Please note that VMI has always been an optimization and non-VMI kernels
-       still work fine on VMware's platform.
-       Latest versions of VMware's product which support VMI are,
-       Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
-       releases for these products will continue supporting VMI.
-
-       For more details about VMI retirement take a look at this,
-       http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
-
-Who:   Alok N Kataria <akataria@vmware.com>
-
-----------------------------
-
 What:  Support for lcd_switch and display_get in asus-laptop driver
 When:  March 2010
 Why:   These two features use non-standard interfaces. There are the
index 1f7ae144f6d89bc351c8aa34076262bf366f4a4d..5393e6611691617db6c933a945df25baa0bd1090 100644 (file)
@@ -87,3 +87,10 @@ dir_resv_level=      (*)     By default, directory reservations will scale with file
                        reservations - users should rarely need to change this
                        value. If allocation reservations are turned off, this
                        option will have no effect.
+coherency=full  (*)    Disallow concurrent O_DIRECT writes, cluster inode
+                       lock will be taken to force other nodes drop cache,
+                       therefore full cluster coherency is guaranteed even
+                       for O_DIRECT writes.
+coherency=buffered     Allow concurrent O_DIRECT writes without EX lock among
+                       nodes, which gains high performance at risk of getting
+                       stale data on other nodes.
index d96a6dba57489bc6bbf3e747d82cd450084e5609..9633da01ff46afb008566ccb53aa381606654e85 100644 (file)
@@ -109,17 +109,19 @@ use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
 
 If you want to initialize a structure with an invalid GPIO number, use
 some negative number (perhaps "-EINVAL"); that will never be valid.  To
-test if a number could reference a GPIO, you may use this predicate:
+test if such number from such a structure could reference a GPIO, you
+may use this predicate:
 
        int gpio_is_valid(int number);
 
 A number that's not valid will be rejected by calls which may request
 or free GPIOs (see below).  Other numbers may also be rejected; for
-example, a number might be valid but unused on a given board.
-
-Whether a platform supports multiple GPIO controllers is currently a
-platform-specific implementation issue.
+example, a number might be valid but temporarily unused on a given board.
 
+Whether a platform supports multiple GPIO controllers is a platform-specific
+implementation issue, as are whether that support can leave "holes" in the space
+of GPIO numbers, and whether new controllers can be added at runtime.  Such issues
+can affect things including whether adjacent GPIO numbers are both valid.
 
 Using GPIOs
 -----------
@@ -480,12 +482,16 @@ To support this framework, a platform's Kconfig will "select" either
 ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
 and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
 three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
-They may also want to provide a custom value for ARCH_NR_GPIOS.
 
-ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled
+It may also provide a custom value for ARCH_NR_GPIOS, so that it better
+reflects the number of GPIOs in actual use on that platform, without
+wasting static table space.  (It should count both built-in/SoC GPIOs and
+also ones on GPIO expanders.
+
+ARCH_REQUIRE_GPIOLIB means that the gpiolib code will always get compiled
 into the kernel on that architecture.
 
-ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user
+ARCH_WANT_OPTIONAL_GPIOLIB means the gpiolib code defaults to off and the user
 can enable it and build it into the kernel optionally.
 
 If neither of these options are selected, the platform does not support
index ff45d1f837c89ab6706726ae525083e22d05af16..48ceabedf55df87dddff2d62864f6f93db9d315b 100644 (file)
@@ -91,12 +91,11 @@ name                The chip name.
                I2C devices get this attribute created automatically.
                RO
 
-update_rate    The rate at which the chip will update readings.
+update_interval        The interval at which the chip will update readings.
                Unit: millisecond
                RW
-               Some devices have a variable update rate. This attribute
-               can be used to change the update rate to the desired
-               frequency.
+               Some devices have a variable update rate or interval.
+               This attribute can be used to change it to the desired value.
 
 
 ************
index 27a52b35d55bf1b6009551c97f400da5c14f59bc..3d8a97747f7731c801ca7d3a1483858feeb76b6c 100644 (file)
@@ -345,5 +345,10 @@ documentation, in <filename>, for the functions listed.
 section titled <section title> from <filename>.
 Spaces are allowed in <section title>; do not quote the <section title>.
 
+!C<filename> is replaced by nothing, but makes the tools check that
+all DOC: sections and documented functions, symbols, etc. are used.
+This makes sense to use when you use !F/!P only and want to verify
+that all documentation is included.
+
 Tim.
 */ <twaugh@redhat.com>
index 2c85c0692b015cc099710b0ba4b9a4f0c30a745d..02f21d9220ce8e5749ce7eb811039d4d396aaf80 100644 (file)
@@ -455,7 +455,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        [ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
                                pxa_timer,timer3,32k_counter,timer0_1
                        [AVR32] avr32
-                       [X86-32] pit,hpet,tsc,vmi-timer;
+                       [X86-32] pit,hpet,tsc;
                                scx200_hrt on Geode; cyclone on IBM x440
                        [MIPS] MIPS
                        [PARISC] cr16
@@ -1974,15 +1974,18 @@ and is between 256 and 4096 characters. It is defined in the file
                force   Enable ASPM even on devices that claim not to support it.
                        WARNING: Forcing ASPM on may cause system lockups.
 
+       pcie_ports=     [PCIE] PCIe ports handling:
+               auto    Ask the BIOS whether or not to use native PCIe services
+                       associated with PCIe ports (PME, hot-plug, AER).  Use
+                       them only if that is allowed by the BIOS.
+               native  Use native PCIe services associated with PCIe ports
+                       unconditionally.
+               compat  Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
+                       ports driver.
+
        pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
-                       Format: {auto|force}[,nomsi]
-               auto    Use native PCIe PME signaling if the BIOS allows the
-                       kernel to control PCIe config registers of root ports.
-               force   Use native PCIe PME signaling even if the BIOS refuses
-                       to allow the kernel to control the relevant PCIe config
-                       registers.
                nomsi   Do not use MSI for native PCIe PME signaling (this makes
-                       all PCIe root ports use INTx for everything).
+                       all PCIe root ports use INTx for all services).
 
        pcmv=           [HW,PCMCIA] BadgePAD 4
 
@@ -2150,6 +2153,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        Reserves a hole at the top of the kernel virtual
                        address space.
 
+       reservelow=     [X86]
+                       Format: nn[K]
+                       Set the amount of memory to reserve for BIOS at
+                       the bottom of the address space.
+
        reset_devices   [KNL] Force drivers to reset the underlying device
                        during initialization.
 
@@ -2162,6 +2170,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        in <PAGE_SIZE> units (needed only for swap files).
                        See  Documentation/power/swsusp-and-swap-files.txt
 
+       hibernate=      [HIBERNATION]
+               noresume        Don't check if there's a hibernation image
+                               present during boot.
+               nocompress      Don't compress/decompress hibernation images.
+
        retain_initrd   [RAM] Keep initrd memory after extraction
 
        rhash_entries=  [KNL,NET]
@@ -2432,6 +2445,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        disables clocksource verification at runtime.
                        Used to enable high-resolution timer mode on older
                        hardware, and in virtualized environment.
+                       [x86] noirqtime: Do not use TSC to do irq accounting.
+                       Used to run time disable IRQ_TIME_ACCOUNTING on any
+                       platforms where RDTSC is slow and this accounting
+                       can add overhead.
 
        turbografx.map[2|3]=    [HW,JOY]
                        TurboGraFX parallel port interface
@@ -2629,8 +2646,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        aux-ide-disks -- unplug non-primary-master IDE devices
                        nics -- unplug network devices
                        all -- unplug all emulated devices (NICs and IDE disks)
-                       ignore -- continue loading the Xen platform PCI driver even
-                               if the version check failed
+                       unnecessary -- unplugging emulated devices is
+                               unnecessary even if the host did not respond to
+                               the unplug protocol
+                       never -- do not unplug even if version check succeeds
 
        xirc2ps_cs=     [NET,PCMCIA]
                        Format:
index 1762b81fcdf2ec4a235423687865453a16196aed..741fe66d6eca4852894cac79d6ad2d3162486c7a 100644 (file)
@@ -542,9 +542,11 @@ Kprobes does not use mutexes or allocate memory except during
 registration and unregistration.
 
 Probe handlers are run with preemption disabled.  Depending on the
-architecture, handlers may also run with interrupts disabled.  In any
-case, your handler should not yield the CPU (e.g., by attempting to
-acquire a semaphore).
+architecture and optimization state, handlers may also run with
+interrupts disabled (e.g., kretprobe handlers and optimized kprobe
+handlers run without interrupt disabled on x86/x86-64).  In any case,
+your handler should not yield the CPU (e.g., by attempting to acquire
+a semaphore).
 
 Since a return probe is implemented by replacing the return
 address with the trampoline's address, stack backtraces and calls
index 28c8cdfcafd8693898ae4c4a4d9bc5f4f9f77d62..bebac6b4f332cc117287f58c0cf5df11bf5531f8 100644 (file)
@@ -1,5 +1,6 @@
 # This creates the demonstration utility "lguest" which runs a Linux guest.
-CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include -U_FORTIFY_SOURCE
+# Missing headers?  Add "-I../../include -I../../arch/x86/include"
+CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE
 
 all: lguest
 
index e9ce3c5545145f9b2c683c26690c0159b6c437fc..8a6a8c6d498043dc00184906d71a55e680844ef2 100644 (file)
 #include <limits.h>
 #include <stddef.h>
 #include <signal.h>
-#include "linux/lguest_launcher.h"
-#include "linux/virtio_config.h"
-#include "linux/virtio_net.h"
-#include "linux/virtio_blk.h"
-#include "linux/virtio_console.h"
-#include "linux/virtio_rng.h"
-#include "linux/virtio_ring.h"
-#include "asm/bootparam.h"
+#include <linux/virtio_config.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_blk.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_rng.h>
+#include <linux/virtio_ring.h>
+#include <asm/bootparam.h>
+#include "../../include/linux/lguest_launcher.h"
 /*L:110
  * We can ignore the 42 include files we need for this program, but I do want
  * to draw attention to the use of kernel-style types.
@@ -1447,14 +1447,15 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
 static void configure_device(int fd, const char *tapif, u32 ipaddr)
 {
        struct ifreq ifr;
-       struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
+       struct sockaddr_in sin;
 
        memset(&ifr, 0, sizeof(ifr));
        strcpy(ifr.ifr_name, tapif);
 
        /* Don't read these incantations.  Just cut & paste them like I did! */
-       sin->sin_family = AF_INET;
-       sin->sin_addr.s_addr = htonl(ipaddr);
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = htonl(ipaddr);
+       memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
        if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
                err(1, "Setting %s interface address", tapif);
        ifr.ifr_flags = IFF_UP;
index c91ccc0720fa97f42a1a616fd83e23628ae85ab1..38c10fd7f4110448facd7089b985c4776d264d85 100644 (file)
@@ -9,7 +9,7 @@ firstly, there's nothing wrong with semaphores. But if the simpler
 mutex semantics are sufficient for your code, then there are a couple
 of advantages of mutexes:
 
- - 'struct mutex' is smaller on most architectures: .e.g on x86,
+ - 'struct mutex' is smaller on most architectures: E.g. on x86,
    'struct semaphore' is 20 bytes, 'struct mutex' is 16 bytes.
    A smaller structure size means less RAM footprint, and better
    CPU-cache utilization.
@@ -136,3 +136,4 @@ the APIs of 'struct mutex' have been streamlined:
  void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
  int  mutex_lock_interruptible_nested(struct mutex *lock,
                                       unsigned int subclass);
+ int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
index 2df71861e578b6ebcb2b94371d4a32fbdf7fca61..d9271e74e488a54177c548a5ad859d51ffdaff28 100644 (file)
@@ -1,82 +1,35 @@
 Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
 ===============================================================
 
-September 26, 2006
-
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
 
 Contents
 ========
 
-- In This Release
 - Identifying Your Adapter
-- Building and Installation
 - Command Line Parameters
 - Speed and Duplex Configuration
 - Additional Configurations
-- Known Issues
 - Support
 
-
-In This Release
-===============
-
-This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters.  This driver includes support for Itanium(R)2-based systems.
-
-For questions related to hardware requirements, refer to the documentation
-supplied with your Intel PRO/1000 adapter. All hardware requirements listed
-apply to use with Linux.
-
-The following features are now available in supported kernels:
- - Native VLANs
- - Channel Bonding (teaming)
- - SNMP
-
-Channel Bonding documentation can be found in the Linux kernel source:
-/Documentation/networking/bonding.txt
-
-The driver information previously displayed in the /proc filesystem is not
-supported in this release.  Alternatively, you can use ethtool (version 1.6
-or later), lspci, and ifconfig to obtain the same information.
-
-Instructions on updating ethtool can be found in the section "Additional
-Configurations" later in this document.
-
-NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100
-support.
-
-
 Identifying Your Adapter
 ========================
 
 For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
-    http://support.intel.com/support/network/adapter/pro100/21397.htm
+    http://support.intel.com/support/go/network/adapter/idguide.htm
 
 For the latest Intel network drivers for Linux, refer to the following
 website.  In the search field, enter your adapter name or type, or use the
 networking link on the left to search for your adapter:
 
-    http://downloadfinder.intel.com/scripts-df/support_intel.asp
-
+    http://support.intel.com/support/go/network/adapter/home.htm
 
 Command Line Parameters
 =======================
 
-If the driver is built as a module, the  following optional parameters
-are used by entering them on the command line with the modprobe command
-using this syntax:
-
-     modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
-
-For example, with two PRO/1000 PCI adapters, entering:
-
-     modprobe e1000 TxDescriptors=80,128
-
-loads the e1000 driver with 80 TX descriptors for the first adapter and
-128 TX descriptors for the second adapter.
-
 The default value for each parameter is generally the recommended setting,
 unless otherwise noted.
 
@@ -89,10 +42,6 @@ NOTES:  For more information about the AutoNeg, Duplex, and Speed
         parameters, see the application note at:
         http://www.intel.com/design/network/applnots/ap450.htm
 
-        A descriptor describes a data buffer and attributes related to
-        the data buffer.  This information is accessed by the hardware.
-
-
 AutoNeg
 -------
 (Supported only on adapters with copper connections)
@@ -106,7 +55,6 @@ Duplex parameters must not be specified.
 NOTE:  Refer to the Speed and Duplex section of this readme for more
        information on the AutoNeg parameter.
 
-
 Duplex
 ------
 (Supported only on adapters with copper connections)
@@ -119,7 +67,6 @@ set to auto-negotiate, the board auto-detects the correct duplex.  If the
 link partner is forced (either full or half), Duplex defaults to half-
 duplex.
 
-
 FlowControl
 -----------
 Valid Range:   0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
@@ -128,16 +75,16 @@ Default Value: Reads flow control settings from the EEPROM
 This parameter controls the automatic generation(Tx) and response(Rx)
 to Ethernet PAUSE frames.
 
-
 InterruptThrottleRate
 ---------------------
 (not supported on Intel(R) 82542, 82543 or 82544-based adapters)
-Valid Range:   0,1,3,100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+Valid Range:   0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+                                   4=simplified balancing)
 Default Value: 3
 
 The driver can limit the amount of interrupts per second that the adapter
-will generate for incoming packets. It does this by writing a value to the 
-adapter that is based on the maximum amount of interrupts that the adapter 
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
 will generate per second.
 
 Setting InterruptThrottleRate to a value greater or equal to 100
@@ -146,37 +93,43 @@ per second, even if more packets have come in. This reduces interrupt
 load on the system and can lower CPU utilization under heavy load,
 but will increase latency as packets are not processed as quickly.
 
-The default behaviour of the driver previously assumed a static 
-InterruptThrottleRate value of 8000, providing a good fallback value for 
-all traffic types,but lacking in small packet performance and latency. 
-The hardware can handle many more small packets per second however, and 
+The default behaviour of the driver previously assumed a static
+InterruptThrottleRate value of 8000, providing a good fallback value for
+all traffic types,but lacking in small packet performance and latency.
+The hardware can handle many more small packets per second however, and
 for this reason an adaptive interrupt moderation algorithm was implemented.
 
 Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which
-it dynamically adjusts the InterruptThrottleRate value based on the traffic 
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
 that it receives. After determining the type of incoming traffic in the last
-timeframe, it will adjust the InterruptThrottleRate to an appropriate value 
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
 for that traffic.
 
 The algorithm classifies the incoming traffic every interval into
-classes.  Once the class is determined, the InterruptThrottleRate value is 
-adjusted to suit that traffic type the best. There are three classes defined: 
+classes.  Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
 "Bulk traffic", for large amounts of packets of normal size; "Low latency",
 for small amounts of traffic and/or a significant percentage of small
-packets; and "Lowest latency", for almost completely small packets or 
+packets; and "Lowest latency", for almost completely small packets or
 minimal traffic.
 
-In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 
-for traffic that falls in class "Bulk traffic". If traffic falls in the "Low 
-latency" or "Lowest latency" class, the InterruptThrottleRate is increased 
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
 stepwise to 20000. This default mode is suitable for most applications.
 
 For situations where low latency is vital such as cluster or
 grid computing, the algorithm can reduce latency even more when
 InterruptThrottleRate is set to mode 1. In this mode, which operates
-the same as mode 3, the InterruptThrottleRate will be increased stepwise to 
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
 70000 for traffic in class "Lowest latency".
 
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic.  If the bytes per second rate is approximately equal, the
+interrupt rate will drop as low as 2000 interrupts per second.  If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
 Setting InterruptThrottleRate to 0 turns off any interrupt moderation
 and may improve small packet latency, but is generally not suitable
 for bulk throughput traffic.
@@ -212,8 +165,6 @@ NOTE:  When e1000 is loaded with default settings and multiple adapters
        be platform-specific.  If CPU utilization is not a concern, use
        RX_POLLING (NAPI) and default driver settings.
 
-
-
 RxDescriptors
 -------------
 Valid Range:   80-256 for 82542 and 82543-based adapters
@@ -225,15 +176,14 @@ by the driver.  Increasing this value allows the driver to buffer more
 incoming packets, at the expense of increased system memory utilization.
 
 Each descriptor is 16 bytes.  A receive buffer is also allocated for each
-descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending 
+descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
 on the MTU setting. The maximum MTU size is 16110.
 
-NOTE:  MTU designates the frame size.  It only needs to be set for Jumbo 
-       Frames.  Depending on the available system resources, the request 
-       for a higher number of receive descriptors may be denied.  In this 
+NOTE:  MTU designates the frame size.  It only needs to be set for Jumbo
+       Frames.  Depending on the available system resources, the request
+       for a higher number of receive descriptors may be denied.  In this
        case, use a lower number.
 
-
 RxIntDelay
 ----------
 Valid Range:   0-65535 (0=off)
@@ -254,7 +204,6 @@ CAUTION:  When setting RxIntDelay to a value other than 0, adapters may
           restoring the network connection.  To eliminate the potential
           for the hang ensure that RxIntDelay is set to 0.
 
-
 RxAbsIntDelay
 -------------
 (This parameter is supported only on 82540, 82545 and later adapters.)
@@ -268,7 +217,6 @@ packet is received within the set amount of time.  Proper tuning,
 along with RxIntDelay, may improve traffic throughput in specific network
 conditions.
 
-
 Speed
 -----
 (This parameter is supported only on adapters with copper connections.)
@@ -280,7 +228,6 @@ Speed forces the line speed to the specified value in megabits per second
 partner is set to auto-negotiate, the board will auto-detect the correct
 speed.  Duplex should also be set when Speed is set to either 10 or 100.
 
-
 TxDescriptors
 -------------
 Valid Range:   80-256 for 82542 and 82543-based adapters
@@ -295,6 +242,36 @@ NOTE:  Depending on the available system resources, the request for a
        higher number of transmit descriptors may be denied.  In this case,
        use a lower number.
 
+TxDescriptorStep
+----------------
+Valid Range:    1 (use every Tx Descriptor)
+               4 (use every 4th Tx Descriptor)
+
+Default Value:  1 (use every Tx Descriptor)
+
+On certain non-Intel architectures, it has been observed that intense TX
+traffic bursts of short packets may result in an improper descriptor
+writeback. If this occurs, the driver will report a "TX Timeout" and reset
+the adapter, after which the transmit flow will restart, though data may
+have stalled for as much as 10 seconds before it resumes.
+
+The improper writeback does not occur on the first descriptor in a system
+memory cache-line, which is typically 32 bytes, or 4 descriptors long.
+
+Setting TxDescriptorStep to a value of 4 will ensure that all TX descriptors
+are aligned to the start of a system memory cache line, and so this problem
+will not occur.
+
+NOTES: Setting TxDescriptorStep to 4 effectively reduces the number of
+       TxDescriptors available for transmits to 1/4 of the normal allocation.
+       This has a possible negative performance impact, which may be
+       compensated for by allocating more descriptors using the TxDescriptors
+       module parameter.
+
+       There are other conditions which may result in "TX Timeout", which will
+       not be resolved by the use of the TxDescriptorStep parameter. As the
+       issue addressed by this parameter has never been observed on Intel
+       Architecture platforms, it should not be used on Intel platforms.
 
 TxIntDelay
 ----------
@@ -307,7 +284,6 @@ efficiency if properly tuned for specific network traffic.  If the
 system is reporting dropped transmits, this value may be set too high
 causing the driver to run out of available transmit descriptors.
 
-
 TxAbsIntDelay
 -------------
 (This parameter is supported only on 82540, 82545 and later adapters.)
@@ -330,6 +306,35 @@ Default Value: 1
 A value of '1' indicates that the driver should enable IP checksum
 offload for received packets (both UDP and TCP) to the adapter hardware.
 
+Copybreak
+---------
+Valid Range:   0-xxxxxxx (0=off)
+Default Value: 256
+Usage: insmod e1000.ko copybreak=128
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value:  0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can turn off
+this parameter in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
 
 Speed and Duplex Configuration
 ==============================
@@ -385,40 +390,9 @@ If the link partner is forced to a specific speed and duplex, then this
 parameter should not be used.  Instead, use the Speed and Duplex parameters
 previously mentioned to force the adapter to the same speed and duplex.
 
-
 Additional Configurations
 =========================
 
-  Configuring the Driver on Different Distributions
-  -------------------------------------------------
-  Configuring a network driver to load properly when the system is started
-  is distribution dependent.  Typically, the configuration process involves
-  adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well
-  as editing other system startup scripts and/or configuration files.  Many
-  popular Linux distributions ship with tools to make these changes for you.
-  To learn the proper way to configure a network device for your system,
-  refer to your distribution documentation.  If during this process you are
-  asked for the driver or module name, the name for the Linux Base Driver
-  for the Intel(R) PRO/1000 Family of Adapters is e1000.
-
-  As an example, if you install the e1000 driver for two PRO/1000 adapters
-  (eth0 and eth1) and set the speed and duplex to 10full and 100half, add
-  the following to modules.conf or or modprobe.conf:
-
-       alias eth0 e1000
-       alias eth1 e1000
-       options e1000 Speed=10,100 Duplex=2,1
-
-  Viewing Link Messages
-  ---------------------
-  Link messages will not be displayed to the console if the distribution is
-  restricting system messages.  In order to see network driver link messages
-  on your console, set dmesg to eight by entering the following:
-
-       dmesg -n 8
-
-  NOTE: This setting is not saved across reboots.
-
   Jumbo Frames
   ------------
   Jumbo Frames support is enabled by changing the MTU to a value larger than
@@ -437,9 +411,11 @@ Additional Configurations
    setting in a different location.
 
   Notes:
-
-  - To enable Jumbo Frames, increase the MTU size on the interface beyond
-    1500.
+  Degradation in throughput performance may be observed in some Jumbo frames
+  environments. If this is observed, increasing the application's socket buffer
+  size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values may help.
+  See the specific application manual and /usr/src/linux*/Documentation/
+  networking/ip-sysctl.txt for more details.
 
   - The maximum MTU setting for Jumbo Frames is 16110.  This value coincides
     with the maximum Jumbo Frames size of 16128.
@@ -447,40 +423,11 @@ Additional Configurations
   - Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
     loss of link.
 
-  - Some Intel gigabit adapters that support Jumbo Frames have a frame size
-    limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
-    The adapters with this limitation are based on the Intel(R) 82571EB,
-    82572EI, 82573L and 80003ES2LAN controller.  These correspond to the
-    following product names:
-     Intel(R) PRO/1000 PT Server Adapter
-     Intel(R) PRO/1000 PT Desktop Adapter
-     Intel(R) PRO/1000 PT Network Connection
-     Intel(R) PRO/1000 PT Dual Port Server Adapter
-     Intel(R) PRO/1000 PT Dual Port Network Connection
-     Intel(R) PRO/1000 PF Server Adapter
-     Intel(R) PRO/1000 PF Network Connection
-     Intel(R) PRO/1000 PF Dual Port Server Adapter
-     Intel(R) PRO/1000 PB Server Connection
-     Intel(R) PRO/1000 PL Network Connection
-     Intel(R) PRO/1000 EB Network Connection with I/O Acceleration
-     Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration
-     Intel(R) PRO/1000 PT Quad Port Server Adapter
-
   - Adapters based on the Intel(R) 82542 and 82573V/E controller do not
     support Jumbo Frames. These correspond to the following product names:
      Intel(R) PRO/1000 Gigabit Server Adapter
      Intel(R) PRO/1000 PM Network Connection
 
-  - The following adapters do not support Jumbo Frames:
-     Intel(R) 82562V 10/100 Network Connection
-     Intel(R) 82566DM Gigabit Network Connection
-     Intel(R) 82566DC Gigabit Network Connection
-     Intel(R) 82566MM Gigabit Network Connection
-     Intel(R) 82566MC Gigabit Network Connection
-     Intel(R) 82562GT 10/100 Network Connection
-     Intel(R) 82562G 10/100 Network Connection
-
-
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
@@ -490,142 +437,14 @@ Additional Configurations
   The latest release of ethtool can be found from
   http://sourceforge.net/projects/gkernel.
 
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options.  Support
-  for a more complete ethtool feature set can be enabled by upgrading
-  ethtool to ethtool-1.8.1.
-
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is configured through the Ethtool* utility.  Ethtool is included with
-  all versions of Red Hat after Red Hat 7.2.  For other Linux distributions,
-  download and install Ethtool from the following website:
-  http://sourceforge.net/projects/gkernel.
-
-  For instructions on enabling WoL with Ethtool, refer to the website listed
-  above.
+  WoL is configured through the Ethtool* utility.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the e1000 driver must be
   loaded when shutting down or rebooting the system.
 
-  Wake On LAN is only supported on port A for the following devices:
-  Intel(R) PRO/1000 PT Dual Port Network Connection
-  Intel(R) PRO/1000 PT Dual Port Server Connection
-  Intel(R) PRO/1000 PT Dual Port Server Adapter
-  Intel(R) PRO/1000 PF Dual Port Server Adapter
-  Intel(R) PRO/1000 PT Quad Port Server Adapter
-
-  NAPI
-  ----
-  NAPI (Rx polling mode) is enabled in the e1000 driver.
-
-  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
-
-
-Known Issues
-============
-
-Dropped Receive Packets on Half-duplex 10/100 Networks
-------------------------------------------------------
-If you have an Intel PCI Express adapter running at 10mbps or 100mbps, half-
-duplex, you may observe occasional dropped receive packets.  There are no
-workarounds for this problem in this network configuration.  The network must
-be updated to operate in full-duplex, and/or 1000mbps only.
-
-Jumbo Frames System Requirement
--------------------------------
-Memory allocation failures have been observed on Linux systems with 64 MB
-of RAM or less that are running Jumbo Frames.  If you are using Jumbo
-Frames, your system may require more than the advertised minimum
-requirement of 64 MB of system memory.
-
-Performance Degradation with Jumbo Frames
------------------------------------------
-Degradation in throughput performance may be observed in some Jumbo frames
-environments.  If this is observed, increasing the application's socket
-buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
-may help.  See the specific application manual and
-/usr/src/linux*/Documentation/
-networking/ip-sysctl.txt for more details.
-
-Jumbo Frames on Foundry BigIron 8000 switch
--------------------------------------------
-There is a known issue using Jumbo frames when connected to a Foundry
-BigIron 8000 switch.  This is a 3rd party limitation.  If you experience
-loss of packets, lower the MTU size.
-
-Allocating Rx Buffers when Using Jumbo Frames 
----------------------------------------------
-Allocating Rx buffers when using Jumbo Frames on 2.6.x kernels may fail if 
-the available memory is heavily fragmented. This issue may be seen with PCI-X 
-adapters or with packet split disabled. This can be reduced or eliminated 
-by changing the amount of available memory for receive buffer allocation, by
-increasing /proc/sys/vm/min_free_kbytes. 
-
-Multiple Interfaces on Same Ethernet Broadcast Network
-------------------------------------------------------
-Due to the default ARP behavior on Linux, it is not possible to have
-one system on two IP networks in the same Ethernet broadcast domain
-(non-partitioned switch) behave as expected.  All Ethernet interfaces
-will respond to IP traffic for any IP address assigned to the system.
-This results in unbalanced receive traffic.
-
-If you have multiple interfaces in a server, either turn on ARP
-filtering by entering:
-
-    echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
-(this only works if your kernel's version is higher than 2.4.5),
-
-NOTE: This setting is not saved across reboots.  The configuration
-change can be made permanent by adding the line:
-    net.ipv4.conf.all.arp_filter = 1
-to the file /etc/sysctl.conf
-
-      or,
-
-install the interfaces in separate broadcast domains (either in
-different switches or in a switch partitioned to VLANs).
-
-82541/82547 can't link or are slow to link with some link partners
------------------------------------------------------------------
-There is a known compatibility issue with 82541/82547 and some
-low-end switches where the link will not be established, or will
-be slow to establish.  In particular, these switches are known to
-be incompatible with 82541/82547:
-
-    Planex FXG-08TE
-    I-O Data ETG-SH8
-
-To workaround this issue, the driver can be compiled with an override
-of the PHY's master/slave setting.  Forcing master or forcing slave
-mode will improve time-to-link.
-
-    # make CFLAGS_EXTRA=-DE1000_MASTER_SLAVE=<n>
-
-Where <n> is:
-
-    0 = Hardware default
-    1 = Master mode
-    2 = Slave mode
-    3 = Auto master/slave
-
-Disable rx flow control with ethtool
-------------------------------------
-In order to disable receive flow control using ethtool, you must turn
-off auto-negotiation on the same command line.
-
-For example:
-
-   ethtool -A eth? autoneg off rx off
-
-Unplugging network cable while ethtool -p is running
-----------------------------------------------------
-In kernel versions 2.5.50 and later (including 2.6 kernel), unplugging
-the network cable while ethtool -p is running will cause the system to
-become unresponsive to keyboard commands, except for control-alt-delete.
-Restarting the system appears to be the only remedy.
-
-
 Support
 =======
 
diff --git a/Documentation/networking/e1000e.txt b/Documentation/networking/e1000e.txt
new file mode 100644 (file)
index 0000000..6aa048b
--- /dev/null
@@ -0,0 +1,302 @@
+Linux* Driver for Intel(R) Network Connection
+===============================================================
+
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
+
+Contents
+========
+
+- Identifying Your Adapter
+- Command Line Parameters
+- Additional Configurations
+- Support
+
+Identifying Your Adapter
+========================
+
+The e1000e driver supports all PCI Express Intel(R) Gigabit Network
+Connections, except those that are 82575, 82576 and 82580-based*.
+
+* NOTE: The Intel(R) PRO/1000 P Dual Port Server Adapter is supported by
+  the e1000 driver, not the e1000e driver due to the 82546 part being used
+  behind a PCI Express bridge.
+
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
+
+    http://support.intel.com/support/go/network/adapter/idguide.htm
+
+For the latest Intel network drivers for Linux, refer to the following
+website.  In the search field, enter your adapter name or type, or use the
+networking link on the left to search for your adapter:
+
+    http://support.intel.com/support/go/network/adapter/home.htm
+
+Command Line Parameters
+=======================
+
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
+NOTES:  For more information about the InterruptThrottleRate,
+        RxIntDelay, TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay
+        parameters, see the application note at:
+        http://www.intel.com/design/network/applnots/ap450.htm
+
+InterruptThrottleRate
+---------------------
+Valid Range:   0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+                                   4=simplified balancing)
+Default Value: 3
+
+The driver can limit the amount of interrupts per second that the adapter
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
+will generate per second.
+
+Setting InterruptThrottleRate to a value greater or equal to 100
+will program the adapter to send out a maximum of that many interrupts
+per second, even if more packets have come in. This reduces interrupt
+load on the system and can lower CPU utilization under heavy load,
+but will increase latency as packets are not processed as quickly.
+
+The driver has two adaptive modes (setting 1 or 3) in which
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
+that it receives. After determining the type of incoming traffic in the last
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
+for that traffic.
+
+The algorithm classifies the incoming traffic every interval into
+classes.  Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
+"Bulk traffic", for large amounts of packets of normal size; "Low latency",
+for small amounts of traffic and/or a significant percentage of small
+packets; and "Lowest latency", for almost completely small packets or
+minimal traffic.
+
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
+stepwise to 20000. This default mode is suitable for most applications.
+
+For situations where low latency is vital such as cluster or
+grid computing, the algorithm can reduce latency even more when
+InterruptThrottleRate is set to mode 1. In this mode, which operates
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
+70000 for traffic in class "Lowest latency".
+
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic.  If the bytes per second rate is approximately equal the
+interrupt rate will drop as low as 2000 interrupts per second.  If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
+Setting InterruptThrottleRate to 0 turns off any interrupt moderation
+and may improve small packet latency, but is generally not suitable
+for bulk throughput traffic.
+
+NOTE:  InterruptThrottleRate takes precedence over the TxAbsIntDelay and
+       RxAbsIntDelay parameters.  In other words, minimizing the receive
+       and/or transmit absolute delays does not force the controller to
+       generate more interrupts than what the Interrupt Throttle Rate
+       allows.
+
+NOTE:  When e1000e is loaded with default settings and multiple adapters
+       are in use simultaneously, the CPU utilization may increase non-
+       linearly.  In order to limit the CPU utilization without impacting
+       the overall throughput, we recommend that you load the driver as
+       follows:
+
+           modprobe e1000e InterruptThrottleRate=3000,3000,3000
+
+       This sets the InterruptThrottleRate to 3000 interrupts/sec for
+       the first, second, and third instances of the driver.  The range
+       of 2000 to 3000 interrupts per second works on a majority of
+       systems and is a good starting point, but the optimal value will
+       be platform-specific.  If CPU utilization is not a concern, use
+       RX_POLLING (NAPI) and default driver settings.
+
+RxIntDelay
+----------
+Valid Range:   0-65535 (0=off)
+Default Value: 0
+
+This value delays the generation of receive interrupts in units of 1.024
+microseconds.  Receive interrupt reduction can improve CPU efficiency if
+properly tuned for specific network traffic.  Increasing this value adds
+extra latency to frame reception and can end up decreasing the throughput
+of TCP traffic.  If the system is reporting dropped receives, this value
+may be set too high, causing the driver to run out of available receive
+descriptors.
+
+CAUTION:  When setting RxIntDelay to a value other than 0, adapters may
+          hang (stop transmitting) under certain network conditions.  If
+          this occurs a NETDEV WATCHDOG message is logged in the system
+          event log.  In addition, the controller is automatically reset,
+          restoring the network connection.  To eliminate the potential
+          for the hang ensure that RxIntDelay is set to 0.
+
+RxAbsIntDelay
+-------------
+Valid Range:   0-65535 (0=off)
+Default Value: 8
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+receive interrupt is generated.  Useful only if RxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is received within the set amount of time.  Proper tuning,
+along with RxIntDelay, may improve traffic throughput in specific network
+conditions.
+
+TxIntDelay
+----------
+Valid Range:   0-65535 (0=off)
+Default Value: 8
+
+This value delays the generation of transmit interrupts in units of
+1.024 microseconds.  Transmit interrupt reduction can improve CPU
+efficiency if properly tuned for specific network traffic.  If the
+system is reporting dropped transmits, this value may be set too high
+causing the driver to run out of available transmit descriptors.
+
+TxAbsIntDelay
+-------------
+Valid Range:   0-65535 (0=off)
+Default Value: 32
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+transmit interrupt is generated.  Useful only if TxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is sent on the wire within the set amount of time.  Proper tuning,
+along with TxIntDelay, may improve traffic throughput in specific
+network conditions.
+
+Copybreak
+---------
+Valid Range:   0-xxxxxxx (0=off)
+Default Value: 256
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000e/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value:  0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can set this parameter
+in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
+
+IntMode
+-------
+Valid Range: 0-2 (0=legacy, 1=MSI, 2=MSI-X)
+Default Value: 2
+
+Allows changing the interrupt mode at module load time, without requiring a
+recompile. If the driver load fails to enable a specific interrupt mode, the
+driver will try other interrupt modes, from least to most compatible.  The
+interrupt order is MSI-X, MSI, Legacy.  If specifying MSI (IntMode=1)
+interrupts, only MSI and Legacy will be attempted.
+
+CrcStripping
+------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Strip the CRC from received packets before sending up the network stack.  If
+you have a machine with a BMC enabled but cannot receive IPMI traffic after
+loading or enabling the driver, try disabling this feature.
+
+WriteProtectNVM
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Set the hardware to ignore all write/erase cycles to the GbE region in the
+ICHx NVM (non-volatile memory).  This feature can be disabled by the
+WriteProtectNVM module parameter (enabled by default) only after a hardware
+reset, but the machine must be power cycled before trying to enable writes.
+
+Note: the kernel boot option iomem=relaxed may need to be set if the kernel
+config option CONFIG_STRICT_DEVMEM=y, if the root user wants to write the
+NVM from user space via ethtool.
+
+Additional Configurations
+=========================
+
+  Jumbo Frames
+  ------------
+  Jumbo Frames support is enabled by changing the MTU to a value larger than
+  the default of 1500.  Use the ifconfig command to increase the MTU size.
+  For example:
+
+       ifconfig eth<x> mtu 9000 up
+
+  This setting is not saved across reboots.
+
+  Notes:
+
+  - The maximum MTU setting for Jumbo Frames is 9216.  This value coincides
+    with the maximum Jumbo Frames size of 9234 bytes.
+
+  - Using Jumbo Frames at 10 or 100 Mbps is not supported and may result in
+    poor performance or loss of link.
+
+  - Some adapters limit Jumbo Frames sized packets to a maximum of
+    4096 bytes and some adapters do not support Jumbo Frames.
+
+
+  Ethtool
+  -------
+  The driver utilizes the ethtool interface for driver configuration and
+  diagnostics, as well as displaying statistical information.  We
+  strongly recommend downloading the latest version of Ethtool at:
+
+  http://sourceforge.net/projects/gkernel.
+
+  Speed and Duplex
+  ----------------
+  Speed and Duplex are configured through the Ethtool* utility. For
+  instructions,  refer to the Ethtool man page.
+
+  Enabling Wake on LAN* (WoL)
+  ---------------------------
+  WoL is configured through the Ethtool* utility. For instructions on
+  enabling WoL with Ethtool, refer to the Ethtool man page.
+
+  WoL will be enabled on the system during the next shut down or reboot.
+  For this driver version, in order to enable WoL, the e1000e driver must be
+  loaded when shutting down or rebooting the system.
+
+  In most cases Wake On LAN is only supported on port A for multiple port
+  adapters. To verify if a port supports Wake on LAN run ethtool eth<X>.
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+    www.intel.com/support/
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://sourceforge.net/projects/e1000
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
old mode 100755 (executable)
new mode 100644 (file)
index 19015de..21dd5d1
@@ -1,19 +1,16 @@
 Linux* Base Driver for Intel(R) Network Connection
 ==================================================
 
-November 24, 2009
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
 
 Contents
 ========
 
-- In This Release
 - Identifying Your Adapter
 - Known Issues/Troubleshooting
 - Support
 
-In This Release
-===============
-
 This file describes the ixgbevf Linux* Base Driver for Intel Network
 Connection.
 
@@ -33,7 +30,7 @@ Identifying Your Adapter
 For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
-    http://support.intel.com/support/network/sb/CS-008441.htm
+    http://support.intel.com/support/go/network/adapter/idguide.htm
 
 Known Issues/Troubleshooting
 ============================
@@ -57,34 +54,3 @@ or the Intel Wired Networking project hosted by Sourceforge at:
 If an issue is identified with the released source code on the supported
 kernel with a supported adapter, email the specific information related
 to the issue to e1000-devel@lists.sf.net
-
-License
-=======
-
-Intel 10 Gigabit Linux driver.
-Copyright(c) 1999 - 2009 Intel Corporation.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms and conditions of the GNU General Public License,
-version 2, as published by the Free Software Foundation.
-
-This program is distributed in the hope it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-The full GNU General Public License is included in this distribution in
-the file called "COPYING".
-
-Trademarks
-==========
-
-Intel, Itanium, and Pentium are trademarks or registered trademarks of
-Intel Corporation or its subsidiaries in the United States and other
-countries.
-
-* Other names and brands may be claimed as the property of others.
index 26c0f9c00545300aeef860eba18422ba79bd2e75..dd04361dd361afe814b98eb46942924bda757f17 100644 (file)
@@ -1,4 +1,29 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
+   If struct pcmcia_device *p_dev->config_flags is set accordingly,
+   pcmcia_loop_config() now sets up certain configuration values
+   automatically, though the driver may still override the settings
+   in the callback function. The following autoconfiguration options
+   are provided at the moment:
+       CONF_AUTO_CHECK_VCC : check for matching Vcc
+       CONF_AUTO_SET_VPP   : set Vpp
+       CONF_AUTO_AUDIO     : auto-enable audio line, if required
+       CONF_AUTO_SET_IO    : set ioport resources (->resource[0,1])
+       CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])
+
+* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
+   pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
+   as it mirrors pcmcia_disable_device(). Configuration settings are now
+   stored in struct pcmcia_device, e.g. in the fields config_flags,
+   config_index, config_base, vpp.
+
+* pcmcia_request_window changes (as of 2.6.36)
+   Instead of win_req_t, drivers are now requested to fill out
+   struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four ioport
+   ranges. After a call to pcmcia_request_window(), the regions found there
+   are reserved and may be used immediately -- until pcmcia_release_window()
+   is called.
+
 * pcmcia_request_io changes (as of 2.6.36)
    Instead of io_req_t, drivers are now requested to fill out
    struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
index fb742c213c9eb37b9e8216c96f029bebed6a86e9..45e9d4a91284678e9a9acf55ab5a23b07d17ce33 100644 (file)
@@ -14,6 +14,8 @@ interface.txt
        - Power management user interface in /sys/power
 notifiers.txt
        - Registering suspend notifiers in device drivers
+opp.txt
+       - Operating Performance Point library
 pci.txt
        - How the PCI Subsystem Does Power Management
 pm_qos_interface.txt
index e67211fe0ee2f432044efe62e8909702f0b46fc9..c537834af00566e0fee8058a9643803d2c2b3954 100644 (file)
@@ -57,7 +57,7 @@ smallest image possible.  In particular, if "0" is written to this file, the
 suspend image will be as small as possible.
 
 Reading from this file will display the current image size limit, which
-is set to 500 MB by default.
+is set to 2/5 of available RAM by default.
 
 /sys/power/pm_trace controls the code which saves the last PM event point in
 the RTC across reboots, so that you can debug a machine that just hangs
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644 (file)
index 0000000..44d87ad
--- /dev/null
@@ -0,0 +1,375 @@
+*=============*
+* OPP Library *
+*=============*
+
+(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users)                -> registers a set of default OPPs              -> (library)
+SoC framework  -> modifies on required cases certain OPPs      -> OPP layer
+               -> queries to search/retrieve information       ->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+       The OPP is defined using the frequency and voltage. Once added, the OPP
+       is assumed to be available and control of it's availability can be done
+       with the opp_enable/disable functions. OPP library internally stores
+       and manages this information in the opp struct. This function may be
+       used by SoC framework to define a optimal list as per the demands of
+       SoC usage environment.
+
+       WARNING: Do not use this function in interrupt context.
+
+       Example:
+        soc_pm_init()
+        {
+               /* Do things */
+               r = opp_add(mpu_dev, 1000000, 900000);
+               if (!r) {
+                       pr_err("%s: unable to register mpu opp(%d)\n", r);
+                       goto no_cpufreq;
+               }
+               /* Do cpufreq things */
+        no_cpufreq:
+               /* Do remaining things */
+        }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+       availability. This function is especially useful to enable an OPP which
+       is not available by default.
+       Example: In a case when SoC framework detects a situation where a
+       higher frequency could be made available, it can use this function to
+       find the OPP prior to call the opp_enable to actually make it available.
+        rcu_read_lock();
+        opp = opp_find_freq_exact(dev, 1000000000, false);
+        rcu_read_unlock();
+        /* dont operate on the pointer.. just do a sanity check.. */
+        if (IS_ERR(opp)) {
+               pr_err("frequency not disabled!\n");
+               /* trigger appropriate actions.. */
+        } else {
+               opp_enable(dev,1000000000);
+        }
+
+       NOTE: This is the only search function that operates on OPPs which are
+       not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+       provided frequency. This function is useful while searching for a lesser
+       match OR operating on OPP information in the order of decreasing
+       frequency.
+       Example: To find the highest opp for a device:
+        freq = ULONG_MAX;
+        rcu_read_lock();
+        opp_find_freq_floor(dev, &freq);
+        rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+       provided frequency. This function is useful while searching for a
+       higher match OR operating on OPP information in the order of increasing
+       frequency.
+       Example 1: To find the lowest opp for a device:
+        freq = 0;
+        rcu_read_lock();
+        opp_find_freq_ceil(dev, &freq);
+        rcu_read_unlock();
+       Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+        soc_cpufreq_target(..)
+        {
+               /* Do stuff like policy checks etc. */
+               /* Find the best frequency match for the req */
+               rcu_read_lock();
+               opp = opp_find_freq_ceil(dev, &freq);
+               rcu_read_unlock();
+               if (!IS_ERR(opp))
+                       soc_switch_to_freq_voltage(freq);
+               else
+                       /* do something when we cant satisfy the req */
+               /* do other stuff */
+        }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+       Example: Lets say that 1GHz OPP is to be made available only if the
+       SoC temperature is lower than a certain threshold. The SoC framework
+       implementation might choose to do something as follows:
+        if (cur_temp < temp_low_thresh) {
+               /* Enable 1GHz if it was disabled */
+               rcu_read_lock();
+               opp = opp_find_freq_exact(dev, 1000000000, false);
+               rcu_read_unlock();
+               /* just error check */
+               if (!IS_ERR(opp))
+                       ret = opp_enable(dev, 1000000000);
+               else
+                       goto try_something_else;
+        }
+
+opp_disable - Make an OPP to be not available for operation
+       Example: Lets say that 1GHz OPP is to be disabled if the temperature
+       exceeds a threshold value. The SoC framework implementation might
+       choose to do something as follows:
+        if (cur_temp > temp_high_thresh) {
+               /* Disable 1GHz if it was enabled */
+               rcu_read_lock();
+               opp = opp_find_freq_exact(dev, 1000000000, true);
+               rcu_read_unlock();
+               /* just error check */
+               if (!IS_ERR(opp))
+                       ret = opp_disable(dev, 1000000000);
+               else
+                       goto try_something_else;
+        }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+       Example: At a cpufreq transition to a different frequency, SoC
+       framework requires to set the voltage represented by the OPP using
+       the regulator framework to the Power Management chip providing the
+       voltage.
+        soc_switch_to_freq_voltage(freq)
+        {
+               /* do things */
+               rcu_read_lock();
+               opp = opp_find_freq_ceil(dev, &freq);
+               v = opp_get_voltage(opp);
+               rcu_read_unlock();
+               if (v)
+                       regulator_set_voltage(.., v);
+               /* do other things */
+        }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+       Example: Lets say the SoC framework uses a couple of helper functions
+       we could pass opp pointers instead of doing additional parameters to
+       handle quiet a bit of data parameters.
+        soc_cpufreq_target(..)
+        {
+               /* do things.. */
+                max_freq = ULONG_MAX;
+                rcu_read_lock();
+                max_opp = opp_find_freq_floor(dev,&max_freq);
+                requested_opp = opp_find_freq_ceil(dev,&freq);
+                if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+                       r = soc_test_validity(max_opp, requested_opp);
+                rcu_read_unlock();
+               /* do other things */
+        }
+        soc_test_validity(..)
+        {
+                if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+                        return -EINVAL;
+                if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+                        return -EINVAL;
+               /* do things.. */
+        }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+       Example: Lets say a co-processor in the SoC needs to know the available
+       frequencies in a table, the main processor can notify as following:
+        soc_notify_coproc_available_frequencies()
+        {
+               /* Do things */
+               rcu_read_lock();
+               num_available = opp_get_opp_count(dev);
+               speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+               /* populate the table in increasing order */
+               freq = 0;
+               while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+                       speeds[i] = freq;
+                       freq++;
+                       i++;
+               }
+               rcu_read_unlock();
+
+               soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+               /* Do other things */
+        }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+       cpufreq_frequency_table_cpuinfo which is provided with the list of
+       frequencies that are available for operation. This function provides
+       a ready to use conversion routine to translate the OPP layer's internal
+       information about the available frequencies into a format readily
+       providable to cpufreq.
+
+       WARNING: Do not use this function in interrupt context.
+
+       Example:
+        soc_pm_init()
+        {
+               /* Do things */
+               r = opp_init_cpufreq_table(dev, &freq_table);
+               if (!r)
+                       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+               /* Do other things */
+        }
+
+       NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+       addition to CONFIG_PM as power management feature is required to
+       dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ |     |- opp 1 (availability, freq, voltage)
+ |     |- opp 2 ..
+ ...   ...
+ |     `- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+       represent an OPP. In addition to the freq, voltage, availability
+       information, it also contains internal book keeping information required
+       for the OPP library to operate on.  Pointer to this structure is
+       provided back to the users such as SoC framework to be used as a
+       identifier for OPP in the interactions with OPP layer.
+
+       WARNING: The struct opp pointer should not be parsed or modified by the
+       users. The defaults of for an instance is populated by opp_add, but the
+       availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+       nature of the device and it's implementation is left to the user of
+       OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+            +-----+        /- opp_enable
+opp_add --> | opp | <-------
+  |         +-----+        \- opp_disable
+  \-------> domain_info(device)
+
+Search functions:
+             /-- opp_find_freq_ceil  ---\   +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+             \-- opp_find_freq_floor ---/   +-----+
+
+Retrieval functions:
++-----+     /- opp_get_voltage
+| opp | <---
++-----+     \- opp_get_freq
+
+domain_info <- opp_get_opp_count
index 9363e056188ac87282c2477e25df2eebe6e837fa..8ed17587a74bdc006b2d2922b5709f0e16ec08ad 100644 (file)
@@ -13,7 +13,7 @@ regulators (where voltage output is controllable) and current sinks (where
 current limit is controllable).
 
 (C) 2008  Wolfson Microelectronics PLC.
-Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Author: Liam Girdwood <lrg@slimlogic.co.uk>
 
 
 Nomenclature
index 55b859b3bc723267db79d1b274bf820c37c7469a..489e9bacd165ad4a354130edcf7e03d97471b52b 100644 (file)
@@ -1,6 +1,7 @@
 Run-time Power Management Framework for I/O Devices
 
 (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+(C) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 1. Introduction
 
@@ -157,7 +158,8 @@ rules:
     to execute it, the other callbacks will not be executed for the same device.
 
   * A request to execute ->runtime_resume() will cancel any pending or
-    scheduled requests to execute the other callbacks for the same device.
+    scheduled requests to execute the other callbacks for the same device,
+    except for scheduled autosuspends.
 
 3. Run-time PM Device Fields
 
@@ -165,7 +167,7 @@ The following device run-time PM fields are present in 'struct dev_pm_info', as
 defined in include/linux/pm.h:
 
   struct timer_list suspend_timer;
-    - timer used for scheduling (delayed) suspend request
+    - timer used for scheduling (delayed) suspend and autosuspend requests
 
   unsigned long timer_expires;
     - timer expiration time, in jiffies (if this is different from zero, the
@@ -230,6 +232,28 @@ defined in include/linux/pm.h:
       interface; it may only be modified with the help of the pm_runtime_allow()
       and pm_runtime_forbid() helper functions
 
+  unsigned int no_callbacks;
+    - indicates that the device does not use the run-time PM callbacks (see
+      Section 8); it may be modified only by the pm_runtime_no_callbacks()
+      helper function
+
+  unsigned int use_autosuspend;
+    - indicates that the device's driver supports delayed autosuspend (see
+      Section 9); it may be modified only by the
+      pm_runtime{_dont}_use_autosuspend() helper functions
+
+  unsigned int timer_autosuspends;
+    - indicates that the PM core should attempt to carry out an autosuspend
+      when the timer expires rather than a normal suspend
+
+  int autosuspend_delay;
+    - the delay time (in milliseconds) to be used for autosuspend
+
+  unsigned long last_busy;
+    - the time (in jiffies) when the pm_runtime_mark_last_busy() helper
+      function was last called for this device; used in calculating inactivity
+      periods for autosuspend
+
 All of the above fields are members of the 'power' member of 'struct device'.
 
 4. Run-time PM Device Helper Functions
@@ -255,6 +279,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
       to suspend the device again in future
 
+  int pm_runtime_autosuspend(struct device *dev);
+    - same as pm_runtime_suspend() except that the autosuspend delay is taken
+      into account; if pm_runtime_autosuspend_expiration() says the delay has
+      not yet expired then an autosuspend is scheduled for the appropriate time
+      and 0 is returned
+
   int pm_runtime_resume(struct device *dev);
     - execute the subsystem-level resume callback for the device; returns 0 on
       success, 1 if the device's run-time PM status was already 'active' or
@@ -267,6 +297,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       device (the request is represented by a work item in pm_wq); returns 0 on
       success or error code if the request has not been queued up
 
+  int pm_request_autosuspend(struct device *dev);
+    - schedule the execution of the subsystem-level suspend callback for the
+      device when the autosuspend delay has expired; if the delay has already
+      expired then the work item is queued up immediately
+
   int pm_schedule_suspend(struct device *dev, unsigned int delay);
     - schedule the execution of the subsystem-level suspend callback for the
       device in future, where 'delay' is the time to wait before queuing up a
@@ -298,12 +333,20 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
     - decrement the device's usage counter
 
   int pm_runtime_put(struct device *dev);
-    - decrement the device's usage counter, run pm_request_idle(dev) and return
-      its result
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_request_idle(dev) and return its result
+
+  int pm_runtime_put_autosuspend(struct device *dev);
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_request_autosuspend(dev) and return its result
 
   int pm_runtime_put_sync(struct device *dev);
-    - decrement the device's usage counter, run pm_runtime_idle(dev) and return
-      its result
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_runtime_idle(dev) and return its result
+
+  int pm_runtime_put_sync_autosuspend(struct device *dev);
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_runtime_autosuspend(dev) and return its result
 
   void pm_runtime_enable(struct device *dev);
     - enable the run-time PM helper functions to run the device bus type's
@@ -349,19 +392,51 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       counter (used by the /sys/devices/.../power/control interface to
       effectively prevent the device from being power managed at run time)
 
+  void pm_runtime_no_callbacks(struct device *dev);
+    - set the power.no_callbacks flag for the device and remove the run-time
+      PM attributes from /sys/devices/.../power (or prevent them from being
+      added when the device is registered)
+
+  void pm_runtime_mark_last_busy(struct device *dev);
+    - set the power.last_busy field to the current time
+
+  void pm_runtime_use_autosuspend(struct device *dev);
+    - set the power.use_autosuspend flag, enabling autosuspend delays
+
+  void pm_runtime_dont_use_autosuspend(struct device *dev);
+    - clear the power.use_autosuspend flag, disabling autosuspend delays
+
+  void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+    - set the power.autosuspend_delay value to 'delay' (expressed in
+      milliseconds); if 'delay' is negative then run-time suspends are
+      prevented
+
+  unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+    - calculate the time when the current autosuspend delay period will expire,
+      based on power.last_busy and power.autosuspend_delay; if the delay time
+      is 1000 ms or larger then the expiration time is rounded up to the
+      nearest second; returns 0 if the delay period has already expired or
+      power.use_autosuspend isn't set, otherwise returns the expiration time
+      in jiffies
+
 It is safe to execute the following helper functions from interrupt context:
 
 pm_request_idle()
+pm_request_autosuspend()
 pm_schedule_suspend()
 pm_request_resume()
 pm_runtime_get_noresume()
 pm_runtime_get()
 pm_runtime_put_noidle()
 pm_runtime_put()
+pm_runtime_put_autosuspend()
+pm_runtime_enable()
 pm_suspend_ignore_children()
 pm_runtime_set_active()
 pm_runtime_set_suspended()
-pm_runtime_enable()
+pm_runtime_suspended()
+pm_runtime_mark_last_busy()
+pm_runtime_autosuspend_expiration()
 
 5. Run-time PM Initialization, Device Probing and Removal
 
@@ -524,3 +599,141 @@ poweroff and run-time suspend callback, and similarly for system resume, thaw,
 restore, and run-time resume, can achieve this with the help of the
 UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
 last argument to NULL).
+
+8. "No-Callback" Devices
+
+Some "devices" are only logical sub-devices of their parent and cannot be
+power-managed on their own.  (The prototype example is a USB interface.  Entire
+USB devices can go into low-power mode or send wake-up requests, but neither is
+possible for individual interfaces.)  The drivers for these devices have no
+need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
+and ->runtime_resume() would always return 0 without doing anything else and
+->runtime_idle() would always call pm_runtime_suspend().
+
+Subsystems can tell the PM core about these devices by calling
+pm_runtime_no_callbacks().  This should be done after the device structure is
+initialized and before it is registered (although after device registration is
+also okay).  The routine will set the device's power.no_callbacks flag and
+prevent the non-debugging run-time PM sysfs attributes from being created.
+
+When power.no_callbacks is set, the PM core will not invoke the
+->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
+Instead it will assume that suspends and resumes always succeed and that idle
+devices should be suspended.
+
+As a consequence, the PM core will never directly inform the device's subsystem
+or driver about run-time power changes.  Instead, the driver for the device's
+parent must take responsibility for telling the device's driver when the
+parent's power state changes.
+
+9. Autosuspend, or automatically-delayed suspends
+
+Changing a device's power state isn't free; it requires both time and energy.
+A device should be put in a low-power state only when there's some reason to
+think it will remain in that state for a substantial time.  A common heuristic
+says that a device which hasn't been used for a while is liable to remain
+unused; following this advice, drivers should not allow devices to be suspended
+at run-time until they have been inactive for some minimum period.  Even when
+the heuristic ends up being non-optimal, it will still prevent devices from
+"bouncing" too rapidly between low-power and full-power states.
+
+The term "autosuspend" is an historical remnant.  It doesn't mean that the
+device is automatically suspended (the subsystem or driver still has to call
+the appropriate PM routines); rather it means that run-time suspends will
+automatically be delayed until the desired period of inactivity has elapsed.
+
+Inactivity is determined based on the power.last_busy field.  Drivers should
+call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
+typically just before calling pm_runtime_put_autosuspend().  The desired length
+of the inactivity period is a matter of policy.  Subsystems can set this length
+initially by calling pm_runtime_set_autosuspend_delay(), but after device
+registration the length should be controlled by user space, using the
+/sys/devices/.../power/autosuspend_delay_ms attribute.
+
+In order to use autosuspend, subsystems or drivers must call
+pm_runtime_use_autosuspend() (preferably before registering the device), and
+thereafter they should use the various *_autosuspend() helper functions instead
+of the non-autosuspend counterparts:
+
+       Instead of: pm_runtime_suspend    use: pm_runtime_autosuspend;
+       Instead of: pm_schedule_suspend   use: pm_request_autosuspend;
+       Instead of: pm_runtime_put        use: pm_runtime_put_autosuspend;
+       Instead of: pm_runtime_put_sync   use: pm_runtime_put_sync_autosuspend.
+
+Drivers may also continue to use the non-autosuspend helper functions; they
+will behave normally, not taking the autosuspend delay into account.
+Similarly, if the power.use_autosuspend field isn't set then the autosuspend
+helper functions will behave just like the non-autosuspend counterparts.
+
+The implementation is well suited for asynchronous use in interrupt contexts.
+However such use inevitably involves races, because the PM core can't
+synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
+This synchronization must be handled by the driver, using its private lock.
+Here is a schematic pseudo-code example:
+
+       foo_read_or_write(struct foo_priv *foo, void *data)
+       {
+               lock(&foo->private_lock);
+               add_request_to_io_queue(foo, data);
+               if (foo->num_pending_requests++ == 0)
+                       pm_runtime_get(&foo->dev);
+               if (!foo->is_suspended)
+                       foo_process_next_request(foo);
+               unlock(&foo->private_lock);
+       }
+
+       foo_io_completion(struct foo_priv *foo, void *req)
+       {
+               lock(&foo->private_lock);
+               if (--foo->num_pending_requests == 0) {
+                       pm_runtime_mark_last_busy(&foo->dev);
+                       pm_runtime_put_autosuspend(&foo->dev);
+               } else {
+                       foo_process_next_request(foo);
+               }
+               unlock(&foo->private_lock);
+               /* Send req result back to the user ... */
+       }
+
+       int foo_runtime_suspend(struct device *dev)
+       {
+               struct foo_priv foo = container_of(dev, ...);
+               int ret = 0;
+
+               lock(&foo->private_lock);
+               if (foo->num_pending_requests > 0) {
+                       ret = -EBUSY;
+               } else {
+                       /* ... suspend the device ... */
+                       foo->is_suspended = 1;
+               }
+               unlock(&foo->private_lock);
+               return ret;
+       }
+
+       int foo_runtime_resume(struct device *dev)
+       {
+               struct foo_priv foo = container_of(dev, ...);
+
+               lock(&foo->private_lock);
+               /* ... resume the device ... */
+               foo->is_suspended = 0;
+               pm_runtime_mark_last_busy(&foo->dev);
+               if (foo->num_pending_requests > 0)
+                       foo_process_requests(foo);
+               unlock(&foo->private_lock);
+               return 0;
+       }
+
+The important point is that after foo_io_completion() asks for an autosuspend,
+the foo_runtime_suspend() callback may race with foo_read_or_write().
+Therefore foo_runtime_suspend() has to check whether there are any pending I/O
+requests (while holding the private lock) before allowing the suspend to
+proceed.
+
+In addition, the power.autosuspend_delay field can be changed by user space at
+any time.  If a driver cares about this, it can call
+pm_runtime_autosuspend_expiration() from within the ->runtime_suspend()
+callback while holding its private lock.  If the function returns a nonzero
+value then the delay has not yet expired and the callback should return
+-EAGAIN.
index 514b94fc931e09b337fd297401d9f9c1aa391dac..1bdfa04437732753636e3b6adfc84d7e2626adab 100644 (file)
@@ -49,6 +49,13 @@ machine that doesn't boot) is:
    device (lspci and /sys/devices/pci* is your friend), and see if you can
    fix it, disable it, or trace into its resume function.
 
+   If no device matches the hash (or any matches appear to be false positives),
+   the culprit may be a device from a loadable kernel module that is not loaded
+   until after the hash is checked. You can check the hash against the current
+   devices again after more modules are loaded using sysfs:
+
+       cat /sys/power/pm_trace_dev_match
+
 For example, the above happens to be the VGA device on my EVO, which I
 used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out
 that "radeonfb" simply cannot resume that device - it tries to set the
index 9d60ab717a7b3c8dc0daa4d14e6a914884965bf0..ea718891a665b0cad258ec2881f6ab0b8b5fe96f 100644 (file)
@@ -66,7 +66,8 @@ swsusp saves the state of the machine into active swaps and then reboots or
 powerdowns.  You must explicitly specify the swap partition to resume from with
 ``resume='' kernel option. If signature is found it loads and restores saved
 state. If the option ``noresume'' is specified as a boot parameter, it skips
-the resuming.
+the resuming.  If the option ``hibernate=nocompress'' is specified as a boot
+parameter, it saves hibernation image without compression.
 
 In the meantime while the system is suspended you should not add/remove any
 of the hardware, write to the filesystems, etc.
index 80510c018eeaaec359d5d3b5f980d91938411a6e..777abd7399d5b4249abdd2fd427fca0942c7891e 100644 (file)
@@ -1,7 +1,9 @@
 * SPI (Serial Peripheral Interface)
 
 Required properties:
-- cell-index : SPI controller index.
+- cell-index : QE SPI subblock index.
+               0: QE subblock SPI1
+               1: QE subblock SPI2
 - compatible : should be "fsl,spi".
 - mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
 - reg : Offset and length of the register set for the device
@@ -29,3 +31,23 @@ Example:
                gpios = <&gpio 18 1     // device reg=<0>
                         &gpio 19 1>;   // device reg=<1>
        };
+
+
+* eSPI (Enhanced Serial Peripheral Interface)
+
+Required properties:
+- compatible : should be "fsl,mpc8536-espi".
+- reg : Offset and length of the register set for the device.
+- interrupts : should contain eSPI interrupt, the device has one interrupt.
+- fsl,espi-num-chipselects : the number of the chipselect signals.
+
+Example:
+       spi@110000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "fsl,mpc8536-espi";
+               reg = <0x110000 0x1000>;
+               interrupts = <53 0x2>;
+               interrupt-parent = <&mpic>;
+               fsl,espi-num-chipselects = <4>;
+       };
index ce46fa1e643e876344071d480e1e6d6d54b89856..37c6aad5e590ac1375944b8edf0656aa7b106607 100644 (file)
@@ -296,6 +296,7 @@ Conexant 5051
 Conexant 5066
 =============
   laptop       Basic Laptop config (default)
+  hp-laptop    HP laptops, e g G60
   dell-laptop  Dell laptops
   dell-vostro  Dell Vostro
   olpc-xo-1_5  OLPC XO 1.5
index ccd951fa94eeda42a5a50c854b6b92e512fe6724..cc96ee2666f2e5f10f13b83b1fab72bcf8e18924 100644 (file)
@@ -478,7 +478,7 @@ static void prepare_hwpoison_fd(void)
        }
 
        if (opt_unpoison && !hwpoison_forget_fd) {
-               sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs);
+               sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs);
                hwpoison_forget_fd = checked_open(buf, O_WRONLY);
        }
 }
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt
new file mode 100644 (file)
index 0000000..e4498a2
--- /dev/null
@@ -0,0 +1,380 @@
+
+Concurrency Managed Workqueue (cmwq)
+
+September, 2010                Tejun Heo <tj@kernel.org>
+                       Florian Mickler <florian@mickler.org>
+
+CONTENTS
+
+1. Introduction
+2. Why cmwq?
+3. The Design
+4. Application Programming Interface (API)
+5. Example Execution Scenarios
+6. Guidelines
+
+
+1. Introduction
+
+There are many cases where an asynchronous process execution context
+is needed and the workqueue (wq) API is the most commonly used
+mechanism for such cases.
+
+When such an asynchronous execution context is needed, a work item
+describing which function to execute is put on a queue.  An
+independent thread serves as the asynchronous execution context.  The
+queue is called workqueue and the thread is called worker.
+
+While there are work items on the workqueue the worker executes the
+functions associated with the work items one after the other.  When
+there is no work item left on the workqueue the worker becomes idle.
+When a new work item gets queued, the worker begins executing again.
+
+
+2. Why cmwq?
+
+In the original wq implementation, a multi threaded (MT) wq had one
+worker thread per CPU and a single threaded (ST) wq had one worker
+thread system-wide.  A single MT wq needed to keep around the same
+number of workers as the number of CPUs.  The kernel grew a lot of MT
+wq users over the years and with the number of CPU cores continuously
+rising, some systems saturated the default 32k PID space just booting
+up.
+
+Although MT wq wasted a lot of resource, the level of concurrency
+provided was unsatisfactory.  The limitation was common to both ST and
+MT wq albeit less severe on MT.  Each wq maintained its own separate
+worker pool.  A MT wq could provide only one execution context per CPU
+while a ST wq one for the whole system.  Work items had to compete for
+those very limited execution contexts leading to various problems
+including proneness to deadlocks around the single execution context.
+
+The tension between the provided level of concurrency and resource
+usage also forced its users to make unnecessary tradeoffs like libata
+choosing to use ST wq for polling PIOs and accepting an unnecessary
+limitation that no two polling PIOs can progress at the same time.  As
+MT wq don't provide much better concurrency, users which require
+higher level of concurrency, like async or fscache, had to implement
+their own thread pool.
+
+Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with
+focus on the following goals.
+
+* Maintain compatibility with the original workqueue API.
+
+* Use per-CPU unified worker pools shared by all wq to provide
+  flexible level of concurrency on demand without wasting a lot of
+  resource.
+
+* Automatically regulate worker pool and level of concurrency so that
+  the API users don't need to worry about such details.
+
+
+3. The Design
+
+In order to ease the asynchronous execution of functions a new
+abstraction, the work item, is introduced.
+
+A work item is a simple struct that holds a pointer to the function
+that is to be executed asynchronously.  Whenever a driver or subsystem
+wants a function to be executed asynchronously it has to set up a work
+item pointing to that function and queue that work item on a
+workqueue.
+
+Special purpose threads, called worker threads, execute the functions
+off of the queue, one after the other.  If no work is queued, the
+worker threads become idle.  These worker threads are managed in so
+called thread-pools.
+
+The cmwq design differentiates between the user-facing workqueues that
+subsystems and drivers queue work items on and the backend mechanism
+which manages thread-pool and processes the queued work items.
+
+The backend is called gcwq.  There is one gcwq for each possible CPU
+and one gcwq to serve work items queued on unbound workqueues.
+
+Subsystems and drivers can create and queue work items through special
+workqueue API functions as they see fit. They can influence some
+aspects of the way the work items are executed by setting flags on the
+workqueue they are putting the work item on. These flags include
+things like CPU locality, reentrancy, concurrency limits and more. To
+get a detailed overview refer to the API description of
+alloc_workqueue() below.
+
+When a work item is queued to a workqueue, the target gcwq is
+determined according to the queue parameters and workqueue attributes
+and appended on the shared worklist of the gcwq.  For example, unless
+specifically overridden, a work item of a bound workqueue will be
+queued on the worklist of exactly that gcwq that is associated to the
+CPU the issuer is running on.
+
+For any worker pool implementation, managing the concurrency level
+(how many execution contexts are active) is an important issue.  cmwq
+tries to keep the concurrency at a minimal but sufficient level.
+Minimal to save resources and sufficient in that the system is used at
+its full capacity.
+
+Each gcwq bound to an actual CPU implements concurrency management by
+hooking into the scheduler.  The gcwq is notified whenever an active
+worker wakes up or sleeps and keeps track of the number of the
+currently runnable workers.  Generally, work items are not expected to
+hog a CPU and consume many cycles.  That means maintaining just enough
+concurrency to prevent work processing from stalling should be
+optimal.  As long as there are one or more runnable workers on the
+CPU, the gcwq doesn't start execution of a new work, but, when the
+last running worker goes to sleep, it immediately schedules a new
+worker so that the CPU doesn't sit idle while there are pending work
+items.  This allows using a minimal number of workers without losing
+execution bandwidth.
+
+Keeping idle workers around doesn't cost other than the memory space
+for kthreads, so cmwq holds onto idle ones for a while before killing
+them.
+
+For an unbound wq, the above concurrency management doesn't apply and
+the gcwq for the pseudo unbound CPU tries to start executing all work
+items as soon as possible.  The responsibility of regulating
+concurrency level is on the users.  There is also a flag to mark a
+bound wq to ignore the concurrency management.  Please refer to the
+API section for details.
+
+Forward progress guarantee relies on that workers can be created when
+more execution contexts are necessary, which in turn is guaranteed
+through the use of rescue workers.  All work items which might be used
+on code paths that handle memory reclaim are required to be queued on
+wq's that have a rescue-worker reserved for execution under memory
+pressure.  Else it is possible that the thread-pool deadlocks waiting
+for execution contexts to free up.
+
+
+4. Application Programming Interface (API)
+
+alloc_workqueue() allocates a wq.  The original create_*workqueue()
+functions are deprecated and scheduled for removal.  alloc_workqueue()
+takes three arguments - @name, @flags and @max_active.  @name is the
+name of the wq and also used as the name of the rescuer thread if
+there is one.
+
+A wq no longer manages execution resources but serves as a domain for
+forward progress guarantee, flush and work item attributes.  @flags
+and @max_active control how work items are assigned execution
+resources, scheduled and executed.
+
+@flags:
+
+  WQ_NON_REENTRANT
+
+       By default, a wq guarantees non-reentrance only on the same
+       CPU.  A work item may not be executed concurrently on the same
+       CPU by multiple workers but is allowed to be executed
+       concurrently on multiple CPUs.  This flag makes sure
+       non-reentrance is enforced across all CPUs.  Work items queued
+       to a non-reentrant wq are guaranteed to be executed by at most
+       one worker system-wide at any given time.
+
+  WQ_UNBOUND
+
+       Work items queued to an unbound wq are served by a special
+       gcwq which hosts workers which are not bound to any specific
+       CPU.  This makes the wq behave as a simple execution context
+       provider without concurrency management.  The unbound gcwq
+       tries to start execution of work items as soon as possible.
+       Unbound wq sacrifices locality but is useful for the following
+       cases.
+
+       * Wide fluctuation in the concurrency level requirement is
+         expected and using bound wq may end up creating large number
+         of mostly unused workers across different CPUs as the issuer
+         hops through different CPUs.
+
+       * Long running CPU intensive workloads which can be better
+         managed by the system scheduler.
+
+  WQ_FREEZEABLE
+
+       A freezeable wq participates in the freeze phase of the system
+       suspend operations.  Work items on the wq are drained and no
+       new work item starts execution until thawed.
+
+  WQ_RESCUER
+
+       All wq which might be used in the memory reclaim paths _MUST_
+       have this flag set.  This reserves one worker exclusively for
+       the execution of this wq under memory pressure.
+
+  WQ_HIGHPRI
+
+       Work items of a highpri wq are queued at the head of the
+       worklist of the target gcwq and start execution regardless of
+       the current concurrency level.  In other words, highpri work
+       items will always start execution as soon as execution
+       resource is available.
+
+       Ordering among highpri work items is preserved - a highpri
+       work item queued after another highpri work item will start
+       execution after the earlier highpri work item starts.
+
+       Although highpri work items are not held back by other
+       runnable work items, they still contribute to the concurrency
+       level.  Highpri work items in runnable state will prevent
+       non-highpri work items from starting execution.
+
+       This flag is meaningless for unbound wq.
+
+  WQ_CPU_INTENSIVE
+
+       Work items of a CPU intensive wq do not contribute to the
+       concurrency level.  In other words, runnable CPU intensive
+       work items will not prevent other work items from starting
+       execution.  This is useful for bound work items which are
+       expected to hog CPU cycles so that their execution is
+       regulated by the system scheduler.
+
+       Although CPU intensive work items don't contribute to the
+       concurrency level, start of their executions is still
+       regulated by the concurrency management and runnable
+       non-CPU-intensive work items can delay execution of CPU
+       intensive work items.
+
+       This flag is meaningless for unbound wq.
+
+  WQ_HIGHPRI | WQ_CPU_INTENSIVE
+
+       This combination makes the wq avoid interaction with
+       concurrency management completely and behave as a simple
+       per-CPU execution context provider.  Work items queued on a
+       highpri CPU-intensive wq start execution as soon as resources
+       are available and don't affect execution of other work items.
+
+@max_active:
+
+@max_active determines the maximum number of execution contexts per
+CPU which can be assigned to the work items of a wq.  For example,
+with @max_active of 16, at most 16 work items of the wq can be
+executing at the same time per CPU.
+
+Currently, for a bound wq, the maximum limit for @max_active is 512
+and the default value used when 0 is specified is 256.  For an unbound
+wq, the limit is higher of 512 and 4 * num_possible_cpus().  These
+values are chosen sufficiently high such that they are not the
+limiting factor while providing protection in runaway cases.
+
+The number of active work items of a wq is usually regulated by the
+users of the wq, more specifically, by how many work items the users
+may queue at the same time.  Unless there is a specific need for
+throttling the number of active work items, specifying '0' is
+recommended.
+
+Some users depend on the strict execution ordering of ST wq.  The
+combination of @max_active of 1 and WQ_UNBOUND is used to achieve this
+behavior.  Work items on such wq are always queued to the unbound gcwq
+and only one work item can be active at any given time thus achieving
+the same ordering property as ST wq.
+
+
+5. Example Execution Scenarios
+
+The following example execution scenarios try to illustrate how cmwq
+behave under different configurations.
+
+ Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU.
+ w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms
+ again before finishing.  w1 and w2 burn CPU for 5ms then sleep for
+ 10ms.
+
+Ignoring all other tasks, works and processing overhead, and assuming
+simple FIFO scheduling, the following is one highly simplified version
+of possible sequences of events with the original wq.
+
+ TIME IN MSECS EVENT
+ 0             w0 starts and burns CPU
+ 5             w0 sleeps
+ 15            w0 wakes up and burns CPU
+ 20            w0 finishes
+ 20            w1 starts and burns CPU
+ 25            w1 sleeps
+ 35            w1 wakes up and finishes
+ 35            w2 starts and burns CPU
+ 40            w2 sleeps
+ 50            w2 wakes up and finishes
+
+And with cmwq with @max_active >= 3,
+
+ TIME IN MSECS EVENT
+ 0             w0 starts and burns CPU
+ 5             w0 sleeps
+ 5             w1 starts and burns CPU
+ 10            w1 sleeps
+ 10            w2 starts and burns CPU
+ 15            w2 sleeps
+ 15            w0 wakes up and burns CPU
+ 20            w0 finishes
+ 20            w1 wakes up and finishes
+ 25            w2 wakes up and finishes
+
+If @max_active == 2,
+
+ TIME IN MSECS EVENT
+ 0             w0 starts and burns CPU
+ 5             w0 sleeps
+ 5             w1 starts and burns CPU
+ 10            w1 sleeps
+ 15            w0 wakes up and burns CPU
+ 20            w0 finishes
+ 20            w1 wakes up and finishes
+ 20            w2 starts and burns CPU
+ 25            w2 sleeps
+ 35            w2 wakes up and finishes
+
+Now, let's assume w1 and w2 are queued to a different wq q1 which has
+WQ_HIGHPRI set,
+
+ TIME IN MSECS EVENT
+ 0             w1 and w2 start and burn CPU
+ 5             w1 sleeps
+ 10            w2 sleeps
+ 10            w0 starts and burns CPU
+ 15            w0 sleeps
+ 15            w1 wakes up and finishes
+ 20            w2 wakes up and finishes
+ 25            w0 wakes up and burns CPU
+ 30            w0 finishes
+
+If q1 has WQ_CPU_INTENSIVE set,
+
+ TIME IN MSECS EVENT
+ 0             w0 starts and burns CPU
+ 5             w0 sleeps
+ 5             w1 and w2 start and burn CPU
+ 10            w1 sleeps
+ 15            w2 sleeps
+ 15            w0 wakes up and burns CPU
+ 20            w0 finishes
+ 20            w1 wakes up and finishes
+ 25            w2 wakes up and finishes
+
+
+6. Guidelines
+
+* Do not forget to use WQ_RESCUER if a wq may process work items which
+  are used during memory reclaim.  Each wq with WQ_RESCUER set has one
+  rescuer thread reserved for it.  If there is dependency among
+  multiple work items used during memory reclaim, they should be
+  queued to separate wq each with WQ_RESCUER.
+
+* Unless strict ordering is required, there is no need to use ST wq.
+
+* Unless there is a specific need, using 0 for @max_active is
+  recommended.  In most use cases, concurrency level usually stays
+  well under the default limit.
+
+* A wq serves as a domain for forward progress guarantee (WQ_RESCUER),
+  flush and work item attributes.  Work items which are not involved
+  in memory reclaim and don't need to be flushed as a part of a group
+  of work items, and don't require any special attribute, can use one
+  of the system wq.  There is no difference in execution
+  characteristics between using a dedicated wq and a system wq.
+
+* Unless work items are expected to consume a huge amount of CPU
+  cycles, using a bound wq is usually beneficial due to the increased
+  level of locality in wq operations and work item execution.
index 5ad65d51fb95a64e1fbc646bb416c06e30a77541..a01eec5d1d0b2b4898dc09e175f240cbc33a8ea5 100644 (file)
@@ -18,9 +18,9 @@ specialized stacks contain no useful data.  The main CPU stacks are:
   Used for external hardware interrupts.  If this is the first external
   hardware interrupt (i.e. not a nested hardware interrupt) then the
   kernel switches from the current task to the interrupt stack.  Like
-  the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS),
-  this gives more room for kernel interrupt processing without having
-  to increase the size of every per thread stack.
+  the split thread and interrupt stacks on i386, this gives more room
+  for kernel interrupt processing without having to increase the size
+  of every per thread stack.
 
   The interrupt stack is also used when processing a softirq.
 
index 433f353857563f596df86cf95bc4b8114c45d3ea..b618b1e86c46b671fc2a766e1bd4127362129448 100644 (file)
@@ -454,6 +454,17 @@ L: linux-rdma@vger.kernel.org
 S:     Maintained
 F:     drivers/infiniband/hw/amso1100/
 
+ANALOG DEVICES INC ASOC DRIVERS
+L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+W:     http://blackfin.uclinux.org/
+S:     Supported
+F:     sound/soc/blackfin/*
+F:     sound/soc/codecs/ad1*
+F:     sound/soc/codecs/adau*
+F:     sound/soc/codecs/adav*
+F:     sound/soc/codecs/ssm*
+
 AOA (Apple Onboard Audio) ALSA DRIVER
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linuxppc-dev@lists.ozlabs.org
@@ -951,6 +962,23 @@ W: http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/mach-s3c6410/
 
+ARM/S5P ARM ARCHITECTURES
+M:     Kukjin Kim <kgene.kim@samsung.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-s5p*/
+
+ARM/SAMSUNG S5P SERIES FIMC SUPPORT
+M:     Kyungmin Park <kyungmin.park@samsung.com>
+M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
+L:     linux-arm-kernel@lists.infradead.org
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     arch/arm/plat-s5p/dev-fimc*
+F:     arch/arm/plat-samsung/include/plat/*fimc*
+F:     drivers/media/video/s5p-fimc/
+
 ARM/SHMOBILE ARM ARCHITECTURE
 M:     Paul Mundt <lethal@linux-sh.org>
 M:     Magnus Damm <magnus.damm@gmail.com>
@@ -962,11 +990,23 @@ S:        Supported
 F:     arch/arm/mach-shmobile/
 F:     drivers/sh/
 
+ARM/TELECHIPS ARM ARCHITECTURE
+M:     "Hans J. Koch" <hjk@linutronix.de>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/plat-tcc/
+F:     arch/arm/mach-tcc8k/
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 
+ARM/TETON BGA MACHINE SUPPORT
+M:     Mark F. Brown <mark.brown314@gmail.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+
 ARM/THECUS N2100 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1124,7 +1164,7 @@ ATLX ETHERNET DRIVERS
 M:     Jay Cliburn <jcliburn@gmail.com>
 M:     Chris Snook <chris.snook@gmail.com>
 M:     Jie Yang <jie.yang@atheros.com>
-L:     atl1-devel@lists.sourceforge.net
+L:     netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/atl1
 W:     http://atl1.sourceforge.net
 S:     Maintained
@@ -1209,7 +1249,7 @@ F:        drivers/auxdisplay/
 F:     include/linux/cfag12864b.h
 
 AVR32 ARCHITECTURE
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
 W:     http://www.atmel.com/products/AVR32/
 W:     http://avr32linux.org/
 W:     http://avrfreaks.net/
@@ -1217,7 +1257,7 @@ S:        Supported
 F:     arch/avr32/
 
 AVR32/AT32AP MACHINE SUPPORT
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
 S:     Supported
 F:     arch/avr32/mach-at32ap/
 
@@ -1434,6 +1474,16 @@ S:       Maintained
 F:     Documentation/video4linux/cafe_ccic
 F:     drivers/media/video/cafe_ccic*
 
+CAIF NETWORK LAYER
+M:     Sjur Braendeland <sjur.brandeland@stericsson.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     Documentation/networking/caif/
+F:     drivers/net/caif/
+F:     include/linux/caif/
+F:     include/net/caif/
+F:     net/caif/
+
 CALGARY x86-64 IOMMU
 M:     Muli Ben-Yehuda <muli@il.ibm.com>
 M:     "Jon D. Mason" <jdmason@kudzu.us>
@@ -1489,6 +1539,8 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 S:     Supported
 F:     Documentation/filesystems/ceph.txt
 F:     fs/ceph
+F:     net/ceph
+F:     include/linux/ceph
 
 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
 M:     David Vrabel <david.vrabel@csr.com>
@@ -1665,8 +1717,7 @@ F:        kernel/cgroup*
 F:     mm/*cgroup*
 
 CORETEMP HARDWARE MONITORING DRIVER
-M:     Rudolf Marek <r.marek@assembler.cz>
-M:     Huaxu Wan <huaxu.wan@intel.com>
+M:     Fenghua Yu <fenghua.yu@intel.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/coretemp
@@ -2179,6 +2230,12 @@ W:       http://acpi4asus.sf.net
 S:     Maintained
 F:     drivers/platform/x86/eeepc-laptop.c
 
+EFIFB FRAMEBUFFER DRIVER
+L:     linux-fbdev@vger.kernel.org
+M:     Peter Jones <pjones@redhat.com>
+S:     Maintained
+F:     drivers/video/efifb.c
+
 EFS FILESYSTEM
 W:     http://aeschi.ch.eu.org/efs/
 S:     Orphan
@@ -2191,6 +2248,12 @@ L:       linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/ehca/
 
+EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
+M:     Breno Leitao <leitao@linux.vnet.ibm.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ehea/
+
 EMBEDDED LINUX
 M:     Paul Gortmaker <paul.gortmaker@windriver.com>
 M:     Matt Mackall <mpm@selenic.com>
@@ -2286,6 +2349,12 @@ S:       Maintained
 F:     Documentation/hwmon/f71805f
 F:     drivers/hwmon/f71805f.c
 
+FANOTIFY
+M:     Eric Paris <eparis@redhat.com>
+S:     Maintained
+F:     fs/notify/fanotify/
+F:     include/linux/fanotify.h
+
 FARSYNC SYNCHRONOUS DRIVER
 M:     Kevin Curtis <kevin.curtis@farsite.co.uk>
 W:     http://www.farsite.co.uk/
@@ -2490,7 +2559,7 @@ S:        Supported
 F:     drivers/scsi/gdt*
 
 GENERIC GPIO I2C DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Haavard Skinnemoen <hskinnemoen@gmail.com>
 S:     Supported
 F:     drivers/i2c/busses/i2c-gpio.c
 F:     include/linux/i2c-gpio.h
@@ -2625,9 +2694,14 @@ S:       Maintained
 F:     drivers/media/video/gspca/
 
 HARDWARE MONITORING
+M:     Jean Delvare <khali@linux-fr.org>
+M:     Guenter Roeck <guenter.roeck@ericsson.com>
 L:     lm-sensors@lm-sensors.org
 W:     http://www.lm-sensors.org/
-S:     Orphan
+T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
+T:     quilt kernel.org/pub/linux/kernel/people/groeck/linux-staging/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
+S:     Maintained
 F:     Documentation/hwmon/
 F:     drivers/hwmon/
 F:     include/linux/hwmon*.h
@@ -2765,11 +2839,6 @@ S:       Maintained
 F:     arch/x86/kernel/hpet.c
 F:     arch/x86/include/asm/hpet.h
 
-HPET:  ACPI
-M:     Bob Picco <bob.picco@hp.com>
-S:     Maintained
-F:     drivers/char/hpet.c
-
 HPFS FILESYSTEM
 M:     Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
 W:     http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
@@ -3018,16 +3087,27 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ixp2000/
 
-INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe)
+INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
 M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
 M:     Jesse Brandeburg <jesse.brandeburg@intel.com>
 M:     Bruce Allan <bruce.w.allan@intel.com>
-M:     Alex Duyck <alexander.h.duyck@intel.com>
+M:     Carolyn Wyborny <carolyn.wyborny@intel.com>
+M:     Don Skidmore <donald.c.skidmore@intel.com>
+M:     Greg Rose <gregory.v.rose@intel.com>
 M:     PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
+M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://e1000.sourceforge.net/
 S:     Supported
+F:     Documentation/networking/e100.txt
+F:     Documentation/networking/e1000.txt
+F:     Documentation/networking/e1000e.txt
+F:     Documentation/networking/igb.txt
+F:     Documentation/networking/igbvf.txt
+F:     Documentation/networking/ixgb.txt
+F:     Documentation/networking/ixgbe.txt
+F:     Documentation/networking/ixgbevf.txt
 F:     drivers/net/e100.c
 F:     drivers/net/e1000/
 F:     drivers/net/e1000e/
@@ -3035,6 +3115,7 @@ F:        drivers/net/igb/
 F:     drivers/net/igbvf/
 F:     drivers/net/ixgb/
 F:     drivers/net/ixgbe/
+F:     drivers/net/ixgbevf/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
 L:     linux-wireless@vger.kernel.org
@@ -3095,7 +3176,7 @@ F:        drivers/net/ioc3-eth.c
 
 IOC3 SERIAL DRIVER
 M:     Pat Gefre <pfg@sgi.com>
-L:     linux-mips@linux-mips.org
+L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/serial/ioc3_serial.c
 
@@ -3172,6 +3253,12 @@ F:       drivers/net/irda/
 F:     include/net/irda/
 F:     net/irda/
 
+IRQ SUBSYSTEM
+M:     Thomas Gleixner <tglx@linutronix.de>
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git irq/core
+F:     kernel/irq/
+
 ISAPNP
 M:     Jaroslav Kysela <perex@perex.cz>
 S:     Maintained
@@ -3382,7 +3469,7 @@ F:        drivers/s390/kvm/
 
 KEXEC
 M:     Eric Biederman <ebiederm@xmission.com>
-W:     http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
+W:     http://kernel.org/pub/linux/utils/kernel/kexec/
 L:     kexec@lists.infradead.org
 S:     Maintained
 F:     include/linux/kexec.h
@@ -3478,7 +3565,7 @@ LGUEST
 M:     Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@lists.ozlabs.org
 W:     http://lguest.ozlabs.org/
-S:     Maintained
+S:     Odd Fixes
 F:     Documentation/lguest/
 F:     arch/x86/lguest/
 F:     drivers/lguest/
@@ -3743,9 +3830,8 @@ W:        http://www.syskonnect.com
 S:     Supported
 
 MATROX FRAMEBUFFER DRIVER
-M:     Petr Vandrovec <vandrove@vc.cvut.cz>
 L:     linux-fbdev@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/video/matrox/matroxfb_*
 F:     include/linux/matroxfb.h
 
@@ -3869,10 +3955,8 @@ F:       Documentation/serial/moxa-smartio
 F:     drivers/char/mxser.*
 
 MSI LAPTOP SUPPORT
-M:     Lennart Poettering <mzxreary@0pointer.de>
+M:     Lee, Chun-Yi <jlee@novell.com>
 L:     platform-driver-x86@vger.kernel.org
-W:     https://tango.0pointer.de/mailman/listinfo/s270-linux
-W:     http://0pointer.de/lennart/tchibo.html
 S:     Maintained
 F:     drivers/platform/x86/msi-laptop.c
 
@@ -3889,8 +3973,10 @@ S:       Supported
 F:     drivers/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
-S:     Orphan
+M:     Chris Ball <cjb@laptop.org>
 L:     linux-mmc@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
+S:     Maintained
 F:     drivers/mmc/
 F:     include/linux/mmc/
 
@@ -3907,13 +3993,12 @@ F:      Documentation/sound/oss/MultiSound
 F:     sound/oss/msnd*
 
 MULTITECH MULTIPORT CARD (ISICOM)
-M:     Jiri Slaby <jirislaby@gmail.com>
-S:     Maintained
+S:     Orphan
 F:     drivers/char/isicom.c
 F:     include/linux/isicom.h
 
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
-M:     Felipe Balbi <felipe.balbi@nokia.com>
+M:     Felipe Balbi <balbi@ti.com>
 L:     linux-usb@vger.kernel.org
 T:     git git://gitorious.org/usb/usb.git
 S:     Maintained
@@ -3933,8 +4018,8 @@ S:        Maintained
 F:     drivers/net/natsemi.c
 
 NCP FILESYSTEM
-M:     Petr Vandrovec <vandrove@vc.cvut.cz>
-S:     Maintained
+M:     Petr Vandrovec <petr@vandrovec.name>
+S:     Odd Fixes
 F:     fs/ncpfs/
 
 NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
@@ -4211,7 +4296,7 @@ S:        Maintained
 F:     drivers/char/hw_random/omap-rng.c
 
 OMAP USB SUPPORT
-M:     Felipe Balbi <felipe.balbi@nokia.com>
+M:     Felipe Balbi <balbi@ti.com>
 M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 L:     linux-omap@vger.kernel.org
@@ -4588,7 +4673,7 @@ F:        include/linux/preempt.h
 PRISM54 WIRELESS DRIVER
 M:     "Luis R. Rodriguez" <mcgrof@gmail.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://prism54.org
+W:     http://wireless.kernel.org/en/users/Drivers/p54
 S:     Obsolete
 F:     drivers/net/wireless/prism54/
 
@@ -4740,6 +4825,15 @@ F:       fs/qnx4/
 F:     include/linux/qnx4_fs.h
 F:     include/linux/qnxtypes.h
 
+RADOS BLOCK DEVICE (RBD)
+F:     include/linux/qnxtypes.h
+M:     Yehuda Sadeh <yehuda@hq.newdream.net>
+M:     Sage Weil <sage@newdream.net>
+M:     ceph-devel@vger.kernel.org
+S:     Supported
+F:     drivers/block/rbd.c
+F:     drivers/block/rbd_types.h
+
 RADEON FRAMEBUFFER DISPLAY DRIVER
 M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
 L:     linux-fbdev@vger.kernel.org
@@ -4789,6 +4883,7 @@ RCUTORTURE MODULE
 M:     Josh Triplett <josh@freedesktop.org>
 M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 S:     Supported
+T:     git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:     Documentation/RCU/torture.txt
 F:     kernel/rcutorture.c
 
@@ -4813,6 +4908,7 @@ M:        Dipankar Sarma <dipankar@in.ibm.com>
 M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 W:     http://www.rdrop.com/users/paulmck/rclock/
 S:     Supported
+T:     git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:     Documentation/RCU/
 F:     include/linux/rcu*
 F:     include/linux/srcu*
@@ -4820,12 +4916,10 @@ F:      kernel/rcu*
 F:     kernel/srcu*
 X:     kernel/rcutorture.c
 
-REAL TIME CLOCK DRIVER
+REAL TIME CLOCK DRIVER (LEGACY)
 M:     Paul Gortmaker <p_gortmaker@yahoo.com>
 S:     Maintained
-F:     Documentation/rtc.txt
-F:     drivers/rtc/
-F:     include/linux/rtc.h
+F:     drivers/char/rtc.c
 
 REAL TIME CLOCK (RTC) SUBSYSTEM
 M:     Alessandro Zummo <a.zummo@towertech.it>
@@ -4965,6 +5059,12 @@ F:       drivers/media/common/saa7146*
 F:     drivers/media/video/*7146*
 F:     include/media/*7146*
 
+SAMSUNG AUDIO (ASoC) DRIVERS
+M:     Jassi Brar <jassi.brar@samsung.com>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:     Supported
+F:     sound/soc/s3c24xx
+
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:     Huang Shijie <shijie8@gmail.com>
 M:     Kang Yong <kangyong@telegent.com>
@@ -5062,8 +5162,10 @@ S:       Maintained
 F:     drivers/mmc/host/sdricoh_cs.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-S:     Orphan
+M:     Chris Ball <cjb@laptop.org>
 L:     linux-mmc@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
+S:     Maintained
 F:     drivers/mmc/host/sdhci.*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
@@ -6405,8 +6507,10 @@ F:       include/linux/wm97xx.h
 WOLFSON MICROELECTRONICS DRIVERS
 M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 M:     Ian Lartey <ian@opensource.wolfsonmicro.com>
+M:     Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+T:     git git://opensource.wolfsonmicro.com/linux-2.6-asoc
 T:     git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
-W:     http://opensource.wolfsonmicro.com/node/8
+W:     http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:     Supported
 F:     Documentation/hwmon/wm83??
 F:     drivers/leds/leds-wm83*.c
index 2c0299f18d71f934af5cbc03fc047b99ce3d800c..3e438055a92c503d48858761d56e00bcd9848276 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 36
-EXTRAVERSION = -rc2
-NAME = Sheep on Meth
+EXTRAVERSION =
+NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -554,8 +554,15 @@ endif
 ifdef CONFIG_FRAME_POINTER
 KBUILD_CFLAGS  += -fno-omit-frame-pointer -fno-optimize-sibling-calls
 else
+# Some targets (ARM with Thumb2, for example), can't be built with frame
+# pointers.  For those, we don't have FUNCTION_TRACER automatically
+# select FRAME_POINTER.  However, FUNCTION_TRACER adds -pg, and this is
+# incompatible with -fomit-frame-pointer with current GCC, so we don't use
+# -fomit-frame-pointer with FUNCTION_TRACER.
+ifndef CONFIG_FUNCTION_TRACER
 KBUILD_CFLAGS  += -fomit-frame-pointer
 endif
+endif
 
 ifdef CONFIG_DEBUG_INFO
 KBUILD_CFLAGS  += -g
@@ -568,6 +575,12 @@ endif
 
 ifdef CONFIG_FUNCTION_TRACER
 KBUILD_CFLAGS  += -pg
+ifdef CONFIG_DYNAMIC_FTRACE
+       ifdef CONFIG_HAVE_C_RECORDMCOUNT
+               BUILD_C_RECORDMCOUNT := y
+               export BUILD_C_RECORDMCOUNT
+       endif
+endif
 endif
 
 # We trigger additional mismatches with less inlining
@@ -591,6 +604,11 @@ KBUILD_CFLAGS      += $(call cc-option,-fno-strict-overflow)
 # conserve stack if available
 KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)
 
+# check for 'asm goto'
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
+       KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+endif
+
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
 # But warn user when we do so
 warn-assign = \
@@ -1408,8 +1426,8 @@ checkstack:
        $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
        $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
 
-kernelrelease: include/config/kernel.release
-       @echo $(KERNELRELEASE)
+kernelrelease:
+       @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
 
 kernelversion:
        @echo $(KERNELVERSION)
index 4877a8c8ee1697599289f35107824f95ba8daf84..53d7f619a1b9b46643c59cd3c7d4ace354148c20 100644 (file)
@@ -32,8 +32,9 @@ config HAVE_OPROFILE
 
 config KPROBES
        bool "Kprobes"
-       depends on KALLSYMS && MODULES
+       depends on MODULES
        depends on HAVE_KPROBES
+       select KALLSYMS
        help
          Kprobes allows you to trap at almost any kernel address and
          execute a callback function.  register_kprobe() establishes
@@ -45,7 +46,6 @@ config OPTPROBES
        def_bool y
        depends on KPROBES && HAVE_OPTPROBES
        depends on !PREEMPT
-       select KALLSYMS_ALL
 
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
        bool
@@ -158,4 +158,7 @@ config HAVE_PERF_EVENTS_NMI
          subsystem.  Also has support for calculating CPU cycle events
          to determine how many clock cycles in a given period.
 
+config HAVE_ARCH_JUMP_LABEL
+       bool
+
 source "kernel/gcov/Kconfig"
index b9647bb66d1388d9c13503748252c2a1df4ac830..d04ccd73af45f6487f442a0dba26921db884e218 100644 (file)
@@ -9,6 +9,7 @@ config ALPHA
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_DMA_ATTRS
        help
index f199e69a5d0b0a83fd39e7d5464a5fa439c79265..ad368a93a46a6c5c7e1bf0d25ab17f08ebc19fd8 100644 (file)
@@ -17,7 +17,6 @@
 # define L1_CACHE_SHIFT     5
 #endif
 
-#define L1_CACHE_ALIGN(x)  (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define SMP_CACHE_BYTES    L1_CACHE_BYTES
 
 #endif
index 01d71e1c8a9eb6df57fe8bc13e1f94f634a8eaf7..012f1243b1c1a0024af9cffe0afdfc204f4dcf11 100644 (file)
@@ -43,6 +43,8 @@ extern void smp_imb(void);
 /* ??? Ought to use this in arch/alpha/kernel/signal.c too.  */
 
 #ifndef CONFIG_SMP
+#include <linux/sched.h>
+
 extern void __load_new_mm_context(struct mm_struct *);
 static inline void
 flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
diff --git a/arch/alpha/include/asm/irqflags.h b/arch/alpha/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..299bbc7
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __ALPHA_IRQFLAGS_H
+#define __ALPHA_IRQFLAGS_H
+
+#include <asm/system.h>
+
+#define IPL_MIN                0
+#define IPL_SW0                1
+#define IPL_SW1                2
+#define IPL_DEV0       3
+#define IPL_DEV1       4
+#define IPL_TIMER      5
+#define IPL_PERF       6
+#define IPL_POWERFAIL  6
+#define IPL_MCHECK     7
+#define IPL_MAX                7
+
+#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
+#undef IPL_MIN
+#define IPL_MIN                __min_ipl
+extern int __min_ipl;
+#endif
+
+#define getipl()               (rdps() & 7)
+#define setipl(ipl)            ((void) swpipl(ipl))
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       return rdps();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       setipl(IPL_MAX);
+       barrier();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = swpipl(IPL_MAX);
+       barrier();
+       return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       barrier();
+       setipl(IPL_MIN);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       barrier();
+       setipl(flags);
+       barrier();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return flags == IPL_MAX;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(getipl());
+}
+
+#endif /* __ALPHA_IRQFLAGS_H */
index 4157cd3c44a96d2811410b334a35f11923ba6fbf..fe792ca818f64c4d9954e8b62e5f8064a5d5777e 100644 (file)
@@ -1,11 +1,6 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-/* Alpha only supports software events through this interface. */
-extern void set_perf_event_pending(void);
-
-#define PERF_EVENT_INDEX_OFFSET 0
-
 #ifdef CONFIG_PERF_EVENTS
 extern void init_hw_perf_events(void);
 #else
index 5aa40cca4f2356ea12a62e8576d50303a2b704b5..9f78e693463755d8deb1194476e6adf12b673f4f 100644 (file)
@@ -259,34 +259,6 @@ __CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
 __CALL_PAL_W1(wrusp, unsigned long);
 __CALL_PAL_W1(wrvptptr, unsigned long);
 
-#define IPL_MIN                0
-#define IPL_SW0                1
-#define IPL_SW1                2
-#define IPL_DEV0       3
-#define IPL_DEV1       4
-#define IPL_TIMER      5
-#define IPL_PERF       6
-#define IPL_POWERFAIL  6
-#define IPL_MCHECK     7
-#define IPL_MAX                7
-
-#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
-#undef IPL_MIN
-#define IPL_MIN                __min_ipl
-extern int __min_ipl;
-#endif
-
-#define getipl()               (rdps() & 7)
-#define setipl(ipl)            ((void) swpipl(ipl))
-
-#define local_irq_disable()                    do { setipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_enable()                     do { barrier(); setipl(IPL_MIN); } while(0)
-#define local_save_flags(flags)        ((flags) = rdps())
-#define local_irq_save(flags)  do { (flags) = swpipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_restore(flags)       do { barrier(); setipl(flags); barrier(); } while(0)
-
-#define irqs_disabled()        (getipl() == IPL_MAX)
-
 /*
  * TB routines..
  */
index 804e5311c84188fbc14a62b7afb97bc35a232003..058937bf5a77718983126f2ab3813a023cb8c1d0 100644 (file)
 #define __NR_pwritev                   491
 #define __NR_rt_tgsigqueueinfo         492
 #define __NR_perf_event_open           493
+#define __NR_fanotify_init             494
+#define __NR_fanotify_mark             495
+#define __NR_prlimit64                 496
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS                    494
+#define NR_SYSCALLS                    497
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 /* "Conditional" syscalls.  What we want is
 
index b45d913a51c368881b4311d1f1887566829b09a8..6d159cee5f2f43a48bc9aac8355069a3e588ef7f 100644 (file)
@@ -73,8 +73,6 @@
        ldq     $20, HAE_REG($19);      \
        stq     $21, HAE_CACHE($19);    \
        stq     $21, 0($20);            \
-       ldq     $0, 0($sp);             \
-       ldq     $1, 8($sp);             \
 99:;                                   \
        ldq     $19, 72($sp);           \
        ldq     $20, 80($sp);           \
@@ -316,19 +314,24 @@ ret_from_sys_call:
        cmovne  $26, 0, $19             /* $19 = 0 => non-restartable */
        ldq     $0, SP_OFF($sp)
        and     $0, 8, $0
-       beq     $0, restore_all
-ret_from_reschedule:
+       beq     $0, ret_to_kernel
+ret_to_user:
        /* Make sure need_resched and sigpending don't change between
                sampling and the rti.  */
        lda     $16, 7
        call_pal PAL_swpipl
        ldl     $5, TI_FLAGS($8)
        and     $5, _TIF_WORK_MASK, $2
-       bne     $5, work_pending
+       bne     $2, work_pending
 restore_all:
        RESTORE_ALL
        call_pal PAL_rti
 
+ret_to_kernel:
+       lda     $16, 7
+       call_pal PAL_swpipl
+       br restore_all
+
        .align 3
 $syscall_error:
        /*
@@ -363,7 +366,7 @@ $ret_success:
  *       $8: current.
  *      $19: The old syscall number, or zero if this is not a return
  *           from a syscall that errored and is possibly restartable.
- *      $20: Error indication.
+ *      $20: The old a3 value
  */
 
        .align  4
@@ -392,12 +395,18 @@ $work_resched:
 
 $work_notifysig:
        mov     $sp, $16
-       b     $1, do_switch_stack
+       bsr     $1, do_switch_stack
        mov     $sp, $17
        mov     $5, $18
+       mov     $19, $9         /* save old syscall number */
+       mov     $20, $10        /* save old a3 */
+       and     $5, _TIF_SIGPENDING, $2
+       cmovne  $2, 0, $9       /* we don't want double syscall restarts */
        jsr     $26, do_notify_resume
+       mov     $9, $19
+       mov     $10, $20
        bsr     $1, undo_switch_stack
-       br      restore_all
+       br      ret_to_user
 .end work_pending
 
 /*
@@ -430,6 +439,7 @@ strace:
        beq     $1, 1f
        ldq     $27, 0($2)
 1:     jsr     $26, ($27), sys_gettimeofday
+ret_from_straced:
        ldgp    $gp, 0($26)
 
        /* check return.. */
@@ -650,7 +660,7 @@ kernel_thread:
        /* We don't actually care for a3 success widgetry in the kernel.
           Not for positive errno values.  */
        stq     $0, 0($sp)              /* $0 */
-       br      restore_all
+       br      ret_to_kernel
 .end kernel_thread
 
 /*
@@ -757,11 +767,15 @@ sys_vfork:
        .ent    sys_sigreturn
 sys_sigreturn:
        .prologue 0
+       lda     $9, ret_from_straced
+       cmpult  $26, $9, $9
        mov     $sp, $17
        lda     $18, -SWITCH_STACK_SIZE($sp)
        lda     $sp, -SWITCH_STACK_SIZE($sp)
        jsr     $26, do_sigreturn
-       br      $1, undo_switch_stack
+       bne     $9, 1f
+       jsr     $26, syscall_trace
+1:     br      $1, undo_switch_stack
        br      ret_from_sys_call
 .end sys_sigreturn
 
@@ -770,46 +784,18 @@ sys_sigreturn:
        .ent    sys_rt_sigreturn
 sys_rt_sigreturn:
        .prologue 0
+       lda     $9, ret_from_straced
+       cmpult  $26, $9, $9
        mov     $sp, $17
        lda     $18, -SWITCH_STACK_SIZE($sp)
        lda     $sp, -SWITCH_STACK_SIZE($sp)
        jsr     $26, do_rt_sigreturn
-       br      $1, undo_switch_stack
+       bne     $9, 1f
+       jsr     $26, syscall_trace
+1:     br      $1, undo_switch_stack
        br      ret_from_sys_call
 .end sys_rt_sigreturn
 
-       .align  4
-       .globl  sys_sigsuspend
-       .ent    sys_sigsuspend
-sys_sigsuspend:
-       .prologue 0
-       mov     $sp, $17
-       br      $1, do_switch_stack
-       mov     $sp, $18
-       subq    $sp, 16, $sp
-       stq     $26, 0($sp)
-       jsr     $26, do_sigsuspend
-       ldq     $26, 0($sp)
-       lda     $sp, SWITCH_STACK_SIZE+16($sp)
-       ret
-.end sys_sigsuspend
-
-       .align  4
-       .globl  sys_rt_sigsuspend
-       .ent    sys_rt_sigsuspend
-sys_rt_sigsuspend:
-       .prologue 0
-       mov     $sp, $18
-       br      $1, do_switch_stack
-       mov     $sp, $19
-       subq    $sp, 16, $sp
-       stq     $26, 0($sp)
-       jsr     $26, do_rt_sigsuspend
-       ldq     $26, 0($sp)
-       lda     $sp, SWITCH_STACK_SIZE+16($sp)
-       ret
-.end sys_rt_sigsuspend
-
        .align  4
        .globl  sys_sethae
        .ent    sys_sethae
@@ -928,15 +914,6 @@ sys_execve:
        jmp     $31, do_sys_execve
 .end sys_execve
 
-       .align  4
-       .globl  osf_sigprocmask
-       .ent    osf_sigprocmask
-osf_sigprocmask:
-       .prologue 0
-       mov     $sp, $18
-       jmp     $31, sys_osf_sigprocmask
-.end osf_sigprocmask
-
        .align  4
        .globl  alpha_ni_syscall
        .ent    alpha_ni_syscall
index 8ca6345bf13167842d3c0fb60637e51e18e3db93..253cf1a87481e815ad9a724dde1fef51b5616d09 100644 (file)
@@ -90,11 +90,13 @@ static int
 ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn, 
               u64 c_stat, u64 c_sts, int print)
 {
-       char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN",
-                              "MEMORY", "BCACHE", "DCACHE", 
-                              "BCACHE PROBE", "BCACHE PROBE" };
-       char *streamname[] = { "D", "I" };
-       char *bitsname[] = { "SINGLE", "DOUBLE" };
+       static const char * const sourcename[] = {
+               "UNKNOWN", "UNKNOWN", "UNKNOWN",
+               "MEMORY", "BCACHE", "DCACHE",
+               "BCACHE PROBE", "BCACHE PROBE"
+       };
+       static const char * const streamname[] = { "D", "I" };
+       static const char * const bitsname[] = { "SINGLE", "DOUBLE" };
        int status = MCHK_DISPOSITION_REPORT;
        int source = -1, stream = -1, bits = -1;
 
index 52a79dfc13c6774ec1f88f2e288af1a42f774f51..648ae88aeb8ae0cce7dcedbe215bf56417e5eebc 100644 (file)
@@ -109,7 +109,7 @@ marvel_print_err_cyc(u64 err_cyc)
 #define IO7__ERR_CYC__CYCLE__M (0x7)
 
        printk("%s        Packet In Error: %s\n"
-              "%s        Error in %s, cycle %ld%s%s\n",
+              "%s        Error in %s, cycle %lld%s%s\n",
               err_print_prefix, 
               packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)],
               err_print_prefix,
@@ -313,7 +313,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym)
        }
 
        printk("%s      Up Hose Garbage Symptom:\n"
-              "%s        Source Port: %ld - Dest PID: %ld - OpCode: %s\n", 
+              "%s        Source Port: %lld - Dest PID: %lld - OpCode: %s\n",
               err_print_prefix,
               err_print_prefix, 
               EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT),
@@ -552,7 +552,7 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt)
 #define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M   (0xfff)
 
        printk("%s      Split Completion Error:\n"      
-              "%s         Source (Bus:Dev:Func): %ld:%ld:%ld\n",
+              "%s         Source (Bus:Dev:Func): %lld:%lld:%lld\n",
               err_print_prefix,
               err_print_prefix,
               EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS),
@@ -589,22 +589,23 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt)
 static void
 marvel_print_pox_trans_sum(u64 trans_sum)
 {
-       char *pcix_cmd[] = { "Interrupt Acknowledge",
-                            "Special Cycle",
-                            "I/O Read",
-                            "I/O Write",
-                            "Reserved",
-                            "Reserved / Device ID Message",
-                            "Memory Read",
-                            "Memory Write",
-                            "Reserved / Alias to Memory Read Block",
-                            "Reserved / Alias to Memory Write Block",
-                            "Configuration Read",
-                            "Configuration Write",
-                            "Memory Read Multiple / Split Completion",
-                            "Dual Address Cycle",
-                            "Memory Read Line / Memory Read Block",
-                            "Memory Write and Invalidate / Memory Write Block"
+       static const char * const pcix_cmd[] = {
+               "Interrupt Acknowledge",
+               "Special Cycle",
+               "I/O Read",
+               "I/O Write",
+               "Reserved",
+               "Reserved / Device ID Message",
+               "Memory Read",
+               "Memory Write",
+               "Reserved / Alias to Memory Read Block",
+               "Reserved / Alias to Memory Write Block",
+               "Configuration Read",
+               "Configuration Write",
+               "Memory Read Multiple / Split Completion",
+               "Dual Address Cycle",
+               "Memory Read Line / Memory Read Block",
+               "Memory Write and Invalidate / Memory Write Block"
        };
 
 #define IO7__POX_TRANSUM__PCI_ADDR__S          (0)
index f7ed97ce0dfd72458dde026292b89702be518477..c3b3781a03de01045ebd270319173ae2b5d347ee 100644 (file)
@@ -75,8 +75,12 @@ titan_parse_p_serror(int which, u64 serror, int print)
        int status = MCHK_DISPOSITION_REPORT;
 
 #ifdef CONFIG_VERBOSE_MCHECK
-       char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
-       char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
+       static const char * const serror_src[] = {
+               "GPCI", "APCI", "AGP HP", "AGP LP"
+       };
+       static const char * const serror_cmd[] = {
+               "DMA Read", "DMA RMW", "SGTE Read", "Reserved"
+       };
 #endif /* CONFIG_VERBOSE_MCHECK */
 
 #define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0)
@@ -140,14 +144,15 @@ titan_parse_p_perror(int which, int port, u64 perror, int print)
        int status = MCHK_DISPOSITION_REPORT;
 
 #ifdef CONFIG_VERBOSE_MCHECK
-       char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
-                              "I/O Read",              "I/O Write",
-                              "Reserved",              "Reserved",
-                              "Memory Read",           "Memory Write",
-                              "Reserved",              "Reserved",
-                              "Configuration Read",    "Configuration Write",
-                              "Memory Read Multiple",  "Dual Address Cycle",
-                              "Memory Read Line","Memory Write and Invalidate"
+       static const char * const perror_cmd[] = {
+               "Interrupt Acknowledge", "Special Cycle",
+               "I/O Read",             "I/O Write",
+               "Reserved",             "Reserved",
+               "Memory Read",          "Memory Write",
+               "Reserved",             "Reserved",
+               "Configuration Read",   "Configuration Write",
+               "Memory Read Multiple", "Dual Address Cycle",
+               "Memory Read Line",     "Memory Write and Invalidate"
        };
 #endif /* CONFIG_VERBOSE_MCHECK */
 
@@ -273,11 +278,11 @@ titan_parse_p_agperror(int which, u64 agperror, int print)
        int cmd, len;
        unsigned long addr;
 
-       char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
-                                "Write (low-priority)",
-                                "Write (high-priority)",
-                                "Reserved",            "Reserved",
-                                "Flush",               "Fence"
+       static const char * const agperror_cmd[] = {
+               "Read (low-priority)",  "Read (high-priority)",
+               "Write (low-priority)", "Write (high-priority)",
+               "Reserved",             "Reserved",
+               "Flush",                "Fence"
        };
 #endif /* CONFIG_VERBOSE_MCHECK */
 
index fb58150a7e8f4fb667f10ac7ae0a772b021f9b53..547e8b84b2f794ab546aca3b1927c80bdc1104bf 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/syscalls.h>
 #include <linux/unistd.h>
@@ -69,7 +68,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start,
 {
        struct mm_struct *mm;
 
-       lock_kernel();
        mm = current->mm;
        mm->end_code = bss_start + bss_len;
        mm->start_brk = bss_start + bss_len;
@@ -78,7 +76,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start,
        printk("set_program_attributes(%lx %lx %lx %lx)\n",
                text_start, text_len, bss_start, bss_len);
 #endif
-       unlock_kernel();
        return 0;
 }
 
@@ -252,7 +249,7 @@ SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
 
        retval = user_path(pathname, &path);
        if (!retval) {
-               retval = do_osf_statfs(&path buffer, bufsiz);
+               retval = do_osf_statfs(&path, buffer, bufsiz);
                path_put(&path);
        }
        return retval;
@@ -517,7 +514,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code,
        long error;
        int __user *min_buf_size_ptr;
 
-       lock_kernel();
        switch (code) {
        case PL_SET:
                if (get_user(error, &args->set.nbytes))
@@ -547,7 +543,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code,
                error = -EOPNOTSUPP;
                break;
        };
-       unlock_kernel();
        return error;
 }
 
@@ -594,7 +589,7 @@ SYSCALL_DEFINE2(osf_sigstack, struct sigstack __user *, uss,
 
 SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
 {
-       char *sysinfo_table[] = {
+       const char *sysinfo_table[] = {
                utsname()->sysname,
                utsname()->nodename,
                utsname()->release,
@@ -606,7 +601,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
                "dummy",        /* secure RPC domain */
        };
        unsigned long offset;
-       char *res;
+       const char *res;
        long len, err = -EINVAL;
 
        offset = command-1;
index 738fc824e2ea373f85b3ae04fb7eb1346ecacdac..b899e95f79fdb424ea9b07d31153edb0e824ac8e 100644 (file)
@@ -66,7 +66,7 @@ static int pci_mmap_resource(struct kobject *kobj,
 {
        struct pci_dev *pdev = to_pci_dev(container_of(kobj,
                                                       struct device, kobj));
-       struct resource *res = (struct resource *)attr->private;
+       struct resource *res = attr->private;
        enum pci_mmap_state mmap_type;
        struct pci_bus_region bar;
        int i;
index 51c39fa41693bcbcbc880130a8af6e0ce411c2dc..1cc49683fb69b2a5f96639e71a2f1af821479e77 100644 (file)
@@ -241,20 +241,20 @@ static inline unsigned long alpha_read_pmc(int idx)
 static int alpha_perf_event_set_period(struct perf_event *event,
                                struct hw_perf_event *hwc, int idx)
 {
-       long left = atomic64_read(&hwc->period_left);
+       long left = local64_read(&hwc->period_left);
        long period = hwc->sample_period;
        int ret = 0;
 
        if (unlikely(left <= -period)) {
                left = period;
-               atomic64_set(&hwc->period_left, left);
+               local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                ret = 1;
        }
 
        if (unlikely(left <= 0)) {
                left += period;
-               atomic64_set(&hwc->period_left, left);
+               local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                ret = 1;
        }
@@ -269,7 +269,7 @@ static int alpha_perf_event_set_period(struct perf_event *event,
        if (left > (long)alpha_pmu->pmc_max_period[idx])
                left = alpha_pmu->pmc_max_period[idx];
 
-       atomic64_set(&hwc->prev_count, (unsigned long)(-left));
+       local64_set(&hwc->prev_count, (unsigned long)(-left));
 
        alpha_write_pmc(idx, (unsigned long)(-left));
 
@@ -300,14 +300,14 @@ static unsigned long alpha_perf_event_update(struct perf_event *event,
        long delta;
 
 again:
-       prev_raw_count = atomic64_read(&hwc->prev_count);
+       prev_raw_count = local64_read(&hwc->prev_count);
        new_raw_count = alpha_read_pmc(idx);
 
-       if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
                             new_raw_count) != prev_raw_count)
                goto again;
 
-       delta = (new_raw_count  - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
+       delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
 
        /* It is possible on very rare occasions that the PMC has overflowed
         * but the interrupt is yet to come.  Detect and fix this situation.
@@ -316,8 +316,8 @@ again:
                delta += alpha_pmu->pmc_max_period[idx] + 1;
        }
 
-       atomic64_add(delta, &event->count);
-       atomic64_sub(delta, &hwc->period_left);
+       local64_add(delta, &event->count);
+       local64_sub(delta, &hwc->period_left);
 
        return new_raw_count;
 }
@@ -402,14 +402,13 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)
                struct hw_perf_event *hwc = &pe->hw;
                int idx = hwc->idx;
 
-               if (cpuc->current_idx[j] != PMC_NO_INDEX) {
-                       cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
-                       continue;
+               if (cpuc->current_idx[j] == PMC_NO_INDEX) {
+                       alpha_perf_event_set_period(pe, hwc, idx);
+                       cpuc->current_idx[j] = idx;
                }
 
-               alpha_perf_event_set_period(pe, hwc, idx);
-               cpuc->current_idx[j] = idx;
-               cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
+               if (!(hwc->state & PERF_HES_STOPPED))
+                       cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
        }
        cpuc->config = cpuc->event[0]->hw.config_base;
 }
@@ -420,12 +419,13 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)
  *  - this function is called from outside this module via the pmu struct
  *    returned from perf event initialisation.
  */
-static int alpha_pmu_enable(struct perf_event *event)
+static int alpha_pmu_add(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
        int n0;
        int ret;
-       unsigned long flags;
+       unsigned long irq_flags;
 
        /*
         * The Sparc code has the IRQ disable first followed by the perf
@@ -435,8 +435,8 @@ static int alpha_pmu_enable(struct perf_event *event)
         * nevertheless we disable the PMCs first to enable a potential
         * final PMI to occur before we disable interrupts.
         */
-       perf_disable();
-       local_irq_save(flags);
+       perf_pmu_disable(event->pmu);
+       local_irq_save(irq_flags);
 
        /* Default to error to be returned */
        ret = -EAGAIN;
@@ -455,8 +455,12 @@ static int alpha_pmu_enable(struct perf_event *event)
                }
        }
 
-       local_irq_restore(flags);
-       perf_enable();
+       hwc->state = PERF_HES_UPTODATE;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_STOPPED;
+
+       local_irq_restore(irq_flags);
+       perf_pmu_enable(event->pmu);
 
        return ret;
 }
@@ -467,15 +471,15 @@ static int alpha_pmu_enable(struct perf_event *event)
  *  - this function is called from outside this module via the pmu struct
  *    returned from perf event initialisation.
  */
-static void alpha_pmu_disable(struct perf_event *event)
+static void alpha_pmu_del(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       unsigned long flags;
+       unsigned long irq_flags;
        int j;
 
-       perf_disable();
-       local_irq_save(flags);
+       perf_pmu_disable(event->pmu);
+       local_irq_save(irq_flags);
 
        for (j = 0; j < cpuc->n_events; j++) {
                if (event == cpuc->event[j]) {
@@ -501,8 +505,8 @@ static void alpha_pmu_disable(struct perf_event *event)
                }
        }
 
-       local_irq_restore(flags);
-       perf_enable();
+       local_irq_restore(irq_flags);
+       perf_pmu_enable(event->pmu);
 }
 
 
@@ -514,13 +518,44 @@ static void alpha_pmu_read(struct perf_event *event)
 }
 
 
-static void alpha_pmu_unthrottle(struct perf_event *event)
+static void alpha_pmu_stop(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               cpuc->idx_mask &= ~(1UL<<hwc->idx);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               alpha_perf_event_update(event, hwc, hwc->idx, 0);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+
+       if (cpuc->enabled)
+               wrperfmon(PERFMON_CMD_DISABLE, (1UL<<hwc->idx));
+}
+
+
+static void alpha_pmu_start(struct perf_event *event, int flags)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
+       if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+               return;
+
+       if (flags & PERF_EF_RELOAD) {
+               WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+               alpha_perf_event_set_period(event, hwc, hwc->idx);
+       }
+
+       hwc->state = 0;
+
        cpuc->idx_mask |= 1UL<<hwc->idx;
-       wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
+       if (cpuc->enabled)
+               wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
 }
 
 
@@ -636,45 +671,42 @@ static int __hw_perf_event_init(struct perf_event *event)
        if (!hwc->sample_period) {
                hwc->sample_period = alpha_pmu->pmc_max_period[0];
                hwc->last_period = hwc->sample_period;
-               atomic64_set(&hwc->period_left, hwc->sample_period);
+               local64_set(&hwc->period_left, hwc->sample_period);
        }
 
        return 0;
 }
 
-static const struct pmu pmu = {
-       .enable         = alpha_pmu_enable,
-       .disable        = alpha_pmu_disable,
-       .read           = alpha_pmu_read,
-       .unthrottle     = alpha_pmu_unthrottle,
-};
-
-
 /*
  * Main entry point to initialise a HW performance event.
  */
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int alpha_pmu_event_init(struct perf_event *event)
 {
        int err;
 
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+       case PERF_TYPE_HARDWARE:
+       case PERF_TYPE_HW_CACHE:
+               break;
+
+       default:
+               return -ENOENT;
+       }
+
        if (!alpha_pmu)
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
 
        /* Do the real initialisation work. */
        err = __hw_perf_event_init(event);
 
-       if (err)
-               return ERR_PTR(err);
-
-       return &pmu;
+       return err;
 }
 
-
-
 /*
  * Main entry point - enable HW performance counters.
  */
-void hw_perf_enable(void)
+static void alpha_pmu_enable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -700,7 +732,7 @@ void hw_perf_enable(void)
  * Main entry point - disable HW performance counters.
  */
 
-void hw_perf_disable(void)
+static void alpha_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -713,6 +745,17 @@ void hw_perf_disable(void)
        wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
 }
 
+static struct pmu pmu = {
+       .pmu_enable     = alpha_pmu_enable,
+       .pmu_disable    = alpha_pmu_disable,
+       .event_init     = alpha_pmu_event_init,
+       .add            = alpha_pmu_add,
+       .del            = alpha_pmu_del,
+       .start          = alpha_pmu_start,
+       .stop           = alpha_pmu_stop,
+       .read           = alpha_pmu_read,
+};
+
 
 /*
  * Main entry point - don't know when this is called but it
@@ -766,7 +809,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
        wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
 
        /* la_ptr is the counter that overflowed. */
-       if (unlikely(la_ptr >= perf_max_events)) {
+       if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
                /* This should never occur! */
                irq_err_count++;
                pr_warning("PMI: silly index %ld\n", la_ptr);
@@ -807,7 +850,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
                        /* Interrupts coming too quickly; "throttle" the
                         * counter, i.e., disable it for a little while.
                         */
-                       cpuc->idx_mask &= ~(1UL<<idx);
+                       alpha_pmu_stop(event, 0);
                }
        }
        wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
@@ -837,6 +880,7 @@ void __init init_hw_perf_events(void)
 
        /* And set up PMU specification */
        alpha_pmu = &ev67_pmu;
-       perf_max_events = alpha_pmu->num_pmcs;
+
+       perf_pmu_register(&pmu);
 }
 
index 842dba308eab3065510857e50312496c674c1097..3ec35066f1dc51c09367c32bea106453a109953d 100644 (file)
@@ -356,7 +356,7 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
        dest[27] = pt->r27;
        dest[28] = pt->r28;
        dest[29] = pt->gp;
-       dest[30] = rdusp();
+       dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
        dest[31] = pt->pc;
 
        /* Once upon a time this was the PS value.  Which is stupid
index 3d2627ec986006e956f161b2bedcfa1c2ec32272..d3e52d3fd59299771ed3e90d0fc13f0aca9faa6f 100644 (file)
@@ -156,9 +156,6 @@ extern void SMC669_Init(int);
 /* es1888.c */
 extern void es1888_init(void);
 
-/* ns87312.c */
-extern void ns87312_enable_ide(long ide_base);
-
 /* ../lib/fpreg.c */
 extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
 extern unsigned long alpha_read_fp_reg (unsigned long reg);
index 0932dbb1ef8eff444943645e15b0802b1d4cf5d5..6f7feb5db27193f33e24e962e4d1be257d8464ef 100644 (file)
@@ -41,46 +41,20 @@ static void do_signal(struct pt_regs *, struct switch_stack *,
 /*
  * The OSF/1 sigprocmask calling sequence is different from the
  * C sigprocmask() sequence..
- *
- * how:
- * 1 - SIG_BLOCK
- * 2 - SIG_UNBLOCK
- * 3 - SIG_SETMASK
- *
- * We change the range to -1 .. 1 in order to let gcc easily
- * use the conditional move instructions.
- *
- * Note that we don't need to acquire the kernel lock for SMP
- * operation, as all of this is local to this thread.
  */
-SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask,
-               struct pt_regs *, regs)
+SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
 {
-       unsigned long oldmask = -EINVAL;
-
-       if ((unsigned long)how-1 <= 2) {
-               long sign = how-2;              /* -1 .. 1 */
-               unsigned long block, unblock;
-
-               newmask &= _BLOCKABLE;
-               spin_lock_irq(&current->sighand->siglock);
-               oldmask = current->blocked.sig[0];
-
-               unblock = oldmask & ~newmask;
-               block = oldmask | newmask;
-               if (!sign)
-                       block = unblock;
-               if (sign <= 0)
-                       newmask = block;
-               if (_NSIG_WORDS > 1 && sign > 0)
-                       sigemptyset(&current->blocked);
-               current->blocked.sig[0] = newmask;
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-
-               regs->r0 = 0;           /* special no error return */
+       sigset_t oldmask;
+       sigset_t mask;
+       unsigned long res;
+
+       siginitset(&mask, newmask & _BLOCKABLE);
+       res = sigprocmask(how, &mask, &oldmask);
+       if (!res) {
+               force_successful_syscall_return();
+               res = oldmask.sig[0];
        }
-       return oldmask;
+       return res;
 }
 
 SYSCALL_DEFINE3(osf_sigaction, int, sig,
@@ -94,9 +68,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig,
                old_sigset_t mask;
                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        return -EFAULT;
-               __get_user(mask, &act->sa_mask);
                siginitset(&new_ka.sa.sa_mask, mask);
                new_ka.ka_restorer = NULL;
        }
@@ -106,9 +80,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig,
        if (!ret && oact) {
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        return -EFAULT;
-               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
        }
 
        return ret;
@@ -144,8 +118,7 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage int
-do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
+SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
 {
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
@@ -154,41 +127,6 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       /* Indicate EINTR on return from any possible signal handler,
-          which will not come back through here, but via sigreturn.  */
-       regs->r0 = EINTR;
-       regs->r19 = 1;
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
-}
-
-asmlinkage int
-do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-                struct pt_regs *regs, struct switch_stack *sw)
-{
-       sigset_t set;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-       if (copy_from_user(&set, uset, sizeof(set)))
-               return -EFAULT;
-
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       /* Indicate EINTR on return from any possible signal handler,
-          which will not come back through here, but via sigreturn.  */
-       regs->r0 = EINTR;
-       regs->r19 = 1;
-
        current->state = TASK_INTERRUPTIBLE;
        schedule();
        set_thread_flag(TIF_RESTORE_SIGMASK);
@@ -239,6 +177,8 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
        unsigned long usp;
        long i, err = __get_user(regs->pc, &sc->sc_pc);
 
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        sw->r26 = (unsigned long) ret_from_sys_call;
 
        err |= __get_user(regs->r0, sc->sc_regs+0);
@@ -591,7 +531,6 @@ syscall_restart(unsigned long r0, unsigned long r19,
                regs->pc -= 4;
                break;
        case ERESTART_RESTARTBLOCK:
-               current_thread_info()->restart_block.fn = do_no_restart_syscall;
                regs->r0 = EINTR;
                break;
        }
index 4afc1a1e2e5a055ccda3d11a7d2f1b96c3670235..f0df3fbd84025eff9bf304fd179bed8785e865dc 100644 (file)
@@ -87,7 +87,7 @@ static int srm_env_proc_show(struct seq_file *m, void *v)
        srm_env_t       *entry;
        char            *page;
 
-       entry = (srm_env_t *)m->private;
+       entry = m->private;
        page = (char *)__get_free_page(GFP_USER);
        if (!page)
                return -ENOMEM;
index affd0f3f25df09b147c4a1e06146ff2f57e550ce..14c8898d19ec86fb8d4273dc527e7d860bcb8132 100644 (file)
@@ -33,7 +33,7 @@
 #include "irq_impl.h"
 #include "pci_impl.h"
 #include "machvec_impl.h"
-
+#include "pc873xx.h"
 
 /* Note mask bit is true for DISABLED irqs.  */
 static unsigned long cached_irq_mask = ~0UL;
@@ -235,18 +235,31 @@ cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
+static inline void __init
+cabriolet_enable_ide(void)
+{
+       if (pc873xx_probe() == -1) {
+               printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
+        } else {
+               printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
+                       pc873xx_get_model(), pc873xx_get_base());
+
+               pc873xx_enable_ide();
+       }
+}
+
 static inline void __init
 cabriolet_init_pci(void)
 {
        common_init_pci();
-       ns87312_enable_ide(0x398);
+       cabriolet_enable_ide();
 }
 
 static inline void __init
 cia_cab_init_pci(void)
 {
        cia_init_pci();
-       ns87312_enable_ide(0x398);
+       cabriolet_enable_ide();
 }
 
 /*
index 230464885b5cbe1a7683a2c76acdf1e46fbb9bac..4da596b6adbbb408ee9bb1e918b8891d3b148a29 100644 (file)
@@ -29,7 +29,7 @@
 #include "irq_impl.h"
 #include "pci_impl.h"
 #include "machvec_impl.h"
-
+#include "pc873xx.h"
 
 /* Note mask bit is true for DISABLED irqs.  */
 static unsigned long cached_irq_mask[2] = { -1, -1 };
@@ -264,7 +264,14 @@ takara_init_pci(void)
                alpha_mv.pci_map_irq = takara_map_irq_srm;
 
        cia_init_pci();
-       ns87312_enable_ide(0x26e);
+
+       if (pc873xx_probe() == -1) {
+               printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
+       } else {
+               printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
+                       pc873xx_get_model(), pc873xx_get_base());
+               pc873xx_enable_ide();
+       }
 }
 
 
index 09acb786e72b0d665d3aa9e38346148adbdb08c5..a6a1de9db16fd6e57d96c4e0b1f76db70f27147f 100644 (file)
@@ -58,7 +58,7 @@ sys_call_table:
        .quad sys_open                          /* 45 */
        .quad alpha_ni_syscall
        .quad sys_getxgid
-       .quad osf_sigprocmask
+       .quad sys_osf_sigprocmask
        .quad alpha_ni_syscall
        .quad alpha_ni_syscall                  /* 50 */
        .quad sys_acct
@@ -512,6 +512,9 @@ sys_call_table:
        .quad sys_pwritev
        .quad sys_rt_tgsigqueueinfo
        .quad sys_perf_event_open
+       .quad sys_fanotify_init
+       .quad sys_fanotify_mark                         /* 495 */
+       .quad sys_prlimit64
 
        .size sys_call_table, . - sys_call_table
        .type sys_call_table, @object
index eacceb26d9c8aa8bd250b409e821c277a9b51c73..0f1d8493cfca9c498a5187b97ae7c9dff8195b71 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/init.h>
 #include <linux/bcd.h>
 #include <linux/profile.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -83,25 +83,25 @@ static struct {
 
 unsigned long est_cycle_freq;
 
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
 
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
 
-#define set_perf_event_pending_flag()  __get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending()      __get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending()     __get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag()  __get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending()      __get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending()     __get_cpu_var(irq_work_pending) = 0
 
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
 {
-       set_perf_event_pending_flag();
+       set_irq_work_pending_flag();
 }
 
-#else  /* CONFIG_PERF_EVENTS */
+#else  /* CONFIG_IRQ_WORK */
 
-#define test_perf_event_pending()      0
-#define clear_perf_event_pending()
+#define test_irq_work_pending()      0
+#define clear_irq_work_pending()
 
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
 
 
 static inline __u32 rpcc(void)
@@ -191,16 +191,16 @@ irqreturn_t timer_interrupt(int irq, void *dev)
 
        write_sequnlock(&xtime_lock);
 
+       if (test_irq_work_pending()) {
+               clear_irq_work_pending();
+               irq_work_run();
+       }
+
 #ifndef CONFIG_SMP
        while (nticks--)
                update_process_times(user_mode(get_irq_regs()));
 #endif
 
-       if (test_perf_event_pending()) {
-               clear_perf_event_pending();
-               perf_event_do_pending();
-       }
-
        return IRQ_HANDLED;
 }
 
index b14f015008ada5e90d580b0589d4ff5144a1602e..0414e021a91c3ba8756674dea873f0dabd6c0abd 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kallsyms.h>
@@ -623,7 +622,6 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
                return;
        }
 
-       lock_kernel();
        printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
                pc, va, opcode, reg);
        do_exit(SIGSEGV);
@@ -646,7 +644,6 @@ got_exception:
         * Yikes!  No one to forward the exception to.
         * Since the registers are in a weird format, dump them ourselves.
         */
-       lock_kernel();
 
        printk("%s(%d): unhandled unaligned exception\n",
               current->comm, task_pid_nr(current));
index 92951103255a1dff3e30d237a676f8d8bfa137e3..3849887157e72050188f7b627ece321ffe771e60 100644 (file)
@@ -19,13 +19,17 @@ config ARM
        select HAVE_KPROBES if (!XIP_KERNEL)
        select HAVE_KRETPROBES if (HAVE_KPROBES)
        select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+       select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
+       select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_REGS_AND_STACK_ACCESS_API
+       select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -145,6 +149,9 @@ config ARCH_HAS_CPUFREQ
          and that the relevant menu configurations are displayed for
          it.
 
+config ARCH_HAS_CPU_IDLE_WAIT
+       def_bool y
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -271,7 +278,6 @@ config ARCH_AT91
        bool "Atmel AT91"
        select ARCH_REQUIRE_GPIOLIB
        select HAVE_CLK
-       select ARCH_USES_GETTIMEOFFSET
        help
          This enables support for systems based on the Atmel AT91RM9200,
          AT91SAM9 and AT91CAP9 processors.
@@ -511,6 +517,7 @@ config ARCH_MMP
        select GENERIC_CLOCKEVENTS
        select TICK_ONESHOT
        select PLAT_PXA
+       select SPARSE_IRQ
        help
          Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -588,6 +595,7 @@ config ARCH_PXA
        select GENERIC_CLOCKEVENTS
        select TICK_ONESHOT
        select PLAT_PXA
+       select SPARSE_IRQ
        help
          Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -679,8 +687,8 @@ config ARCH_S3C64XX
        help
          Samsung S3C64XX series based systems
 
-config ARCH_S5P6440
-       bool "Samsung S5P6440"
+config ARCH_S5P64X0
+       bool "Samsung S5P6440 S5P6450"
        select CPU_V6
        select GENERIC_GPIO
        select HAVE_CLK
@@ -689,7 +697,8 @@ config ARCH_S5P6440
        select HAVE_S3C2410_I2C
        select HAVE_S3C_RTC
        help
-         Samsung S5P6440 CPU based systems
+         Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
+         SMDK6450.
 
 config ARCH_S5P6442
        bool "Samsung S5P6442"
@@ -748,6 +757,15 @@ config ARCH_SHARK
          Support for the StrongARM based Digital DNARD machine, also known
          as "Shark" (<http://www.shark-linux.de/shark.html>).
 
+config ARCH_TCC_926
+       bool "Telechips TCC ARM926-based systems"
+       select CPU_ARM926T
+       select HAVE_CLK
+       select COMMON_CLKDEV
+       select GENERIC_CLOCKEVENTS
+       help
+         Support for Telechips TCC ARM926-based systems.
+
 config ARCH_LH7A40X
        bool "Sharp LH7A40X"
        select CPU_ARM922T
@@ -916,6 +934,8 @@ source "arch/arm/plat-s5p/Kconfig"
 
 source "arch/arm/plat-spear/Kconfig"
 
+source "arch/arm/plat-tcc/Kconfig"
+
 if ARCH_S3C2410
 source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
@@ -929,7 +949,7 @@ if ARCH_S3C64XX
 source "arch/arm/mach-s3c64xx/Kconfig"
 endif
 
-source "arch/arm/mach-s5p6440/Kconfig"
+source "arch/arm/mach-s5p64x0/Kconfig"
 
 source "arch/arm/mach-s5p6442/Kconfig"
 
@@ -1003,7 +1023,7 @@ endif
 
 config ARM_ERRATA_411920
        bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
-       depends on CPU_V6 && !SMP
+       depends on CPU_V6
        help
          Invalidation of the Instruction Cache operation can
          fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
@@ -1051,6 +1071,32 @@ config ARM_ERRATA_460075
          ACTLR register. Note that setting specific bits in the ACTLR register
          may not be available in non-secure mode.
 
+config ARM_ERRATA_742230
+       bool "ARM errata: DMB operation may be faulty"
+       depends on CPU_V7 && SMP
+       help
+         This option enables the workaround for the 742230 Cortex-A9
+         (r1p0..r2p2) erratum. Under rare circumstances, a DMB instruction
+         between two write operations may not ensure the correct visibility
+         ordering of the two writes. This workaround sets a specific bit in
+         the diagnostic register of the Cortex-A9 which causes the DMB
+         instruction to behave as a DSB, ensuring the correct behaviour of
+         the two writes.
+
+config ARM_ERRATA_742231
+       bool "ARM errata: Incorrect hazard handling in the SCU may lead to data corruption"
+       depends on CPU_V7 && SMP
+       help
+         This option enables the workaround for the 742231 Cortex-A9
+         (r2p0..r2p2) erratum. Under certain conditions, specific to the
+         Cortex-A9 MPCore micro-architecture, two CPUs working in SMP mode,
+         accessing some data located in the same cache line, may get corrupted
+         data due to bad handling of the address hazard when the line gets
+         replaced from one of the CPUs at the same time as another CPU is
+         accessing it. This workaround sets specific bits in the diagnostic
+         register of the Cortex-A9 which reduces the linefill issuing
+         capabilities of the processor.
+
 config PL310_ERRATA_588369
        bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
        depends on CACHE_L2X0 && ARCH_OMAP4
@@ -1076,6 +1122,20 @@ config ARM_ERRATA_720789
          invalidated are not, resulting in an incoherency in the system page
          tables. The workaround changes the TLB flushing routines to invalidate
          entries regardless of the ASID.
+
+config ARM_ERRATA_743622
+       bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
+       depends on CPU_V7
+       help
+         This option enables the workaround for the 743622 Cortex-A9
+         (r2p0..r2p2) erratum. Under very rare conditions, a faulty
+         optimisation in the Cortex-A9 Store Buffer may lead to data
+         corruption. This workaround sets a specific bit in the diagnostic
+         register of the Cortex-A9 which disables the Store Buffer
+         optimisation, preventing the defect from occurring. This has no
+         visible impact on the overall performance or power consumption of the
+         processor.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1142,13 +1202,13 @@ source "kernel/time/Kconfig"
 
 config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
-                MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-                ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+       depends on EXPERIMENTAL
        depends on GENERIC_CLOCKEVENTS
+       depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
+                MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
+                ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
        select USE_GENERIC_SMP_HELPERS
-       select HAVE_ARM_SCU if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 ||\
-                ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+       select HAVE_ARM_SCU
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@ -1166,6 +1226,19 @@ config SMP
 
          If you don't know what to do here, say N.
 
+config SMP_ON_UP
+       bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       depends on SMP && !XIP && !THUMB2_KERNEL
+       default y
+       help
+         SMP kernels contain instructions which fail on non-SMP processors.
+         Enabling this option allows the kernel to modify itself to make
+         these instructions safe.  Disabling it allows about 1K of space
+         savings.
+
+         If you don't know what to do here, say Y.
+
 config HAVE_ARM_SCU
        bool
        depends on SMP
@@ -1216,12 +1289,9 @@ config HOTPLUG_CPU
 
 config LOCAL_TIMERS
        bool "Use local timer interrupts"
-       depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
-               REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-               ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+       depends on SMP
        default y
-       select HAVE_ARM_TWD if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 || \
-               ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS
+       select HAVE_ARM_TWD
        help
          Enable support for local timers on SMP platforms, rather then the
          legacy IPI broadcast method.  Local timers allows the system
@@ -1232,7 +1302,7 @@ source kernel/Kconfig.preempt
 
 config HZ
        int
-       default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \
+       default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
                ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
        default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
        default AT91_TIMER_HZ if ARCH_AT91
@@ -1438,6 +1508,20 @@ config UACCESS_WITH_MEMCPY
          However, if the CPU data cache is using a write-allocate mode,
          this option is unlikely to provide any performance gain.
 
+config SECCOMP
+       bool
+       prompt "Enable seccomp to safely compute untrusted bytecode"
+       ---help---
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
 config CC_STACKPROTECTOR
        bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
        help
@@ -1576,95 +1660,6 @@ config AUTO_ZRELADDR
          0xf8000000. This assumes the zImage being placed in the first 128MB
          from start of memory.
 
-config ZRELADDR
-       hex "Physical address of the decompressed kernel image"
-       depends on !AUTO_ZRELADDR
-       default 0x00008000 if ARCH_BCMRING ||\
-               ARCH_CNS3XXX ||\
-               ARCH_DOVE ||\
-               ARCH_EBSA110 ||\
-               ARCH_FOOTBRIDGE ||\
-               ARCH_INTEGRATOR ||\
-               ARCH_IOP13XX ||\
-               ARCH_IOP33X ||\
-               ARCH_IXP2000 ||\
-               ARCH_IXP23XX ||\
-               ARCH_IXP4XX ||\
-               ARCH_KIRKWOOD ||\
-               ARCH_KS8695 ||\
-               ARCH_LOKI ||\
-               ARCH_MMP ||\
-               ARCH_MV78XX0 ||\
-               ARCH_NOMADIK ||\
-               ARCH_NUC93X ||\
-               ARCH_NS9XXX ||\
-               ARCH_ORION5X ||\
-               ARCH_SPEAR3XX ||\
-               ARCH_SPEAR6XX ||\
-               ARCH_U8500 ||\
-               ARCH_VERSATILE ||\
-               ARCH_W90X900
-       default 0x08008000 if ARCH_MX1 ||\
-               ARCH_SHARK
-       default 0x10008000 if ARCH_MSM ||\
-               ARCH_OMAP1 ||\
-               ARCH_RPC
-       default 0x20008000 if ARCH_S5P6440 ||\
-               ARCH_S5P6442 ||\
-               ARCH_S5PC100 ||\
-               ARCH_S5PV210
-       default 0x30008000 if ARCH_S3C2410 ||\
-               ARCH_S3C2400 ||\
-               ARCH_S3C2412 ||\
-               ARCH_S3C2416 ||\
-               ARCH_S3C2440 ||\
-               ARCH_S3C2443
-       default 0x40008000 if ARCH_STMP378X ||\
-               ARCH_STMP37XX ||\
-               ARCH_SH7372 ||\
-               ARCH_SH7377
-       default 0x50008000 if ARCH_S3C64XX ||\
-               ARCH_SH7367
-       default 0x60008000 if ARCH_VEXPRESS
-       default 0x80008000 if ARCH_MX25 ||\
-               ARCH_MX3 ||\
-               ARCH_NETX ||\
-               ARCH_OMAP2PLUS ||\
-               ARCH_PNX4008
-       default 0x90008000 if ARCH_MX5 ||\
-               ARCH_MX91231
-       default 0xa0008000 if ARCH_IOP32X ||\
-               ARCH_PXA ||\
-               MACH_MX27
-       default 0xc0008000 if ARCH_LH7A40X ||\
-               MACH_MX21
-       default 0xf0008000 if ARCH_AAEC2000 ||\
-               ARCH_L7200
-       default 0xc0028000 if ARCH_CLPS711X
-       default 0x70008000 if ARCH_AT91 && (ARCH_AT91CAP9 || ARCH_AT91SAM9G45)
-       default 0x20008000 if ARCH_AT91 && !(ARCH_AT91CAP9 || ARCH_AT91SAM9G45)
-       default 0xc0008000 if ARCH_DAVINCI && ARCH_DAVINCI_DA8XX
-       default 0x80008000 if ARCH_DAVINCI && !ARCH_DAVINCI_DA8XX
-       default 0x00008000 if ARCH_EP93XX && EP93XX_SDCE3_SYNC_PHYS_OFFSET
-       default 0xc0008000 if ARCH_EP93XX && EP93XX_SDCE0_PHYS_OFFSET
-       default 0xd0008000 if ARCH_EP93XX && EP93XX_SDCE1_PHYS_OFFSET
-       default 0xe0008000 if ARCH_EP93XX && EP93XX_SDCE2_PHYS_OFFSET
-       default 0xf0008000 if ARCH_EP93XX && EP93XX_SDCE3_ASYNC_PHYS_OFFSET
-       default 0x00008000 if ARCH_GEMINI && GEMINI_MEM_SWAP
-       default 0x10008000 if ARCH_GEMINI && !GEMINI_MEM_SWAP
-       default 0x70008000 if ARCH_REALVIEW && REALVIEW_HIGH_PHYS_OFFSET
-       default 0x00008000 if ARCH_REALVIEW && !REALVIEW_HIGH_PHYS_OFFSET
-       default 0xc0208000 if ARCH_SA1100 && SA1111
-       default 0xc0008000 if ARCH_SA1100 && !SA1111
-       default 0x30108000 if ARCH_S3C2410 && PM_H1940
-       default 0x28E08000 if ARCH_U300 && MACH_U300_SINGLE_RAM
-       default 0x48008000 if ARCH_U300 && !MACH_U300_SINGLE_RAM
-       help
-         ZRELADDR is the physical address where the decompressed kernel
-         image will be placed. ZRELADDR has to be specified when the
-         assumption of AUTO_ZRELADDR is not valid, or when ZBOOT_ROM is
-         selected.
-
 endmenu
 
 menu "CPU Power Management"
index 91344af75f39694f89d1b4e16529184816f42965..2fd0b99afc4bc849cd448780358fa5fdd68ff644 100644 (file)
@@ -2,6 +2,20 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
+config STRICT_DEVMEM
+       bool "Filter access to /dev/mem"
+       depends on MMU
+       ---help---
+         If this option is disabled, you allow userspace (root) access to all
+         of memory, including kernel and userspace memory. Accidental
+         access to this is obviously disastrous, but specific access can
+         be used by people debugging the kernel.
+
+         If this option is switched on, the /dev/mem file only allows
+         userspace access to memory mapped peripherals.
+
+          If in doubt, say Y.
+
 # RMK wants arm kernels compiled with frame pointers or stack unwinding.
 # If you know what you are doing and are willing to live without stack
 # traces, you can get a slightly smaller kernel by setting this option to
@@ -27,6 +41,11 @@ config ARM_UNWIND
          the performance is not affected. Currently, this feature
          only works with EABI compilers. If unsure say Y.
 
+config OLD_MCOUNT
+       bool
+       depends on FUNCTION_TRACER && FRAME_POINTER
+       default y
+
 config DEBUG_USER
        bool "Verbose user fault messages"
        help
index 59c1ce858fc8b18d4ec613e6dd2bfe62ed06047e..b87aed028eeff2dc50bb4b7c1005f9daadac26a8 100644 (file)
@@ -173,7 +173,7 @@ machine-$(CONFIG_ARCH_RPC)          := rpc
 machine-$(CONFIG_ARCH_S3C2410)         := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
 machine-$(CONFIG_ARCH_S3C24A0)         := s3c24a0
 machine-$(CONFIG_ARCH_S3C64XX)         := s3c64xx
-machine-$(CONFIG_ARCH_S5P6440)         := s5p6440
+machine-$(CONFIG_ARCH_S5P64X0)         := s5p64x0
 machine-$(CONFIG_ARCH_S5P6442)         := s5p6442
 machine-$(CONFIG_ARCH_S5PC100)         := s5pc100
 machine-$(CONFIG_ARCH_S5PV210)         := s5pv210
@@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_SHARK)                := shark
 machine-$(CONFIG_ARCH_SHMOBILE)        := shmobile
 machine-$(CONFIG_ARCH_STMP378X)                := stmp378x
 machine-$(CONFIG_ARCH_STMP37XX)                := stmp37xx
+machine-$(CONFIG_ARCH_TCC8K)           := tcc8k
 machine-$(CONFIG_ARCH_TEGRA)           := tegra
 machine-$(CONFIG_ARCH_U300)            := u300
 machine-$(CONFIG_ARCH_U8500)           := ux500
@@ -202,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC)             := mxc
 plat-$(CONFIG_ARCH_OMAP)       := omap
 plat-$(CONFIG_ARCH_S3C64XX)    := samsung
 plat-$(CONFIG_ARCH_STMP3XXX)   := stmp3xxx
+plat-$(CONFIG_ARCH_TCC_926)    := tcc
 plat-$(CONFIG_PLAT_IOP)                := iop
 plat-$(CONFIG_PLAT_NOMADIK)    := nomadik
 plat-$(CONFIG_PLAT_ORION)      := orion
@@ -245,13 +247,14 @@ ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
 FASTFPE_OBJ    :=$(FASTFPE)/
 endif
 
-# If we have a machine-specific directory, then include it in the build.
-core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
-core-y                         += $(machdirs) $(platdirs)
 core-$(CONFIG_FPE_NWFPE)       += arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)     += $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)             += arch/arm/vfp/
 
+# If we have a machine-specific directory, then include it in the build.
+core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y                         += $(machdirs) $(platdirs)
+
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 
 libs-y                         := arch/arm/lib/ $(libs-y)
index f705213caa881af9c07e181c0d2a3a1a26a5d98a..4a590f4113e2af044ea1764aeb0681ad7f50a74c 100644 (file)
 MKIMAGE         := $(srctree)/scripts/mkuboot.sh
 
 ifneq ($(MACHINE),)
--include $(srctree)/$(MACHINE)/Makefile.boot
+include $(srctree)/$(MACHINE)/Makefile.boot
 endif
 
 # Note: the following conditions must always be true:
+#   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
 #   INITRD_PHYS must be in RAM
+ZRELADDR    := $(zreladdr-y)
 PARAMS_PHYS := $(params_phys-y)
 INITRD_PHYS := $(initrd_phys-y)
 
-export INITRD_PHYS PARAMS_PHYS
+export ZRELADDR INITRD_PHYS PARAMS_PHYS
 
 targets := Image zImage xipImage bootpImage uImage
 
@@ -65,7 +67,7 @@ quiet_cmd_uimage = UIMAGE  $@
 ifeq ($(CONFIG_ZBOOT_ROM),y)
 $(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)
 else
-$(obj)/uImage: LOADADDR=$(CONFIG_ZRELADDR)
+$(obj)/uImage: LOADADDR=$(ZRELADDR)
 endif
 
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
index 68775e33476c2fafb4c20d88f7f676c836a8edc1..65a7c1c588a94ab4623be0ddfe02a691fb2954c6 100644 (file)
@@ -79,6 +79,10 @@ endif
 EXTRA_CFLAGS  := -fpic -fno-builtin
 EXTRA_AFLAGS  := -Wa,-march=all
 
+# Supply ZRELADDR to the decompressor via a linker symbol.
+ifneq ($(CONFIG_AUTO_ZRELADDR),y)
+LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
+endif
 ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux += --be8
 endif
@@ -112,5 +116,5 @@ CFLAGS_font.o := -Dstatic=
 $(obj)/font.c: $(FONTC)
        $(call cmd,shipped)
 
-$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
        @sed "$(SEDFLAGS)" < $< > $@
index 6af9907c3b5ccad2ae2d73e37f5470c5b2f6b897..6825c34646d4e02f24b0eefe7ab4e012bca05208 100644 (file)
@@ -177,7 +177,7 @@ not_angel:
                and     r4, pc, #0xf8000000
                add     r4, r4, #TEXT_OFFSET
 #else
-               ldr     r4, =CONFIG_ZRELADDR
+               ldr     r4, =zreladdr
 #endif
                subs    r0, r0, r1              @ calculate the delta offset
 
index 7dfa9a85bc0c875b11567025f68e92bd768d7419..ada6359160ebef12614e9cd725449e5353a7a85b 100644 (file)
@@ -67,25 +67,11 @@ static inline unsigned int gic_irq(unsigned int irq)
 
 /*
  * Routines to acknowledge, disable and enable interrupts
- *
- * Linux assumes that when we're done with an interrupt we need to
- * unmask it, in the same way we need to unmask an interrupt when
- * we first enable it.
- *
- * The GIC has a separate notion of "end of interrupt" to re-enable
- * an interrupt after handling, in order to support hardware
- * prioritisation.
- *
- * We can make the GIC behave in the way that Linux expects by making
- * our "acknowledge" routine disable the interrupt, then mark it as
- * complete.
  */
 static void gic_ack_irq(unsigned int irq)
 {
-       u32 mask = 1 << (irq % 32);
 
        spin_lock(&irq_controller_lock);
-       writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
        writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
        spin_unlock(&irq_controller_lock);
 }
index 6c091356245593b87860d2ccb6221650fc62855b..1bec96e851967101df7a796745b84d24bd320ab8 100644 (file)
@@ -263,6 +263,22 @@ static int it8152_pci_platform_notify_remove(struct device *dev)
        return 0;
 }
 
+int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+       dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
+               __func__, dma_addr, size);
+       return (dev->bus == &pci_bus_type) &&
+               ((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
+}
+
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+       if (mask >= PHYS_OFFSET + SZ_64M - 1)
+               return 0;
+
+       return -EIO;
+}
+
 int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
 {
        it8152_io.start = IT8152_IO_BASE + 0x12000;
index 5ebbab6242a78ccb1c23d649cb9a4ee608e2ed3c..8f0f86db36024e885778f9ddd864fab69eed1c27 100644 (file)
 #define DESIGNER       0x41
 #define REVISION       0x0
 #define INTEG_CFG      0x0
-#define PERIPH_ID_VAL  ((PART << 0) | (DESIGNER << 12) \
-                         | (REVISION << 20) | (INTEG_CFG << 24))
+#define PERIPH_ID_VAL  ((PART << 0) | (DESIGNER << 12))
 
 #define PCELL_ID_VAL   0xb105f00d
 
@@ -1859,10 +1858,10 @@ int pl330_add(struct pl330_info *pi)
        regs = pi->base;
 
        /* Check if we can handle this DMAC */
-       if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL
+       if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
           || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
                dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-                       readl(regs + PERIPH_ID), readl(regs + PCELL_ID));
+                       get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
                return -EINVAL;
        }
 
index 517d50ddbeb3153d102e426fc915405bae76012b..c0258a8c103bd49c354154e4d3c66d9b12dd2f6b 100644 (file)
@@ -678,7 +678,7 @@ out:
  *     %-EBUSY         physical address already marked in-use.
  *     %0              successful.
  */
-static int
+static int __devinit
 __sa1111_probe(struct device *me, struct resource *mem, int irq)
 {
        struct sa1111 *sachip;
index f1bac70d6ce95f7ae364dd6eb8d4e745dea19fdf..9e90e6d792973042ec81faf2f78433e416a2752d 100644 (file)
@@ -13,6 +13,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_AT91=y
 CONFIG_ARCH_AT91SAM9G20=y
 CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_AEABI=y
index ccc9c9959b82baf75d0faa04769a85e79ac23d51..2f7042813765f783fd139d4a7680b880bf9574e5 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_ESATA_SHEEVAPLUG=y
 CONFIG_MACH_GURUPLUG=y
+CONFIG_MACH_DOCKSTAR=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
 CONFIG_MACH_OPENRD_BASE=y
index b2038b0e266f351cfca1b583c894cb8c0bc98028..813cfb366c1830bd3fc5e0df3ff1328931cd921d 100644 (file)
@@ -21,8 +21,14 @@ CONFIG_ARCH_MX2=y
 CONFIG_MACH_MX27=y
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
 CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
 CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 CONFIG_NO_HZ=y
@@ -76,7 +82,9 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
@@ -85,19 +93,20 @@ CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_IMX=y
 CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
+CONFIG_SPI_IMX=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=m
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_MXC=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/mx31pdk_defconfig b/arch/arm/configs/mx31pdk_defconfig
deleted file mode 100644 (file)
index 2d29329..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-# CONFIG_MACH_MX31ADS is not set
-CONFIG_MACH_MX31_3DS=y
-CONFIG_AEABI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_LRO is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRC32 is not set
index 161f907b611f388badcb21d4ecbb1d0923ff670f..f0c339fd5d21374e1721c9516822cae038c3639d 100644 (file)
@@ -24,6 +24,7 @@ CONFIG_MACH_PCM043=y
 CONFIG_MACH_ARMADILLO5X0=y
 CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 CONFIG_NO_HZ=y
@@ -108,7 +109,6 @@ CONFIG_MMC=y
 CONFIG_MMC_MXC=y
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
index a665ecbbe2bc2b64cad0aa439b9bf32c6c4d6c11..163cfee7644c72c3699cd807f5571d1e79aa6123 100644 (file)
@@ -15,6 +15,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_ARCH_MXC=y
 CONFIG_ARCH_MX5=y
 CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -69,7 +71,6 @@ CONFIG_REALTEK_PHY=y
 CONFIG_NATIONAL_PHY=y
 CONFIG_STE10XP=y
 CONFIG_LSI_ET1011C_PHY=y
-CONFIG_FIXED_PHY=y
 CONFIG_MDIO_BITBANG=y
 CONFIG_MDIO_GPIO=y
 CONFIG_NET_ETHERNET=y
@@ -100,7 +101,6 @@ CONFIG_I2C_ALGOPCF=m
 CONFIG_I2C_ALGOPCA=m
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
@@ -117,13 +117,11 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
-CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
@@ -136,6 +134,7 @@ CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -151,7 +150,6 @@ CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -159,7 +157,6 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_ARM_UNWIND is not set
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_KEYS=y
 CONFIG_SECURITYFS=y
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_LZO=y
index 63e0c2d50f324c6eb7ed3c1ff84ded9930f12538..14c1e18c648f7340c243bd821645df57f955f950 100644 (file)
@@ -13,6 +13,9 @@ CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_OMAP=y
 CONFIG_ARCH_OMAP4=y
+# CONFIG_ARCH_OMAP2PLUS_TYPICAL is not set
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
 # CONFIG_OMAP_MUX is not set
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_DM_TIMER=y
index 9312ef9f9bf42b82ca2e05ad99bb951bc5c2306b..5ca7a61f7c01d6d5eef1591f80fad1152a9dab31 100644 (file)
@@ -39,6 +39,7 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -52,10 +53,13 @@ CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
@@ -70,7 +74,13 @@ CONFIG_SND_ARMAACI=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
@@ -80,6 +90,7 @@ CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
index fb75192ee7e5afa21f5d8c2907a476e36d02cee6..fcaa60328051254439df8f96dc2013b8dc750a4e 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -51,10 +52,13 @@ CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
@@ -69,7 +73,13 @@ CONFIG_SND_ARMAACI=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
@@ -79,6 +89,7 @@ CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
similarity index 97%
rename from arch/arm/configs/s5p6440_defconfig
rename to arch/arm/configs/s5p64x0_defconfig
index 0b0266c6d3269592ed882fc664dee73dd045d5e1..2993ecd35145265d0cf2566bbf227158cd07a5c5 100644 (file)
@@ -5,10 +5,11 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5P6440=y
+CONFIG_ARCH_S5P64X0=y
 CONFIG_S3C_BOOT_ERROR_RESET=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDK6440=y
+CONFIG_MACH_SMDK6450=y
 CONFIG_CPU_32v6K=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
index 46e5e0747269beade612d95c01ba4707acdfc59b..c1c252cdca60702334e1f6e0abae37836c5b7462 100644 (file)
@@ -28,26 +28,9 @@ CONFIG_CPU_IDLE=y
 CONFIG_FPE_NWFPE=y
 CONFIG_PM=y
 # CONFIG_SUSPEND is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MISC_DEVICES is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -58,7 +41,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
-CONFIG_POWER_SUPPLY=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_REGULATOR=y
@@ -66,24 +48,10 @@ CONFIG_FB=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PROCFS is not set
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
 CONFIG_RTC_DRV_COH901331=y
@@ -93,12 +61,11 @@ CONFIG_COH901318=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
index 6e8f05c8a1c8f61efbffbb8cab303dd28e36efc0..062b58c029ab92ceb23cf0616568a76d3ec3a6b1 100644 (file)
        .long   9999b,9001f;                    \
        .popsection
 
+#ifdef CONFIG_SMP
+#define ALT_SMP(instr...)                                      \
+9998:  instr
+#define ALT_UP(instr...)                                       \
+       .pushsection ".alt.smp.init", "a"                       ;\
+       .long   9998b                                           ;\
+       instr                                                   ;\
+       .popsection
+#define ALT_UP_B(label)                                        \
+       .equ    up_b_offset, label - 9998b                      ;\
+       .pushsection ".alt.smp.init", "a"                       ;\
+       .long   9998b                                           ;\
+       b       . + up_b_offset                                 ;\
+       .popsection
+#else
+#define ALT_SMP(instr...)
+#define ALT_UP(instr...) instr
+#define ALT_UP_B(label) b label
+#endif
+
 /*
  * SMP data memory barrier
  */
        .macro  smp_dmb
 #ifdef CONFIG_SMP
 #if __LINUX_ARM_ARCH__ >= 7
-       dmb
+       ALT_SMP(dmb)
 #elif __LINUX_ARM_ARCH__ == 6
-       mcr     p15, 0, r0, c7, c10, 5  @ dmb
+       ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
+#else
+#error Incompatible SMP platform
 #endif
+       ALT_UP(nop)
 #endif
        .endm
 
index 4656a24058d21f75d30097ae5b06a1b66863bdd9..3acd8fa25e347dc1bcd276ba036e9107ff5d06d9 100644 (file)
 #endif
 
 /*
- * This flag is used to indicate that the page pointed to by a pte
- * is dirty and requires cleaning before returning it to the user.
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
  */
-#define PG_dcache_dirty PG_arch_1
+#define PG_dcache_clean PG_arch_1
 
 /*
  *     MM Cache Management
  *     Please note that the implementation of these, and the required
  *     effects are cache-type (VIVT/VIPT/PIPT) specific.
  *
+ *     flush_icache_all()
+ *
+ *             Unconditionally clean and invalidate the entire icache.
+ *             Currently only needed for cache-v6.S and cache-v7.S, see
+ *             __flush_icache_all for the generic implementation.
+ *
  *     flush_kern_all()
  *
  *             Unconditionally clean and invalidate the entire cache.
  */
 
 struct cpu_cache_fns {
+       void (*flush_icache_all)(void);
        void (*flush_kern_all)(void);
        void (*flush_user_all)(void);
        void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
@@ -227,6 +234,7 @@ struct cpu_cache_fns {
 
 extern struct cpu_cache_fns cpu_cache;
 
+#define __cpuc_flush_icache_all                cpu_cache.flush_icache_all
 #define __cpuc_flush_kern_all          cpu_cache.flush_kern_all
 #define __cpuc_flush_user_all          cpu_cache.flush_user_all
 #define __cpuc_flush_user_range                cpu_cache.flush_user_range
@@ -246,6 +254,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 #else
 
+#define __cpuc_flush_icache_all                __glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all          __glue(_CACHE,_flush_kern_cache_all)
 #define __cpuc_flush_user_all          __glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range                __glue(_CACHE,_flush_user_cache_range)
@@ -253,6 +262,7 @@ extern struct cpu_cache_fns cpu_cache;
 #define __cpuc_coherent_user_range     __glue(_CACHE,_coherent_user_range)
 #define __cpuc_flush_dcache_area       __glue(_CACHE,_flush_kern_dcache_area)
 
+extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
@@ -291,6 +301,37 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 /*
  * Convert calls to our calling convention.
  */
+
+/* Invalidate I-cache */
+#define __flush_icache_all_generic()                                   \
+       asm("mcr        p15, 0, %0, c7, c5, 0"                          \
+           : : "r" (0));
+
+/* Invalidate I-cache inner shareable */
+#define __flush_icache_all_v7_smp()                                    \
+       asm("mcr        p15, 0, %0, c7, c1, 0"                          \
+           : : "r" (0));
+
+/*
+ * Optimized __flush_icache_all for the common cases. Note that UP ARMv7
+ * will fall through to use __flush_icache_all_generic.
+ */
+#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) ||              \
+       defined(CONFIG_SMP_ON_UP)
+#define __flush_icache_preferred       __cpuc_flush_icache_all
+#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+#define __flush_icache_preferred       __flush_icache_all_v7_smp
+#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920)
+#define __flush_icache_preferred       __cpuc_flush_icache_all
+#else
+#define __flush_icache_preferred       __flush_icache_all_generic
+#endif
+
+static inline void __flush_icache_all(void)
+{
+       __flush_icache_preferred();
+}
+
 #define flush_cache_all()              __cpuc_flush_kern_all()
 
 static inline void vivt_flush_cache_mm(struct mm_struct *mm)
@@ -366,21 +407,6 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static inline void __flush_icache_all(void)
-{
-#ifdef CONFIG_ARM_ERRATA_411920
-       extern void v6_icache_inval_all(void);
-       v6_icache_inval_all();
-#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
-       asm("mcr        p15, 0, %0, c7, c1, 0   @ invalidate I-cache inner shareable\n"
-           :
-           : "r" (0));
-#else
-       asm("mcr        p15, 0, %0, c7, c5, 0   @ invalidate I-cache\n"
-           :
-           : "r" (0));
-#endif
-}
 static inline void flush_kernel_vmap_range(void *addr, int size)
 {
        if ((cache_is_vivt() || cache_is_vipt_aliasing()))
@@ -405,9 +431,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 static inline void flush_kernel_dcache_page(struct page *page)
 {
-       /* highmem pages are always flushed upon kunmap already */
-       if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
-               __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 
 #define flush_dcache_mmap_lock(mapping) \
index d3a4c2cb9f2f662f5348175baa2a03995c66835d..c023db09fcc14ced27ec4bacaca40b44c48005ad 100644 (file)
@@ -6,6 +6,7 @@
 #define CACHEID_VIPT_ALIASING          (1 << 2)
 #define CACHEID_VIPT                   (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
 #define CACHEID_ASID_TAGGED            (1 << 3)
+#define CACHEID_VIPT_I_ALIASING                (1 << 4)
 
 extern unsigned int cacheid;
 
@@ -14,15 +15,18 @@ extern unsigned int cacheid;
 #define cache_is_vipt_nonaliasing()    cacheid_is(CACHEID_VIPT_NONALIASING)
 #define cache_is_vipt_aliasing()       cacheid_is(CACHEID_VIPT_ALIASING)
 #define icache_is_vivt_asid_tagged()   cacheid_is(CACHEID_ASID_TAGGED)
+#define icache_is_vipt_aliasing()      cacheid_is(CACHEID_VIPT_I_ALIASING)
 
 /*
  * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
  * Mask out support which will never be present on newer CPUs.
  * - v6+ is never VIVT
- * - v7+ VIPT never aliases
+ * - v7+ VIPT never aliases on D-side
  */
 #if __LINUX_ARM_ARCH__ >= 7
-#define __CACHEID_ARCH_MIN     (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
+#define __CACHEID_ARCH_MIN     (CACHEID_VIPT_NONALIASING |\
+                                CACHEID_ASID_TAGGED |\
+                                CACHEID_VIPT_I_ALIASING)
 #elif __LINUX_ARM_ARCH__ >= 6
 #define        __CACHEID_ARCH_MIN      (~CACHEID_VIVT)
 #else
index c226fe10553e2952ec982ef3ec5fcaf8538586e0..c568da7dcae45e60e8630e2b3060599f561d6555 100644 (file)
@@ -288,15 +288,7 @@ extern void dmabounce_unregister_dev(struct device *);
  * DMA access and 1 if the buffer needs to be bounced.
  *
  */
-#ifdef CONFIG_SA1111
 extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
-#else
-static inline int dma_needs_bounce(struct device *dev, dma_addr_t addr,
-                                  size_t size)
-{
-       return 0;
-}
-#endif
 
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
index 5747a8baa4135b44c25711197799255c9f5f61ff..8bb66bca2e3eb8a8561f2c63d9334e8991ebb728 100644 (file)
@@ -127,4 +127,8 @@ struct mm_struct;
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+extern int vectors_user_mapping(void);
+#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+
 #endif
index 103f7ee9731357fa7a8e19bb83416a1465c53cb4..f89515adac60ef579ad27cce19d827784ad59b36 100644 (file)
@@ -2,12 +2,30 @@
 #define _ASM_ARM_FTRACE
 
 #ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_ADDR            ((long)(mcount))
+#define MCOUNT_ADDR            ((unsigned long)(__gnu_mcount_nc))
 #define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */
 
 #ifndef __ASSEMBLY__
 extern void mcount(void);
 extern void __gnu_mcount_nc(void);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+#ifdef CONFIG_OLD_MCOUNT
+       bool    old_mcount;
+#endif
+};
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+       /* With Thumb-2, the recorded addresses have the lsb set */
+       return addr & ~1;
+}
+
+extern void ftrace_caller_old(void);
+extern void ftrace_call_old(void);
+#endif
+
 #endif
 
 #endif
index 212e47828c791e44c16f93783cba17d10eadddff..7ecd793b8f5a94ebdbba19ee26ac9a75eaaa33d6 100644 (file)
 #define TRACER_RUNNING         BIT(TRACER_RUNNING_BIT)
 #define TRACER_CYCLE_ACC       BIT(TRACER_CYCLE_ACC_BIT)
 
-struct tracectx {
-       unsigned int    etb_bufsz;
-       void __iomem    *etb_regs;
-       void __iomem    *etm_regs;
-       unsigned long   flags;
-       int             ncmppairs;
-       int             etm_portsz;
-       struct device   *dev;
-       struct clk      *emu_clk;
-       struct mutex    mutex;
-};
-
 #define TRACER_TIMEOUT 10000
 
 #define etm_writel(t, v, x) \
@@ -112,10 +100,10 @@ struct tracectx {
 
 /* ETM status register, "ETM Architecture", 3.3.2 */
 #define ETMR_STATUS            (0x10)
-#define ETMST_OVERFLOW         (1 << 0)
-#define ETMST_PROGBIT          (1 << 1)
-#define ETMST_STARTSTOP                (1 << 2)
-#define ETMST_TRIGGER          (1 << 3)
+#define ETMST_OVERFLOW         BIT(0)
+#define ETMST_PROGBIT          BIT(1)
+#define ETMST_STARTSTOP                BIT(2)
+#define ETMST_TRIGGER          BIT(3)
 
 #define etm_progbit(t)         (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
 #define etm_started(t)         (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
@@ -123,7 +111,7 @@ struct tracectx {
 
 #define ETMR_TRACEENCTRL2      0x1c
 #define ETMR_TRACEENCTRL       0x24
-#define ETMTE_INCLEXCL         (1 << 24)
+#define ETMTE_INCLEXCL         BIT(24)
 #define ETMR_TRACEENEVT                0x20
 #define ETMCTRL_OPTS           (ETMCTRL_DO_CPRT | \
                                ETMCTRL_DATA_DO_ADDR | \
@@ -146,12 +134,12 @@ struct tracectx {
 #define ETBR_CTRL              0x20
 #define ETBR_FORMATTERCTRL     0x304
 #define ETBFF_ENFTC            1
-#define ETBFF_ENFCONT          (1 << 1)
-#define ETBFF_FONFLIN          (1 << 4)
-#define ETBFF_MANUAL_FLUSH     (1 << 6)
-#define ETBFF_TRIGIN           (1 << 8)
-#define ETBFF_TRIGEVT          (1 << 9)
-#define ETBFF_TRIGFL           (1 << 10)
+#define ETBFF_ENFCONT          BIT(1)
+#define ETBFF_FONFLIN          BIT(4)
+#define ETBFF_MANUAL_FLUSH     BIT(6)
+#define ETBFF_TRIGIN           BIT(8)
+#define ETBFF_TRIGEVT          BIT(9)
+#define ETBFF_TRIGFL           BIT(10)
 
 #define etb_writel(t, v, x) \
        (__raw_writel((v), (t)->etb_regs + (x)))
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..4d8ae9d
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef _ARM_HW_BREAKPOINT_H
+#define _ARM_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+
+struct task_struct;
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+
+struct arch_hw_breakpoint_ctrl {
+               u32 __reserved  : 9,
+               mismatch        : 1,
+                               : 9,
+               len             : 8,
+               type            : 2,
+               privilege       : 2,
+               enabled         : 1;
+};
+
+struct arch_hw_breakpoint {
+       u32     address;
+       u32     trigger;
+       struct perf_event *suspended_wp;
+       struct arch_hw_breakpoint_ctrl ctrl;
+};
+
+static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
+{
+       return (ctrl.mismatch << 22) | (ctrl.len << 5) | (ctrl.type << 3) |
+               (ctrl.privilege << 1) | ctrl.enabled;
+}
+
+static inline void decode_ctrl_reg(u32 reg,
+                                  struct arch_hw_breakpoint_ctrl *ctrl)
+{
+       ctrl->enabled   = reg & 0x1;
+       reg >>= 1;
+       ctrl->privilege = reg & 0x3;
+       reg >>= 2;
+       ctrl->type      = reg & 0x3;
+       reg >>= 2;
+       ctrl->len       = reg & 0xff;
+       reg >>= 17;
+       ctrl->mismatch  = reg & 0x1;
+}
+
+/* Debug architecture numbers. */
+#define ARM_DEBUG_ARCH_RESERVED        0       /* In case of ptrace ABI updates. */
+#define ARM_DEBUG_ARCH_V6      1
+#define ARM_DEBUG_ARCH_V6_1    2
+#define ARM_DEBUG_ARCH_V7_ECP14        3
+#define ARM_DEBUG_ARCH_V7_MM   4
+
+/* Breakpoint */
+#define ARM_BREAKPOINT_EXECUTE 0
+
+/* Watchpoints */
+#define ARM_BREAKPOINT_LOAD    1
+#define ARM_BREAKPOINT_STORE   2
+
+/* Privilege Levels */
+#define ARM_BREAKPOINT_PRIV    1
+#define ARM_BREAKPOINT_USER    2
+
+/* Lengths */
+#define ARM_BREAKPOINT_LEN_1   0x1
+#define ARM_BREAKPOINT_LEN_2   0x3
+#define ARM_BREAKPOINT_LEN_4   0xf
+#define ARM_BREAKPOINT_LEN_8   0xff
+
+/* Limits */
+#define ARM_MAX_BRP            16
+#define ARM_MAX_WRP            16
+#define ARM_MAX_HBP_SLOTS      (ARM_MAX_BRP + ARM_MAX_WRP)
+
+/* DSCR method of entry bits. */
+#define ARM_DSCR_MOE(x)                        ((x >> 2) & 0xf)
+#define ARM_ENTRY_BREAKPOINT           0x1
+#define ARM_ENTRY_ASYNC_WATCHPOINT     0x2
+#define ARM_ENTRY_SYNC_WATCHPOINT      0xa
+
+/* DSCR monitor/halting bits. */
+#define ARM_DSCR_HDBGEN                (1 << 14)
+#define ARM_DSCR_MDBGEN                (1 << 15)
+
+/* opcode2 numbers for the co-processor instructions. */
+#define ARM_OP2_BVR            4
+#define ARM_OP2_BCR            5
+#define ARM_OP2_WVR            6
+#define ARM_OP2_WCR            7
+
+/* Base register numbers for the debug registers. */
+#define ARM_BASE_BVR           64
+#define ARM_BASE_BCR           80
+#define ARM_BASE_WVR           96
+#define ARM_BASE_WCR           112
+
+/* Accessor macros for the debug registers. */
+#define ARM_DBG_READ(M, OP2, VAL) do {\
+       asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+} while (0)
+
+#define ARM_DBG_WRITE(M, OP2, VAL) do {\
+       asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+} while (0)
+
+struct notifier_block;
+struct perf_event;
+struct pmu;
+
+extern struct pmu perf_ops_bp;
+extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+                                 int *gen_len, int *gen_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+                                          unsigned long val, void *data);
+
+extern u8 arch_get_debug_arch(void);
+extern u8 arch_get_max_wp_len(void);
+extern void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+int hw_breakpoint_slots(int type);
+
+#else
+static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk) {}
+
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+#endif /* __KERNEL__ */
+#endif /* _ARM_HW_BREAKPOINT_H */
index 90831f6f5f5cb9b033097f895cfb5edc5dc8b7b6..5586b7c8ef6fd7b1f112890d07e87b03aa695257 100644 (file)
@@ -24,4 +24,6 @@ void set_irq_flags(unsigned int irq, unsigned int flags);
 #define IRQF_PROBE     (1 << 1)
 #define IRQF_NOAUTOEN  (1 << 2)
 
+#define ARCH_IRQ_INIT_FLAGS    (IRQ_NOREQUEST | IRQ_NOPROBE)
+
 #endif
index 1261b1f928d95a9ac1cf374148208415c4dc248d..815efa2d4e07b5087e31965a06fc05c1fdfd9fa0 100644 (file)
@@ -294,6 +294,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 extern int valid_phys_addr_range(unsigned long addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+extern int devmem_is_allowed(unsigned long pfn);
 #endif
 
 /*
index 6d09974e66462c6801d869dafbf7d3e54b9c45d7..1e6cca55c750486b98ef85ca5a04c9af471d64ea 100644 (file)
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
-#define raw_local_irq_save(x)                                  \
-       ({                                                      \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_save\n"     \
-       "cpsid  i"                                              \
-       : "=r" (x) : : "memory", "cc");                         \
-       })
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+
+       asm volatile(
+               "       mrs     %0, cpsr        @ arch_local_irq_save\n"
+               "       cpsid   i"
+               : "=r" (flags) : : "memory", "cc");
+       return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile(
+               "       cpsie i                 @ arch_local_irq_enable"
+               :
+               :
+               : "memory", "cc");
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile(
+               "       cpsid i                 @ arch_local_irq_disable"
+               :
+               :
+               : "memory", "cc");
+}
 
-#define raw_local_irq_enable()  __asm__("cpsie i       @ __sti" : : : "memory", "cc")
-#define raw_local_irq_disable() __asm__("cpsid i       @ __cli" : : : "memory", "cc")
 #define local_fiq_enable()  __asm__("cpsie f   @ __stf" : : : "memory", "cc")
 #define local_fiq_disable() __asm__("cpsid f   @ __clf" : : : "memory", "cc")
-
 #else
 
 /*
  * Save the current interrupt enable state & disable IRQs
  */
-#define raw_local_irq_save(x)                                  \
-       ({                                                      \
-               unsigned long temp;                             \
-               (void) (&temp == &x);                           \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_save\n"     \
-"      orr     %1, %0, #128\n"                                 \
-"      msr     cpsr_c, %1"                                     \
-       : "=r" (x), "=r" (temp)                                 \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-       
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags, temp;
+
+       asm volatile(
+               "       mrs     %0, cpsr        @ arch_local_irq_save\n"
+               "       orr     %1, %0, #128\n"
+               "       msr     cpsr_c, %1"
+               : "=r" (flags), "=r" (temp)
+               :
+               : "memory", "cc");
+       return flags;
+}
+
 /*
  * Enable IRQs
  */
-#define raw_local_irq_enable()                                 \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_enable\n"   \
-"      bic     %0, %0, #128\n"                                 \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
+static inline void arch_local_irq_enable(void)
+{
+       unsigned long temp;
+       asm volatile(
+               "       mrs     %0, cpsr        @ arch_local_irq_enable\n"
+               "       bic     %0, %0, #128\n"
+               "       msr     cpsr_c, %0"
+               : "=r" (temp)
+               :
+               : "memory", "cc");
+}
 
 /*
  * Disable IRQs
  */
-#define raw_local_irq_disable()                                        \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_disable\n"  \
-"      orr     %0, %0, #128\n"                                 \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
+static inline void arch_local_irq_disable(void)
+{
+       unsigned long temp;
+       asm volatile(
+               "       mrs     %0, cpsr        @ arch_local_irq_disable\n"
+               "       orr     %0, %0, #128\n"
+               "       msr     cpsr_c, %0"
+               : "=r" (temp)
+               :
+               : "memory", "cc");
+}
 
 /*
  * Enable FIQs
 /*
  * Save the current interrupt enable state.
  */
-#define raw_local_save_flags(x)                                        \
-       ({                                                      \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_save_flags"     \
-       : "=r" (x) : : "memory", "cc");                         \
-       })
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile(
+               "       mrs     %0, cpsr        @ local_save_flags"
+               : "=r" (flags) : : "memory", "cc");
+       return flags;
+}
 
 /*
  * restore saved IRQ & FIQ state
  */
-#define raw_local_irq_restore(x)                               \
-       __asm__ __volatile__(                                   \
-       "msr    cpsr_c, %0              @ local_irq_restore\n"  \
-       :                                                       \
-       : "r" (x)                                               \
-       : "memory", "cc")
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile(
+               "       msr     cpsr_c, %0      @ local_irq_restore"
+               :
+               : "r" (flags)
+               : "memory", "cc");
+}
 
-#define raw_irqs_disabled_flags(flags) \
-({                                     \
-       (int)((flags) & PSR_I_BIT);     \
-})
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+       return flags & PSR_I_BIT;
+}
 
 #endif
 #endif
index 8a0dd18ba6427301ed4b802739a390dec64d12c2..d97a964207fa15693c011f88f27dc64f4c7c3f16 100644 (file)
@@ -16,18 +16,15 @@ struct sys_timer;
 
 struct machine_desc {
        /*
-        * Note! The first four elements are used
+        * Note! The first two elements are used
         * by assembler code in head.S, head-common.S
         */
        unsigned int            nr;             /* architecture number  */
-       unsigned int            nr_irqs;        /* number of IRQs */
-       unsigned int            phys_io;        /* start of physical io */
-       unsigned int            io_pg_offst;    /* byte offset for io 
-                                                * page tabe entry      */
-
        const char              *name;          /* architecture name    */
        unsigned long           boot_params;    /* tagged list          */
 
+       unsigned int            nr_irqs;        /* number of IRQs */
+
        unsigned int            video_start;    /* start of video RAM   */
        unsigned int            video_end;      /* end of video RAM     */
 
index a0b3cac0547c0a9949c30cc919adcf5e08fcf500..71605d9f8e421ad36a058992c032ad5459114929 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/proc-fns.h>
-#include <asm-generic/mm_hooks.h>
 
 void __check_kvm_seq(struct mm_struct *mm);
 
@@ -134,4 +133,32 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #define deactivate_mm(tsk,mm)  do { } while (0)
 #define activate_mm(prev,next) switch_mm(prev, next, NULL)
 
+/*
+ * We are inserting a "fake" vma for the user-accessible vector page so
+ * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
+ * But we also want to remove it before the generic code gets to see it
+ * during process exit or the unmapping of it would  cause total havoc.
+ * (the macro is used as remove_vma() is static to mm/mmap.c)
+ */
+#define arch_exit_mmap(mm) \
+do { \
+       struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
+       if (high_vma) { \
+               BUG_ON(high_vma->vm_next);  /* it should be last */ \
+               if (high_vma->vm_prev) \
+                       high_vma->vm_prev->vm_next = NULL; \
+               else \
+                       mm->mmap = NULL; \
+               rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
+               mm->mmap_cache = NULL; \
+               mm->map_count--; \
+               remove_vma(high_vma); \
+       } \
+} while (0)
+
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+                                struct mm_struct *mm)
+{
+}
+
 #endif
index e4dfa69abb68fa4868eaaacd2bdd67b83876704e..cbb0bc295d2b184d380e63920dcb55930c7b76b7 100644 (file)
@@ -7,20 +7,27 @@
 
 struct unwind_table;
 
-struct mod_arch_specific
-{
 #ifdef CONFIG_ARM_UNWIND
-       Elf_Shdr *unw_sec_init;
-       Elf_Shdr *unw_sec_devinit;
-       Elf_Shdr *unw_sec_core;
-       Elf_Shdr *sec_init_text;
-       Elf_Shdr *sec_devinit_text;
-       Elf_Shdr *sec_core_text;
-       struct unwind_table *unwind_init;
-       struct unwind_table *unwind_devinit;
-       struct unwind_table *unwind_core;
-#endif
+struct arm_unwind_mapping {
+       Elf_Shdr *unw_sec;
+       Elf_Shdr *sec_text;
+       struct unwind_table *unwind;
+};
+enum {
+       ARM_SEC_INIT,
+       ARM_SEC_DEVINIT,
+       ARM_SEC_CORE,
+       ARM_SEC_EXIT,
+       ARM_SEC_DEVEXIT,
+       ARM_SEC_MAX,
+};
+struct mod_arch_specific {
+       struct arm_unwind_mapping map[ARM_SEC_MAX];
 };
+#else
+struct mod_arch_specific {
+};
+#endif
 
 /*
  * Include the ARM architecture version.
index 48837e6d888722dc96f594247a80026bf9b75e29..c4aa4e8c6af9cda0b7e88a46cbed94dc6e3b565d 100644 (file)
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-/*
- * NOP: on *most* (read: all supported) ARM platforms, the performance
- * counter interrupts are regular interrupts and not an NMI. This
- * means that when we receive the interrupt we can call
- * perf_event_do_pending() that handles all of the work with
- * interrupts enabled.
- */
-static inline void
-set_perf_event_pending(void)
-{
-}
-
 /* ARM performance counters start from 1 (in the cp15 accesses) so use the
  * same indexes here for consistency. */
 #define PERF_EVENT_INDEX_OFFSET 1
index ab68cf1ef80fe7ccad28bfdd5d5084bb6f1b61dc..a9672e8406a3cdb5efd45f69b0cbe10e47196ec2 100644 (file)
@@ -278,9 +278,24 @@ extern struct page *empty_zero_page;
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
 
-#define set_pte_at(mm,addr,ptep,pteval) do { \
-       set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
- } while (0)
+#if __LINUX_ARM_ARCH__ < 6
+static inline void __sync_icache_dcache(pte_t pteval)
+{
+}
+#else
+extern void __sync_icache_dcache(pte_t pteval);
+#endif
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval)
+{
+       if (addr >= TASK_SIZE)
+               set_pte_ext(ptep, pteval, 0);
+       else {
+               __sync_icache_dcache(pteval);
+               set_pte_ext(ptep, pteval, PTE_EXT_NG);
+       }
+}
 
 /*
  * The following only work if pte_present() is true.
@@ -290,8 +305,13 @@ extern struct page *empty_zero_page;
 #define pte_write(pte)         (pte_val(pte) & L_PTE_WRITE)
 #define pte_dirty(pte)         (pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)         (pte_val(pte) & L_PTE_YOUNG)
+#define pte_exec(pte)          (pte_val(pte) & L_PTE_EXEC)
 #define pte_special(pte)       (0)
 
+#define pte_present_user(pte) \
+       ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+        (L_PTE_PRESENT | L_PTE_USER))
+
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
@@ -317,6 +337,10 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
 #define pgprot_dmacoherent(prot) \
        __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
 #else
 #define pgprot_dmacoherent(prot) \
        __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
index 7bed3daf83b8f27547ac608d574ffb00de8d1871..67357baaeeebd93417932c70ca0d370d17818f51 100644 (file)
@@ -19,6 +19,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
@@ -41,6 +42,9 @@ struct debug_entry {
 struct debug_info {
        int                     nsaved;
        struct debug_entry      bp[2];
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+       struct perf_event       *hbp[ARM_MAX_HBP_SLOTS];
+#endif
 };
 
 struct thread_struct {
index 7ce15eb15f72992289c899b5fa05385300aa0c8e..783d50f326181c274facb3c2de3a91975a29ee7f 100644 (file)
@@ -29,6 +29,8 @@
 #define PTRACE_SETCRUNCHREGS   26
 #define PTRACE_GETVFPREGS      27
 #define PTRACE_SETVFPREGS      28
+#define PTRACE_GETHBPREGS      29
+#define PTRACE_SETHBPREGS      30
 
 /*
  * PSR bits
diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..52b156b
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_ARM_SECCOMP_H
+#define _ASM_ARM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#endif /* _ASM_ARM_SECCOMP_H */
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
new file mode 100644 (file)
index 0000000..6a9307d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef ASMARM_SMP_MIDR_H
+#define ASMARM_SMP_MIDR_H
+
+#define hard_smp_processor_id()                                                \
+       ({                                                              \
+               unsigned int cpunum;                                    \
+               __asm__("\n"                                            \
+                       "1:     mrc p15, 0, %0, c0, c0, 5\n"            \
+                       "       .pushsection \".alt.smp.init\", \"a\"\n"\
+                       "       .long   1b\n"                           \
+                       "       mov     %0, #0\n"                       \
+                       "       .popsection"                            \
+                       : "=r" (cpunum));                               \
+               cpunum &= 0x0F;                                         \
+       })
+
+#endif
index e6215305544aa9c63db768c53a7c194fe38c6747..f24c1b9e211dd180a6caf548260110a33f75b33c 100644 (file)
@@ -7,15 +7,40 @@
 
 #include <asm/cputype.h>
 
+/*
+ * Return true if we are running on a SMP platform
+ */
+static inline bool is_smp(void)
+{
+#ifndef CONFIG_SMP
+       return false;
+#elif defined(CONFIG_SMP_ON_UP)
+       extern unsigned int smp_on_up;
+       return !!smp_on_up;
+#else
+       return true;
+#endif
+}
+
 /* all SMP configurations have the extended CPUID registers */
 static inline int tlb_ops_need_broadcast(void)
 {
+       if (!is_smp())
+               return 0;
+
        return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
 }
 
+#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7
+#define cache_ops_need_broadcast()     0
+#else
 static inline int cache_ops_need_broadcast(void)
 {
+       if (!is_smp())
+               return 0;
+
        return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
 }
+#endif
 
 #endif
index 8ba1ccf82a0200283367db344ed79259f8d57c05..1120f18a6b17695e48c37a6b4d1d7e50d306e478 100644 (file)
@@ -85,6 +85,10 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
                                       struct pt_regs *),
                     int sig, int code, const char *name);
 
+void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
+                                      struct pt_regs *),
+                    int sig, int code, const char *name);
+
 #define xchg(ptr,x) \
        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
@@ -325,6 +329,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
 extern void disable_hlt(void);
 extern void enable_hlt(void);
 
+void cpu_idle_wait(void);
+
 #include <asm-generic/cmpxchg-local.h>
 
 #if __LINUX_ARM_ARCH__ < 6
index 763e29fa85300b23180221a0c832c71b71b3e382..7b5cc8dae06e6e99b1dfc18edf6cef748629f25f 100644 (file)
@@ -144,6 +144,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_FREEZE             19
 #define TIF_RESTORE_SIGMASK    20
+#define TIF_SECCOMP            21
 
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
@@ -153,6 +154,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define _TIF_USING_IWMMXT      (1 << TIF_USING_IWMMXT)
 #define _TIF_FREEZE            (1 << TIF_FREEZE)
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 
 /*
  * Change these and you break ASM code in entry-common.S
index 33b546ae72d49c82545271372a1972283f7ddb5b..ce7378ea15a2b30c3aea7ce22d0a793b8838d7c4 100644 (file)
 #undef _TLB
 #undef MULTI_TLB
 
+#ifdef CONFIG_SMP_ON_UP
+#define MULTI_TLB 1
+#endif
+
 #define v3_tlb_flags   (TLB_V3_FULL | TLB_V3_PAGE)
 
 #ifdef CONFIG_CPU_TLB_V3
 # define v6wbi_always_flags    (-1UL)
 #endif
 
-#ifdef CONFIG_SMP
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
+#define v7wbi_tlb_flags_smp    (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
                         TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
-#else
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags_up     (TLB_WB | TLB_DCLEAN | TLB_BTB | \
                         TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
-#endif
 
 #ifdef CONFIG_CPU_TLB_V7
-# define v7wbi_possible_flags  v7wbi_tlb_flags
-# define v7wbi_always_flags    v7wbi_tlb_flags
+
+# ifdef CONFIG_SMP_ON_UP
+#  define v7wbi_possible_flags (v7wbi_tlb_flags_smp | v7wbi_tlb_flags_up)
+#  define v7wbi_always_flags   (v7wbi_tlb_flags_smp & v7wbi_tlb_flags_up)
+# elif defined(CONFIG_SMP)
+#  define v7wbi_possible_flags v7wbi_tlb_flags_smp
+#  define v7wbi_always_flags   v7wbi_tlb_flags_smp
+# else
+#  define v7wbi_possible_flags v7wbi_tlb_flags_up
+#  define v7wbi_always_flags   v7wbi_tlb_flags_up
+# endif
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
@@ -560,12 +570,20 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
 #endif
 
 /*
- * if PG_dcache_dirty is set for the page, we need to ensure that any
+ * If PG_dcache_clean is not set for the page, we need to ensure that any
  * cache entries for the kernels virtual memory range are written
- * back to the page.
+ * back to the page. On ARMv6 and later, the cache coherency is handled via
+ * the set_pte_at() function.
  */
+#if __LINUX_ARM_ARCH__ < 6
 extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
        pte_t *ptep);
+#else
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+                                   unsigned long addr, pte_t *ptep)
+{
+}
+#endif
 
 #endif
 
index d02cfb683487eeafea4ef407a1a4e6f2d4ce4112..c891eb76c0e313406847e7b9fbe968bb1b8fa459 100644 (file)
 #define __NR_perf_event_open           (__NR_SYSCALL_BASE+364)
 #define __NR_recvmmsg                  (__NR_SYSCALL_BASE+365)
 #define __NR_accept4                   (__NR_SYSCALL_BASE+366)
+#define __NR_fanotify_init             (__NR_SYSCALL_BASE+367)
+#define __NR_fanotify_mark             (__NR_SYSCALL_BASE+368)
+#define __NR_prlimit64                 (__NR_SYSCALL_BASE+369)
 
 /*
  * The following SWIs are ARM private.
index 980b78e31328156925f361cf5f6a2deac14c1500..5b9b268f4fbb368ecc34942c6bebed1c421beaca 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_KGDB)            += kgdb.o
 obj-$(CONFIG_ARM_UNWIND)       += unwind.o
 obj-$(CONFIG_HAVE_TCM)         += tcm.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o           := -Wa,-mcpu=ep9312
index 8214bfebfaca6625226f8b2dd041d978e5ddc25e..e5e1e5387678f7ff5d9df7811b4f902c2b385f41 100644 (file)
@@ -165,6 +165,8 @@ EXPORT_SYMBOL(_find_next_bit_be);
 #endif
 
 #ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_OLD_MCOUNT
 EXPORT_SYMBOL(mcount);
+#endif
 EXPORT_SYMBOL(__gnu_mcount_nc);
 #endif
index 85f2a019f77bc93b17e0c55bf60693d18a8e2ffa..82da661721327c12744b58f3a7686e76f182cff3 100644 (file)
@@ -102,8 +102,6 @@ int main(void)
   DEFINE(SIZEOF_MACHINE_DESC,  sizeof(struct machine_desc));
   DEFINE(MACHINFO_TYPE,                offsetof(struct machine_desc, nr));
   DEFINE(MACHINFO_NAME,                offsetof(struct machine_desc, name));
-  DEFINE(MACHINFO_PHYSIO,      offsetof(struct machine_desc, phys_io));
-  DEFINE(MACHINFO_PGOFFIO,     offsetof(struct machine_desc, io_pg_offst));
   BLANK();
   DEFINE(PROC_INFO_SZ,         sizeof(struct proc_info_list));
   DEFINE(PROCINFO_INITFUNC,    offsetof(struct proc_info_list, __cpu_flush));
index afeb71fa72cb81fc0e2fb5652c653ef34e7258bb..5c26eccef9982665b1e1672416b9bc996f3b2dae 100644 (file)
                CALL(sys_perf_event_open)
 /* 365 */      CALL(sys_recvmmsg)
                CALL(sys_accept4)
+               CALL(sys_fanotify_init)
+               CALL(sys_fanotify_mark)
+               CALL(sys_prlimit64)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index a38b4879441d1715b42c4e7994f9f4d8e67b7fe4..a0f07521ca8a2dd1b5a3ffc375b6eaadc9f51131 100644 (file)
 #if defined(CONFIG_DEBUG_ICEDCC)
                @@ debug using ARM EmbeddedICE DCC channel
 
-#if defined(CONFIG_CPU_V6)
-
-               .macro  addruart, rx, tmp
+               .macro  addruart, rp, rv
                .endm
 
+#if defined(CONFIG_CPU_V6)
+
                .macro  senduart, rd, rx
                mcr     p14, 0, \rd, c0, c5, 0
                .endm
@@ -51,9 +51,6 @@
 
 #elif defined(CONFIG_CPU_V7)
 
-               .macro  addruart, rx, tmp
-               .endm
-
                .macro  senduart, rd, rx
                mcr     p14, 0, \rd, c0, c5, 0
                .endm
@@ -71,9 +68,6 @@ wait:         mrc     p14, 0, pc, c0, c1, 0
 
 #elif defined(CONFIG_CPU_XSCALE)
 
-               .macro  addruart, rx, tmp
-               .endm
-
                .macro  senduart, rd, rx
                mcr     p14, 0, \rd, c8, c0, 0
                .endm
@@ -98,9 +92,6 @@ wait:         mrc     p14, 0, pc, c0, c1, 0
 
 #else
 
-               .macro  addruart, rx, tmp
-               .endm
-
                .macro  senduart, rd, rx
                mcr     p14, 0, \rd, c1, c0, 0
                .endm
@@ -130,6 +121,22 @@ wait:              mrc     p14, 0, pc, c0, c1, 0
 #include <mach/debug-macro.S>
 #endif /* CONFIG_DEBUG_ICEDCC */
 
+#ifdef CONFIG_MMU
+               .macro  addruart_current, rx, tmp1, tmp2
+               addruart        \tmp1, \tmp2
+               mrc             p15, 0, \rx, c1, c0
+               tst             \rx, #1
+               moveq           \rx, \tmp1
+               movne           \rx, \tmp2
+               .endm
+
+#else /* !CONFIG_MMU */
+               .macro  addruart_current, rx, tmp1, tmp2
+               addruart        \rx, \tmp1
+               .endm
+
+#endif /* CONFIG_MMU */
+
 /*
  * Useful debugging routines
  */
@@ -164,7 +171,7 @@ ENDPROC(printhex2)
                .ltorg
 
 ENTRY(printascii)
-               addruart r3, r1
+               addruart_current r3, r1, r2
                b       2f
 1:             waituart r2, r3
                senduart r1, r3
@@ -180,7 +187,7 @@ ENTRY(printascii)
 ENDPROC(printascii)
 
 ENTRY(printch)
-               addruart r3, r1
+               addruart_current r3, r1, r2
                mov     r1, r0
                mov     r0, #0
                b       1b
index bb8e93a76407241042345c51273690f6cdc35578..c09e3573c5deb5795042eb1073f210472b0eadbc 100644 (file)
@@ -46,7 +46,8 @@
         * this macro assumes that irqstat (r6) and base (r5) are
         * preserved from get_irqnr_and_base above
         */
-       test_for_ipi r0, r6, r5, lr
+       ALT_SMP(test_for_ipi r0, r6, r5, lr)
+       ALT_UP_B(9997f)
        movne   r0, sp
        adrne   lr, BSYM(1b)
        bne     do_IPI
@@ -57,6 +58,7 @@
        adrne   lr, BSYM(1b)
        bne     do_local_timer
 #endif
+9997:
 #endif
 
        .endm
@@ -965,11 +967,8 @@ kuser_cmpxchg_fixup:
        beq     1b
        rsbs    r0, r3, #0
        /* beware -- each __kuser slot must be 8 instructions max */
-#ifdef CONFIG_SMP
-       b       __kuser_memory_barrier
-#else
-       usr_ret lr
-#endif
+       ALT_SMP(b       __kuser_memory_barrier)
+       ALT_UP(usr_ret  lr)
 
 #endif
 
index f05a35a59694dc7af54a76ffb899e02f8b849875..8bfa98757cd2f3fc9ef128011944a55fa7838ffd 100644 (file)
@@ -48,6 +48,8 @@ work_pending:
        beq     no_work_pending
        mov     r0, sp                          @ 'regs'
        mov     r2, why                         @ 'syscall'
+       tst     r1, #_TIF_SIGPENDING            @ delivering a signal?
+       movne   why, #0                         @ prevent further restarts
        bl      do_notify_resume
        b       ret_slow_syscall                @ Check work again
 
@@ -127,30 +129,58 @@ ENDPROC(ret_from_fork)
  * clobber the ip register.  This is OK because the ARM calling convention
  * allows it to be clobbered in subroutines and doesn't use it to hold
  * parameters.)
+ *
+ * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0"
+ * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see
+ * arch/arm/kernel/ftrace.c).
  */
+
+#ifndef CONFIG_OLD_MCOUNT
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0.
+#endif
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(mcount)
+ENTRY(__gnu_mcount_nc)
+       mov     ip, lr
+       ldmia   sp!, {lr}
+       mov     pc, ip
+ENDPROC(__gnu_mcount_nc)
+
+ENTRY(ftrace_caller)
        stmdb   sp!, {r0-r3, lr}
        mov     r0, lr
        sub     r0, r0, #MCOUNT_INSN_SIZE
+       ldr     r1, [sp, #20]
 
-       .globl mcount_call
-mcount_call:
+       .global ftrace_call
+ftrace_call:
        bl      ftrace_stub
-       ldr     lr, [fp, #-4]                   @ restore lr
-       ldmia   sp!, {r0-r3, pc}
+       ldmia   sp!, {r0-r3, ip, lr}
+       mov     pc, ip
+ENDPROC(ftrace_caller)
 
-ENTRY(ftrace_caller)
+#ifdef CONFIG_OLD_MCOUNT
+ENTRY(mcount)
+       stmdb   sp!, {lr}
+       ldr     lr, [fp, #-4]
+       ldmia   sp!, {pc}
+ENDPROC(mcount)
+
+ENTRY(ftrace_caller_old)
        stmdb   sp!, {r0-r3, lr}
        ldr     r1, [fp, #-4]
        mov     r0, lr
        sub     r0, r0, #MCOUNT_INSN_SIZE
 
-       .globl ftrace_call
-ftrace_call:
+       .globl ftrace_call_old
+ftrace_call_old:
        bl      ftrace_stub
        ldr     lr, [fp, #-4]                   @ restore lr
        ldmia   sp!, {r0-r3, pc}
+ENDPROC(ftrace_caller_old)
+#endif
 
 #else
 
@@ -158,7 +188,7 @@ ENTRY(__gnu_mcount_nc)
        stmdb   sp!, {r0-r3, lr}
        ldr     r0, =ftrace_trace_function
        ldr     r2, [r0]
-       adr     r0, ftrace_stub
+       adr     r0, .Lftrace_stub
        cmp     r0, r2
        bne     gnu_trace
        ldmia   sp!, {r0-r3, ip, lr}
@@ -168,11 +198,19 @@ gnu_trace:
        ldr     r1, [sp, #20]                   @ lr of instrumented routine
        mov     r0, lr
        sub     r0, r0, #MCOUNT_INSN_SIZE
-       mov     lr, pc
+       adr     lr, BSYM(1f)
        mov     pc, r2
+1:
        ldmia   sp!, {r0-r3, ip, lr}
        mov     pc, ip
+ENDPROC(__gnu_mcount_nc)
 
+#ifdef CONFIG_OLD_MCOUNT
+/*
+ * This is under an ifdef in order to force link-time errors for people trying
+ * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
+ * mcount.
+ */
 ENTRY(mcount)
        stmdb   sp!, {r0-r3, lr}
        ldr     r0, =ftrace_trace_function
@@ -191,12 +229,15 @@ trace:
        mov     pc, r2
        ldr     lr, [fp, #-4]                   @ restore lr
        ldmia   sp!, {r0-r3, pc}
+ENDPROC(mcount)
+#endif
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
-       .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
+.Lftrace_stub:
        mov     pc, lr
+ENDPROC(ftrace_stub)
 
 #endif /* CONFIG_FUNCTION_TRACER */
 
@@ -293,7 +334,6 @@ ENTRY(vector_swi)
 
        get_thread_info tsk
        adr     tbl, sys_call_table             @ load syscall table pointer
-       ldr     ip, [tsk, #TI_FLAGS]            @ check for syscall tracing
 
 #if defined(CONFIG_OABI_COMPAT)
        /*
@@ -310,8 +350,20 @@ ENTRY(vector_swi)
        eor     scno, scno, #__NR_SYSCALL_BASE  @ check OS number
 #endif
 
+       ldr     r10, [tsk, #TI_FLAGS]           @ check for syscall tracing
        stmdb   sp!, {r4, r5}                   @ push fifth and sixth args
-       tst     ip, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
+
+#ifdef CONFIG_SECCOMP
+       tst     r10, #_TIF_SECCOMP
+       beq     1f
+       mov     r0, scno
+       bl      __secure_computing      
+       add     r0, sp, #S_R0 + S_OFF           @ pointer to regs
+       ldmia   r0, {r0 - r3}                   @ have to reload r0 - r3
+1:
+#endif
+
+       tst     r10, #_TIF_SYSCALL_TRACE                @ are we tracing syscalls?
        bne     __sys_trace
 
        cmp     scno, #NR_syscalls              @ check upper syscall limit
@@ -418,11 +470,13 @@ ENDPROC(sys_clone_wrapper)
 
 sys_sigreturn_wrapper:
                add     r0, sp, #S_OFF
+               mov     why, #0         @ prevent syscall restart handling
                b       sys_sigreturn
 ENDPROC(sys_sigreturn_wrapper)
 
 sys_rt_sigreturn_wrapper:
                add     r0, sp, #S_OFF
+               mov     why, #0         @ prevent syscall restart handling
                b       sys_rt_sigreturn
 ENDPROC(sys_rt_sigreturn_wrapper)
 
index 56418f98cd016e9e3668e15c4473c9ba43bf1ca6..11db62806a1a205b82f74b6c55d22dc772d80120 100644 (file)
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shishkin");
 
+/*
+ * ETM tracer state
+ */
+struct tracectx {
+       unsigned int    etb_bufsz;
+       void __iomem    *etb_regs;
+       void __iomem    *etm_regs;
+       unsigned long   flags;
+       int             ncmppairs;
+       int             etm_portsz;
+       struct device   *dev;
+       struct clk      *emu_clk;
+       struct mutex    mutex;
+};
+
 static struct tracectx tracer;
 
 static inline bool trace_isrunning(struct tracectx *t)
@@ -230,7 +245,7 @@ static void etm_dump(void)
        etb_lock(t);
 }
 
-static void sysrq_etm_dump(int key, struct tty_struct *tty)
+static void sysrq_etm_dump(int key)
 {
        dev_dbg(tracer.dev, "Dumping ETB buffer\n");
        etm_dump();
@@ -314,6 +329,7 @@ static const struct file_operations etb_fops = {
        .read = etb_read,
        .open = etb_open,
        .release = etb_release,
+       .llseek = no_llseek,
 };
 
 static struct miscdevice etb_miscdev = {
index 0298286ad4ad5971302a6690c5046e66826bccb2..971ac8c36ea775ca58702cb0f17c18aba7b1c4a7 100644 (file)
  * Dynamic function tracing support.
  *
  * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
+ * Copyright (C) 2010 Rabin Vincent <rabin@rab.in>
  *
  * For licencing details, see COPYING.
  *
  * Defines low-level handling of mcount calls when the kernel
  * is compiled with the -pg flag. When using dynamic ftrace, the
- * mcount call-sites get patched lazily with NOP till they are
- * enabled. All code mutation routines here take effect atomically.
+ * mcount call-sites get patched with NOP till they are enabled.
+ * All code mutation routines here are called under stop_machine().
  */
 
 #include <linux/ftrace.h>
+#include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
 #include <asm/ftrace.h>
 
-#define PC_OFFSET      8
-#define BL_OPCODE      0xeb000000
-#define BL_OFFSET_MASK 0x00ffffff
+#ifdef CONFIG_THUMB2_KERNEL
+#define        NOP             0xeb04f85d      /* pop.w {lr} */
+#else
+#define        NOP             0xe8bd4000      /* pop {lr} */
+#endif
 
-static unsigned long bl_insn;
-static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
+#ifdef CONFIG_OLD_MCOUNT
+#define OLD_MCOUNT_ADDR        ((unsigned long) mcount)
+#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
 
-unsigned char *ftrace_nop_replace(void)
+#define        OLD_NOP         0xe1a00000      /* mov r0, r0 */
+
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
 {
-       return (char *)&NOP;
+       return rec->arch.old_mcount ? OLD_NOP : NOP;
 }
 
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+       if (!rec->arch.old_mcount)
+               return addr;
+
+       if (addr == MCOUNT_ADDR)
+               addr = OLD_MCOUNT_ADDR;
+       else if (addr == FTRACE_ADDR)
+               addr = OLD_FTRACE_ADDR;
+
+       return addr;
+}
+#else
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
+{
+       return NOP;
+}
+
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+       return addr;
+}
+#endif
+
 /* construct a branch (BL) instruction to addr */
-unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
+#ifdef CONFIG_THUMB2_KERNEL
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
 {
+       unsigned long s, j1, j2, i1, i2, imm10, imm11;
+       unsigned long first, second;
        long offset;
 
-       offset = (long)addr - (long)(pc + PC_OFFSET);
+       offset = (long)addr - (long)(pc + 4);
+       if (offset < -16777216 || offset > 16777214) {
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+
+       s       = (offset >> 24) & 0x1;
+       i1      = (offset >> 23) & 0x1;
+       i2      = (offset >> 22) & 0x1;
+       imm10   = (offset >> 12) & 0x3ff;
+       imm11   = (offset >>  1) & 0x7ff;
+
+       j1 = (!i1) ^ s;
+       j2 = (!i2) ^ s;
+
+       first = 0xf000 | (s << 10) | imm10;
+       second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+
+       return (second << 16) | first;
+}
+#else
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+       long offset;
+
+       offset = (long)addr - (long)(pc + 8);
        if (unlikely(offset < -33554432 || offset > 33554428)) {
                /* Can't generate branches that far (from ARM ARM). Ftrace
                 * doesn't generate branches outside of kernel text.
                 */
                WARN_ON_ONCE(1);
-               return NULL;
+               return 0;
        }
-       offset = (offset >> 2) & BL_OFFSET_MASK;
-       bl_insn = BL_OPCODE | offset;
-       return (unsigned char *)&bl_insn;
-}
 
-int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
-                      unsigned char *new_code)
-{
-       unsigned long err = 0, replaced = 0, old, new;
+       offset = (offset >> 2) & 0x00ffffff;
 
-       old = *(unsigned long *)old_code;
-       new = *(unsigned long *)new_code;
+       return 0xeb000000 | offset;
+}
+#endif
 
-       __asm__ __volatile__ (
-               "1:  ldr    %1, [%2]  \n"
-               "    cmp    %1, %4    \n"
-               "2:  streq  %3, [%2]  \n"
-               "    cmpne  %1, %3    \n"
-               "    movne  %0, #2    \n"
-               "3:\n"
+static int ftrace_modify_code(unsigned long pc, unsigned long old,
+                             unsigned long new)
+{
+       unsigned long replaced;
 
-               ".pushsection .fixup, \"ax\"\n"
-               "4:  mov  %0, #1  \n"
-               "    b    3b      \n"
-               ".popsection\n"
+       if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+               return -EFAULT;
 
-               ".pushsection __ex_table, \"a\"\n"
-               "    .long 1b, 4b \n"
-               "    .long 2b, 4b \n"
-               ".popsection\n"
+       if (replaced != old)
+               return -EINVAL;
 
-               : "=r"(err), "=r"(replaced)
-               : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
-               : "memory");
+       if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
+               return -EPERM;
 
-       if (!err && (replaced == old))
-               flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+       flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
 
-       return err;
+       return 0;
 }
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-       int ret;
        unsigned long pc, old;
-       unsigned char *new;
+       unsigned long new;
+       int ret;
 
        pc = (unsigned long)&ftrace_call;
        memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
        new = ftrace_call_replace(pc, (unsigned long)func);
-       ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
+
+       ret = ftrace_modify_code(pc, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+       if (!ret) {
+               pc = (unsigned long)&ftrace_call_old;
+               memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
+               new = ftrace_call_replace(pc, (unsigned long)func);
+
+               ret = ftrace_modify_code(pc, old, new);
+       }
+#endif
+
+       return ret;
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned long new, old;
+       unsigned long ip = rec->ip;
+
+       old = ftrace_nop_replace(rec);
+       new = ftrace_call_replace(ip, adjust_address(rec, addr));
+
+       return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_make_nop(struct module *mod,
+                   struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned long ip = rec->ip;
+       unsigned long old;
+       unsigned long new;
+       int ret;
+
+       old = ftrace_call_replace(ip, adjust_address(rec, addr));
+       new = ftrace_nop_replace(rec);
+       ret = ftrace_modify_code(ip, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+       if (ret == -EINVAL && addr == MCOUNT_ADDR) {
+               rec->arch.old_mcount = true;
+
+               old = ftrace_call_replace(ip, adjust_address(rec, addr));
+               new = ftrace_nop_replace(rec);
+               ret = ftrace_modify_code(ip, old, new);
+       }
+#endif
+
        return ret;
 }
 
-/* run from ftrace_init with irqs disabled */
 int __init ftrace_dyn_arch_init(void *data)
 {
-       ftrace_mcount_set(data);
+       *(unsigned long *)data = 0;
+
        return 0;
 }
index b9505aa267c003a84b2101b1e66af809932f867e..bbecaac1e0135132dd7b208735fd18130030ec76 100644 (file)
 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
 #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
 
-       .align  2
-       .type   __switch_data, %object
-__switch_data:
-       .long   __mmap_switched
-       .long   __data_loc                      @ r4
-       .long   _data                           @ r5
-       .long   __bss_start                     @ r6
-       .long   _end                            @ r7
-       .long   processor_id                    @ r4
-       .long   __machine_arch_type             @ r5
-       .long   __atags_pointer                 @ r6
-       .long   cr_alignment                    @ r7
-       .long   init_thread_union + THREAD_START_SP @ sp
-
-/*
- * The following fragment of code is executed with the MMU on in MMU mode,
- * and uses absolute addresses; this is not position independent.
- *
- *  r0  = cp#15 control register
- *  r1  = machine ID
- *  r2  = atags pointer
- *  r9  = processor ID
- */
-__mmap_switched:
-       adr     r3, __switch_data + 4
-
-       ldmia   r3!, {r4, r5, r6, r7}
-       cmp     r4, r5                          @ Copy data segment if needed
-1:     cmpne   r5, r6
-       ldrne   fp, [r4], #4
-       strne   fp, [r5], #4
-       bne     1b
-
-       mov     fp, #0                          @ Clear BSS (and zero fp)
-1:     cmp     r6, r7
-       strcc   fp, [r6],#4
-       bcc     1b
-
- ARM(  ldmia   r3, {r4, r5, r6, r7, sp})
- THUMB(        ldmia   r3, {r4, r5, r6, r7}    )
- THUMB(        ldr     sp, [r3, #16]           )
-       str     r9, [r4]                        @ Save processor ID
-       str     r1, [r5]                        @ Save machine type
-       str     r2, [r6]                        @ Save atags pointer
-       bic     r4, r0, #CR_A                   @ Clear 'A' bit
-       stmia   r7, {r0, r4}                    @ Save control register values
-       b       start_kernel
-ENDPROC(__mmap_switched)
-
 /*
  * Exception handling.  Something went wrong and we can't proceed.  We
  * ought to tell the user, but since we don't have any guarantee that
@@ -73,21 +24,7 @@ ENDPROC(__mmap_switched)
  * and hope for the best (useful if bootloader fails to pass a proper
  * machine ID for example).
  */
-__error_p:
-#ifdef CONFIG_DEBUG_LL
-       adr     r0, str_p1
-       bl      printascii
-       mov     r0, r9
-       bl      printhex8
-       adr     r0, str_p2
-       bl      printascii
-       b       __error
-str_p1:        .asciz  "\nError: unrecognized/unsupported processor variant (0x"
-str_p2:        .asciz  ").\n"
-       .align
-#endif
-ENDPROC(__error_p)
-
+       __HEAD
 __error_a:
 #ifdef CONFIG_DEBUG_LL
        mov     r4, r1                          @ preserve machine ID
@@ -97,7 +34,7 @@ __error_a:
        bl      printhex8
        adr     r0, str_a2
        bl      printascii
-       adr     r3, 4f
+       adr     r3, __lookup_machine_type_data
        ldmia   r3, {r4, r5, r6}                @ get machine desc list
        sub     r4, r3, r4                      @ get offset between virt&phys
        add     r5, r5, r4                      @ convert virt addresses to
@@ -125,78 +62,6 @@ str_a3:     .asciz  "\nPlease check your kernel config and/or bootloader.\n"
        .align
 #endif
 
-__error:
-#ifdef CONFIG_ARCH_RPC
-/*
- * Turn the screen red on a error - RiscPC only.
- */
-       mov     r0, #0x02000000
-       mov     r3, #0x11
-       orr     r3, r3, r3, lsl #8
-       orr     r3, r3, r3, lsl #16
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-#endif
-1:     mov     r0, r0
-       b       1b
-ENDPROC(__error)
-
-
-/*
- * Read processor ID register (CP#15, CR0), and look up in the linker-built
- * supported processor list.  Note that we can't use the absolute addresses
- * for the __proc_info lists since we aren't running with the MMU on
- * (and therefore, we are not in the correct address space).  We have to
- * calculate the offset.
- *
- *     r9 = cpuid
- * Returns:
- *     r3, r4, r6 corrupted
- *     r5 = proc_info pointer in physical address space
- *     r9 = cpuid (preserved)
- */
-__lookup_processor_type:
-       adr     r3, 3f
-       ldmia   r3, {r5 - r7}
-       add     r3, r3, #8
-       sub     r3, r3, r7                      @ get offset between virt&phys
-       add     r5, r5, r3                      @ convert virt addresses to
-       add     r6, r6, r3                      @ physical address space
-1:     ldmia   r5, {r3, r4}                    @ value, mask
-       and     r4, r4, r9                      @ mask wanted bits
-       teq     r3, r4
-       beq     2f
-       add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)
-       cmp     r5, r6
-       blo     1b
-       mov     r5, #0                          @ unknown processor
-2:     mov     pc, lr
-ENDPROC(__lookup_processor_type)
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_processor_type)
-       stmfd   sp!, {r4 - r7, r9, lr}
-       mov     r9, r0
-       bl      __lookup_processor_type
-       mov     r0, r5
-       ldmfd   sp!, {r4 - r7, r9, pc}
-ENDPROC(lookup_processor_type)
-
-/*
- * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
- * more information about the __proc_info and __arch_info structures.
- */
-       .align  2
-3:     .long   __proc_info_begin
-       .long   __proc_info_end
-4:     .long   .
-       .long   __arch_info_begin
-       .long   __arch_info_end
-
 /*
  * Lookup machine architecture in the linker-build list of architectures.
  * Note that we can't use the absolute addresses for the __arch_info
@@ -209,7 +74,7 @@ ENDPROC(lookup_processor_type)
  *  r5 = mach_info pointer in physical address space
  */
 __lookup_machine_type:
-       adr     r3, 4b
+       adr     r3, __lookup_machine_type_data
        ldmia   r3, {r4, r5, r6}
        sub     r3, r3, r4                      @ get offset between virt&phys
        add     r5, r5, r3                      @ convert virt addresses to
@@ -225,15 +90,16 @@ __lookup_machine_type:
 ENDPROC(__lookup_machine_type)
 
 /*
- * This provides a C-API version of the above function.
+ * Look in arch/arm/kernel/arch.[ch] for information about the
+ * __arch_info structures.
  */
-ENTRY(lookup_machine_type)
-       stmfd   sp!, {r4 - r6, lr}
-       mov     r1, r0
-       bl      __lookup_machine_type
-       mov     r0, r5
-       ldmfd   sp!, {r4 - r6, pc}
-ENDPROC(lookup_machine_type)
+       .align  2
+       .type   __lookup_machine_type_data, %object
+__lookup_machine_type_data:
+       .long   .
+       .long   __arch_info_begin
+       .long   __arch_info_end
+       .size   __lookup_machine_type_data, . - __lookup_machine_type_data
 
 /* Determine validity of the r2 atags pointer.  The heuristic requires
  * that the pointer be aligned, in the first 16k of physical RAM and
@@ -265,3 +131,150 @@ __vet_atags:
 1:     mov     r2, #0
        mov     pc, lr
 ENDPROC(__vet_atags)
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r9  = processor ID
+ */
+       __INIT
+__mmap_switched:
+       adr     r3, __mmap_switched_data
+
+       ldmia   r3!, {r4, r5, r6, r7}
+       cmp     r4, r5                          @ Copy data segment if needed
+1:     cmpne   r5, r6
+       ldrne   fp, [r4], #4
+       strne   fp, [r5], #4
+       bne     1b
+
+       mov     fp, #0                          @ Clear BSS (and zero fp)
+1:     cmp     r6, r7
+       strcc   fp, [r6],#4
+       bcc     1b
+
+ ARM(  ldmia   r3, {r4, r5, r6, r7, sp})
+ THUMB(        ldmia   r3, {r4, r5, r6, r7}    )
+ THUMB(        ldr     sp, [r3, #16]           )
+       str     r9, [r4]                        @ Save processor ID
+       str     r1, [r5]                        @ Save machine type
+       str     r2, [r6]                        @ Save atags pointer
+       bic     r4, r0, #CR_A                   @ Clear 'A' bit
+       stmia   r7, {r0, r4}                    @ Save control register values
+       b       start_kernel
+ENDPROC(__mmap_switched)
+
+       .align  2
+       .type   __mmap_switched_data, %object
+__mmap_switched_data:
+       .long   __data_loc                      @ r4
+       .long   _sdata                          @ r5
+       .long   __bss_start                     @ r6
+       .long   _end                            @ r7
+       .long   processor_id                    @ r4
+       .long   __machine_arch_type             @ r5
+       .long   __atags_pointer                 @ r6
+       .long   cr_alignment                    @ r7
+       .long   init_thread_union + THREAD_START_SP @ sp
+       .size   __mmap_switched_data, . - __mmap_switched_data
+
+/*
+ * This provides a C-API version of __lookup_machine_type
+ */
+ENTRY(lookup_machine_type)
+       stmfd   sp!, {r4 - r6, lr}
+       mov     r1, r0
+       bl      __lookup_machine_type
+       mov     r0, r5
+       ldmfd   sp!, {r4 - r6, pc}
+ENDPROC(lookup_machine_type)
+
+/*
+ * This provides a C-API version of __lookup_processor_type
+ */
+ENTRY(lookup_processor_type)
+       stmfd   sp!, {r4 - r6, r9, lr}
+       mov     r9, r0
+       bl      __lookup_processor_type
+       mov     r0, r5
+       ldmfd   sp!, {r4 - r6, r9, pc}
+ENDPROC(lookup_processor_type)
+
+/*
+ * Read processor ID register (CP#15, CR0), and look up in the linker-built
+ * supported processor list.  Note that we can't use the absolute addresses
+ * for the __proc_info lists since we aren't running with the MMU on
+ * (and therefore, we are not in the correct address space).  We have to
+ * calculate the offset.
+ *
+ *     r9 = cpuid
+ * Returns:
+ *     r3, r4, r6 corrupted
+ *     r5 = proc_info pointer in physical address space
+ *     r9 = cpuid (preserved)
+ */
+       __CPUINIT
+__lookup_processor_type:
+       adr     r3, __lookup_processor_type_data
+       ldmia   r3, {r4 - r6}
+       sub     r3, r3, r4                      @ get offset between virt&phys
+       add     r5, r5, r3                      @ convert virt addresses to
+       add     r6, r6, r3                      @ physical address space
+1:     ldmia   r5, {r3, r4}                    @ value, mask
+       and     r4, r4, r9                      @ mask wanted bits
+       teq     r3, r4
+       beq     2f
+       add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)
+       cmp     r5, r6
+       blo     1b
+       mov     r5, #0                          @ unknown processor
+2:     mov     pc, lr
+ENDPROC(__lookup_processor_type)
+
+/*
+ * Look in <asm/procinfo.h> for information about the __proc_info structure.
+ */
+       .align  2
+       .type   __lookup_processor_type_data, %object
+__lookup_processor_type_data:
+       .long   .
+       .long   __proc_info_begin
+       .long   __proc_info_end
+       .size   __lookup_processor_type_data, . - __lookup_processor_type_data
+
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+       adr     r0, str_p1
+       bl      printascii
+       mov     r0, r9
+       bl      printhex8
+       adr     r0, str_p2
+       bl      printascii
+       b       __error
+str_p1:        .asciz  "\nError: unrecognized/unsupported processor variant (0x"
+str_p2:        .asciz  ").\n"
+       .align
+#endif
+ENDPROC(__error_p)
+
+__error:
+#ifdef CONFIG_ARCH_RPC
+/*
+ * Turn the screen red on a error - RiscPC only.
+ */
+       mov     r0, #0x02000000
+       mov     r3, #0x11
+       orr     r3, r3, r3, lsl #8
+       orr     r3, r3, r3, lsl #16
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+#endif
+1:     mov     r0, r0
+       b       1b
+ENDPROC(__error)
index 573b803dc6bf667e49270f3873119c453e1c50d7..814ce1a732706d0cdb24f5e49007530715ba0b0a 100644 (file)
@@ -48,8 +48,6 @@ ENTRY(stext)
        movs    r8, r5                          @ invalid machine (r5=0)?
        beq     __error_a                       @ yes, error 'a'
 
-       ldr     r13, __switch_data              @ address to jump to after
-                                               @ the initialization is done
        adr     lr, BSYM(__after_proc_init)     @ return (PIC) address
  ARM(  add     pc, r10, #PROCINFO_INITFUNC     )
  THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
@@ -87,8 +85,7 @@ __after_proc_init:
        mcr     p15, 0, r0, c1, c0, 0           @ write control reg
 #endif /* CONFIG_CPU_CP15 */
 
-       mov     r3, r13
-       mov     pc, r3                          @ clear the BSS and jump
+       b       __mmap_switched                 @ clear the BSS and jump
                                                @ to start_kernel
 ENDPROC(__after_proc_init)
        .ltorg
index eb62bf947212ababff5175d10d784dc4f465273f..dd6b369ac69cae5c86dca1e30edd4574b80a2052 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_DEBUG_LL
+#include <mach/debug-macro.S>
+#endif
+
 #if (PHYS_OFFSET & 0x001fffff)
 #error "PHYS_OFFSET must be at an even 2MiB boundary!"
 #endif
@@ -86,6 +90,9 @@ ENTRY(stext)
        movs    r8, r5                          @ invalid machine (r5=0)?
        beq     __error_a                       @ yes, error 'a'
        bl      __vet_atags
+#ifdef CONFIG_SMP_ON_UP
+       bl      __fixup_smp
+#endif
        bl      __create_page_tables
 
        /*
@@ -95,113 +102,15 @@ ENTRY(stext)
         * above.  On return, the CPU will be ready for the MMU to be
         * turned on, and r0 will hold the CPU control register value.
         */
-       ldr     r13, __switch_data              @ address to jump to after
+       ldr     r13, =__mmap_switched           @ address to jump to after
                                                @ mmu has been enabled
-       adr     lr, BSYM(__enable_mmu)          @ return (PIC) address
+       adr     lr, BSYM(1f)                    @ return (PIC) address
  ARM(  add     pc, r10, #PROCINFO_INITFUNC     )
  THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
  THUMB(        mov     pc, r12                         )
+1:     b       __enable_mmu
 ENDPROC(stext)
-
-#if defined(CONFIG_SMP)
-ENTRY(secondary_startup)
-       /*
-        * Common entry point for secondary CPUs.
-        *
-        * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
-        * the processor type - there is no need to check the machine type
-        * as it has already been validated by the primary processor.
-        */
-       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
-       mrc     p15, 0, r9, c0, c0              @ get processor id
-       bl      __lookup_processor_type
-       movs    r10, r5                         @ invalid processor?
-       moveq   r0, #'p'                        @ yes, error 'p'
-       beq     __error
-
-       /*
-        * Use the page tables supplied from  __cpu_up.
-        */
-       adr     r4, __secondary_data
-       ldmia   r4, {r5, r7, r12}               @ address to jump to after
-       sub     r4, r4, r5                      @ mmu has been enabled
-       ldr     r4, [r7, r4]                    @ get secondary_data.pgdir
-       adr     lr, BSYM(__enable_mmu)          @ return address
-       mov     r13, r12                        @ __secondary_switched address
- ARM(  add     pc, r10, #PROCINFO_INITFUNC     ) @ initialise processor
-                                                 @ (return control reg)
- THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
- THUMB(        mov     pc, r12                         )
-ENDPROC(secondary_startup)
-
-       /*
-        * r6  = &secondary_data
-        */
-ENTRY(__secondary_switched)
-       ldr     sp, [r7, #4]                    @ get secondary_data.stack
-       mov     fp, #0
-       b       secondary_start_kernel
-ENDPROC(__secondary_switched)
-
-       .type   __secondary_data, %object
-__secondary_data:
-       .long   .
-       .long   secondary_data
-       .long   __secondary_switched
-#endif /* defined(CONFIG_SMP) */
-
-
-
-/*
- * Setup common bits before finally enabling the MMU.  Essentially
- * this is just loading the page table pointer and domain access
- * registers.
- */
-__enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
-       orr     r0, r0, #CR_A
-#else
-       bic     r0, r0, #CR_A
-#endif
-#ifdef CONFIG_CPU_DCACHE_DISABLE
-       bic     r0, r0, #CR_C
-#endif
-#ifdef CONFIG_CPU_BPREDICT_DISABLE
-       bic     r0, r0, #CR_Z
-#endif
-#ifdef CONFIG_CPU_ICACHE_DISABLE
-       bic     r0, r0, #CR_I
-#endif
-       mov     r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
-                     domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
-                     domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
-                     domain_val(DOMAIN_IO, DOMAIN_CLIENT))
-       mcr     p15, 0, r5, c3, c0, 0           @ load domain access register
-       mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
-       b       __turn_mmu_on
-ENDPROC(__enable_mmu)
-
-/*
- * Enable the MMU.  This completely changes the structure of the visible
- * memory space.  You will not be able to trace execution through this.
- * If you have an enquiry about this, *please* check the linux-arm-kernel
- * mailing list archives BEFORE sending another post to the list.
- *
- *  r0  = cp#15 control register
- *  r13 = *virtual* address to jump to upon completion
- *
- * other registers depend on the function called upon completion
- */
-       .align  5
-__turn_mmu_on:
-       mov     r0, r0
-       mcr     p15, 0, r0, c1, c0, 0           @ write control reg
-       mrc     p15, 0, r3, c0, c0, 0           @ read id reg
-       mov     r3, r3
-       mov     r3, r13
-       mov     pc, r3
-ENDPROC(__turn_mmu_on)
-
+       .ltorg
 
 /*
  * Setup the initial page tables.  We only setup the barest
@@ -213,7 +122,7 @@ ENDPROC(__turn_mmu_on)
  * r10 = procinfo
  *
  * Returns:
- *  r0, r3, r6, r7 corrupted
+ *  r0, r3, r5-r7 corrupted
  *  r4 = physical page table address
  */
 __create_page_tables:
@@ -235,20 +144,30 @@ __create_page_tables:
        ldr     r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
 
        /*
-        * Create identity mapping for first MB of kernel to
-        * cater for the MMU enable.  This identity mapping
-        * will be removed by paging_init().  We use our current program
-        * counter to determine corresponding section base address.
+        * Create identity mapping to cater for __enable_mmu.
+        * This identity mapping will be removed by paging_init().
         */
-       mov     r6, pc
-       mov     r6, r6, lsr #20                 @ start of kernel section
-       orr     r3, r7, r6, lsl #20             @ flags + kernel base
-       str     r3, [r4, r6, lsl #2]            @ identity mapping
+       adr     r0, __enable_mmu_loc
+       ldmia   r0, {r3, r5, r6}
+       sub     r0, r0, r3                      @ virt->phys offset
+       add     r5, r5, r0                      @ phys __enable_mmu
+       add     r6, r6, r0                      @ phys __enable_mmu_end
+       mov     r5, r5, lsr #20
+       mov     r6, r6, lsr #20
+
+1:     orr     r3, r7, r5, lsl #20             @ flags + kernel base
+       str     r3, [r4, r5, lsl #2]            @ identity mapping
+       teq     r5, r6
+       addne   r5, r5, #1                      @ next section
+       bne     1b
 
        /*
         * Now setup the pagetables for our kernel direct
         * mapped region.
         */
+       mov     r3, pc
+       mov     r3, r3, lsr #20
+       orr     r3, r7, r3, lsl #20
        add     r0, r4,  #(KERNEL_START & 0xff000000) >> 18
        str     r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
        ldr     r6, =(KERNEL_END - 1)
@@ -289,24 +208,35 @@ __create_page_tables:
        str     r6, [r0]
 
 #ifdef CONFIG_DEBUG_LL
-       ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#ifndef CONFIG_DEBUG_ICEDCC
        /*
         * Map in IO space for serial debugging.
         * This allows debug messages to be output
         * via a serial console before paging_init.
         */
-       ldr     r3, [r8, #MACHINFO_PGOFFIO]
+       addruart r7, r3
+
+       mov     r3, r3, lsr #20
+       mov     r3, r3, lsl #2
+
        add     r0, r4, r3
        rsb     r3, r3, #0x4000                 @ PTRS_PER_PGD*sizeof(long)
        cmp     r3, #0x0800                     @ limit to 512MB
        movhi   r3, #0x0800
        add     r6, r0, r3
-       ldr     r3, [r8, #MACHINFO_PHYSIO]
-       orr     r3, r3, r7
+       mov     r3, r7, lsr #20
+       ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+       orr     r3, r7, r3, lsl #20
 1:     str     r3, [r0], #4
        add     r3, r3, #1 << 20
        teq     r0, r6
        bne     1b
+
+#else /* CONFIG_DEBUG_ICEDCC */
+       /* we don't need any serial debugging mappings for ICEDCC */
+       ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#endif /* !CONFIG_DEBUG_ICEDCC */
+
 #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
        /*
         * If we're using the NetWinder or CATS, we also need to map
@@ -332,5 +262,168 @@ __create_page_tables:
        mov     pc, lr
 ENDPROC(__create_page_tables)
        .ltorg
+__enable_mmu_loc:
+       .long   .
+       .long   __enable_mmu
+       .long   __enable_mmu_end
+
+#if defined(CONFIG_SMP)
+       __CPUINIT
+ENTRY(secondary_startup)
+       /*
+        * Common entry point for secondary CPUs.
+        *
+        * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
+        * the processor type - there is no need to check the machine type
+        * as it has already been validated by the primary processor.
+        */
+       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
+       mrc     p15, 0, r9, c0, c0              @ get processor id
+       bl      __lookup_processor_type
+       movs    r10, r5                         @ invalid processor?
+       moveq   r0, #'p'                        @ yes, error 'p'
+       beq     __error_p
+
+       /*
+        * Use the page tables supplied from  __cpu_up.
+        */
+       adr     r4, __secondary_data
+       ldmia   r4, {r5, r7, r12}               @ address to jump to after
+       sub     r4, r4, r5                      @ mmu has been enabled
+       ldr     r4, [r7, r4]                    @ get secondary_data.pgdir
+       adr     lr, BSYM(__enable_mmu)          @ return address
+       mov     r13, r12                        @ __secondary_switched address
+ ARM(  add     pc, r10, #PROCINFO_INITFUNC     ) @ initialise processor
+                                                 @ (return control reg)
+ THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
+ THUMB(        mov     pc, r12                         )
+ENDPROC(secondary_startup)
+
+       /*
+        * r6  = &secondary_data
+        */
+ENTRY(__secondary_switched)
+       ldr     sp, [r7, #4]                    @ get secondary_data.stack
+       mov     fp, #0
+       b       secondary_start_kernel
+ENDPROC(__secondary_switched)
+
+       .type   __secondary_data, %object
+__secondary_data:
+       .long   .
+       .long   secondary_data
+       .long   __secondary_switched
+#endif /* defined(CONFIG_SMP) */
+
+
+
+/*
+ * Setup common bits before finally enabling the MMU.  Essentially
+ * this is just loading the page table pointer and domain access
+ * registers.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r4  = page table pointer
+ *  r9  = processor ID
+ *  r13 = *virtual* address to jump to upon completion
+ */
+__enable_mmu:
+#ifdef CONFIG_ALIGNMENT_TRAP
+       orr     r0, r0, #CR_A
+#else
+       bic     r0, r0, #CR_A
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+       bic     r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_BPREDICT_DISABLE
+       bic     r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+       bic     r0, r0, #CR_I
+#endif
+       mov     r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
+                     domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
+                     domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
+                     domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+       mcr     p15, 0, r5, c3, c0, 0           @ load domain access register
+       mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
+       b       __turn_mmu_on
+ENDPROC(__enable_mmu)
+
+/*
+ * Enable the MMU.  This completely changes the structure of the visible
+ * memory space.  You will not be able to trace execution through this.
+ * If you have an enquiry about this, *please* check the linux-arm-kernel
+ * mailing list archives BEFORE sending another post to the list.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r9  = processor ID
+ *  r13 = *virtual* address to jump to upon completion
+ *
+ * other registers depend on the function called upon completion
+ */
+       .align  5
+__turn_mmu_on:
+       mov     r0, r0
+       mcr     p15, 0, r0, c1, c0, 0           @ write control reg
+       mrc     p15, 0, r3, c0, c0, 0           @ read id reg
+       mov     r3, r3
+       mov     r3, r13
+       mov     pc, r3
+__enable_mmu_end:
+ENDPROC(__turn_mmu_on)
+
+
+#ifdef CONFIG_SMP_ON_UP
+__fixup_smp:
+       mov     r7, #0x00070000
+       orr     r6, r7, #0xff000000     @ mask 0xff070000
+       orr     r7, r7, #0x41000000     @ val 0x41070000
+       and     r0, r9, r6
+       teq     r0, r7                  @ ARM CPU and ARMv6/v7?
+       bne     __fixup_smp_on_up       @ no, assume UP
+
+       orr     r6, r6, #0x0000ff00
+       orr     r6, r6, #0x000000f0     @ mask 0xff07fff0
+       orr     r7, r7, #0x0000b000
+       orr     r7, r7, #0x00000020     @ val 0x4107b020
+       and     r0, r9, r6
+       teq     r0, r7                  @ ARM 11MPCore?
+       moveq   pc, lr                  @ yes, assume SMP
+
+       mrc     p15, 0, r0, c0, c0, 5   @ read MPIDR
+       tst     r0, #1 << 31
+       movne   pc, lr                  @ bit 31 => SMP
+
+__fixup_smp_on_up:
+       adr     r0, 1f
+       ldmia   r0, {r3, r6, r7}
+       sub     r3, r0, r3
+       add     r6, r6, r3
+       add     r7, r7, r3
+2:     cmp     r6, r7
+       ldmia   r6!, {r0, r4}
+       strlo   r4, [r0, r3]
+       blo     2b
+       mov     pc, lr
+ENDPROC(__fixup_smp)
+
+1:     .word   .
+       .word   __smpalt_begin
+       .word   __smpalt_end
+
+       .pushsection .data
+       .globl  smp_on_up
+smp_on_up:
+       ALT_SMP(.long   1)
+       ALT_UP(.long    0)
+       .popsection
+
+#endif
 
 #include "head-common.S"
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
new file mode 100644 (file)
index 0000000..54593b0
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2009, 2010 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ */
+#define pr_fmt(fmt) "hw-breakpoint: " fmt
+
+#include <linux/errno.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/current.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/kdebug.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+/* Breakpoint currently in use for each BRP. */
+static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
+
+/* Watchpoint currently in use for each WRP. */
+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_wrps;
+
+/* Debug architecture version. */
+static u8 debug_arch;
+
+/* Maximum supported watchpoint length. */
+static u8 max_watchpoint_len;
+
+/* Determine number of BRP registers available. */
+static int get_num_brps(void)
+{
+       u32 didr;
+       ARM_DBG_READ(c0, 0, didr);
+       return ((didr >> 24) & 0xf) + 1;
+}
+
+/* Determine number of WRP registers available. */
+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.
+        *
+        * Furthermore, we can only do this if the watchpoint was precise
+        * since imprecise watchpoints prevent us from calculating register
+        * based addresses.
+        *
+        * For the time being, we only report 1 watchpoint register so we
+        * always know which watchpoint fired. In the future we can either
+        * add a disassembler and address generation emulator, or we can
+        * insert a check to see if the DFAR is set on watchpoint exception
+        * entry [the ARM ARM states that the DFAR is UNKNOWN, but
+        * experience shows that it is set on some implementations].
+        */
+
+#if 0
+       u32 didr, wrps;
+       ARM_DBG_READ(c0, 0, didr);
+       return ((didr >> 28) & 0xf) + 1;
+#endif
+
+       return 1;
+}
+
+int hw_breakpoint_slots(int type)
+{
+       /*
+        * We can be called early, so don't rely on
+        * our static variables being initialised.
+        */
+       switch (type) {
+       case TYPE_INST:
+               return get_num_brps();
+       case TYPE_DATA:
+               return get_num_wrps();
+       default:
+               pr_warning("unknown slot type: %d\n", type);
+               return 0;
+       }
+}
+
+/* Determine debug architecture. */
+static u8 get_debug_arch(void)
+{
+       u32 didr;
+
+       /* Do we implement the extended CPUID interface? */
+       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;
+}
+
+/* Does this core support mismatch breakpoints? */
+static int core_has_mismatch_bps(void)
+{
+       return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
+}
+
+u8 arch_get_debug_arch(void)
+{
+       return debug_arch;
+}
+
+#define READ_WB_REG_CASE(OP2, M, VAL)          \
+       case ((OP2 << 4) + M):                  \
+               ARM_DBG_READ(c ## M, OP2, VAL); \
+               break
+
+#define WRITE_WB_REG_CASE(OP2, M, VAL)         \
+       case ((OP2 << 4) + M):                  \
+               ARM_DBG_WRITE(c ## M, OP2, VAL);\
+               break
+
+#define GEN_READ_WB_REG_CASES(OP2, VAL)                \
+       READ_WB_REG_CASE(OP2, 0, VAL);          \
+       READ_WB_REG_CASE(OP2, 1, VAL);          \
+       READ_WB_REG_CASE(OP2, 2, VAL);          \
+       READ_WB_REG_CASE(OP2, 3, VAL);          \
+       READ_WB_REG_CASE(OP2, 4, VAL);          \
+       READ_WB_REG_CASE(OP2, 5, VAL);          \
+       READ_WB_REG_CASE(OP2, 6, VAL);          \
+       READ_WB_REG_CASE(OP2, 7, VAL);          \
+       READ_WB_REG_CASE(OP2, 8, VAL);          \
+       READ_WB_REG_CASE(OP2, 9, VAL);          \
+       READ_WB_REG_CASE(OP2, 10, VAL);         \
+       READ_WB_REG_CASE(OP2, 11, VAL);         \
+       READ_WB_REG_CASE(OP2, 12, VAL);         \
+       READ_WB_REG_CASE(OP2, 13, VAL);         \
+       READ_WB_REG_CASE(OP2, 14, VAL);         \
+       READ_WB_REG_CASE(OP2, 15, VAL)
+
+#define GEN_WRITE_WB_REG_CASES(OP2, VAL)       \
+       WRITE_WB_REG_CASE(OP2, 0, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 1, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 2, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 3, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 4, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 5, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 6, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 7, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 8, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 9, VAL);         \
+       WRITE_WB_REG_CASE(OP2, 10, VAL);        \
+       WRITE_WB_REG_CASE(OP2, 11, VAL);        \
+       WRITE_WB_REG_CASE(OP2, 12, VAL);        \
+       WRITE_WB_REG_CASE(OP2, 13, VAL);        \
+       WRITE_WB_REG_CASE(OP2, 14, VAL);        \
+       WRITE_WB_REG_CASE(OP2, 15, VAL)
+
+static u32 read_wb_reg(int n)
+{
+       u32 val = 0;
+
+       switch (n) {
+       GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val);
+       GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val);
+       GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val);
+       GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val);
+       default:
+               pr_warning("attempt to read from unknown breakpoint "
+                               "register %d\n", n);
+       }
+
+       return val;
+}
+
+static void write_wb_reg(int n, u32 val)
+{
+       switch (n) {
+       GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val);
+       GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val);
+       GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val);
+       GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val);
+       default:
+               pr_warning("attempt to write to unknown breakpoint "
+                               "register %d\n", n);
+       }
+       isb();
+}
+
+/*
+ * In order to access the breakpoint/watchpoint control registers,
+ * we must be running in debug monitor mode. Unfortunately, we can
+ * be put into halting debug mode at any time by an external debugger
+ * but there is nothing we can do to prevent that.
+ */
+static int enable_monitor_mode(void)
+{
+       u32 dscr;
+       int ret = 0;
+
+       ARM_DBG_READ(c1, 0, dscr);
+
+       /* Ensure that halting mode is disabled. */
+       if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
+                               "Unable to access hardware resources.")) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       /* Write to the corresponding DSCR. */
+       switch (debug_arch) {
+       case ARM_DEBUG_ARCH_V6:
+       case ARM_DEBUG_ARCH_V6_1:
+               ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
+               break;
+       case ARM_DEBUG_ARCH_V7_ECP14:
+               ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
+               break;
+       default:
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* Check that the write made it through. */
+       ARM_DBG_READ(c1, 0, dscr);
+       if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
+                               "failed to enable monitor mode.")) {
+               ret = -EPERM;
+       }
+
+out:
+       return ret;
+}
+
+/*
+ * Check if 8-bit byte-address select is available.
+ * This clobbers WRP 0.
+ */
+static u8 get_max_wp_len(void)
+{
+       u32 ctrl_reg;
+       struct arch_hw_breakpoint_ctrl ctrl;
+       u8 size = 4;
+
+       if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
+               goto out;
+
+       if (enable_monitor_mode())
+               goto out;
+
+       memset(&ctrl, 0, sizeof(ctrl));
+       ctrl.len = ARM_BREAKPOINT_LEN_8;
+       ctrl_reg = encode_ctrl_reg(ctrl);
+
+       write_wb_reg(ARM_BASE_WVR, 0);
+       write_wb_reg(ARM_BASE_WCR, ctrl_reg);
+       if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg)
+               size = 8;
+
+out:
+       return size;
+}
+
+u8 arch_get_max_wp_len(void)
+{
+       return max_watchpoint_len;
+}
+
+/*
+ * Handler for reactivating a suspended watchpoint when the single
+ * step `mismatch' breakpoint is triggered.
+ */
+static void wp_single_step_handler(struct perf_event *bp, int unused,
+                                  struct perf_sample_data *data,
+                                  struct pt_regs *regs)
+{
+       perf_event_enable(counter_arch_bp(bp)->suspended_wp);
+       unregister_hw_breakpoint(bp);
+}
+
+static int bp_is_single_step(struct perf_event *bp)
+{
+       return bp->overflow_handler == wp_single_step_handler;
+}
+
+/*
+ * Install a perf counter breakpoint.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       struct perf_event **slot, **slots;
+       int i, max_slots, ctrl_base, val_base, ret = 0;
+
+       /* Ensure that we are in monitor mode and halting mode is disabled. */
+       ret = enable_monitor_mode();
+       if (ret)
+               goto out;
+
+       if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+               /* Breakpoint */
+               ctrl_base = ARM_BASE_BCR;
+               val_base = ARM_BASE_BVR;
+               slots = __get_cpu_var(bp_on_reg);
+               max_slots = core_num_brps - 1;
+
+               if (bp_is_single_step(bp)) {
+                       info->ctrl.mismatch = 1;
+                       i = max_slots;
+                       slots[i] = bp;
+                       goto setup;
+               }
+       } else {
+               /* Watchpoint */
+               ctrl_base = ARM_BASE_WCR;
+               val_base = ARM_BASE_WVR;
+               slots = __get_cpu_var(wp_on_reg);
+               max_slots = core_num_wrps;
+       }
+
+       for (i = 0; i < max_slots; ++i) {
+               slot = &slots[i];
+
+               if (!*slot) {
+                       *slot = bp;
+                       break;
+               }
+       }
+
+       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+setup:
+       /* Setup the address register. */
+       write_wb_reg(val_base + i, info->address);
+
+       /* Setup the control register. */
+       write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
+
+out:
+       return ret;
+}
+
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       struct perf_event **slot, **slots;
+       int i, max_slots, base;
+
+       if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+               /* Breakpoint */
+               base = ARM_BASE_BCR;
+               slots = __get_cpu_var(bp_on_reg);
+               max_slots = core_num_brps - 1;
+
+               if (bp_is_single_step(bp)) {
+                       i = max_slots;
+                       slots[i] = NULL;
+                       goto reset;
+               }
+       } else {
+               /* Watchpoint */
+               base = ARM_BASE_WCR;
+               slots = __get_cpu_var(wp_on_reg);
+               max_slots = core_num_wrps;
+       }
+
+       /* Remove the breakpoint. */
+       for (i = 0; i < max_slots; ++i) {
+               slot = &slots[i];
+
+               if (*slot == bp) {
+                       *slot = NULL;
+                       break;
+               }
+       }
+
+       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+               return;
+
+reset:
+       /* Reset the control register. */
+       write_wb_reg(base + i, 0);
+}
+
+static int get_hbp_len(u8 hbp_len)
+{
+       unsigned int len_in_bytes = 0;
+
+       switch (hbp_len) {
+       case ARM_BREAKPOINT_LEN_1:
+               len_in_bytes = 1;
+               break;
+       case ARM_BREAKPOINT_LEN_2:
+               len_in_bytes = 2;
+               break;
+       case ARM_BREAKPOINT_LEN_4:
+               len_in_bytes = 4;
+               break;
+       case ARM_BREAKPOINT_LEN_8:
+               len_in_bytes = 8;
+               break;
+       }
+
+       return len_in_bytes;
+}
+
+/*
+ * Check whether bp virtual address is in kernel space.
+ */
+int arch_check_bp_in_kernelspace(struct perf_event *bp)
+{
+       unsigned int len;
+       unsigned long va;
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+       va = info->address;
+       len = get_hbp_len(info->ctrl.len);
+
+       return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
+ * Hopefully this will disappear when ptrace can bypass the conversion
+ * to generic breakpoint descriptions.
+ */
+int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+                          int *gen_len, int *gen_type)
+{
+       /* Type */
+       switch (ctrl.type) {
+       case ARM_BREAKPOINT_EXECUTE:
+               *gen_type = HW_BREAKPOINT_X;
+               break;
+       case ARM_BREAKPOINT_LOAD:
+               *gen_type = HW_BREAKPOINT_R;
+               break;
+       case ARM_BREAKPOINT_STORE:
+               *gen_type = HW_BREAKPOINT_W;
+               break;
+       case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
+               *gen_type = HW_BREAKPOINT_RW;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Len */
+       switch (ctrl.len) {
+       case ARM_BREAKPOINT_LEN_1:
+               *gen_len = HW_BREAKPOINT_LEN_1;
+               break;
+       case ARM_BREAKPOINT_LEN_2:
+               *gen_len = HW_BREAKPOINT_LEN_2;
+               break;
+       case ARM_BREAKPOINT_LEN_4:
+               *gen_len = HW_BREAKPOINT_LEN_4;
+               break;
+       case ARM_BREAKPOINT_LEN_8:
+               *gen_len = HW_BREAKPOINT_LEN_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Construct an arch_hw_breakpoint from a perf_event.
+ */
+static int arch_build_bp_info(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+       /* Type */
+       switch (bp->attr.bp_type) {
+       case HW_BREAKPOINT_X:
+               info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
+               break;
+       case HW_BREAKPOINT_R:
+               info->ctrl.type = ARM_BREAKPOINT_LOAD;
+               break;
+       case HW_BREAKPOINT_W:
+               info->ctrl.type = ARM_BREAKPOINT_STORE;
+               break;
+       case HW_BREAKPOINT_RW:
+               info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Len */
+       switch (bp->attr.bp_len) {
+       case HW_BREAKPOINT_LEN_1:
+               info->ctrl.len = ARM_BREAKPOINT_LEN_1;
+               break;
+       case HW_BREAKPOINT_LEN_2:
+               info->ctrl.len = ARM_BREAKPOINT_LEN_2;
+               break;
+       case HW_BREAKPOINT_LEN_4:
+               info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+               break;
+       case HW_BREAKPOINT_LEN_8:
+               info->ctrl.len = ARM_BREAKPOINT_LEN_8;
+               if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE)
+                       && max_watchpoint_len >= 8)
+                       break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Address */
+       info->address = bp->attr.bp_addr;
+
+       /* Privilege */
+       info->ctrl.privilege = ARM_BREAKPOINT_USER;
+       if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
+               info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
+
+       /* Enabled? */
+       info->ctrl.enabled = !bp->attr.disabled;
+
+       /* Mismatch */
+       info->ctrl.mismatch = 0;
+
+       return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings.
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp)
+{
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+       int ret = 0;
+       u32 bytelen, max_len, offset, alignment_mask = 0x3;
+
+       /* Build the arch_hw_breakpoint. */
+       ret = arch_build_bp_info(bp);
+       if (ret)
+               goto out;
+
+       /* Check address alignment. */
+       if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+               alignment_mask = 0x7;
+       if (info->address & alignment_mask) {
+               /*
+                * Try to fix the alignment. This may result in a length
+                * that is too large, so we must check for that.
+                */
+               bytelen = get_hbp_len(info->ctrl.len);
+               max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
+                               max_watchpoint_len;
+
+               if (max_len >= 8)
+                       offset = info->address & 0x7;
+               else
+                       offset = info->address & 0x3;
+
+               if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
+                       ret = -EFBIG;
+                       goto out;
+               }
+
+               info->ctrl.len <<= offset;
+               info->address &= ~offset;
+
+               pr_debug("breakpoint alignment fixup: length = 0x%x, "
+                       "address = 0x%x\n", info->ctrl.len, info->address);
+       }
+
+       /*
+        * Currently we rely on an overflow handler to take
+        * care of single-stepping the breakpoint when it fires.
+        * In the case of userspace breakpoints on a core with V7 debug,
+        * we can use the mismatch feature as a poor-man's hardware single-step.
+        */
+       if (WARN_ONCE(!bp->overflow_handler &&
+               (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
+                       "overflow handler required but none found")) {
+               ret = -EINVAL;
+               goto out;
+       }
+out:
+       return ret;
+}
+
+static void update_mismatch_flag(int idx, int flag)
+{
+       struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
+       struct arch_hw_breakpoint *info;
+
+       if (bp == NULL)
+               return;
+
+       info = counter_arch_bp(bp);
+
+       /* Update the mismatch field to enter/exit `single-step' mode */
+       if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
+               info->ctrl.mismatch = flag;
+               write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
+       }
+}
+
+static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+       int i;
+       struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
+       struct arch_hw_breakpoint *info;
+       struct perf_event_attr attr;
+
+       /* Without a disassembler, we can only handle 1 watchpoint. */
+       BUG_ON(core_num_wrps > 1);
+
+       hw_breakpoint_init(&attr);
+       attr.bp_addr    = regs->ARM_pc & ~0x3;
+       attr.bp_len     = HW_BREAKPOINT_LEN_4;
+       attr.bp_type    = HW_BREAKPOINT_X;
+
+       for (i = 0; i < core_num_wrps; ++i) {
+               rcu_read_lock();
+
+               if (slots[i] == NULL) {
+                       rcu_read_unlock();
+                       continue;
+               }
+
+               /*
+                * The DFAR is an unknown value. Since we only allow a
+                * single watchpoint, we can set the trigger to the lowest
+                * possible faulting address.
+                */
+               info = counter_arch_bp(slots[i]);
+               info->trigger = slots[i]->attr.bp_addr;
+               pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+               perf_bp_event(slots[i], regs);
+
+               /*
+                * If no overflow handler is present, insert a temporary
+                * mismatch breakpoint so we can single-step over the
+                * watchpoint trigger.
+                */
+               if (!slots[i]->overflow_handler) {
+                       bp = register_user_hw_breakpoint(&attr,
+                                                        wp_single_step_handler,
+                                                        current);
+                       counter_arch_bp(bp)->suspended_wp = slots[i];
+                       perf_event_disable(slots[i]);
+               }
+
+               rcu_read_unlock();
+       }
+}
+
+static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+       int i;
+       int mismatch;
+       u32 ctrl_reg, val, addr;
+       struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
+       struct arch_hw_breakpoint *info;
+       struct arch_hw_breakpoint_ctrl ctrl;
+
+       /* The exception entry code places the amended lr in the PC. */
+       addr = regs->ARM_pc;
+
+       for (i = 0; i < core_num_brps; ++i) {
+               rcu_read_lock();
+
+               bp = slots[i];
+
+               if (bp == NULL) {
+                       rcu_read_unlock();
+                       continue;
+               }
+
+               mismatch = 0;
+
+               /* Check if the breakpoint value matches. */
+               val = read_wb_reg(ARM_BASE_BVR + i);
+               if (val != (addr & ~0x3))
+                       goto unlock;
+
+               /* Possible match, check the byte address select to confirm. */
+               ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
+               decode_ctrl_reg(ctrl_reg, &ctrl);
+               if ((1 << (addr & 0x3)) & ctrl.len) {
+                       mismatch = 1;
+                       info = counter_arch_bp(bp);
+                       info->trigger = addr;
+               }
+
+unlock:
+               if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
+                       pr_debug("breakpoint fired: address = 0x%x\n", addr);
+                       perf_bp_event(bp, regs);
+               }
+
+               update_mismatch_flag(i, mismatch);
+               rcu_read_unlock();
+       }
+}
+
+/*
+ * Called from either the Data Abort Handler [watchpoint] or the
+ * Prefetch Abort Handler [breakpoint].
+ */
+static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
+                                struct pt_regs *regs)
+{
+       int ret = 1; /* Unhandled fault. */
+       u32 dscr;
+
+       /* We only handle watchpoints and hardware breakpoints. */
+       ARM_DBG_READ(c1, 0, dscr);
+
+       /* Perform perf callbacks. */
+       switch (ARM_DSCR_MOE(dscr)) {
+       case ARM_ENTRY_BREAKPOINT:
+               breakpoint_handler(addr, regs);
+               break;
+       case ARM_ENTRY_ASYNC_WATCHPOINT:
+               WARN_ON("Asynchronous watchpoint exception taken. "
+                       "Debugging results may be unreliable");
+       case ARM_ENTRY_SYNC_WATCHPOINT:
+               watchpoint_handler(addr, regs);
+               break;
+       default:
+               goto out;
+       }
+
+       ret = 0;
+out:
+       return ret;
+}
+
+/*
+ * One-time initialisation.
+ */
+static void __init reset_ctrl_regs(void *unused)
+{
+       int i;
+
+       if (enable_monitor_mode())
+               return;
+
+       for (i = 0; i < core_num_brps; ++i) {
+               write_wb_reg(ARM_BASE_BCR + i, 0UL);
+               write_wb_reg(ARM_BASE_BVR + i, 0UL);
+       }
+
+       for (i = 0; i < core_num_wrps; ++i) {
+               write_wb_reg(ARM_BASE_WCR + i, 0UL);
+               write_wb_reg(ARM_BASE_WVR + i, 0UL);
+       }
+}
+
+static int __init arch_hw_breakpoint_init(void)
+{
+       int ret = 0;
+       u32 dscr;
+
+       debug_arch = get_debug_arch();
+
+       if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
+               pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* Determine how many BRPs/WRPs are available. */
+       core_num_brps = get_num_brps();
+       core_num_wrps = get_num_wrps();
+
+       pr_info("found %d breakpoint and %d watchpoint registers.\n",
+                       core_num_brps, core_num_wrps);
+
+       if (core_has_mismatch_bps())
+               pr_info("1 breakpoint reserved for watchpoint single-step.\n");
+
+       ARM_DBG_READ(c1, 0, dscr);
+       if (dscr & ARM_DSCR_HDBGEN) {
+               pr_warning("halting debug mode enabled. Assuming maximum "
+                               "watchpoint size of 4 bytes.");
+       } else {
+               /* Work out the maximum supported watchpoint length. */
+               max_watchpoint_len = get_max_wp_len();
+               pr_info("maximum watchpoint size is %u bytes.\n",
+                               max_watchpoint_len);
+
+               /*
+                * Reset the breakpoint resources. We assume that a halting
+                * debugger will leave the world in a nice state for us.
+                */
+               smp_call_function(reset_ctrl_regs, NULL, 1);
+               reset_ctrl_regs(NULL);
+       }
+
+       /* Register debug fault handler. */
+       hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+                       "watchpoint debug exception");
+       hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+                       "breakpoint debug exception");
+
+out:
+       return ret;
+}
+arch_initcall(arch_hw_breakpoint_init);
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+}
+
+/*
+ * Dummy function to register with die_notifier.
+ */
+int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+                                       unsigned long val, void *data)
+{
+       return NOTIFY_DONE;
+}
index c0d5c3b3a760fa79624657ebc495b1d7b81b8c66..36ad3be4692a21c4970de80b8d8562327571f681 100644 (file)
@@ -154,14 +154,6 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
 
 void __init init_IRQ(void)
 {
-       struct irq_desc *desc;
-       int irq;
-
-       for (irq = 0; irq < nr_irqs; irq++) {
-               desc = irq_to_desc_alloc_node(irq, 0);
-               desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
-       }
-
        init_arch_irq();
 }
 
@@ -169,7 +161,7 @@ void __init init_IRQ(void)
 int __init arch_probe_nr_irqs(void)
 {
        nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
-       return 0;
+       return nr_irqs;
 }
 #endif
 
index 8bccbfa693ffc359dc55d6004837d2a149e2c5cd..2c1f0050c9c4d9fd74ac08b1c0a9c193e16df4de 100644 (file)
@@ -1162,11 +1162,12 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
        /*
         * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-        * Undef : cccc 0011 0x00 xxxx xxxx xxxx xxxx xxxx
+        * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
         * ALU op with S bit and Rd == 15 :
         *         cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
         */
-       if ((insn & 0x0f900000) == 0x03200000 ||        /* MSR & Undef */
+       if ((insn & 0x0fb00000) == 0x03200000 ||        /* MSR */
+           (insn & 0x0ff00000) == 0x03400000 ||        /* Undef */
            (insn & 0x0e10f000) == 0x0210f000)          /* ALU s-bit, R15  */
                return INSN_REJECTED;
 
@@ -1177,7 +1178,7 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
         * *S (bit 20) updates condition codes
         * ADC/SBC/RSC reads the C flag
         */
-       insn &= 0xfff00fff;     /* Rn = r0, Rd = r0 */
+       insn &= 0xffff0fff;     /* Rd = r0 */
        asi->insn[0] = insn;
        asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                        emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
index 6b4605893f1e45329ab4058e33c2590056e02468..d9bd786ce23dc1228ac7937ad442292f08c74cca 100644 (file)
@@ -69,20 +69,31 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
 {
 #ifdef CONFIG_ARM_UNWIND
        Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+       struct arm_unwind_mapping *maps = mod->arch.map;
 
        for (s = sechdrs; s < sechdrs_end; s++) {
-               if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
-                       mod->arch.unw_sec_init = s;
-               else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
-                       mod->arch.unw_sec_devinit = s;
-               else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
-                       mod->arch.unw_sec_core = s;
-               else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
-                       mod->arch.sec_init_text = s;
-               else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
-                       mod->arch.sec_devinit_text = s;
-               else if (strcmp(".text", secstrings + s->sh_name) == 0)
-                       mod->arch.sec_core_text = s;
+               char const *secname = secstrings + s->sh_name;
+
+               if (strcmp(".ARM.exidx.init.text", secname) == 0)
+                       maps[ARM_SEC_INIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+                       maps[ARM_SEC_DEVINIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx", secname) == 0)
+                       maps[ARM_SEC_CORE].unw_sec = s;
+               else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+                       maps[ARM_SEC_EXIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+                       maps[ARM_SEC_DEVEXIT].unw_sec = s;
+               else if (strcmp(".init.text", secname) == 0)
+                       maps[ARM_SEC_INIT].sec_text = s;
+               else if (strcmp(".devinit.text", secname) == 0)
+                       maps[ARM_SEC_DEVINIT].sec_text = s;
+               else if (strcmp(".text", secname) == 0)
+                       maps[ARM_SEC_CORE].sec_text = s;
+               else if (strcmp(".exit.text", secname) == 0)
+                       maps[ARM_SEC_EXIT].sec_text = s;
+               else if (strcmp(".devexit.text", secname) == 0)
+                       maps[ARM_SEC_DEVEXIT].sec_text = s;
        }
 #endif
        return 0;
@@ -292,31 +303,22 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
 #ifdef CONFIG_ARM_UNWIND
 static void register_unwind_tables(struct module *mod)
 {
-       if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
-               mod->arch.unwind_init =
-                       unwind_table_add(mod->arch.unw_sec_init->sh_addr,
-                                        mod->arch.unw_sec_init->sh_size,
-                                        mod->arch.sec_init_text->sh_addr,
-                                        mod->arch.sec_init_text->sh_size);
-       if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
-               mod->arch.unwind_devinit =
-                       unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
-                                        mod->arch.unw_sec_devinit->sh_size,
-                                        mod->arch.sec_devinit_text->sh_addr,
-                                        mod->arch.sec_devinit_text->sh_size);
-       if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
-               mod->arch.unwind_core =
-                       unwind_table_add(mod->arch.unw_sec_core->sh_addr,
-                                        mod->arch.unw_sec_core->sh_size,
-                                        mod->arch.sec_core_text->sh_addr,
-                                        mod->arch.sec_core_text->sh_size);
+       int i;
+       for (i = 0; i < ARM_SEC_MAX; ++i) {
+               struct arm_unwind_mapping *map = &mod->arch.map[i];
+               if (map->unw_sec && map->sec_text)
+                       map->unwind = unwind_table_add(map->unw_sec->sh_addr,
+                                                      map->unw_sec->sh_size,
+                                                      map->sec_text->sh_addr,
+                                                      map->sec_text->sh_size);
+       }
 }
 
 static void unregister_unwind_tables(struct module *mod)
 {
-       unwind_table_del(mod->arch.unwind_init);
-       unwind_table_del(mod->arch.unwind_devinit);
-       unwind_table_del(mod->arch.unwind_core);
+       int i = ARM_SEC_MAX;
+       while (--i >= 0)
+               unwind_table_del(mod->arch.map[i].unwind);
 }
 #else
 static inline void register_unwind_tables(struct module *mod) { }
index 417c392ddf1cb55066fa5f99e83e77514bd89901..49643b1467e62d529d4edd661990bb64da1e1f73 100644 (file)
@@ -123,6 +123,12 @@ armpmu_get_max_events(void)
 }
 EXPORT_SYMBOL_GPL(armpmu_get_max_events);
 
+int perf_num_counters(void)
+{
+       return armpmu_get_max_events();
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
 #define HW_OP_UNSUPPORTED              0xFFFF
 
 #define C(_x) \
@@ -221,46 +227,56 @@ again:
 }
 
 static void
-armpmu_disable(struct perf_event *event)
+armpmu_read(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       int idx = hwc->idx;
-
-       WARN_ON(idx < 0);
-
-       clear_bit(idx, cpuc->active_mask);
-       armpmu->disable(hwc, idx);
-
-       barrier();
 
-       armpmu_event_update(event, hwc, idx);
-       cpuc->events[idx] = NULL;
-       clear_bit(idx, cpuc->used_mask);
+       /* Don't read disabled counters! */
+       if (hwc->idx < 0)
+               return;
 
-       perf_event_update_userpage(event);
+       armpmu_event_update(event, hwc, hwc->idx);
 }
 
 static void
-armpmu_read(struct perf_event *event)
+armpmu_stop(struct perf_event *event, int flags)
 {
        struct hw_perf_event *hwc = &event->hw;
 
-       /* Don't read disabled counters! */
-       if (hwc->idx < 0)
+       if (!armpmu)
                return;
 
-       armpmu_event_update(event, hwc, hwc->idx);
+       /*
+        * ARM pmu always has to update the counter, so ignore
+        * PERF_EF_UPDATE, see comments in armpmu_start().
+        */
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               armpmu->disable(hwc, hwc->idx);
+               barrier(); /* why? */
+               armpmu_event_update(event, hwc, hwc->idx);
+               hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+       }
 }
 
 static void
-armpmu_unthrottle(struct perf_event *event)
+armpmu_start(struct perf_event *event, int flags)
 {
        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.
+        */
+       if (flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+       hwc->state = 0;
        /*
         * Set the period again. Some counters can't be stopped, so when we
-        * were throttled we simply disabled the IRQ source and the counter
+        * were stopped we simply disabled the IRQ source and the counter
         * may have been left counting. If we don't do this step then we may
         * get an interrupt too soon or *way* too late if the overflow has
         * happened since disabling.
@@ -269,14 +285,33 @@ armpmu_unthrottle(struct perf_event *event)
        armpmu->enable(hwc, hwc->idx);
 }
 
+static void
+armpmu_del(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_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);
+
+       perf_event_update_userpage(event);
+}
+
 static int
-armpmu_enable(struct perf_event *event)
+armpmu_add(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx;
        int err = 0;
 
+       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);
        if (idx < 0) {
@@ -293,25 +328,19 @@ armpmu_enable(struct perf_event *event)
        cpuc->events[idx] = event;
        set_bit(idx, cpuc->active_mask);
 
-       /* Set the period for the event. */
-       armpmu_event_set_period(event, hwc, idx);
-
-       /* Enable the event. */
-       armpmu->enable(hwc, idx);
+       hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+       if (flags & PERF_EF_START)
+               armpmu_start(event, PERF_EF_RELOAD);
 
        /* Propagate our changes to the userspace mapping. */
        perf_event_update_userpage(event);
 
 out:
+       perf_pmu_enable(event->pmu);
        return err;
 }
 
-static struct pmu pmu = {
-       .enable     = armpmu_enable,
-       .disable    = armpmu_disable,
-       .unthrottle = armpmu_unthrottle,
-       .read       = armpmu_read,
-};
+static struct pmu pmu;
 
 static int
 validate_event(struct cpu_hw_events *cpuc,
@@ -319,8 +348,8 @@ validate_event(struct cpu_hw_events *cpuc,
 {
        struct hw_perf_event fake_event = event->hw;
 
-       if (event->pmu && event->pmu != &pmu)
-               return 0;
+       if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+               return 1;
 
        return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
 }
@@ -491,20 +520,29 @@ __hw_perf_event_init(struct perf_event *event)
        return err;
 }
 
-const struct pmu *
-hw_perf_event_init(struct perf_event *event)
+static int armpmu_event_init(struct perf_event *event)
 {
        int err = 0;
 
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+       case PERF_TYPE_HARDWARE:
+       case PERF_TYPE_HW_CACHE:
+               break;
+
+       default:
+               return -ENOENT;
+       }
+
        if (!armpmu)
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
 
        event->destroy = hw_perf_event_destroy;
 
        if (!atomic_inc_not_zero(&active_events)) {
-               if (atomic_read(&active_events) > perf_max_events) {
+               if (atomic_read(&active_events) > armpmu->num_events) {
                        atomic_dec(&active_events);
-                       return ERR_PTR(-ENOSPC);
+                       return -ENOSPC;
                }
 
                mutex_lock(&pmu_reserve_mutex);
@@ -518,17 +556,16 @@ hw_perf_event_init(struct perf_event *event)
        }
 
        if (err)
-               return ERR_PTR(err);
+               return err;
 
        err = __hw_perf_event_init(event);
        if (err)
                hw_perf_event_destroy(event);
 
-       return err ? ERR_PTR(err) : &pmu;
+       return err;
 }
 
-void
-hw_perf_enable(void)
+static void armpmu_enable(struct pmu *pmu)
 {
        /* Enable all of the perf events on hardware. */
        int idx;
@@ -549,13 +586,23 @@ hw_perf_enable(void)
        armpmu->start();
 }
 
-void
-hw_perf_disable(void)
+static void armpmu_disable(struct pmu *pmu)
 {
        if (armpmu)
                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,
+};
+
 /*
  * ARMv6 Performance counter handling code.
  *
@@ -1041,11 +1088,11 @@ armv6pmu_handle_irq(int irq_num,
        /*
         * Handle the pending perf events.
         *
-        * Note: this call *must* be run with interrupts enabled. For
-        * platforms that can have the PMU interrupts raised as a PMI, this
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
-       perf_event_do_pending();
+       irq_work_run();
 
        return IRQ_HANDLED;
 }
@@ -2017,11 +2064,11 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
        /*
         * Handle the pending perf events.
         *
-        * Note: this call *must* be run with interrupts enabled. For
-        * platforms that can have the PMU interrupts raised as a PMI, this
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
-       perf_event_do_pending();
+       irq_work_run();
 
        return IRQ_HANDLED;
 }
@@ -2389,7 +2436,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
                        armpmu->disable(hwc, idx);
        }
 
-       perf_event_do_pending();
+       irq_work_run();
 
        /*
         * Re-enable the PMU.
@@ -2716,7 +2763,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
                        armpmu->disable(hwc, idx);
        }
 
-       perf_event_do_pending();
+       irq_work_run();
 
        /*
         * Re-enable the PMU.
@@ -2933,14 +2980,12 @@ init_hw_perf_events(void)
                        armpmu = &armv6pmu;
                        memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
                                        sizeof(armv6_perf_cache_map));
-                       perf_max_events = armv6pmu.num_events;
                        break;
                case 0xB020:    /* ARM11mpcore */
                        armpmu = &armv6mpcore_pmu;
                        memcpy(armpmu_perf_cache_map,
                               armv6mpcore_perf_cache_map,
                               sizeof(armv6mpcore_perf_cache_map));
-                       perf_max_events = armv6mpcore_pmu.num_events;
                        break;
                case 0xC080:    /* Cortex-A8 */
                        armv7pmu.id = ARM_PERF_PMU_ID_CA8;
@@ -2952,7 +2997,6 @@ init_hw_perf_events(void)
                        /* Reset PMNC and read the nb of CNTx counters
                            supported */
                        armv7pmu.num_events = armv7_reset_read_pmnc();
-                       perf_max_events = armv7pmu.num_events;
                        break;
                case 0xC090:    /* Cortex-A9 */
                        armv7pmu.id = ARM_PERF_PMU_ID_CA9;
@@ -2964,7 +3008,6 @@ init_hw_perf_events(void)
                        /* Reset PMNC and read the nb of CNTx counters
                            supported */
                        armv7pmu.num_events = armv7_reset_read_pmnc();
-                       perf_max_events = armv7pmu.num_events;
                        break;
                }
        /* Intel CPUs [xscale]. */
@@ -2975,13 +3018,11 @@ init_hw_perf_events(void)
                        armpmu = &xscale1pmu;
                        memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
                                        sizeof(xscale_perf_cache_map));
-                       perf_max_events = xscale1pmu.num_events;
                        break;
                case 2:
                        armpmu = &xscale2pmu;
                        memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
                                        sizeof(xscale_perf_cache_map));
-                       perf_max_events = xscale2pmu.num_events;
                        break;
                }
        }
@@ -2991,9 +3032,10 @@ init_hw_perf_events(void)
                                arm_pmu_names[armpmu->id], armpmu->num_events);
        } else {
                pr_info("no hardware support available\n");
-               perf_max_events = -1;
        }
 
+       perf_pmu_register(&pmu);
+
        return 0;
 }
 arch_initcall(init_hw_perf_events);
@@ -3001,13 +3043,6 @@ arch_initcall(init_hw_perf_events);
 /*
  * Callchain handling code.
  */
-static inline void
-callchain_store(struct perf_callchain_entry *entry,
-               u64 ip)
-{
-       if (entry->nr < PERF_MAX_STACK_DEPTH)
-               entry->ip[entry->nr++] = ip;
-}
 
 /*
  * The registers we're interested in are at the end of the variable
@@ -3039,7 +3074,7 @@ user_backtrace(struct frame_tail *tail,
        if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
                return NULL;
 
-       callchain_store(entry, buftail.lr);
+       perf_callchain_store(entry, buftail.lr);
 
        /*
         * Frame pointers should strictly progress back up the stack
@@ -3051,16 +3086,11 @@ user_backtrace(struct frame_tail *tail,
        return buftail.fp - 1;
 }
 
-static void
-perf_callchain_user(struct pt_regs *regs,
-                   struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        struct frame_tail *tail;
 
-       callchain_store(entry, PERF_CONTEXT_USER);
-
-       if (!user_mode(regs))
-               regs = task_pt_regs(current);
 
        tail = (struct frame_tail *)regs->ARM_fp - 1;
 
@@ -3078,56 +3108,18 @@ callchain_trace(struct stackframe *fr,
                void *data)
 {
        struct perf_callchain_entry *entry = data;
-       callchain_store(entry, fr->pc);
+       perf_callchain_store(entry, fr->pc);
        return 0;
 }
 
-static void
-perf_callchain_kernel(struct pt_regs *regs,
-                     struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        struct stackframe fr;
 
-       callchain_store(entry, PERF_CONTEXT_KERNEL);
        fr.fp = regs->ARM_fp;
        fr.sp = regs->ARM_sp;
        fr.lr = regs->ARM_lr;
        fr.pc = regs->ARM_pc;
        walk_stackframe(&fr, callchain_trace, entry);
 }
-
-static void
-perf_do_callchain(struct pt_regs *regs,
-                 struct perf_callchain_entry *entry)
-{
-       int is_user;
-
-       if (!regs)
-               return;
-
-       is_user = user_mode(regs);
-
-       if (!current || !current->pid)
-               return;
-
-       if (is_user && current->state != TASK_RUNNING)
-               return;
-
-       if (!is_user)
-               perf_callchain_kernel(regs, entry);
-
-       if (current->mm)
-               perf_callchain_user(regs, entry);
-}
-
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-
-struct perf_callchain_entry *
-perf_callchain(struct pt_regs *regs)
-{
-       struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
-
-       entry->nr = 0;
-       perf_do_callchain(regs, entry);
-       return entry;
-}
index 401e38be1f787c16e7b36d6429406a05229d83da..e76fcaadce03fca34f20524bc03df51f73cb2d99 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/utsname.h>
 #include <linux/uaccess.h>
 #include <linux/random.h>
+#include <linux/hw_breakpoint.h>
 
 #include <asm/cacheflush.h>
 #include <asm/leds.h>
@@ -135,6 +136,25 @@ EXPORT_SYMBOL(pm_power_off);
 void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
 EXPORT_SYMBOL_GPL(arm_pm_restart);
 
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+       smp_mb();
+       /* kick all the CPUs so that they exit out of pm_idle */
+       smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
 /*
  * This is our default idle handler.  We need to disable
@@ -317,6 +337,8 @@ void flush_thread(void)
        struct thread_info *thread = current_thread_info();
        struct task_struct *tsk = current;
 
+       flush_ptrace_hw_breakpoint(tsk);
+
        memset(thread->used_cp, 0, sizeof(thread->used_cp));
        memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
        memset(&thread->fpstate, 0, sizeof(union fp_state));
@@ -345,6 +367,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        thread->cpu_context.sp = (unsigned long)childregs;
        thread->cpu_context.pc = (unsigned long)ret_from_fork;
 
+       clear_ptrace_hw_breakpoint(p);
+
        if (clone_flags & CLONE_SETTLS)
                thread->tp_value = regs->ARM_r3;
 
@@ -458,3 +482,24 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
        unsigned long range_end = mm->brk + 0x02000000;
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
+
+/*
+ * The vectors page is always readable from user space for the
+ * atomic helpers and the signal restart code.  Let's declare a mapping
+ * for it so it is visible through ptrace and /proc/<pid>/mem.
+ */
+
+int vectors_user_mapping(void)
+{
+       struct mm_struct *mm = current->mm;
+       return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
+                                      VM_READ | VM_EXEC |
+                                      VM_MAYREAD | VM_MAYEXEC |
+                                      VM_ALWAYSDUMP | VM_RESERVED,
+                                      NULL);
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+}
index f99d489822d50fb23e46f4e7760411b766e040e7..e0cb6370ed148d9c24d6e856bc6c5c46128f38cb 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/uaccess.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -847,6 +849,232 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
 }
 #endif
 
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+/*
+ * Convert a virtual register number into an index for a thread_info
+ * breakpoint array. Breakpoints are identified using positive numbers
+ * whilst watchpoints are negative. The registers are laid out as pairs
+ * of (address, control), each pair mapping to a unique hw_breakpoint struct.
+ * Register 0 is reserved for describing resource information.
+ */
+static int ptrace_hbp_num_to_idx(long num)
+{
+       if (num < 0)
+               num = (ARM_MAX_BRP << 1) - num;
+       return (num - 1) >> 1;
+}
+
+/*
+ * Returns the virtual register number for the address of the
+ * breakpoint at index idx.
+ */
+static long ptrace_hbp_idx_to_num(int idx)
+{
+       long mid = ARM_MAX_BRP << 1;
+       long num = (idx << 1) + 1;
+       return num > mid ? mid - num : num;
+}
+
+/*
+ * Handle hitting a HW-breakpoint.
+ */
+static void ptrace_hbptriggered(struct perf_event *bp, int unused,
+                                    struct perf_sample_data *data,
+                                    struct pt_regs *regs)
+{
+       struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
+       long num;
+       int i;
+       siginfo_t info;
+
+       for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
+               if (current->thread.debug.hbp[i] == bp)
+                       break;
+
+       num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
+
+       info.si_signo   = SIGTRAP;
+       info.si_errno   = (int)num;
+       info.si_code    = TRAP_HWBKPT;
+       info.si_addr    = (void __user *)(bkpt->trigger);
+
+       force_sig_info(SIGTRAP, &info, current);
+}
+
+/*
+ * Set ptrace breakpoint pointers to zero for this task.
+ * This is required in order to prevent child processes from unregistering
+ * breakpoints held by their parent.
+ */
+void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+       memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
+}
+
+/*
+ * Unregister breakpoints from this task and reset the pointers in
+ * the thread_struct.
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+       int i;
+       struct thread_struct *t = &tsk->thread;
+
+       for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
+               if (t->debug.hbp[i]) {
+                       unregister_hw_breakpoint(t->debug.hbp[i]);
+                       t->debug.hbp[i] = NULL;
+               }
+       }
+}
+
+static u32 ptrace_get_hbp_resource_info(void)
+{
+       u8 num_brps, num_wrps, debug_arch, wp_len;
+       u32 reg = 0;
+
+       num_brps        = hw_breakpoint_slots(TYPE_INST);
+       num_wrps        = hw_breakpoint_slots(TYPE_DATA);
+       debug_arch      = arch_get_debug_arch();
+       wp_len          = arch_get_max_wp_len();
+
+       reg             |= debug_arch;
+       reg             <<= 8;
+       reg             |= wp_len;
+       reg             <<= 8;
+       reg             |= num_wrps;
+       reg             <<= 8;
+       reg             |= num_brps;
+
+       return reg;
+}
+
+static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
+{
+       struct perf_event_attr attr;
+
+       ptrace_breakpoint_init(&attr);
+
+       /* Initialise fields to sane defaults. */
+       attr.bp_addr    = 0;
+       attr.bp_len     = HW_BREAKPOINT_LEN_4;
+       attr.bp_type    = type;
+       attr.disabled   = 1;
+
+       return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
+}
+
+static int ptrace_gethbpregs(struct task_struct *tsk, long num,
+                            unsigned long  __user *data)
+{
+       u32 reg;
+       int idx, ret = 0;
+       struct perf_event *bp;
+       struct arch_hw_breakpoint_ctrl arch_ctrl;
+
+       if (num == 0) {
+               reg = ptrace_get_hbp_resource_info();
+       } else {
+               idx = ptrace_hbp_num_to_idx(num);
+               if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               bp = tsk->thread.debug.hbp[idx];
+               if (!bp) {
+                       reg = 0;
+                       goto put;
+               }
+
+               arch_ctrl = counter_arch_bp(bp)->ctrl;
+
+               /*
+                * Fix up the len because we may have adjusted it
+                * to compensate for an unaligned address.
+                */
+               while (!(arch_ctrl.len & 0x1))
+                       arch_ctrl.len >>= 1;
+
+               if (idx & 0x1)
+                       reg = encode_ctrl_reg(arch_ctrl);
+               else
+                       reg = bp->attr.bp_addr;
+       }
+
+put:
+       if (put_user(reg, data))
+               ret = -EFAULT;
+
+out:
+       return ret;
+}
+
+static int ptrace_sethbpregs(struct task_struct *tsk, long num,
+                            unsigned long __user *data)
+{
+       int idx, gen_len, gen_type, implied_type, ret = 0;
+       u32 user_val;
+       struct perf_event *bp;
+       struct arch_hw_breakpoint_ctrl ctrl;
+       struct perf_event_attr attr;
+
+       if (num == 0)
+               goto out;
+       else if (num < 0)
+               implied_type = HW_BREAKPOINT_RW;
+       else
+               implied_type = HW_BREAKPOINT_X;
+
+       idx = ptrace_hbp_num_to_idx(num);
+       if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (get_user(user_val, data)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       bp = tsk->thread.debug.hbp[idx];
+       if (!bp) {
+               bp = ptrace_hbp_create(tsk, implied_type);
+               if (IS_ERR(bp)) {
+                       ret = PTR_ERR(bp);
+                       goto out;
+               }
+               tsk->thread.debug.hbp[idx] = bp;
+       }
+
+       attr = bp->attr;
+
+       if (num & 0x1) {
+               /* Address */
+               attr.bp_addr    = user_val;
+       } else {
+               /* Control */
+               decode_ctrl_reg(user_val, &ctrl);
+               ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
+               if (ret)
+                       goto out;
+
+               if ((gen_type & implied_type) != gen_type) {
+                               ret = -EINVAL;
+                               goto out;
+               }
+
+               attr.bp_len     = gen_len;
+               attr.bp_type    = gen_type;
+               attr.disabled   = !ctrl.enabled;
+       }
+
+       ret = modify_user_hw_breakpoint(bp, &attr);
+out:
+       return ret;
+}
+#endif
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        int ret;
@@ -916,6 +1144,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        break;
 #endif
 
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+               case PTRACE_GETHBPREGS:
+                       ret = ptrace_gethbpregs(child, addr,
+                                               (unsigned long __user *)data);
+                       break;
+               case PTRACE_SETHBPREGS:
+                       ret = ptrace_sethbpregs(child, addr,
+                                               (unsigned long __user *)data);
+                       break;
+#endif
+
                default:
                        ret = ptrace_request(child, request, addr, data);
                        break;
index d5231ae7355aa286bf5503e0180954f84e4f6022..336f14e0e5c212685c09f13f8ecbb30662873354 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/procinfo.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
+#include <asm/smp_plat.h>
 #include <asm/mach-types.h>
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
@@ -238,6 +239,35 @@ int cpu_architecture(void)
        return cpu_arch;
 }
 
+static int cpu_has_aliasing_icache(unsigned int arch)
+{
+       int aliasing_icache;
+       unsigned int id_reg, num_sets, line_size;
+
+       /* arch specifies the register format */
+       switch (arch) {
+       case CPU_ARCH_ARMv7:
+               asm("mcr        p15, 2, %0, c0, c0, 0 @ set CSSELR"
+                   : /* No output operands */
+                   : "r" (1));
+               isb();
+               asm("mrc        p15, 1, %0, c0, c0, 0 @ read CCSIDR"
+                   : "=r" (id_reg));
+               line_size = 4 << ((id_reg & 0x7) + 2);
+               num_sets = ((id_reg >> 13) & 0x7fff) + 1;
+               aliasing_icache = (line_size * num_sets) > PAGE_SIZE;
+               break;
+       case CPU_ARCH_ARMv6:
+               aliasing_icache = read_cpuid_cachetype() & (1 << 11);
+               break;
+       default:
+               /* I-cache aliases will be handled by D-cache aliasing code */
+               aliasing_icache = 0;
+       }
+
+       return aliasing_icache;
+}
+
 static void __init cacheid_init(void)
 {
        unsigned int cachetype = read_cpuid_cachetype();
@@ -249,10 +279,15 @@ static void __init cacheid_init(void)
                        cacheid = CACHEID_VIPT_NONALIASING;
                        if ((cachetype & (3 << 14)) == 1 << 14)
                                cacheid |= CACHEID_ASID_TAGGED;
-               } else if (cachetype & (1 << 23))
+                       else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
+                               cacheid |= CACHEID_VIPT_I_ALIASING;
+               } else if (cachetype & (1 << 23)) {
                        cacheid = CACHEID_VIPT_ALIASING;
-               else
+               } else {
                        cacheid = CACHEID_VIPT_NONALIASING;
+                       if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
+                               cacheid |= CACHEID_VIPT_I_ALIASING;
+               }
        } else {
                cacheid = CACHEID_VIVT;
        }
@@ -263,7 +298,7 @@ static void __init cacheid_init(void)
                cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
                cache_is_vivt() ? "VIVT" :
                icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
-               cache_is_vipt_aliasing() ? "VIPT aliasing" :
+               icache_is_vipt_aliasing() ? "VIPT aliasing" :
                cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 }
 
@@ -490,7 +525,7 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
 
        kernel_code.start   = virt_to_phys(_text);
        kernel_code.end     = virt_to_phys(_etext - 1);
-       kernel_data.start   = virt_to_phys(_data);
+       kernel_data.start   = virt_to_phys(_sdata);
        kernel_data.end     = virt_to_phys(_end - 1);
 
        for (i = 0; i < mi->nr_banks; i++) {
@@ -825,7 +860,8 @@ void __init setup_arch(char **cmdline_p)
        request_standard_resources(&meminfo, mdesc);
 
 #ifdef CONFIG_SMP
-       smp_init_cpus();
+       if (is_smp())
+               smp_init_cpus();
 #endif
        reserve_crashkernel();
 
index 40dc74f2b27f3362f8739f5e9898963dd27a221b..8c1959590252e7161f1da38497eddba9b0538afb 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
+#include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
@@ -67,12 +68,47 @@ enum ipi_msg_type {
        IPI_CPU_STOP,
 };
 
+static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
+       unsigned long end)
+{
+       unsigned long addr, prot;
+       pmd_t *pmd;
+
+       prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
+       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+               prot |= PMD_BIT4;
+
+       for (addr = start & PGDIR_MASK; addr < end;) {
+               pmd = pmd_offset(pgd + pgd_index(addr), addr);
+               pmd[0] = __pmd(addr | prot);
+               addr += SECTION_SIZE;
+               pmd[1] = __pmd(addr | prot);
+               addr += SECTION_SIZE;
+               flush_pmd_entry(pmd);
+               outer_clean_range(__pa(pmd), __pa(pmd + 1));
+       }
+}
+
+static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
+       unsigned long end)
+{
+       unsigned long addr;
+       pmd_t *pmd;
+
+       for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
+               pmd = pmd_offset(pgd + pgd_index(addr), addr);
+               pmd[0] = __pmd(0);
+               pmd[1] = __pmd(0);
+               clean_pmd_entry(pmd);
+               outer_clean_range(__pa(pmd), __pa(pmd + 1));
+       }
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
        struct task_struct *idle = ci->idle;
        pgd_t *pgd;
-       pmd_t *pmd;
        int ret;
 
        /*
@@ -101,11 +137,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
         * a 1:1 mapping for the physical address of the kernel.
         */
        pgd = pgd_alloc(&init_mm);
-       pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
-       *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
-                    PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
-       flush_pmd_entry(pmd);
-       outer_clean_range(__pa(pmd), __pa(pmd + 1));
+       if (!pgd)
+               return -ENOMEM;
+
+       if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+               identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+               identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+               identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
+       }
 
        /*
         * We need to tell the secondary core where to find
@@ -143,8 +184,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
        secondary_data.stack = NULL;
        secondary_data.pgdir = 0;
 
-       *pmd = __pmd(0);
-       clean_pmd_entry(pmd);
+       if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+               identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+               identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
+               identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
+       }
+
        pgd_free(&init_mm, pgd);
 
        if (ret) {
@@ -567,7 +614,8 @@ void smp_send_stop(void)
 {
        cpumask_t mask = cpu_online_map;
        cpu_clear(smp_processor_id(), mask);
-       send_ipi_message(&mask, IPI_CPU_STOP);
+       if (!cpus_empty(mask))
+               send_ipi_message(&mask, IPI_CPU_STOP);
 }
 
 /*
index dd81a918c106ea30029c0b8ce4eb60885f8a69a1..2a161765f6d5fdc0ac07805c2a4a62957adf72a0 100644 (file)
@@ -146,6 +146,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr)
                            addr < table->end_addr) {
                                idx = search_index(addr, table->start,
                                                   table->stop - 1);
+                               /* Move-to-front to exploit common traces */
+                               list_move(&table->list, &unwind_tables);
                                break;
                        }
                }
index b16c07914b55bb0215592a7727e0974b62108dd6..1953e3d21abf28e112b13bdc5f60f03774d6a32e 100644 (file)
@@ -8,6 +8,19 @@
 #include <asm/memory.h>
 #include <asm/page.h>
        
+#define PROC_INFO                                                      \
+       VMLINUX_SYMBOL(__proc_info_begin) = .;                          \
+       *(.proc.info.init)                                              \
+       VMLINUX_SYMBOL(__proc_info_end) = .;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define ARM_CPU_DISCARD(x)
+#define ARM_CPU_KEEP(x)                x
+#else
+#define ARM_CPU_DISCARD(x)     x
+#define ARM_CPU_KEEP(x)
+#endif
+
 OUTPUT_ARCH(arm)
 ENTRY(stext)
 
@@ -31,15 +44,18 @@ SECTIONS
                        HEAD_TEXT
                        INIT_TEXT
                _einittext = .;
-               __proc_info_begin = .;
-                       *(.proc.info.init)
-               __proc_info_end = .;
+               ARM_CPU_DISCARD(PROC_INFO)
                __arch_info_begin = .;
                        *(.arch.info.init)
                __arch_info_end = .;
                __tagtable_begin = .;
                        *(.taglist.init)
                __tagtable_end = .;
+#ifdef CONFIG_SMP_ON_UP
+               __smpalt_begin = .;
+                       *(.alt.smp.init)
+               __smpalt_end = .;
+#endif
 
                INIT_SETUP(16)
 
@@ -68,10 +84,8 @@ SECTIONS
        /DISCARD/ : {
                *(.ARM.exidx.exit.text)
                *(.ARM.extab.exit.text)
-#ifndef CONFIG_HOTPLUG_CPU
-               *(.ARM.exidx.cpuexit.text)
-               *(.ARM.extab.cpuexit.text)
-#endif
+               ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+               ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
 #ifndef CONFIG_HOTPLUG
                *(.ARM.exidx.devexit.text)
                *(.ARM.extab.devexit.text)
@@ -100,12 +114,11 @@ SECTIONS
                        *(.glue_7)
                        *(.glue_7t)
                *(.got)                 /* Global offset table          */
+                       ARM_CPU_KEEP(PROC_INFO)
        }
 
        RO_DATA(PAGE_SIZE)
 
-       _etext = .;                     /* End of text and rodata section */
-
 #ifdef CONFIG_ARM_UNWIND
        /*
         * Stack unwinding tables
@@ -123,6 +136,8 @@ SECTIONS
        }
 #endif
 
+       _etext = .;                     /* End of text and rodata section */
+
 #ifdef CONFIG_XIP_KERNEL
        __data_loc = ALIGN(4);          /* location in binary */
        . = PAGE_OFFSET + TEXT_OFFSET;
@@ -237,6 +252,12 @@ SECTIONS
 
        /* Default discards */
        DISCARDS
+
+#ifndef CONFIG_SMP_ON_UP
+       /DISCARD/ : {
+               *(.alt.smp.init)
+       }
+#endif
 }
 
 /*
index 81a3ecc0d104d0eddc0eb74a7609c42b082aff75..0eb3e3e5b2d1154e16233d2b72386b349a849ac4 100644 (file)
@@ -95,8 +95,6 @@ static void __init aaed2000_map_io(void)
 
 MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
        /* Maintainer: Nicolas Bellido Y Ortega */
-       .phys_io        = PIO_BASE,
-       .io_pg_offst    = ((VIO_BASE) >> 18) & 0xfffc,
        .map_io         = aaed2000_map_io,
        .init_irq       = aaed2000_init_irq,
        .timer          = &aaec2000_timer,
index a9cac368bfe69f184c85ce7058ec29cfe10c83a2..bc7ad5561c4caee31fe32957ec297488b998c576 100644 (file)
  */
 
 #include "hardware.h"
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x80000000                @ physical
-               movne   \rx, #io_p2v(0x80000000)        @ virtual
-               orr     \rx, \rx, #0x00000800
+               .macro  addruart, rp, rv
+               mov     \rp, 0x00000800
+               orr     \rv, \rp, #io_p2v(0x80000000)   @ virtual
+               orr     \rp, \rp, #0x80000000           @ physical
                .endm
 
                .macro  senduart,rd,rx
index 551f68f666bf0273bb465272887cedfbe7244b94..cff4e0a996ce992953780bc1af4f11d72aff34f3 100644 (file)
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END            (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END            0xd0000000
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 939bccd70569846987c6ddb304cd22c7de730bf7..851e8139ef9d1a4c9511022696b10fc17a49ff52 100644 (file)
@@ -33,6 +33,7 @@ config ARCH_AT91SAM9260
        select HAVE_AT91_USART3
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
+       select HAVE_NET_MACB
 
 config ARCH_AT91SAM9261
        bool "AT91SAM9261"
@@ -51,6 +52,7 @@ config ARCH_AT91SAM9263
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
        select HAVE_FB_ATMEL
+       select HAVE_NET_MACB
 
 config ARCH_AT91SAM9RL
        bool "AT91SAM9RL"
@@ -66,6 +68,7 @@ config ARCH_AT91SAM9G20
        select HAVE_AT91_USART3
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
+       select HAVE_NET_MACB
 
 config ARCH_AT91SAM9G45
        bool "AT91SAM9G45"
@@ -73,6 +76,7 @@ config ARCH_AT91SAM9G45
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_USART3
        select HAVE_FB_ATMEL
+       select HAVE_NET_MACB
 
 config ARCH_AT91CAP9
        bool "AT91CAP9"
@@ -248,6 +252,12 @@ config MACH_CPU9260
          Select this if you are using a Eukrea Electromatique's
          CPU9260 Board <http://www.eukrea.com/>
 
+config MACH_FLEXIBITY
+       bool "Flexibity Connect board"
+       help
+         Select this if you are using Flexibity Connect board
+         <http://www.flexibity.com>
+
 endif
 
 # ----------------------------------------------------------
@@ -338,6 +348,7 @@ config MACH_AT91SAM9G20EK
          that embeds only one SD/MMC slot.
 
 config MACH_AT91SAM9G20EK_2MMC
+       depends on MACH_AT91SAM9G20EK
        bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
        select HAVE_NAND_ATMEL_BUSWIDTH_16
        help
@@ -383,8 +394,8 @@ if ARCH_AT91SAM9G45
 
 comment "AT91SAM9G45 Board Type"
 
-config MACH_AT91SAM9G45EKES
-       bool "Atmel AT91SAM9G45-EKES Evaluation Kit"
+config MACH_AT91SAM9M10G45EK
+       bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
        select HAVE_NAND_ATMEL_BUSWIDTH_16
        help
          Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
index ca2ac003f41f5666fb8da8c1e23b34ab3e363ea6..412b3a471a4b43e4a6053c5f57deb822a0e14633 100644 (file)
@@ -46,6 +46,7 @@ obj-$(CONFIG_MACH_USB_A9260)  += board-usb-a9260.o
 obj-$(CONFIG_MACH_QIL_A9260)   += board-qil-a9260.o
 obj-$(CONFIG_MACH_AFEB9260)    += board-afeb-9260v1.o
 obj-$(CONFIG_MACH_CPU9260)     += board-cpu9krea.o
+obj-$(CONFIG_MACH_FLEXIBITY)   += board-flexibity.o
 
 # AT91SAM9261 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
@@ -61,7 +62,6 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK)       += board-sam9rlek.o
 
 # AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
-obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
@@ -70,7 +70,7 @@ obj-$(CONFIG_MACH_PORTUXG20)  += board-stamp9g20.o
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
 
 # AT91SAM9G45 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
+obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
index 753c0d31a3d3f0b407cfe20b68f5ba66189cd1a7..c67b47f1c0fd805751cf226a65315337a2507942 100644 (file)
@@ -121,8 +121,8 @@ static struct clk ssc1_clk = {
        .pmc_mask       = 1 << AT91SAM9G45_ID_SSC1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
-static struct clk tcb_clk = {
-       .name           = "tcb_clk",
+static struct clk tcb0_clk = {
+       .name           = "tcb0_clk",
        .pmc_mask       = 1 << AT91SAM9G45_ID_TCB,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -192,6 +192,14 @@ static struct clk ohci_clk = {
        .parent         = &uhphs_clk,
 };
 
+/* One additional fake clock for second TC block */
+static struct clk tcb1_clk = {
+       .name           = "tcb1_clk",
+       .pmc_mask       = 0,
+       .type           = CLK_TYPE_PERIPHERAL,
+       .parent         = &tcb0_clk,
+};
+
 static struct clk *periph_clocks[] __initdata = {
        &pioA_clk,
        &pioB_clk,
@@ -208,7 +216,7 @@ static struct clk *periph_clocks[] __initdata = {
        &spi1_clk,
        &ssc0_clk,
        &ssc1_clk,
-       &tcb_clk,
+       &tcb0_clk,
        &pwm_clk,
        &tsc_clk,
        &dma_clk,
@@ -221,6 +229,7 @@ static struct clk *periph_clocks[] __initdata = {
        &mmc1_clk,
        // irq0
        &ohci_clk,
+       &tcb1_clk,
 };
 
 /*
index 809114d5a5a6690ec3c4f510bb6cb88fc7fede99..1276babf84d540ad253d06eb089f29d57beab1a7 100644 (file)
@@ -46,7 +46,7 @@ static struct resource hdmac_resources[] = {
                .end    = AT91_BASE_SYS + AT91_DMA + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
-       [2] = {
+       [1] = {
                .start  = AT91SAM9G45_ID_DMA,
                .end    = AT91SAM9G45_ID_DMA,
                .flags  = IORESOURCE_IRQ,
@@ -426,7 +426,7 @@ static struct i2c_gpio_platform_data pdata_i2c0 = {
        .sda_is_open_drain      = 1,
        .scl_pin                = AT91_PIN_PA21,
        .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
+       .udelay                 = 5,            /* ~100 kHz */
 };
 
 static struct platform_device at91sam9g45_twi0_device = {
@@ -440,7 +440,7 @@ static struct i2c_gpio_platform_data pdata_i2c1 = {
        .sda_is_open_drain      = 1,
        .scl_pin                = AT91_PIN_PB11,
        .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
+       .udelay                 = 5,            /* ~100 kHz */
 };
 
 static struct platform_device at91sam9g45_twi1_device = {
@@ -835,9 +835,9 @@ static struct platform_device at91sam9g45_tcb1_device = {
 static void __init at91_add_device_tc(void)
 {
        /* this chip has one clock and irq for all six TC channels */
-       at91_clock_associate("tcb_clk", &at91sam9g45_tcb0_device.dev, "t0_clk");
+       at91_clock_associate("tcb0_clk", &at91sam9g45_tcb0_device.dev, "t0_clk");
        platform_device_register(&at91sam9g45_tcb0_device);
-       at91_clock_associate("tcb_clk", &at91sam9g45_tcb1_device.dev, "t0_clk");
+       at91_clock_associate("tcb1_clk", &at91sam9g45_tcb1_device.dev, "t0_clk");
        platform_device_register(&at91sam9g45_tcb1_device);
 }
 #else
index 9b27d167bff0c0e850f21bebf2994aaf4c84554d..46bdc82d3fbf9985310db451bb2cf8a6eb4b81f7 100644 (file)
@@ -92,8 +92,6 @@ static void __init onearm_board_init(void)
 
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = onearm_map_io,
index 50667bed7cc9f7eb1381b39802afb4b825aa1920..cba7f7771feed1b6fc2286b76a8b63ffbdc9f398 100644 (file)
@@ -218,8 +218,6 @@ static void __init afeb9260_board_init(void)
 
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
        /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = afeb9260_map_io,
index 5daff277f53e0deaccfc8665d75613440ba7bbfa..3929f1c9e4e5ce0fe10bb8ba64c02d4eae27aaed 100644 (file)
@@ -216,7 +216,7 @@ static struct atmel_nand_data __initdata eb_nand_data = {
 /*     .rdy_pin        = AT91_PIN_PC16, */
        .enable_pin     = AT91_PIN_PA15,
        .partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
        .bus_width_16   = 1,
 #else
        .bus_width_16   = 0,
@@ -318,8 +318,6 @@ static void __init eb_board_init(void)
 
 MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
        /* Maintainer: Atmel <costa.antonior@gmail.com> */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = eb_map_io,
index 44eb9f764938985abd52f7d285ad1b456507594c..b54e3e6fceb6774df2318b663131625800b25b0a 100644 (file)
@@ -198,8 +198,6 @@ static void __init cam60_board_init(void)
 
 MACHINE_START(CAM60, "KwikByte CAM60")
        /* Maintainer: KwikByte */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = cam60_map_io,
index d6940870e403fb8d7e1e15bac38ed2e6a0e4899f..e7274440ead99f8970e2abc801d2d752dced6d90 100644 (file)
@@ -399,8 +399,6 @@ static void __init cap9adk_board_init(void)
 
 MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
        /* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = cap9adk_map_io,
index db1f9544d2e0f9af8cb9ef46b8a3d2a126408c27..2e74a19874d11a955d90909dbfec1983508896f8 100644 (file)
@@ -162,8 +162,6 @@ static void __init carmeva_board_init(void)
 
 MACHINE_START(CARMEVA, "Carmeva")
        /* Maintainer: Conitec Datasystems */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = carmeva_map_io,
index 4bc2e9f6ebb537e2b3bf168f90c74f6e15d3fd3b..3838594578f3539d395cfd74bd4f9a90f9c21940 100644 (file)
@@ -375,8 +375,6 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260")
 MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
        /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = cpu9krea_map_io,
index a28d99656190e23cb4d3bdc2648a579f8197bd43..2f4dd8cdd484a50c1276fd48dcc61b68b3519c24 100644 (file)
@@ -175,8 +175,6 @@ static void __init cpuat91_board_init(void)
 
 MACHINE_START(CPUAT91, "Eukrea")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = cpuat91_map_io,
index fea2529ebcf9c781acb131aa7a1517bfc20ca772..464839dc39bd4d1c9acc0d38d17559d84a897e32 100644 (file)
@@ -257,8 +257,6 @@ static void __init csb337_board_init(void)
 
 MACHINE_START(CSB337, "Cogent CSB337")
        /* Maintainer: Bill Gatliff */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = csb337_map_io,
index cfa3f04b22053e7d8d69d7f80fddbaf24a812ae7..431688c6141267f3227f034baa9c9dab2bd9d9d3 100644 (file)
@@ -138,8 +138,6 @@ static void __init csb637_board_init(void)
 
 MACHINE_START(CSB637, "Cogent CSB637")
        /* Maintainer: Bill Gatliff */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = csb637_map_io,
index 0fd0f5bc77ea56623e83a37440da77e33f683af2..e14f0e165680ed39b5a9be326e661b9b415cb1bd 100644 (file)
@@ -225,8 +225,6 @@ static void __init dk_board_init(void)
 
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
        /* Maintainer: SAN People/Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = dk_map_io,
index 528656761ff74d390ee8d5c4c71d467679164b83..6cf6566ae346610a78f29f7de0f0f698f7d16e09 100644 (file)
@@ -120,8 +120,6 @@ static void __init eb9200_board_init(void)
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = eb9200_map_io,
index 1d69908617f07cdb18e58322f9c59fe61069da44..7b58c948a957e851c82b20ab9450fdc98925a78d 100644 (file)
@@ -168,8 +168,6 @@ static void __init ecb_at91board_init(void)
 
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
        /* Maintainer: emQbit.com */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = ecb_at91map_io,
index 295a96609e71753d8b073f2534913d86b1b44a13..a158a0ce458fb36d09a4afe58f184c0e428ed057 100644 (file)
@@ -148,8 +148,6 @@ static void __init eco920_board_init(void)
 
 MACHINE_START(ECO920, "eco920")
        /* Maintainer: Sascha Hauer */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = eco920_map_io,
index 4cdfaac8e590fe2397204d231c1091dde3571a85..56e92c4bbc2a3222c87ddda4c178b13b33bb75dc 100644 (file)
@@ -191,8 +191,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
        /* Maintainer: SAN People/Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = ek_map_io,
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
new file mode 100644 (file)
index 0000000..c8a62dc
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * linux/arch/arm/mach-at91/board-flexibity.c
+ *
+ *  Copyright (C) 2010 Flexibity
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include "generic.h"
+
+static void __init flexibity_map_io(void)
+{
+       /* Initialize processor: 18.432 MHz crystal */
+       at91sam9260_initialize(18432000);
+
+       /* DBGU on ttyS0. (Rx & Tx only) */
+       at91_register_uart(0, 0, 0);
+
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+static void __init flexibity_init_irq(void)
+{
+       at91sam9260_init_interrupts(NULL);
+}
+
+/* USB Host port */
+static struct at91_usbh_data __initdata flexibity_usbh_data = {
+       .ports          = 2,
+};
+
+/* USB Device port */
+static struct at91_udc_data __initdata flexibity_udc_data = {
+       .vbus_pin       = AT91_PIN_PC5,
+       .pullup_pin     = 0,            /* pull-up driven by UDC */
+};
+
+/* SPI devices */
+static struct spi_board_info flexibity_spi_devices[] = {
+       {       /* DataFlash chip */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 1,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+};
+
+/* MCI (SD/MMC) */
+static struct at91_mmc_data __initdata flexibity_mmc_data = {
+       .slot_b         = 0,
+       .wire4          = 1,
+       .det_pin        = AT91_PIN_PC9,
+       .wp_pin         = AT91_PIN_PC4,
+};
+
+/* LEDs */
+static struct gpio_led flexibity_leds[] = {
+       {
+               .name                   = "usb1:green",
+               .gpio                   = AT91_PIN_PA12,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb1:red",
+               .gpio                   = AT91_PIN_PA13,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb2:green",
+               .gpio                   = AT91_PIN_PB26,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb2:red",
+               .gpio                   = AT91_PIN_PB27,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb3:green",
+               .gpio                   = AT91_PIN_PC8,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb3:red",
+               .gpio                   = AT91_PIN_PC6,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb4:green",
+               .gpio                   = AT91_PIN_PB4,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       },
+       {
+               .name                   = "usb4:red",
+               .gpio                   = AT91_PIN_PB5,
+               .active_low             = 1,
+               .default_trigger        = "default-on",
+       }
+};
+
+static void __init flexibity_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* USB Host */
+       at91_add_device_usbh(&flexibity_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&flexibity_udc_data);
+       /* SPI */
+       at91_add_device_spi(flexibity_spi_devices,
+               ARRAY_SIZE(flexibity_spi_devices));
+       /* MMC */
+       at91_add_device_mmc(0, &flexibity_mmc_data);
+       /* LEDs */
+       at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
+}
+
+MACHINE_START(FLEXIBITY, "Flexibity Connect")
+       /* Maintainer: Maxim Osipov */
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = flexibity_map_io,
+       .init_irq       = flexibity_init_irq,
+       .init_machine   = flexibity_board_init,
+MACHINE_END
index a87956c0a74f325adb7d5b9e6247b47ff691b071..c0ce79d431a0c1f3424b232e6a746b40c9f5dc5c 100644 (file)
@@ -99,8 +99,6 @@ static void __init kafa_board_init(void)
 
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
        /* Maintainer: Sergei Sharonov */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = kafa_map_io,
index fe9b9913fa3cd98eeacf1604b76351fa7de5d24a..a13d2063faff8e43dfeedab3531010e0118887b2 100644 (file)
@@ -136,8 +136,6 @@ static void __init kb9202_board_init(void)
 
 MACHINE_START(KB9200, "KB920x")
        /* Maintainer: KwikByte, Inc. */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = kb9202_map_io,
index 7c1e382330fb61de9efabe094b8bdfdbf1481e55..fe5f1d47e6e23884eb2ac6d3ab00d36aa264aba0 100644 (file)
@@ -387,8 +387,6 @@ static void __init neocore926_board_init(void)
 
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
        /* Maintainer: ADENEO */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = neocore926_map_io,
index 859727e7ea301adeb807246c98bb7d2df812f51b..9d833bbc592dcf3c10cfd4233140dd0ec34db8ff 100644 (file)
@@ -156,8 +156,6 @@ static void __init picotux200_board_init(void)
 
 MACHINE_START(PICOTUX2XX, "picotux 200")
        /* Maintainer: Kleinhenz Elektronik GmbH */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = picotux200_map_io,
index 664938e8f6611857c8007251f495a1426375fe26..69d15a875b667f34a68ba4332db47c5a4f6bef4c 100644 (file)
@@ -268,8 +268,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
        /* Maintainer: calao-systems */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index b4834697753499278b85aea36c710d990dd9ce49..25a26beaa728bbee99a15174925a73532ddad949 100644 (file)
@@ -212,8 +212,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
        /* Maintainer: Olimex */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index ba9d501b5c50a83166ba7f2ed8f53f4681a64125..de1816e0e1d967c87825bf6c4de11c8370aaf057 100644 (file)
@@ -356,8 +356,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index c4c8865d52d7bfd84f5a22416ef7fe6bc1c472aa..14acc901e24cdd97ca4c939f5ae3bcfba189feff 100644 (file)
@@ -93,11 +93,12 @@ static struct resource dm9000_resource[] = {
                .start  = AT91_PIN_PC11,
                .end    = AT91_PIN_PC11,
                .flags  = IORESOURCE_IRQ
+                       | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE,
        }
 };
 
 static struct dm9000_plat_data dm9000_platdata = {
-       .flags          = DM9000_PLATF_16BITONLY,
+       .flags          = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
 };
 
 static struct platform_device dm9000_device = {
@@ -167,17 +168,6 @@ static struct at91_udc_data __initdata ek_udc_data = {
 };
 
 
-/*
- * MCI (SD/MMC)
- */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-       .wire4          = 1,
-//     .det_pin        = ... not connected
-//     .wp_pin         = ... not connected
-//     .vcc_pin        = ... not connected
-};
-
-
 /*
  * NAND flash
  */
@@ -246,6 +236,10 @@ static void __init ek_add_device_nand(void)
        at91_add_device_nand(&ek_nand_data);
 }
 
+/*
+ * SPI related devices
+ */
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
 
 /*
  * ADS7846 Touchscreen
@@ -356,6 +350,19 @@ static struct spi_board_info ek_spi_devices[] = {
 #endif
 };
 
+#else /* CONFIG_SPI_ATMEL_* */
+/* spi0 and mmc/sd share the same PIO pins: cannot be used at the same time */
+
+/*
+ * MCI (SD/MMC)
+ * det_pin, wp_pin and vcc_pin are not connected
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+       .wire4          = 1,
+};
+
+#endif /* CONFIG_SPI_ATMEL_* */
+
 
 /*
  * LCD Controller
@@ -616,8 +623,6 @@ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
 MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index 2d867fb0630f0719723b9aa0fde5ab416725ae5f..bfe490df58be9edf63ab20b001ccaf94c368ccd1 100644 (file)
@@ -454,8 +454,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c b/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c
deleted file mode 100644 (file)
index c49f5c0..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2008 Atmel
- *  Copyright (C) 2009 Rob Emanuele
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at73c213.h>
-#include <linux/clk.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_map_io(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
-}
-
-static void __init ek_init_irq(void)
-{
-       at91sam9260_init_interrupts(NULL);
-}
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = 0,            /* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#endif
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PB0,
-       .is_rmii        = 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Bootstrap",
-               .offset = 0,
-               .size   = 4 * SZ_1M,
-       },
-       {
-               .name   = "Partition 1",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 60 * SZ_1M,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
-       .bus_width_16   = 1,
-#else
-       .bus_width_16   = 0,
-#endif
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- * wp_pin is not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata ek_mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC2,
-               .wp_pin         = -ENODEV,
-       },
-       .slot[1] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC9,
-               .wp_pin         = -ENODEV,
-       },
-
-};
-#else
-static struct at91_mmc_data __initdata ek_mmc_data = {
-       .slot_b         = 1,    /* Only one slot so use slot B */
-       .wire4          = 1,
-       .det_pin        = AT91_PIN_PC9,
-};
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "bottom" led, green, userled1 to be defined */
-               .name                   = "ds5",
-               .gpio                   = AT91_PIN_PB8,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "power" led, yellow */
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PB9,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
-       REGULATOR_SUPPLY("AVDD", "0-001b"),
-       REGULATOR_SUPPLY("HPVDD", "0-001b"),
-       REGULATOR_SUPPLY("DBVDD", "0-001b"),
-       REGULATOR_SUPPLY("DCVDD", "0-001b"),
-};
-
-static struct regulator_init_data ek_avdd_reg_init_data = {
-       .constraints    = {
-               .name   = "3V3",
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-       },
-       .consumer_supplies = ek_audio_consumer_supplies,
-       .num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config ek_vdd_pdata = {
-       .supply_name    = "board-3V3",
-       .microvolts     = 3300000,
-       .gpio           = -EINVAL,
-       .enabled_at_boot = 0,
-       .init_data      = &ek_avdd_reg_init_data,
-};
-static struct platform_device ek_voltage_regulator = {
-       .name           = "reg-fixed-voltage",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_vdd_pdata,
-       },
-};
-static void __init ek_add_regulators(void)
-{
-       platform_device_register(&ek_voltage_regulator);
-}
-#else
-static void __init ek_add_regulators(void) {}
-#endif
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("24c512", 0x50),
-       },
-};
-
-
-static void __init ek_board_init(void)
-{
-       /* Serial */
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* NAND */
-       ek_add_device_nand();
-       /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
-       /* Regulators */
-       ek_add_regulators();
-       /* MMC */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-       at91_add_device_mci(0, &ek_mmc_data);
-#else
-       at91_add_device_mmc(0, &ek_mmc_data);
-#endif
-       /* I2C */
-       at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       /* PCK0 provides MCLK to the WM8731 */
-       at91_set_B_periph(AT91_PIN_PC1, 0);
-       /* SSC (for WM8731) */
-       at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-}
-
-MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
-       /* Maintainer: Rob Emanuele */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-       .boot_params    = AT91_SDRAM_BASE + 0x100,
-       .timer          = &at91sam926x_timer,
-       .map_io         = ek_map_io,
-       .init_irq       = ek_init_irq,
-       .init_machine   = ek_board_init,
-MACHINE_END
index 6ea9808b8868d53a0c7cefd1926f921eadd82633..ca8198b3c168bb8a333dc3d08102b082a73e66c4 100644 (file)
 #include "sam9_smc.h"
 #include "generic.h"
 
+/*
+ * board revision encoding
+ * bit 0:
+ *     0 => 1 sd/mmc slot
+ *     1 => 2 sd/mmc slots connectors (board from revision C)
+ */
+#define HAVE_2MMC      (1 << 0)
+static int inline ek_have_2mmc(void)
+{
+       return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC);
+}
+
 
 static void __init ek_map_io(void)
 {
@@ -94,7 +106,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
  * SPI devices.
  */
 static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
        {       /* DataFlash chip */
                .modalias       = "mtd_dataflash",
                .chip_select    = 1,
@@ -121,6 +133,13 @@ static struct at91_eth_data __initdata ek_macb_data = {
        .is_rmii        = 1,
 };
 
+static void __init ek_add_device_macb(void)
+{
+       if (ek_have_2mmc())
+               ek_macb_data.phy_irq_pin = AT91_PIN_PB0;
+
+       at91_add_device_eth(&ek_macb_data);
+}
 
 /*
  * NAND flash
@@ -198,13 +217,36 @@ static void __init ek_add_device_nand(void)
 
 /*
  * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
+ * wp_pin and vcc_pin are not connected
  */
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static struct mci_platform_data __initdata ek_mmc_data = {
+       .slot[1] = {
+               .bus_width      = 4,
+               .detect_pin     = AT91_PIN_PC9,
+       },
+
+};
+#else
 static struct at91_mmc_data __initdata ek_mmc_data = {
-       .slot_b         = 1,
+       .slot_b         = 1,    /* Only one slot so use slot B */
        .wire4          = 1,
+       .det_pin        = AT91_PIN_PC9,
 };
+#endif
 
+static void __init ek_add_device_mmc(void)
+{
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+       if (ek_have_2mmc()) {
+               ek_mmc_data.slot[0].bus_width = 4;
+               ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
+       }
+       at91_add_device_mci(0, &ek_mmc_data);
+#else
+       at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+}
 
 /*
  * LEDs
@@ -223,6 +265,15 @@ static struct gpio_led ek_leds[] = {
        }
 };
 
+static void __init ek_add_device_gpio_leds(void)
+{
+       if (ek_have_2mmc()) {
+               ek_leds[0].gpio = AT91_PIN_PB8;
+               ek_leds[1].gpio = AT91_PIN_PB9;
+       }
+
+       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
 
 /*
  * GPIO Buttons
@@ -336,15 +387,15 @@ static void __init ek_board_init(void)
        /* NAND */
        ek_add_device_nand();
        /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
+       ek_add_device_macb();
        /* Regulators */
        ek_add_regulators();
        /* MMC */
-       at91_add_device_mmc(0, &ek_mmc_data);
+       ek_add_device_mmc();
        /* I2C */
        at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
        /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+       ek_add_device_gpio_leds();
        /* Push Buttons */
        ek_add_device_buttons();
        /* PCK0 provides MCLK to the WM8731 */
@@ -355,8 +406,15 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = ek_map_io,
+       .init_irq       = ek_init_irq,
+       .init_machine   = ek_board_init,
+MACHINE_END
+
+MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
+       /* Maintainer: Atmel */
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index ee800595594d3fa790f6d4737f59d3c9c4b8c473..7913984f6de9bbc1163c987b654afb9d955e0e87 100644 (file)
@@ -135,7 +135,7 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .rdy_pin        = AT91_PIN_PC8,
        .enable_pin     = AT91_PIN_PC14,
        .partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
        .bus_width_16   = 1,
 #else
        .bus_width_16   = 0,
@@ -399,10 +399,8 @@ static void __init ek_board_init(void)
        at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
 }
 
-MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES")
+MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index 7ac20f3a2067d6f4eeac86fb5d7e922665b8b843..3bf3408e94c18f370d5edb3991f7a8ff6dd0b208 100644 (file)
@@ -329,8 +329,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
        /* Maintainer: Atmel */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index 2c08ae4ad3a137b93a3afccc9a6a5f7d6dba3e2c..0a99b3cedd7a433b44bb0b0177aa4b5742017307 100644 (file)
@@ -177,8 +177,6 @@ static void __init snapper9260_board_init(void)
 }
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = snapper9260_map_io,
index 87958274290f352c492c141c117269bbb01a5ede..5206eef4a67eba12e1b22bd7ae0faa48ce29271a 100644 (file)
@@ -294,8 +294,6 @@ static void __init stamp9g20_board_init(void)
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
        /* Maintainer: taskit GmbH */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = portuxg20_map_io,
@@ -305,8 +303,6 @@ MACHINE_END
 
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = stamp9g20_map_io,
index 905d6ef768078dd4e75f0ac2058c267091161315..07784baeae841f2d98709b71cc1fe45917b820f1 100644 (file)
@@ -228,8 +228,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
        /* Maintainer: calao-systems */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index b6a3480383e58b19580417c705203637e7615438..b614508931fd92cc1b7b95a4da438d246cf5f86e 100644 (file)
@@ -244,8 +244,6 @@ static void __init ek_board_init(void)
 
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
        /* Maintainer: calao-systems */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
        .map_io         = ek_map_io,
index e22bf051f835a1485453c7e8dea1102160dc416a..89df00a9d2f72bfd768df2986db8d792fcd3c3d2 100644 (file)
@@ -594,8 +594,6 @@ static void __init yl9200_board_init(void)
 
 MACHINE_START(YL9200, "uCdragon YL-9200")
        /* Maintainer: S.Birtles */
-       .phys_io        = AT91_BASE_SYS,
-       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91rm9200_timer,
        .map_io         = yl9200_map_io,
index 7f7da439341fabc4e85b6febeb8b1f3e2cd6f4ee..7525cee3983f7252fac0542be5955a490ca6869b 100644 (file)
@@ -501,7 +501,8 @@ postcore_initcall(at91_clk_debugfs_init);
 int __init clk_register(struct clk *clk)
 {
        if (clk_is_peripheral(clk)) {
-               clk->parent = &mck;
+               if (!clk->parent)
+                       clk->parent = &mck;
                clk->mode = pmc_periph_mode;
                list_add_tail(&clk->node, &clocks);
        }
index d34cdb8abdca652dfcc64523e089361ed3ff2c0e..063ac44a020423119b52749dc3c866b6dd7eb965 100644 (file)
 #define AT91_DBGU_CIDR (AT91_SF + 0)   /* CIDR in PS segment */
 #define AT91_DBGU_EXID (AT91_SF + 4)   /* EXID in PS segment */
 
+/*
+ * Support defines for the simple Power Controller module.
+ */
+#define        AT91_PS_CR      (AT91_PS + 0)   /* PS Control register */
+#define        AT91_PS_CR_CPU  (1 << 0)        /* CPU clock disable bit */
+
 #endif /* AT91X40_H */
index 9e750a1c1b5a80fbab076f70314f8ffd7f5a1bd2..0f959faf74a9ffe7eb9ddc02ee6d6fddebcae419 100644 (file)
 #include <mach/hardware.h>
 #include <mach/at91_dbgu.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                         @ MMU enabled?
-       ldreq   \rx, =(AT91_BASE_SYS + AT91_DBGU)               @ System peripherals (phys address)
-       ldrne   \rx, =(AT91_VA_BASE_SYS + AT91_DBGU)            @ System peripherals (virt address)
+       .macro  addruart, rp, rv
+       ldr     \rp, =(AT91_BASE_SYS + AT91_DBGU)               @ System peripherals (phys address)
+       ldr     \rv, =(AT91_VA_BASE_SYS + AT91_DBGU)            @ System peripherals (virt address)
        .endm
 
        .macro  senduart,rd,rx
index c80e090b36708706671d8c66ff1a67a1c0106d61..36af14bc13bbbbc88aad80487b6d3cc85b924f0b 100644 (file)
 
 static inline void arch_idle(void)
 {
-#ifndef CONFIG_DEBUG_KERNEL
        /*
         * Disable the processor clock.  The processor will be automatically
         * re-enabled by an interrupt or by a reset.
         */
-       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#ifdef AT91_PS
+       at91_sys_write(AT91_PS_CR, AT91_PS_CR_CPU);
 #else
+       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#endif
+#ifndef CONFIG_CPU_ARM920T
        /*
         * Set the processor (CP15) into 'Wait for Interrupt' mode.
-        * Unlike disabling the processor clock via the PMC (above)
-        *  this allows the processor to be woken via JTAG.
+        * Post-RM9200 processors need this in conjunction with the above
+        * to save power when idle.
         */
        cpu_do_idle();
 #endif
index 2f139196d63de611d4e00ff8d55e5994f375dcf4..73eb066d23292e5757f5592d711531eeca920888 100644 (file)
@@ -167,8 +167,6 @@ static void __init bcmring_fixup(struct machine_desc *desc,
 
 MACHINE_START(BCMRING, "BCMRING")
        /* Maintainer: Broadcom Corporation */
-       .phys_io = MM_IO_START,
-       .io_pg_offst = (MM_IO_BASE >> 18) & 0xfffc,
        .fixup = bcmring_fixup,
        .map_io = bcmring_map_io,
        .init_irq = bcmring_init_irq,
index 29c0a911df262f6d70b5c369afa4788c44f0c07a..77eb35c89cd02161ee1678b049b6d80490423c09 100644 (file)
@@ -691,7 +691,7 @@ int dma_init(void)
 
        memset(&gDMA, 0, sizeof(gDMA));
 
-       init_MUTEX_LOCKED(&gDMA.lock);
+       sema_init(&gDMA.lock, 0);
        init_waitqueue_head(&gDMA.freeChannelQ);
 
        /* Initialize the Hardware */
@@ -1574,7 +1574,7 @@ int dma_init_mem_map(DMA_MemMap_t *memMap)
 {
        memset(memMap, 0, sizeof(*memMap));
 
-       init_MUTEX(&memMap->lock);
+       sema_init(&memMap->lock, 1);
 
        return 0;
 }
index 35e2ead8395c5f05447bca5efeebd7c4e8d9cafe..3db3a09fd3986e7ee452997e75a13180a38475b1 100644 (file)
@@ -22,4 +22,4 @@
  * 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles
  * larger physical memory designs better.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END       0xf0000000
index dc1c4939b0cedc6a03ad5cb7b8e9ba1e5e3f4dad..e3152631eb377e33490536729ae3656bf6575f24 100644 (file)
@@ -67,21 +67,21 @@ static void bcmring_unmask_irq2(unsigned int irq)
 }
 
 static struct irq_chip bcmring_irq0_chip = {
-       .typename = "ARM-INTC0",
+       .name = "ARM-INTC0",
        .ack = bcmring_mask_irq0,
        .mask = bcmring_mask_irq0,      /* mask a specific interrupt, blocking its delivery. */
        .unmask = bcmring_unmask_irq0,  /* unmaks an interrupt */
 };
 
 static struct irq_chip bcmring_irq1_chip = {
-       .typename = "ARM-INTC1",
+       .name = "ARM-INTC1",
        .ack = bcmring_mask_irq1,
        .mask = bcmring_mask_irq1,
        .unmask = bcmring_unmask_irq1,
 };
 
 static struct irq_chip bcmring_irq2_chip = {
-       .typename = "ARM-SINTC",
+       .name = "ARM-SINTC",
        .ack = bcmring_mask_irq2,
        .mask = bcmring_mask_irq2,
        .unmask = bcmring_unmask_irq2,
index 5f18eccdc7252a767c2c4e0bcf4a6167a8b0775a..4a74b2c959bd71391baf377f3e1c3d383fb9a944 100644 (file)
@@ -64,8 +64,6 @@ void __init autcpu12_map_io(void)
 
 MACHINE_START(AUTCPU12, "autronix autcpu12")
        /* Maintainer: Thomas Gleixner */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0020000,
        .map_io         = autcpu12_map_io,
        .init_irq       = clps711x_init_irq,
index 71a80b5b8ad6135eba4821251138c5e730c5ecf8..5a1689d48793c701ee462c277914335eb8a08325 100644 (file)
@@ -55,8 +55,6 @@ static void __init cdb89712_map_io(void)
 
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
        /* Maintainer: Ray Lehtiniemi */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = cdb89712_map_io,
        .init_irq       = clps711x_init_irq,
index 8ada2018497871ef25d414c583af7fa0f0f41b51..16481cf3e931efe7754bf759386567dcbe277809 100644 (file)
@@ -56,8 +56,6 @@ static void __init ceiva_map_io(void)
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
        /* Maintainer: Rob Scott */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = ceiva_map_io,
        .init_irq       = clps711x_init_irq,
index 3c3bf45039ff05f44c122adbc3bb1cceded613ab..67b5abb4a60a803af7a714e7d082611c5014c4c8 100644 (file)
@@ -37,8 +37,6 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
        /* Maintainer: Nobody */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .fixup          = fixup_clep7312,
        .map_io         = clps711x_map_io,
index 4a7a2322979a17c3dcb833bf44122f8af51bba8a..98ca5b2e940dd6a8347d473fbfeae006e45272c2 100644 (file)
@@ -57,8 +57,6 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
        /* Maintainer: Jon McClintock */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0020100,   /* 0xc0000000 - 0xc001ffff can be video RAM */
        .fixup          = fixup_edb7211,
        .map_io         = edb7211_map_io,
index a696099aa4f8f22ddd32e836b4bbb124acdc4ea0..b1cb479e71e909df2228f964ac451bbed40b69f2 100644 (file)
@@ -75,8 +75,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(FORTUNET, "ARM-FortuNet")
        /* Maintainer: FortuNet Inc. */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000000,
        .fixup          = fortunet_fixup,
        .map_io         = clps711x_map_io,
index 072cc6b61ba30b7b6e363040b40d409e8a43e38f..507c6873b7ee7e3b297864838a9767c01e77807b 100644 (file)
 #include <mach/hardware.h>
 #include <asm/hardware/clps7111.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #CLPS7111_PHYS_BASE
-               movne   \rx, #CLPS7111_VIRT_BASE
+               .macro  addruart, rp, rv
 #ifndef CONFIG_DEBUG_CLPS711X_UART2
-               add     \rx, \rx, #0x0000       @ UART1
+               mov     \rp, #0x0000    @ UART1
 #else
-               add     \rx, \rx, #0x1000       @ UART2
+               mov     \rp, #0x1000    @ UART2
 #endif
+               orr     \rv, \rp, #CLPS7111_VIRT_BASE
+               orr     \rp, \rp, #CLPS7111_PHYS_BASE
                .endm
 
                .macro  senduart,rd,rx
index ea6cc7beff287939e117cbc57beed7f3ffa5e155..30b3a287ed8865d897adccbfb2f318cfa4212e9b 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
index 0d94a30fd6fc84745555fc4daabdb5617db728a0..cefbce0480b95e0c6566a513f32c17ac030691b4 100644 (file)
@@ -89,8 +89,6 @@ static void __init p720t_map_io(void)
 
 MACHINE_START(P720T, "ARM-Prospector720T")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xff000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .fixup          = fixup_p720t,
        .map_io         = p720t_map_io,
index 9df8391fd78ac9ebfbb33425261ff9c631db79b1..90fe9ab8591db4f7d96744328c7026ba47dd73df 100644 (file)
@@ -142,8 +142,6 @@ static void __init cns3420_map_io(void)
 }
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
-       .phys_io        = CNS3XXX_UART0_BASE,
-       .io_pg_offst    = (CNS3XXX_UART0_BASE_VIRT >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = cns3420_map_io,
        .init_irq       = cns3xxx_init_irq,
index d16ce7eb00e9092a765bc7968e40f7e5d0fb5ee8..56d828634db5d82a81a711f27bed2f6e9d6ce4d8 100644 (file)
  * published by the Free Software Foundation.
  */
 
-               .macro  addruart,rx
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx,      #0x10000000
-               movne   \rx,      #0xf0000000   @ virtual base
-               orr     \rx, \rx, #0x00009000
+               .macro  addruart,rp,rv
+               mov     \rp, #0x00009000
+               orr     \rv, \rp, #0xf0000000   @ virtual base
+               orr     \rp, \rp, #0x10000000
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index c3994f341e4942869bf24e8c56075be61acda2fc..7f3cdbfc0fbb5229f25b360f4477f28968991cf3 100644 (file)
@@ -597,8 +597,6 @@ static void __init da830_evm_map_io(void)
 }
 
 MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
-       .phys_io        = IO_PHYS,
-       .io_pg_offst    = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params    = (DA8XX_DDR_BASE + 0x100),
        .map_io         = da830_evm_map_io,
        .init_irq       = cp_intc_init,
index fdc2cc500fc6ba712db2e9b53d1f31439c153818..b26f5cbfce3e2f5f1d8b4e8ee47a5e138e1a2999 100644 (file)
@@ -817,8 +817,6 @@ static void __init da850_evm_map_io(void)
 }
 
 MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
-       .phys_io        = IO_PHYS,
-       .io_pg_offst    = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params    = (DA8XX_DDR_BASE + 0x100),
        .map_io         = da850_evm_map_io,
        .init_irq       = cp_intc_init,
index a3191015efee04b4a4f4cc2907db4417a5b8dcb4..6e7cad13352ce6518fe6877bd5b184ab9c78ec59 100644 (file)
@@ -351,8 +351,6 @@ static __init void dm355_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (0x80000100),
        .map_io       = dm355_evm_map_io,
        .init_irq     = davinci_irq_init,
index f1d8132cf0c3945c89a4828ec21c42485f6ec5a5..543f9911b281e86b086bf970cfedfdf48c7165f8 100644 (file)
@@ -270,8 +270,6 @@ static __init void dm355_leopard_init(void)
 }
 
 MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (0x80000100),
        .map_io       = dm355_leopard_map_io,
        .init_irq     = davinci_irq_init,
index 84acef1d0b3d98be0797c1f4c439d58d77173ede..944a0cbaf5cb7cdbaf2fe3f29fbdead6b0174850 100644 (file)
@@ -613,8 +613,6 @@ static __init void dm365_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
-       .phys_io        = IO_PHYS,
-       .io_pg_offst    = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params    = (0x80000100),
        .map_io         = dm365_evm_map_io,
        .init_irq       = davinci_irq_init,
index 34c8b418cd726fc9baaf0b44c3b608c52349ee40..d59fba15ba8de949e6ae1142cada534219d6c4a3 100644 (file)
@@ -706,8 +706,6 @@ static __init void davinci_evm_init(void)
 
 MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
        /* Maintainer: MontaVista Software <source@mvista.com> */
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (DAVINCI_DDR_BASE + 0x100),
        .map_io       = davinci_evm_map_io,
        .init_irq     = davinci_irq_init,
index 4502f346b2b04fe45550bdd4dc4742281ce92aab..6890488fb92b4eb9e67af4138767e2f6efd3a60f 100644 (file)
@@ -786,8 +786,6 @@ void __init dm646x_board_setup_refclk(struct clk *clk)
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (0x80000100),
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
@@ -796,8 +794,6 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (0x80000100),
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
index 4c30e929bbf94231f53d6ee64178a148061961db..a4def889275ccbea6e7064377c2dc8e474a67c1d 100644 (file)
@@ -275,8 +275,6 @@ static __init void davinci_ntosd2_init(void)
 
 MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
        /* Maintainer: Neuros Technologies <neuros@groups.google.com> */
-       .phys_io        = IO_PHYS,
-       .io_pg_offst    = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params    = (DAVINCI_DDR_BASE + 0x100),
        .map_io          = davinci_ntosd2_map_io,
        .init_irq       = davinci_irq_init,
index 23e664a1a802a2c3d22b058cccd8b221b337dabf..9bdf8aafcc840f8fc4f15e9e70a9f153db1ba9d2 100644 (file)
@@ -154,8 +154,6 @@ static __init void davinci_sffsdr_init(void)
 
 MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
        /* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
-       .phys_io      = IO_PHYS,
-       .io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
        .boot_params  = (DAVINCI_DDR_BASE + 0x100),
        .map_io       = davinci_sffsdr_map_io,
        .init_irq     = davinci_irq_init,
index fe2a9d9c8bb7bb37a20a6f1b7ded622aac444dc9..b4de35b78904a0fda72e13a2c702211c998cd3ac 100644 (file)
@@ -164,8 +164,6 @@ console_initcall(tnetv107x_evm_console_init);
 #endif
 
 MACHINE_START(TNETV107X, "TNETV107X EVM")
-       .phys_io        = TNETV107X_IO_BASE,
-       .io_pg_offst    = (TNETV107X_IO_VIRT >> 18) & 0xfffc,
        .boot_params    = (TNETV107X_DDR_BASE + 0x100),
        .map_io         = tnetv107x_init,
        .init_irq       = cp_intc_init,
index 3d996b659ff41e43d794d93c167b409afb90c355..9be261beae7ddb2a72e2e9a76d9dbf2e2bf51316 100644 (file)
@@ -769,8 +769,7 @@ static struct map_desc dm355_io_desc[] = {
                .virtual        = SRAM_VIRT,
                .pfn            = __phys_to_pfn(0x00010000),
                .length         = SZ_32K,
-               /* MT_MEMORY_NONCACHED requires supersection alignment */
-               .type           = MT_DEVICE,
+               .type           = MT_MEMORY_NONCACHED,
        },
 };
 
index 6b6f4c643709c7d14a4b2baf168464ad772be4ce..7781e35daec3d0a7cf9e956aceb7e717f48c7c44 100644 (file)
@@ -969,8 +969,7 @@ static struct map_desc dm365_io_desc[] = {
                .virtual        = SRAM_VIRT,
                .pfn            = __phys_to_pfn(0x00010000),
                .length         = SZ_32K,
-               /* MT_MEMORY_NONCACHED requires supersection alignment */
-               .type           = MT_DEVICE,
+               .type           = MT_MEMORY_NONCACHED,
        },
 };
 
index 40fec315c99a192826d7530d43c6406726ecbcff..5e5b0a7831fbf2b7af156ba76bf4af0b6be26489 100644 (file)
@@ -653,8 +653,7 @@ static struct map_desc dm644x_io_desc[] = {
                .virtual        = SRAM_VIRT,
                .pfn            = __phys_to_pfn(0x00008000),
                .length         = SZ_16K,
-               /* MT_MEMORY_NONCACHED requires supersection alignment */
-               .type           = MT_DEVICE,
+               .type           = MT_MEMORY_NONCACHED,
        },
 };
 
index e4a3df1872aca89404899034ebbe920d453e7f66..26e8a9c7f50b4393f1e716575950fff967658b9a 100644 (file)
@@ -737,8 +737,7 @@ static struct map_desc dm646x_io_desc[] = {
                .virtual        = SRAM_VIRT,
                .pfn            = __phys_to_pfn(0x00010000),
                .length         = SZ_32K,
-               /* MT_MEMORY_NONCACHED requires supersection alignment */
-               .type           = MT_DEVICE,
+               .type           = MT_MEMORY_NONCACHED,
        },
 };
 
index f761dfdb8689b3f191e784b228731d2eff12fbe0..9f1befc5ac387d2d0124c080c88458a67dc0b30f 100644 (file)
@@ -29,35 +29,39 @@ davinci_uart_phys:  .word   0
 davinci_uart_virt:     .word   0
                .popsection
 
-               .macro addruart, rx, tmp
+               .macro addruart, rp, rv
 
                /* Use davinci_uart_phys/virt if already configured */
-10:            mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =__virt_to_phys(davinci_uart_phys)
-               ldrne   \rx, =davinci_uart_virt
-               ldr     \rx, [\rx]
-               cmp     \rx, #0                 @ is port configured?
+10:            mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               ldreq   \rp, =__virt_to_phys(davinci_uart_phys)
+               ldrne   \rp, =davinci_uart_phys
+               add     \rv, \rp, #4            @ davinci_uart_virt
+               ldr     \rp, [\rp, #0]
+               ldr     \rv, [\rv, #0]
+               cmp     \rp, #0                 @ is port configured?
+               cmpne   \rv, #0
                bne     99f                     @ already configured
 
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
+               /* Check the debug UART address set in uncompress.h */
+               mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
 
                /* Copy uart phys address from decompressor uart info */
-               ldreq   \tmp, =__virt_to_phys(davinci_uart_phys)
-               ldrne   \tmp, =davinci_uart_phys
-               ldreq   \rx, =DAVINCI_UART_INFO
-               ldrne   \rx, =__phys_to_virt(DAVINCI_UART_INFO)
-               ldr     \rx, [\rx, #0]
-               str     \rx, [\tmp]
+               ldreq   \rv, =__virt_to_phys(davinci_uart_phys)
+               ldrne   \rv, =davinci_uart_phys
+               ldreq   \rp, =DAVINCI_UART_INFO
+               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldr     \rp, [\rp, #0]
+               str     \rp, [\rv]
 
                /* Copy uart virt address from decompressor uart info */
-               ldreq   \tmp, =__virt_to_phys(davinci_uart_virt)
-               ldrne   \tmp, =davinci_uart_virt
-               ldreq   \rx, =DAVINCI_UART_INFO
-               ldrne   \rx, =__phys_to_virt(DAVINCI_UART_INFO)
-               ldr     \rx, [\rx, #4]
-               str     \rx, [\tmp]
+               ldreq   \rv, =__virt_to_phys(davinci_uart_virt)
+               ldrne   \rv, =davinci_uart_virt
+               ldreq   \rp, =DAVINCI_UART_INFO
+               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldr     \rp, [\rp, #4]
+               str     \rp, [\rv]
 
                b       10b
 99:
index bef70460fbc669353907355d3b9ca04f0a8308f3..95925aa76dd9483fe2c556e706981530b85f9627 100644 (file)
@@ -94,8 +94,6 @@ static void __init dove_db_init(void)
 }
 
 MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
-       .phys_io        = DOVE_SB_REGS_PHYS_BASE,
-       .io_pg_offst    = ((DOVE_SB_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = dove_db_init,
        .map_io         = dove_map_io,
index 1521d13f1d14928a12a1a8b79ad4fd4d5037e3c1..da8bf2bad3b1df0036527ba11b9d1df5ee50bc80 100644 (file)
@@ -8,12 +8,11 @@
 
 #include <mach/bridge-regs.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =DOVE_SB_REGS_PHYS_BASE
-       ldrne   \rx, =DOVE_SB_REGS_VIRT_BASE
-       orr     \rx, \rx, #0x00012000
+       .macro  addruart, rp, rv
+       ldr     \rp, =DOVE_SB_REGS_PHYS_BASE
+       ldr     \rv, =DOVE_SB_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
        .endm
 
 #define UART_SHIFT     2
index 3b3e4721ce2ea0fb9236803e566d4c67b0d5638e..eb4936ff90ad9c42b283fc6c354eae1f01c6c4c7 100644 (file)
@@ -13,8 +13,8 @@
 
 #define IO_SPACE_LIMIT         0xffffffff
 
-#define __io(a)  ((void __iomem *)(((a) - DOVE_PCIE0_IO_PHYS_BASE) +\
-                                  DOVE_PCIE0_IO_VIRT_BASE))
-#define __mem_pci(a)           (a)
+#define __io(a)        ((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \
+                                                DOVE_PCIE0_IO_VIRT_BASE))
+#define __mem_pci(a)   (a)
 
 #endif
index c7bc7fbb11a647800ee6b4fa032c14539eb3f70c..5df4099fc14fbd7798d521baf68a0da69aa0ba70 100644 (file)
@@ -280,8 +280,6 @@ arch_initcall(ebsa110_init);
 
 MACHINE_START(EBSA110, "EBSA110")
        /* Maintainer: Russell King */
-       .phys_io        = 0xe0000000,
-       .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000400,
        .reserve_lp0    = 1,
        .reserve_lp2    = 1,
index ebbd89f0e6c0e8967171396e4113e82c6826d266..7ef5690fd08c876cc27366d0b38451988daf066c 100644 (file)
  *
 **/
 
-               .macro  addruart, rx, tmp
-               mov     \rx, #0xf0000000
-               orr     \rx, \rx, #0x00000be0
+               .macro  addruart, rp, rv
+               mov     \rp, #0xf0000000
+               orr     \rp, \rp, #0x00000be0
+               mov     \rp, \rv
                .endm
 
 #define UART_SHIFT     2
index 9b44c19e95ec5167af7b5607ae5ff05a58e7e4f9..60bde56fba4cf3e4ef90cea65ceb2bf8e2db3111 100644 (file)
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x1f000000)
+#define VMALLOC_END       0xdf000000
index f744f676783f3024c0d18be2bff733432b260d9c..61b98ce4b6735455e148cbf76f397d0a1331cc42 100644 (file)
@@ -33,8 +33,6 @@ static void __init adssphere_init_machine(void)
 
 MACHINE_START(ADSSPHERE, "ADS Sphere board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index 8bf3cec98cfadba46d8ca1816c7aff5b8a871bbf..4566bd1c8660b3fe7ac0cff28473746fd3d34c82 100644 (file)
@@ -560,4 +560,4 @@ static int __init ep93xx_clock_init(void)
        clkdev_add_table(clocks, ARRAY_SIZE(clocks));
        return 0;
 }
-arch_initcall(ep93xx_clock_init);
+postcore_initcall(ep93xx_clock_init);
index 8904ca4e2e24fc9a4984bd0b88ce9d3eab52e7ea..a696d354b1f82598649586e6478be6334a91f978 100644 (file)
@@ -276,7 +276,7 @@ static void channel_disable(struct m2p_channel *ch)
        v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
        m2p_set_control(ch, v);
 
-       while (m2p_channel_state(ch) == STATE_ON)
+       while (m2p_channel_state(ch) >= STATE_ON)
                cpu_relax();
 
        m2p_set_control(ch, 0x0);
index c2ce9034ba87f5b856cb6e1cae89fb69060b8ffe..4b04316521318fb025c0821c9b4c63f52ae60f72 100644 (file)
@@ -124,8 +124,6 @@ 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> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -137,8 +135,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302
 MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
        /* Maintainer: George Kashperko <george@chas.com.ua> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -150,8 +146,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302A
 MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -163,8 +157,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307
 MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
        /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -176,8 +168,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307A
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
        /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -189,8 +179,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9312
 MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
        /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -202,8 +190,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315
 MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -215,8 +201,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315A
 MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index d97168c0ba336fa22179328b9dc72316807c13bb..9bd3152bff9a1257ec6410968ca6847d7f0a661d 100644 (file)
@@ -33,8 +33,6 @@ static void __init gesbc9312_init_machine(void)
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index 5cd22444e2236ae8fb73e59641e8dd82347f0fdf..b25bc90763673df4551e1bf0b6935a1d31e126f0 100644 (file)
  */
 #include <mach/ep93xx-regs.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                         @ MMU enabled?
-               ldreq   \rx, =EP93XX_APB_PHYS_BASE      @ Physical base
-               ldrne   \rx, =EP93XX_APB_VIRT_BASE      @ virtual base
-               orr     \rx, \rx, #0x000c0000
+               .macro  addruart, rp, rv
+               ldr     \rp, =EP93XX_APB_PHYS_BASE      @ Physical base
+               ldr     \rv, =EP93XX_APB_VIRT_BASE      @ virtual base
+               orr     \rp, \rp, #0x000c0000
+               orr     \rv, \rv, #0x000c0000
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index 2ba776320a8282e978d989eea0377d6511dc3ab7..7adea6258efeb01af639824f3e13b46da0b1fee5 100644 (file)
@@ -77,8 +77,6 @@ static void __init micro9_init_machine(void)
 #ifdef CONFIG_MACH_MICRO9H
 MACHINE_START(MICRO9, "Contec Micro9-High")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -90,8 +88,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9M
 MACHINE_START(MICRO9M, "Contec Micro9-Mid")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -103,8 +99,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9L
 MACHINE_START(MICRO9L, "Contec Micro9-Lite")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
@@ -116,8 +110,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9S
 MACHINE_START(MICRO9S, "Contec Micro9-Slim")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index 5dded5884133f89e27898567a61163c583fa8f3d..f22ce8db7947b616f7f45cf7fe6cf7eeebec62f2 100644 (file)
@@ -65,8 +65,6 @@ static void __init simone_init_machine(void)
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
 /* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index a12c89301297f6bb32985854df3a404dcc18fc97..ac601fe2b448b4ec06d08817d193f5c57b1376bc 100644 (file)
@@ -163,8 +163,6 @@ static void __init snappercl15_init_machine(void)
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
        /* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
index 93aeab8af705e8dd3dde989b1658e81e6ed60062..c2d2cf40ead920f323a717185b9fc715d704d96d 100644 (file)
@@ -257,8 +257,6 @@ static void __init ts72xx_init_machine(void)
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = EP93XX_APB_PHYS_BASE,
-       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ts72xx_map_io,
        .init_irq       = ep93xx_init_irq,
index 1b996b26d2e0d06ee020a2fe2e763874536a9920..5b1a8db779be1dc733a985220ab626460783ff48 100644 (file)
@@ -86,8 +86,6 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(CATS, "Chalice-CATS")
        /* Maintainer: Philip Blundell */
-       .phys_io        = DC21285_ARMCSR_BASE,
-       .io_pg_offst    = ((0xfe000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .soft_reboot    = 1,
        .fixup          = fixup_cats,
index 30040fd588cc01661de7b4c01519c9d330e9f014..2ef69ff44ba8070daafeb9a7d9b9c325d33b72a0 100644 (file)
@@ -15,8 +15,6 @@
 
 MACHINE_START(EBSA285, "EBSA285")
        /* Maintainer: Russell King */
-       .phys_io        = DC21285_ARMCSR_BASE,
-       .io_pg_offst    = ((0xfe000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .video_start    = 0x000a0000,
        .video_end      = 0x000bffff,
index 60dda1318f2285785829c46c399889d5da495c89..3c9e0c40c679196ba02766ad7949ae1d504c1bf7 100644 (file)
 
 #ifndef CONFIG_DEBUG_DC21285_PORT
        /* For NetWinder debugging */
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x7c000000        @ physical
-               movne   \rx, #0xff000000        @ virtual
-               orr     \rx, \rx, #0x000003f8
+               .macro  addruart, rp, rv
+               mov     \rp, #0x000003f8
+               orr     \rv, \rp, #0x7c000000   @ physical
+               orr     \rp, \rp, #0xff000000   @ virtual
                .endm
 
 #define UART_SHIFT     0
                .equ    dc21285_high, ARMCSR_BASE & 0xff000000
                .equ    dc21285_low,  ARMCSR_BASE & 0x00ffffff
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x42000000
-               movne   \rx, #dc21285_high
+               .macro  addruart, rp, rv
                .if     dc21285_low
-               orrne   \rx, \rx, #dc21285_low
+               mov     \rp, #dc21285_low
+               .else
+               mov     \rp, #0
                .endif
+               orr     \rv, \rp, #0x42000000
+               orr     \rp, \rp, #dc21285_high
                .endm
 
                .macro  senduart,rd,rx
index d0958d860a3cb52f16f9464cf625c13498f3ec73..0ffbb7c85e59e738ce5d1966788ae72f52252ffe 100644 (file)
@@ -7,4 +7,4 @@
  */
 
 
-#define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END       0xf0000000
index ac7ffa6fc413e78a93a4e308cf1b137a39adc4fd..06e514f372d0f2a702d79d28963f48e18ac26aa6 100644 (file)
@@ -648,8 +648,6 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
        /* Maintainer: Russell King/Rebel.com */
-       .phys_io        = DC21285_ARMCSR_BASE,
-       .io_pg_offst    = ((0xfe000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .video_start    = 0x000a0000,
        .video_end      = 0x000bffff,
index e2c9f0690b1622b69b5b3e828209ec86160809b6..3285e91ca8c1dcc53b9bff733cb1c181be431e53 100644 (file)
@@ -15,8 +15,6 @@
 
 MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
        /* Maintainer: Jamey Hicks / George France */
-       .phys_io        = DC21285_ARMCSR_BASE,
-       .io_pg_offst    = ((0xfe000000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
index 01f1d6daab448ccad6473d15e5555d20aac26bd2..2ba096de00348e2be706127107eb2b845d2e83a1 100644 (file)
@@ -101,8 +101,6 @@ static void __init ib4220b_init(void)
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-       .phys_io        = 0x7fffc000,
-       .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
index e0de968e32a6e0eb24d98298557a471375b897f4..a9a0d8b0194296ab86072eb150fac5db5782af0e 100644 (file)
@@ -85,8 +85,6 @@ static void __init rut1xx_init(void)
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
-       .phys_io        = 0x7fffc000,
-       .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
index 36538c15b3c4341b04062ffd663cb6240427ac37..8b88d50d4337db51378737a70bfd4bc2959b7b3b 100644 (file)
@@ -133,8 +133,6 @@ static void __init wbd111_init(void)
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
-       .phys_io        = 0x7fffc000,
-       .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
index ece8b4c6511030f125ae67c10ffc35c4875c78a3..1eebcecd1c3312109213aba372cd915a2525961b 100644 (file)
@@ -133,8 +133,6 @@ static void __init wbd222_init(void)
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
-       .phys_io        = 0x7fffc000,
-       .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
index ad477047069ddc9188e33657f3ad0b5338b83e11..f40e006d296e66d884d63525e25d7db45517f41c 100644 (file)
  */
 #include <mach/hardware.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =GEMINI_UART_BASE                  @ physical
-       ldrne   \rx, =IO_ADDRESS(GEMINI_UART_BASE)      @ virtual
+       .macro  addruart, rp, rv
+       ldr     \rp, =GEMINI_UART_BASE                  @ physical
+       ldr     \rv, =IO_ADDRESS(GEMINI_UART_BASE)      @ virtual
        .endm
 
 #define UART_SHIFT     2
index 78be457dc32431cc7e2c1a351a22286eb32d6669..79f0b896e446c6023ce53e2c6df71232c710644b 100644 (file)
@@ -30,8 +30,6 @@
 
 MACHINE_START(H7201, "Hynix GMS30C7201")
        /* Maintainer: Robert Schwebel, Pengutronix */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0001000,
        .map_io         = h720x_map_io,
        .init_irq       = h720x_init_irq,
index 8c0ba99d683fea6747cd9b39cb7ca6f4a68d796a..cc28b1efe0472e23e382a84ee016743f04e10995 100644 (file)
@@ -72,8 +72,6 @@ static void __init init_eval_h7202(void)
 
 MACHINE_START(H7202, "Hynix HMS30C7202")
        /* Maintainer: Robert Schwebel, Pengutronix */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,
        .boot_params    = 0x40000100,
        .map_io         = h720x_map_io,
        .init_irq       = h7202_init_irq,
index 27cafd12f033cbba19bd507e5a90ac198c1db8e1..c2093e835720f55bc137362b3d12f8895f2a83b8 100644 (file)
                .equ    io_virt, IO_VIRT
                .equ    io_phys, IO_PHYS
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                @ MMU enabled?
-               moveq   \rx, #io_phys          @ physical base address
-               movne   \rx, #io_virt          @ virtual address
-               add     \rx, \rx, #0x00020000   @ UART1
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00020000        @ UART1
+               add     \rv, \rp, #io_virt      @ virtual address
+               add     \rp, \rp, #io_phys      @ physical base address
                .endm
 
                .macro  senduart,rd,rx
index ff1460d6841ba9c76f85e54d11d0709c4de801a3..a45915b88756d4e8e786e653bba677c5e36488b0 100644 (file)
@@ -5,6 +5,6 @@
 #ifndef __ARCH_ARM_VMALLOC_H
 #define __ARCH_ARM_VMALLOC_H
 
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
 
 #endif
index c5c0369bb481dff32f4bbb8c214f4859a16787ac..197f9e241cffc36e06543fe1eadc60582955fd1a 100644 (file)
@@ -122,6 +122,7 @@ config MACH_CPUIMX27
        select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_MXC_NAND
+       select MXC_ULPI if USB_ULPI
        help
          Include support for Eukrea CPUIMX27 platform. This includes
          specific configurations for the module and its peripherals.
@@ -146,8 +147,8 @@ choice
        default MACH_EUKREA_MBIMX27_BASEBOARD
 
 config MACH_EUKREA_MBIMX27_BASEBOARD
-       prompt "Eukrea MBIMX27 development board"
-       bool
+       bool "Eukrea MBIMX27 development board"
+       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_SPI_IMX
        help
@@ -163,6 +164,15 @@ config MACH_MX27_3DS
          Include support for MX27PDK platform. This includes specific
          configurations for the board and its peripherals.
 
+config MACH_IMX27_VISSTRIM_M10
+       bool "Vista Silicon i.MX27 Visstrim_m10"
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       help
+         Include support for Visstrim_m10 platform and its different variants.
+         This includes specific configurations for the board and its
+         peripherals.
+
 config MACH_IMX27LITE
        bool "LogicPD MX27 LITEKIT platform"
        select IMX_HAVE_PLATFORM_IMX_UART
@@ -173,6 +183,7 @@ config MACH_IMX27LITE
 config MACH_PCA100
        bool "Phytec phyCARD-s (pca100)"
        select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SPI_IMX
index 46a9fdfbbd157101e22fbd19e1edb6d2c2d893af..5582692bb176958f89c67bd3b70d230b7664b536 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
 obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
 obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
+obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o
 obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
 obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
index c05096c38301038292e9b9f6e0bb10990c31433e..daca30b2d5b1ad5d77c03e8166910a8b7ca5a066 100644 (file)
@@ -592,7 +592,7 @@ static struct clk_lookup lookups[] __initdata = {
        _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
        _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
-       _REGISTER_CLOCK("spi_imx.0", NULL, spi_clk)
+       _REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
        _REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk)
        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
        _REGISTER_CLOCK(NULL, "mshc", mshc_clk)
index bb419ef4d133bb7c12f962bad2c961b337247d4c..cf15ea516a72c4e177d1d4d66374ea0a4ed8676f 100644 (file)
@@ -1172,9 +1172,9 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
        _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
        _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
-       _REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
-       _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
-       _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
+       _REGISTER_CLOCK("imx21-cspi.0", NULL, cspi_clk[0])
+       _REGISTER_CLOCK("imx21-cspi.1", NULL, cspi_clk[1])
+       _REGISTER_CLOCK("imx21-cspi.2", NULL, cspi_clk[2])
        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
        _REGISTER_CLOCK(NULL, "csi", csi_clk[0])
        _REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
index 5a1aa15c8a16140f17e75ea451b5441c9c413d10..98a25bada783fef44c1c5911dcc5cd7ca7ab8c9a 100644 (file)
@@ -594,27 +594,27 @@ DEFINE_CLOCK(uart2_clk1,   0, PCCR1, 30, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(uart1_clk1,   0, PCCR1, 31, NULL, NULL, &ipg_clk);
 
 /* Clocks we cannot directly gate, but drivers need their rates */
-DEFINE_CLOCK(cspi1_clk,    0, 0,      0, NULL, &cspi1_clk1, &per2_clk);
-DEFINE_CLOCK(cspi2_clk,    1, 0,      0, NULL, &cspi2_clk1, &per2_clk);
-DEFINE_CLOCK(cspi3_clk,    2, 0,      0, NULL, &cspi13_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc1_clk,    0, 0,      0, NULL, &sdhc1_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc2_clk,    1, 0,      0, NULL, &sdhc2_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc3_clk,    2, 0,      0, NULL, &sdhc3_clk1, &per2_clk);
-DEFINE_CLOCK(pwm_clk,      0, 0,      0, NULL, &pwm_clk1, &per1_clk);
-DEFINE_CLOCK(gpt1_clk,     0, 0,      0, NULL, &gpt1_clk1, &per1_clk);
-DEFINE_CLOCK(gpt2_clk,     1, 0,      0, NULL, &gpt2_clk1, &per1_clk);
-DEFINE_CLOCK(gpt3_clk,     2, 0,      0, NULL, &gpt3_clk1, &per1_clk);
-DEFINE_CLOCK(gpt4_clk,     3, 0,      0, NULL, &gpt4_clk1, &per1_clk);
-DEFINE_CLOCK(gpt5_clk,     4, 0,      0, NULL, &gpt5_clk1, &per1_clk);
-DEFINE_CLOCK(gpt6_clk,     5, 0,      0, NULL, &gpt6_clk1, &per1_clk);
-DEFINE_CLOCK(uart1_clk,    0, 0,      0, NULL, &uart1_clk1, &per1_clk);
-DEFINE_CLOCK(uart2_clk,    1, 0,      0, NULL, &uart2_clk1, &per1_clk);
-DEFINE_CLOCK(uart3_clk,    2, 0,      0, NULL, &uart3_clk1, &per1_clk);
-DEFINE_CLOCK(uart4_clk,    3, 0,      0, NULL, &uart4_clk1, &per1_clk);
-DEFINE_CLOCK(uart5_clk,    4, 0,      0, NULL, &uart5_clk1, &per1_clk);
-DEFINE_CLOCK(uart6_clk,    5, 0,      0, NULL, &uart6_clk1, &per1_clk);
-DEFINE_CLOCK1(lcdc_clk,    0, 0,      0, parent, &lcdc_clk1, &per3_clk);
-DEFINE_CLOCK1(csi_clk,     0, 0,      0, parent, &csi_clk1, &per4_clk);
+DEFINE_CLOCK(cspi1_clk,    0, NULL,   0, NULL, &cspi1_clk1, &per2_clk);
+DEFINE_CLOCK(cspi2_clk,    1, NULL,   0, NULL, &cspi2_clk1, &per2_clk);
+DEFINE_CLOCK(cspi3_clk,    2, NULL,   0, NULL, &cspi13_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc1_clk,    0, NULL,   0, NULL, &sdhc1_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc2_clk,    1, NULL,   0, NULL, &sdhc2_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc3_clk,    2, NULL,   0, NULL, &sdhc3_clk1, &per2_clk);
+DEFINE_CLOCK(pwm_clk,      0, NULL,   0, NULL, &pwm_clk1, &per1_clk);
+DEFINE_CLOCK(gpt1_clk,     0, NULL,   0, NULL, &gpt1_clk1, &per1_clk);
+DEFINE_CLOCK(gpt2_clk,     1, NULL,   0, NULL, &gpt2_clk1, &per1_clk);
+DEFINE_CLOCK(gpt3_clk,     2, NULL,   0, NULL, &gpt3_clk1, &per1_clk);
+DEFINE_CLOCK(gpt4_clk,     3, NULL,   0, NULL, &gpt4_clk1, &per1_clk);
+DEFINE_CLOCK(gpt5_clk,     4, NULL,   0, NULL, &gpt5_clk1, &per1_clk);
+DEFINE_CLOCK(gpt6_clk,     5, NULL,   0, NULL, &gpt6_clk1, &per1_clk);
+DEFINE_CLOCK(uart1_clk,    0, NULL,   0, NULL, &uart1_clk1, &per1_clk);
+DEFINE_CLOCK(uart2_clk,    1, NULL,   0, NULL, &uart2_clk1, &per1_clk);
+DEFINE_CLOCK(uart3_clk,    2, NULL,   0, NULL, &uart3_clk1, &per1_clk);
+DEFINE_CLOCK(uart4_clk,    3, NULL,   0, NULL, &uart4_clk1, &per1_clk);
+DEFINE_CLOCK(uart5_clk,    4, NULL,   0, NULL, &uart5_clk1, &per1_clk);
+DEFINE_CLOCK(uart6_clk,    5, NULL,   0, NULL, &uart6_clk1, &per1_clk);
+DEFINE_CLOCK1(lcdc_clk,    0, NULL,   0, parent, &lcdc_clk1, &per3_clk);
+DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 
 #define _REGISTER_CLOCK(d, n, c) \
        { \
@@ -640,9 +640,9 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
        _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
        _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
-       _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-       _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-       _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+       _REGISTER_CLOCK("imx27-cspi.0", NULL, cspi1_clk)
+       _REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk)
+       _REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk)
        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
        _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
index a8d94f078196cb2b14b74cb12170abc3546acb6b..81979486218ed0eb96f09a12ba078404f28ab595 100644 (file)
@@ -9,10 +9,12 @@
 #include <mach/mx1.h>
 #include <mach/devices-common.h>
 
-#define imx1_add_i2c_imx(pdata)                \
-       imx_add_imx_i2c(0, MX1_I2C_BASE_ADDR, SZ_4K, MX1_INT_I2C, pdata)
+extern const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst;
+#define imx1_add_imx_i2c(pdata)                \
+       imx_add_imx_i2c(&imx1_imx_i2c_data, pdata)
 
-#define imx1_add_imx_uart0(pdata)      \
-       imx_add_imx_uart_3irq(0, MX1_UART1_BASE_ADDR, 0xd0, MX1_INT_UART1RX, MX1_INT_UART1TX, MX1_INT_UART1RTS, pdata)
-#define imx1_add_imx_uart1(pdata)      \
-       imx_add_imx_uart_3irq(0, MX1_UART2_BASE_ADDR, 0xd0, MX1_INT_UART2RX, MX1_INT_UART2TX, MX1_INT_UART2RTS, pdata)
+extern const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst;
+#define imx1_add_imx_uart(id, pdata)   \
+       imx_add_imx_uart_3irq(&imx1_imx_uart_data[id], pdata)
+#define imx1_add_imx_uart0(pdata)      imx1_add_imx_uart(0, pdata)
+#define imx1_add_imx_uart1(pdata)      imx1_add_imx_uart(1, pdata)
index 42788e99d127290714f89af20d75859060f0bcd4..d189039749b0902a7d081a644b6e8d2e97a82a21 100644 (file)
@@ -9,22 +9,28 @@
 #include <mach/mx21.h>
 #include <mach/devices-common.h>
 
-#define imx21_add_i2c_imx(pdata)       \
-       imx_add_imx_i2c(0, MX2x_I2C_BASE_ADDR, SZ_4K, MX2x_INT_I2C, pdata)
+extern const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst;
+#define imx21_add_imx_i2c(pdata)       \
+       imx_add_imx_i2c(&imx21_imx_i2c_data, pdata)
 
-#define imx21_add_imx_uart0(pdata)     \
-       imx_add_imx_uart_1irq(0, MX21_UART1_BASE_ADDR, SZ_4K, MX21_INT_UART1, pdata)
-#define imx21_add_imx_uart1(pdata)     \
-       imx_add_imx_uart_1irq(1, MX21_UART2_BASE_ADDR, SZ_4K, MX21_INT_UART2, pdata)
-#define imx21_add_imx_uart2(pdata)     \
-       imx_add_imx_uart_1irq(2, MX21_UART3_BASE_ADDR, SZ_4K, MX21_INT_UART3, pdata)
-#define imx21_add_imx_uart3(pdata)     \
-       imx_add_imx_uart_1irq(3, MX21_UART4_BASE_ADDR, SZ_4K, MX21_INT_UART4, pdata)
+extern const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst;
+#define imx21_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx21_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst;
+#define imx21_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx21_imx_uart_data[id], pdata)
+#define imx21_add_imx_uart0(pdata)     imx21_add_imx_uart(0, pdata)
+#define imx21_add_imx_uart1(pdata)     imx21_add_imx_uart(1, pdata)
+#define imx21_add_imx_uart2(pdata)     imx21_add_imx_uart(2, pdata)
+#define imx21_add_imx_uart3(pdata)     imx21_add_imx_uart(3, pdata)
+
+extern const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst;
 #define imx21_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand_v1(MX21_NFC_BASE_ADDR, MX21_INT_NANDFC, pdata)
+       imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
 
-#define imx21_add_spi_imx0(pdata)      \
-       imx_add_spi_imx(0, MX21_CSPI1_BASE_ADDR, SZ_4K, MX21_INT_CSPI1, pdata)
-#define imx21_add_spi_imx1(pdata)      \
-       imx_add_spi_imx(1, MX21_CSPI2_BASE_ADDR, SZ_4K, MX21_INT_CSPI2, pdata)
+extern const struct imx_spi_imx_data imx21_cspi_data[] __initconst;
+#define imx21_add_cspi(id, pdata)      \
+       imx_add_spi_imx(&imx21_cspi_data[id], pdata)
+#define imx21_add_spi_imx0(pdata)      imx21_add_cspi(0, pdata)
+#define imx21_add_spi_imx1(pdata)      imx21_add_cspi(1, pdata)
index 65e7bb7ec2e8864400445bb4dc1cc953503e1312..7011690364f270286b8e4bc06d3c58edc868c434 100644 (file)
@@ -9,30 +9,35 @@
 #include <mach/mx27.h>
 #include <mach/devices-common.h>
 
-#define imx27_add_i2c_imx0(pdata)      \
-       imx_add_imx_i2c(0, MX27_I2C1_BASE_ADDR, SZ_4K, MX27_INT_I2C1, pdata)
-#define imx27_add_i2c_imx1(pdata)      \
-       imx_add_imx_i2c(1, MX27_I2C2_BASE_ADDR, SZ_4K, MX27_INT_I2C2, pdata)
+extern const struct imx_fec_data imx27_fec_data __initconst;
+#define imx27_add_fec(pdata)   \
+       imx_add_fec(&imx27_fec_data, pdata)
 
-#define imx27_add_imx_uart0(pdata)     \
-       imx_add_imx_uart_1irq(0, MX27_UART1_BASE_ADDR, SZ_4K, MX27_INT_UART1, pdata)
-#define imx27_add_imx_uart1(pdata)     \
-       imx_add_imx_uart_1irq(1, MX27_UART2_BASE_ADDR, SZ_4K, MX27_INT_UART2, pdata)
-#define imx27_add_imx_uart2(pdata)     \
-       imx_add_imx_uart_1irq(2, MX27_UART3_BASE_ADDR, SZ_4K, MX27_INT_UART3, pdata)
-#define imx27_add_imx_uart3(pdata)     \
-       imx_add_imx_uart_1irq(3, MX27_UART4_BASE_ADDR, SZ_4K, MX27_INT_UART4, pdata)
-#define imx27_add_imx_uart4(pdata)     \
-       imx_add_imx_uart_1irq(4, MX27_UART5_BASE_ADDR, SZ_4K, MX27_INT_UART5, pdata)
-#define imx27_add_imx_uart5(pdata)     \
-       imx_add_imx_uart_1irq(5, MX27_UART6_BASE_ADDR, SZ_4K, MX27_INT_UART6, pdata)
+extern const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst;
+#define imx27_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx27_imx_i2c_data[id], pdata)
 
+extern const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst;
+#define imx27_add_imx_ssi(id, pdata)    \
+       imx_add_imx_ssi(&imx27_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst;
+#define imx27_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx27_imx_uart_data[id], pdata)
+#define imx27_add_imx_uart0(pdata)     imx27_add_imx_uart(0, pdata)
+#define imx27_add_imx_uart1(pdata)     imx27_add_imx_uart(1, pdata)
+#define imx27_add_imx_uart2(pdata)     imx27_add_imx_uart(2, pdata)
+#define imx27_add_imx_uart3(pdata)     imx27_add_imx_uart(3, pdata)
+#define imx27_add_imx_uart4(pdata)     imx27_add_imx_uart(4, pdata)
+#define imx27_add_imx_uart5(pdata)     imx27_add_imx_uart(5, pdata)
+
+extern const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst;
 #define imx27_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand_v1(MX27_NFC_BASE_ADDR, MX27_INT_NANDFC, pdata)
+       imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
 
-#define imx27_add_spi_imx0(pdata)      \
-       imx_add_spi_imx(0, MX27_CSPI1_BASE_ADDR, SZ_4K, MX27_INT_CSPI1, pdata)
-#define imx27_add_spi_imx1(pdata)      \
-       imx_add_spi_imx(1, MX27_CSPI2_BASE_ADDR, SZ_4K, MX27_INT_CSPI2, pdata)
-#define imx27_add_spi_imx2(pdata)      \
-       imx_add_spi_imx(2, MX27_CSPI3_BASE_ADDR, SZ_4K, MX27_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx27_cspi_data[] __initconst;
+#define imx27_add_cspi(id, pdata)      \
+       imx_add_spi_imx(&imx27_cspi_data[id], pdata)
+#define imx27_add_spi_imx0(pdata)      imx27_add_cspi(0, pdata)
+#define imx27_add_spi_imx1(pdata)      imx27_add_cspi(1, pdata)
+#define imx27_add_spi_imx2(pdata)      imx27_add_cspi(2, pdata)
index 9c271a752b84da4e0380bf9fed2c86a5658a9640..fba5047de8b1fde5ee532f6291bcfee700257a66 100644 (file)
@@ -314,27 +314,6 @@ struct platform_device mxc_fb_device = {
        },
 };
 
-#ifdef CONFIG_MACH_MX27
-static struct resource mxc_fec_resources[] = {
-       {
-               .start = MX27_FEC_BASE_ADDR,
-               .end = MX27_FEC_BASE_ADDR + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX27_INT_FEC,
-               .end = MX27_INT_FEC,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_fec_device = {
-       .name = "fec",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(mxc_fec_resources),
-       .resource = mxc_fec_resources,
-};
-#endif
-
 static struct resource mxc_pwm_resources[] = {
        {
                .start = MX2x_PWM_BASE_ADDR,
@@ -480,41 +459,6 @@ struct platform_device mxc_usbh2 = {
 };
 #endif
 
-#define DEFINE_IMX_SSI_DMARES(_name, ssin, suffix)                     \
-       {                                                               \
-               .name = _name,                                          \
-               .start = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,       \
-               .end = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,         \
-               .flags = IORESOURCE_DMA,                                \
-       }
-
-#define DEFINE_IMX_SSI_DEVICE(n, ssin, baseaddr, irq)                  \
-       static struct resource imx_ssi_resources ## n[] = {             \
-               {                                                       \
-                       .start = MX2x_SSI ## ssin ## _BASE_ADDR,        \
-                       .end = MX2x_SSI ## ssin ## _BASE_ADDR + 0x6f,   \
-                       .flags = IORESOURCE_MEM,                        \
-               }, {                                                    \
-                       .start = MX2x_INT_SSI1,                         \
-                       .end = MX2x_INT_SSI1,                           \
-                       .flags = IORESOURCE_IRQ,                        \
-               },                                                      \
-               DEFINE_IMX_SSI_DMARES("tx0", ssin, TX0),                \
-               DEFINE_IMX_SSI_DMARES("rx0", ssin, RX0),                \
-               DEFINE_IMX_SSI_DMARES("tx1", ssin, TX1),                \
-               DEFINE_IMX_SSI_DMARES("rx1", ssin, RX1),                \
-       };                                                              \
-                                                                       \
-       struct platform_device imx_ssi_device ## n = {                  \
-               .name = "imx-ssi",                                      \
-               .id = n,                                                \
-               .num_resources = ARRAY_SIZE(imx_ssi_resources ## n),    \
-               .resource = imx_ssi_resources ## n,                     \
-       }
-
-DEFINE_IMX_SSI_DEVICE(0, 1, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-DEFINE_IMX_SSI_DEVICE(1, 2, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-
 /* GPIO port description */
 #define DEFINE_MXC_GPIO_PORT_IRQ(SOC, n, _irq)                         \
        {                                                               \
index efd4527506a5e661da74c95e9d756c0674ca3d33..807f02a031c9454ce3534e26f508cd34fdc2b36e 100644 (file)
@@ -16,7 +16,6 @@ extern struct platform_device mxc_gpt5;
 extern struct platform_device mxc_wdt;
 extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mxc_fb_device;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxc_pwm_device;
 extern struct platform_device mxc_sdhc_device0;
 extern struct platform_device mxc_sdhc_device1;
@@ -26,7 +25,5 @@ extern struct platform_device mxc_otg_host;
 extern struct platform_device mxc_usbh1;
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mx21_usbhc_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device imx_kpp_device;
 #endif
index 4edc5f43920109011d6e8f8fd64234e3fe3cb992..026263c665cae060cfca17ca86ad2fb36c8c2cad 100644 (file)
 #include <mach/hardware.h>
 #include <mach/mmc.h>
 #include <mach/spi.h>
-#include <mach/ssi.h>
 #include <mach/audmux.h>
 
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int eukrea_mbimx27_pins[] = {
+static const int eukrea_mbimx27_pins[] __initconst = {
        /* UART2 */
        PE3_PF_UART2_CTS,
        PE4_PF_UART2_RTS,
@@ -311,7 +310,8 @@ static struct imxmmc_platform_data sdhc_pdata = {
        .dat3_card_detect = 1,
 };
 
-struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata __initconst = {
        .flags = IMX_SSI_DMA | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -357,7 +357,7 @@ void __init eukrea_mbimx27_baseboard_init(void)
        i2c_register_board_info(0, eukrea_mbimx27_i2c_devices,
                                ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
 
-       mxc_register_device(&imx_ssi_device0, &eukrea_mbimx27_ssi_pdata);
+       imx27_add_imx_ssi(0, &eukrea_mbimx27_ssi_pdata);
 
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) \
        || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
index 575ff1ae85a738f84cf48720d19e850b96caa0e5..745ee60fb068fee9dca479142b0c283bf14659a6 100644 (file)
@@ -46,7 +46,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int eukrea_cpuimx27_pins[] = {
+static const int eukrea_cpuimx27_pins[] __initconst = {
        /* UART1 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -157,7 +157,6 @@ cpuimx27_nand_board_info __initconst = {
 
 static struct platform_device *platform_devices[] __initdata = {
        &eukrea_cpuimx27_nor_mtd_device,
-       &mxc_fec_device,
        &mxc_wdt,
        &mxc_w1_master_device,
 };
@@ -259,8 +258,9 @@ static void __init eukrea_cpuimx27_init(void)
        i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices,
                                ARRAY_SIZE(eukrea_cpuimx27_i2c_devices));
 
-       imx27_add_i2c_imx1(&cpuimx27_i2c1_data);
+       imx27_add_imx_i2c(0, &cpuimx27_i2c1_data);
 
+       imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
@@ -279,13 +279,13 @@ static void __init eukrea_cpuimx27_init(void)
 #if defined(CONFIG_USB_ULPI)
        if (otg_mode_host) {
                otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+                               ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
                mxc_register_device(&mxc_otg_host, &otg_pdata);
        }
 
        usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+                               ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
        mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
@@ -307,8 +307,6 @@ static struct sys_timer eukrea_cpuimx27_timer = {
 };
 
 MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
new file mode 100644 (file)
index 0000000..59716fa
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * mach-imx27_visstrim_m10.c
+ *
+ * Copyright 2010  Javier Martin <javier.martin@vista-silicon.com>
+ *
+ * Based on mach-pcm038.c, mach-pca100.c, mach-mx27ads.c and others.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mmc.h>
+#include <mach/iomux.h>
+#include <mach/mxc_ehci.h>
+
+#include "devices-imx27.h"
+#include "devices.h"
+
+#define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
+#define SDHC1_IRQ IRQ_GPIOB(25)
+
+static const int visstrim_m10_pins[] __initconst = {
+       /* UART1 (console) */
+       PE12_PF_UART1_TXD,
+       PE13_PF_UART1_RXD,
+       PE14_PF_UART1_CTS,
+       PE15_PF_UART1_RTS,
+       /* FEC */
+       PD0_AIN_FEC_TXD0,
+       PD1_AIN_FEC_TXD1,
+       PD2_AIN_FEC_TXD2,
+       PD3_AIN_FEC_TXD3,
+       PD4_AOUT_FEC_RX_ER,
+       PD5_AOUT_FEC_RXD1,
+       PD6_AOUT_FEC_RXD2,
+       PD7_AOUT_FEC_RXD3,
+       PD8_AF_FEC_MDIO,
+       PD9_AIN_FEC_MDC,
+       PD10_AOUT_FEC_CRS,
+       PD11_AOUT_FEC_TX_CLK,
+       PD12_AOUT_FEC_RXD0,
+       PD13_AOUT_FEC_RX_DV,
+       PD14_AOUT_FEC_RX_CLK,
+       PD15_AOUT_FEC_COL,
+       PD16_AIN_FEC_TX_ER,
+       PF23_AIN_FEC_TX_EN,
+       /* SDHC1 */
+       PE18_PF_SD1_D0,
+       PE19_PF_SD1_D1,
+       PE20_PF_SD1_D2,
+       PE21_PF_SD1_D3,
+       PE22_PF_SD1_CMD,
+       PE23_PF_SD1_CLK,
+       /* Both I2Cs */
+       PD17_PF_I2C_DATA,
+       PD18_PF_I2C_CLK,
+       PC5_PF_I2C2_SDA,
+       PC6_PF_I2C2_SCL,
+       /* USB OTG */
+       OTG_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
+       PC9_PF_USBOTG_DATA0,
+       PC11_PF_USBOTG_DATA1,
+       PC10_PF_USBOTG_DATA2,
+       PC13_PF_USBOTG_DATA3,
+       PC12_PF_USBOTG_DATA4,
+       PC7_PF_USBOTG_DATA5,
+       PC8_PF_USBOTG_DATA6,
+       PE25_PF_USBOTG_DATA7,
+       PE24_PF_USBOTG_CLK,
+       PE2_PF_USBOTG_DIR,
+       PE0_PF_USBOTG_NXT,
+       PE1_PF_USBOTG_STP,
+       PB23_PF_USB_PWR,
+       PB24_PF_USB_OC,
+};
+
+/* GPIOs used as events for applications */
+static struct gpio_keys_button visstrim_gpio_keys[] = {
+       {
+               .type   = EV_KEY,
+               .code   = KEY_RESTART,
+               .gpio   = (GPIO_PORTC + 15),
+               .desc   = "Default config",
+               .active_low = 0,
+               .wakeup = 1,
+       },
+       {
+               .type   = EV_KEY,
+               .code   = KEY_RECORD,
+               .gpio   = (GPIO_PORTF + 14),
+               .desc   = "Record",
+               .active_low = 0,
+               .wakeup = 1,
+       },
+       {
+               .type   = EV_KEY,
+               .code   = KEY_STOP,
+               .gpio   = (GPIO_PORTF + 13),
+               .desc   = "Stop",
+               .active_low = 0,
+               .wakeup = 1,
+       }
+};
+
+static struct gpio_keys_platform_data visstrim_gpio_keys_platform_data = {
+       .buttons        = visstrim_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(visstrim_gpio_keys),
+};
+
+static struct platform_device visstrim_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &visstrim_gpio_keys_platform_data,
+       },
+};
+
+/* Visstrim_SM10 has a microSD slot connected to sdhc1 */
+static int visstrim_m10_sdhc1_init(struct device *dev,
+               irq_handler_t detect_irq, void *data)
+{
+       int ret;
+
+       ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING,
+                               "mmc-detect", data);
+       return ret;
+}
+
+static void visstrim_m10_sdhc1_exit(struct device *dev, void *data)
+{
+       free_irq(SDHC1_IRQ, data);
+}
+
+static struct imxmmc_platform_data visstrim_m10_sdhc_pdata = {
+       .init = visstrim_m10_sdhc1_init,
+       .exit = visstrim_m10_sdhc1_exit,
+};
+
+/* Visstrim_SM10 NOR flash */
+static struct physmap_flash_data visstrim_m10_flash_data = {
+       .width = 2,
+};
+
+static struct resource visstrim_m10_flash_resource = {
+       .start = 0xc0000000,
+       .end = 0xc0000000 + SZ_64M - 1,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device visstrim_m10_nor_mtd_device = {
+       .name = "physmap-flash",
+       .id = 0,
+       .dev = {
+               .platform_data = &visstrim_m10_flash_data,
+       },
+       .num_resources = 1,
+       .resource = &visstrim_m10_flash_resource,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+       &visstrim_gpio_keys_device,
+       &visstrim_m10_nor_mtd_device,
+};
+
+/* Visstrim_M10 uses UART0 as console */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* I2C */
+static const struct imxi2c_platform_data visstrim_m10_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static struct pca953x_platform_data visstrim_m10_pca9555_pdata = {
+       .gpio_base = 240, /* After MX27 internal GPIOs */
+       .invert = 0,
+};
+
+static struct i2c_board_info visstrim_m10_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("pca9555", 0x20),
+               .platform_data = &visstrim_m10_pca9555_pdata,
+       },
+};
+
+/* USB OTG */
+static int otg_phy_init(struct platform_device *pdev)
+{
+       gpio_set_value(OTG_PHY_CS_GPIO, 0);
+       return 0;
+}
+
+static struct mxc_usbh_platform_data visstrim_m10_usbotg_pdata = {
+       .init = otg_phy_init,
+       .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+       .flags  = MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static void __init visstrim_m10_board_init(void)
+{
+       int ret;
+
+       ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
+                       ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
+       if (ret)
+               pr_err("Failed to setup pins (%d)\n", ret);
+
+       imx27_add_imx_uart0(&uart_pdata);
+
+       i2c_register_board_info(0, visstrim_m10_i2c_devices,
+                               ARRAY_SIZE(visstrim_m10_i2c_devices));
+       imx27_add_imx_i2c(0, &visstrim_m10_i2c_data);
+       imx27_add_imx_i2c(1, &visstrim_m10_i2c_data);
+       mxc_register_device(&mxc_sdhc_device0, &visstrim_m10_sdhc_pdata);
+       mxc_register_device(&mxc_otg_host, &visstrim_m10_usbotg_pdata);
+       imx27_add_fec(NULL);
+       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init visstrim_m10_timer_init(void)
+{
+       mx27_clocks_init((unsigned long)25000000);
+}
+
+static struct sys_timer visstrim_m10_timer = {
+       .init   = visstrim_m10_timer_init,
+};
+
+MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
+       .boot_params    = MX27_PHYS_OFFSET + 0x100,
+       .map_io         = mx27_map_io,
+       .init_irq       = mx27_init_irq,
+       .init_machine   = visstrim_m10_board_init,
+       .timer          = &visstrim_m10_timer,
+MACHINE_END
index 22a2b5d912136590addc1fcd05f32d905b1af8d0..bbdbc75127d3fd6a09d03bcfad7562eb31808640 100644 (file)
@@ -27,7 +27,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mx27lite_pins[] = {
+static const int mx27lite_pins[] __initconst = {
        /* UART1 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -58,16 +58,12 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-       &mxc_fec_device,
-};
-
 static void __init mx27lite_init(void)
 {
        mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
                "imx27lite");
        imx27_add_imx_uart0(&uart_pdata);
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+       imx27_add_fec(NULL);
 }
 
 static void __init mx27lite_timer_init(void)
@@ -80,8 +76,6 @@ static struct sys_timer mx27lite_timer = {
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
index 77a760cfadc0260dba05324318e00e3d5605defd..6187ce9ba7d54157d0455cd304cc2ec1be650f77 100644 (file)
@@ -32,7 +32,7 @@
 #include "devices-imx1.h"
 #include "devices.h"
 
-static int mx1ads_pins[] = {
+static const int mx1ads_pins[] __initconst = {
        /* UART1 */
        PC9_PF_UART1_CTS,
        PC10_PF_UART1_RTS,
@@ -131,7 +131,7 @@ static void __init mx1ads_init(void)
        i2c_register_board_info(0, mx1ads_i2c_devices,
                                ARRAY_SIZE(mx1ads_i2c_devices));
 
-       imx1_add_i2c_imx(&mx1ads_i2c_data);
+       imx1_add_imx_i2c(&mx1ads_i2c_data);
 }
 
 static void __init mx1ads_timer_init(void)
@@ -145,8 +145,6 @@ struct sys_timer mx1ads_timer = {
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
        /* Maintainer: Sascha Hauer, Pengutronix */
-       .phys_io        = MX1_IO_BASE_ADDR,
-       .io_pg_offst    = (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX1_PHYS_OFFSET + 0x100,
        .map_io         = mx1_map_io,
        .init_irq       = mx1_init_irq,
@@ -155,8 +153,6 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS")
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-       .phys_io        = MX1_IO_BASE_ADDR,
-       .io_pg_offst    = (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX1_PHYS_OFFSET + 0x100,
        .map_io         = mx1_map_io,
        .init_irq       = mx1_init_irq,
index 96d7f8189f3253a0feb79d0278c51abbc3e4e5bf..e1282e9f50ffe38f5861c48209a92b241686d324 100644 (file)
@@ -67,7 +67,7 @@
 #define MX21ADS_IO_LED4_ON      0x4000
 #define MX21ADS_IO_LED3_ON      0x8000
 
-static unsigned int mx21ads_pins[] = {
+static const int mx21ads_pins[] __initconst = {
 
        /* CS8900A */
        (GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
@@ -314,8 +314,6 @@ static struct sys_timer mx21ads_timer = {
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX21_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX21_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX21_PHYS_OFFSET + 0x100,
        .map_io         = mx21ads_map_io,
        .init_irq       = mx21_init_irq,
index e66ffaa1c26c26dbd4ba2b7d7b75c2455b06f5a1..b8bbd31aa850c4332a602d92a79e0d8749afe4fb 100644 (file)
@@ -33,7 +33,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mx27pdk_pins[] = {
+static const int mx27pdk_pins[] __initconst = {
        /* UART1 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -64,10 +64,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-       &mxc_fec_device,
-};
-
 /*
  * Matrix keyboard
  */
@@ -94,7 +90,7 @@ static void __init mx27pdk_init(void)
        mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
                "mx27pdk");
        imx27_add_imx_uart0(&uart_pdata);
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+       imx27_add_fec(NULL);
        mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data);
 }
 
@@ -109,8 +105,6 @@ static struct sys_timer mx27pdk_timer = {
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
index 9c77da98a10eec59060e016088a63516a343aff2..a1e4bc573afc20081720fcb21cbd604e14ce5ff0 100644 (file)
@@ -66,7 +66,7 @@
 /* to determine the correct external crystal reference */
 #define CKIH_27MHZ_BIT_SET      (1 << 3)
 
-static unsigned int mx27ads_pins[] = {
+static const int mx27ads_pins[] __initconst = {
        /* UART0 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -284,7 +284,6 @@ static struct imxmmc_platform_data sdhc2_pdata = {
 
 static struct platform_device *platform_devices[] __initdata = {
        &mx27ads_nor_mtd_device,
-       &mxc_fec_device,
        &mxc_w1_master_device,
 };
 
@@ -308,11 +307,12 @@ static void __init mx27ads_board_init(void)
        /* only the i2c master 1 is used on this CPU card */
        i2c_register_board_info(1, mx27ads_i2c_devices,
                                ARRAY_SIZE(mx27ads_i2c_devices));
-       imx27_add_i2c_imx1(&mx27ads_i2c1_data);
+       imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
        mxc_register_device(&mxc_fb_device, &mx27ads_fb_data);
        mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
        mxc_register_device(&mxc_sdhc_device1, &sdhc2_pdata);
 
+       imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
 
@@ -347,8 +347,6 @@ static void __init mx27ads_map_io(void)
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27ads_map_io,
        .init_irq       = mx27_init_irq,
index a3a1e452d4c5a15bef12ced37d70d275fabd2fad..38d3a4ae17c765f2a4779e67f2ac9967cd130f12 100644 (file)
@@ -37,7 +37,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mxt_td60_pins[] __initdata = {
+static const int mxt_td60_pins[] __initconst = {
        /* UART0 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -231,10 +231,6 @@ static struct imxmmc_platform_data sdhc1_pdata = {
        .exit = mxt_td60_sdhc1_exit,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-       &mxc_fec_device,
-};
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
@@ -255,12 +251,11 @@ static void __init mxt_td60_board_init(void)
        i2c_register_board_info(1, mxt_td60_i2c2_devices,
                                ARRAY_SIZE(mxt_td60_i2c2_devices));
 
-       imx27_add_i2c_imx0(&mxt_td60_i2c0_data);
-       imx27_add_i2c_imx1(&mxt_td60_i2c1_data);
+       imx27_add_imx_i2c(0, &mxt_td60_i2c0_data);
+       imx27_add_imx_i2c(1, &mxt_td60_i2c1_data);
        mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
        mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
-
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+       imx27_add_fec(NULL);
 }
 
 static void __init mxt_td60_timer_init(void)
@@ -274,8 +269,6 @@ static struct sys_timer mxt_td60_timer = {
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
        /* maintainer: Maxtrack Industrial */
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
index a389d1148f18c641cd1c997f4798b6641e084bdc..8c720d44602ab1af61cd18b36316ec44e3613dcc 100644 (file)
@@ -38,7 +38,6 @@
 #include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 #include <mach/mxc_nand.h>
 #include <mach/irqs.h>
 #include <mach/mmc.h>
@@ -55,7 +54,7 @@
 #define SPI1_SS1 (GPIO_PORTD + 27)
 #define SD2_CD (GPIO_PORTC + 29)
 
-static int pca100_pins[] = {
+static const int pca100_pins[] __initconst = {
        /* UART1 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -174,7 +173,6 @@ pca100_nand_board_info __initconst = {
 
 static struct platform_device *platform_devices[] __initdata = {
        &mxc_w1_master_device,
-       &mxc_fec_device,
        &mxc_wdt,
 };
 
@@ -193,11 +191,9 @@ static struct i2c_board_info pca100_i2c_devices[] = {
                I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
                .platform_data = &board_eeprom,
        }, {
-               I2C_BOARD_INFO("rtc-pcf8563", 0x51),
-               .type = "pcf8563"
+               I2C_BOARD_INFO("pcf8563", 0x51),
        }, {
                I2C_BOARD_INFO("lm75", 0x4a),
-               .type = "lm75"
        }
 };
 
@@ -252,7 +248,7 @@ static void pca100_ac97_cold_reset(struct snd_ac97 *ac97)
        msleep(2);
 }
 
-static struct imx_ssi_platform_data pca100_ssi_pdata = {
+static const struct imx_ssi_platform_data pca100_ssi_pdata __initconst = {
        .ac97_reset             = pca100_ac97_cold_reset,
        .ac97_warm_reset        = pca100_ac97_warm_reset,
        .flags                  = IMX_SSI_USE_AC97,
@@ -389,7 +385,7 @@ static void __init pca100_init(void)
        if (ret)
                printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
 
-       mxc_register_device(&imx_ssi_device0, &pca100_ssi_pdata);
+       imx27_add_imx_ssi(0, &pca100_ssi_pdata);
 
        imx27_add_imx_uart0(&uart_pdata);
 
@@ -401,7 +397,7 @@ static void __init pca100_init(void)
        i2c_register_board_info(1, pca100_i2c_devices,
                                ARRAY_SIZE(pca100_i2c_devices));
 
-       imx27_add_i2c_imx1(&pca100_i2c1_data);
+       imx27_add_imx_i2c(1, &pca100_i2c1_data);
 
 #if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
        mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
@@ -419,13 +415,13 @@ static void __init pca100_init(void)
 #if defined(CONFIG_USB_ULPI)
        if (otg_mode_host) {
                otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+                               ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
                mxc_register_device(&mxc_otg_host, &otg_pdata);
        }
 
        usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+                               ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
        mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
@@ -436,6 +432,7 @@ static void __init pca100_init(void)
 
        mxc_register_device(&mxc_fb_device, &pca100_fb_data);
 
+       imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
 
@@ -449,8 +446,6 @@ static struct sys_timer pca100_timer = {
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
index 9212e8f37001d050418b505bdb7c8874b94cd9f0..49a97ce0742665b9e82b5a12224a06b6c80307da 100644 (file)
@@ -43,7 +43,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int pcm038_pins[] = {
+static const int pcm038_pins[] __initconst = {
        /* UART1 */
        PE12_PF_UART1_TXD,
        PE13_PF_UART1_RXD,
@@ -173,7 +173,6 @@ pcm038_nand_board_info __initconst = {
 static struct platform_device *platform_devices[] __initdata = {
        &pcm038_nor_mtd_device,
        &mxc_w1_master_device,
-       &mxc_fec_device,
        &pcm038_sram_mtd_device,
        &mxc_wdt,
 };
@@ -257,7 +256,7 @@ static struct regulator_init_data cam_data = {
        .consumer_supplies = cam_consumers,
 };
 
-struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13783_regulator_init_data pcm038_regulators[] = {
        {
                .id = MC13783_REGU_VCAM,
                .init_data = &cam_data,
@@ -309,7 +308,7 @@ static void __init pcm038_init(void)
        i2c_register_board_info(1, pcm038_i2c_devices,
                                ARRAY_SIZE(pcm038_i2c_devices));
 
-       imx27_add_i2c_imx1(&pcm038_i2c1_data);
+       imx27_add_imx_i2c(1, &pcm038_i2c1_data);
 
        /* PE18 for user-LED D40 */
        mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
@@ -325,6 +324,7 @@ static void __init pcm038_init(void)
 
        mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 
+       imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
@@ -342,8 +342,6 @@ static struct sys_timer pcm038_timer = {
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-       .phys_io        = MX27_AIPI_BASE_ADDR,
-       .io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX27_PHYS_OFFSET + 0x100,
        .map_io         = mx27_map_io,
        .init_irq       = mx27_init_irq,
index 88bf0d1e26e6ebb3400e07db4f545e3f86c97b9b..1fbdd3faa7abf5a8d68e7981e46791a7acac7369 100644 (file)
@@ -95,7 +95,7 @@ static struct platform_device dm9000x_device = {
        }
 };
 
-static int mxc_uart1_pins[] = {
+static const int mxc_uart1_pins[] = {
        PC9_PF_UART1_CTS,
        PC10_PF_UART1_RTS,
        PC11_PF_UART1_TXD,
@@ -147,8 +147,6 @@ static struct sys_timer scb9328_timer = {
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
     /* Sascha Hauer */
-       .phys_io        = 0x00200000,
-       .io_pg_offst    = ((0xe0200000) >> 18) & 0xfffc,
        .boot_params    = 0x08000100,
        .map_io         = mx1_map_io,
        .init_irq       = mx1_init_irq,
index f490a406d57e737b46a343cb0c780e83f72cb056..9110d9cca7a2dc4b66adc85950541b5a9a7bc81b 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "devices.h"
 
-static int pcm970_pins[] = {
+static const int pcm970_pins[] __initconst = {
        /* SDHC */
        PB4_PF_SD2_D0,
        PB5_PF_SD2_D1,
@@ -200,7 +200,7 @@ static struct resource pcm970_sja1000_resources[] = {
        },
 };
 
-struct sja1000_platform_data pcm970_sja1000_platform_data = {
+static struct sja1000_platform_data pcm970_sja1000_platform_data = {
        .osc_freq       = 16000000,
        .ocr            = OCR_TX1_PULLDOWN | OCR_TX0_PUSHPULL,
        .cdr            = CDR_CBP,
index 87a6888ae011ba71e3764f02ab97a1b74260e839..a1f598fd3a567292a6abf0f9857a5f455ed9c614 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x16000000        @ physical base address
-               movne   \rx, #0xf0000000        @ virtual base
-               addne   \rx, \rx, #0x16000000 >> 4
+               .macro  addruart, rp, rv
+               mov     \rp, #0x16000000        @ physical base address
+               mov     \rv, #0xf0000000        @ virtual base
+               add     \rv, \rv, #0x16000000 >> 4
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index e87ab0b37bddb353810f97bd25461a536cf167c1..e056e7cf5645f8c936f4144f8d584f2772ae9bf2 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
index 6ab5a03ab9d8b0a7f45311595b0ee1fa16474ef3..548208f11179c0aafbed4b3d23b5fc998196f1d3 100644 (file)
@@ -500,8 +500,6 @@ static struct sys_timer ap_timer = {
 
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = 0x16000000,
-       .io_pg_offst    = ((0xf1600000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ap_map_io,
        .reserve        = integrator_reserve,
index 05db40e3c4f75a7fcf661718269cdcf330d7f9cc..6258c90d020c30edf75faa7f06976d6cedef2e7e 100644 (file)
@@ -599,8 +599,6 @@ static struct sys_timer cp_timer = {
 
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = 0x16000000,
-       .io_pg_offst    = ((0xf1600000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = intcp_map_io,
        .reserve        = integrator_reserve,
index c9d6ba46963da99c4f5c8ede984a27f470238024..e664466d51bf47a410235c19a1e60a9170e0a0bc 100644 (file)
  * published by the Free Software Foundation.
  */
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                 @ mmu enabled?
-       moveq   \rx, #0xff000000        @ physical
-       orreq   \rx, \rx, #0x00d80000
-       movne   \rx, #0xfe000000        @ virtual
-       orrne   \rx, \rx, #0x00e80000
-       orr     \rx, \rx, #0x00002300
-       orr     \rx, \rx, #0x00000040
+       .macro  addruart, rp, rv
+       mov     \rp, #0x00002300
+       orr     \rp, \rp, #0x00000040
+       orr     \rv, \rp, #0xfe000000   @ virtual
+       orr     \rv, \rv, #0x00e80000
+       orr     \rp, \rp, #0xff000000   @ physical
+       orr     \rp, \rp, #0x00d80000
        .endm
 
 #define UART_SHIFT     2
index f91f3154577df1b0e1373239c756dd6d5fd1e33a..9b5a63f5d07d4368fcc6247d8815a2e272ac1ebf 100644 (file)
@@ -91,8 +91,6 @@ static struct sys_timer iq81340mc_timer = {
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-       .phys_io        = IOP13XX_PMMR_PHYS_MEM_BASE,
-       .io_pg_offst    = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
index ddb7a3435de9e906e0017549a39a255d975bc05b..df3492a9c280e25e7201fae6947bee6b0f7e9b47 100644 (file)
@@ -93,8 +93,6 @@ static struct sys_timer iq81340sc_timer = {
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-       .phys_io        = IOP13XX_PMMR_PHYS_MEM_BASE,
-       .io_pg_offst    = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
index f34b0ed806305474221051fa2b000199330b9e73..7149fcc16c8a0d87fda786bb76ebe24bda621ef0 100644 (file)
@@ -164,10 +164,10 @@ static void iop13xx_msi_nop(unsigned int irq)
 static struct irq_chip iop13xx_msi_chip = {
        .name = "PCI-MSI",
        .ack = iop13xx_msi_nop,
-       .enable = unmask_msi_irq,
-       .disable = mask_msi_irq,
-       .mask = mask_msi_irq,
-       .unmask = unmask_msi_irq,
+       .irq_enable = unmask_msi_irq,
+       .irq_disable = mask_msi_irq,
+       .irq_mask = mask_msi_irq,
+       .irq_unmask = unmask_msi_irq,
 };
 
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
index 2bef9b6e1cc91700c631fb93438589db938bbd67..779f924af302d6894b50484d15d31370485be9b6 100644 (file)
@@ -203,8 +203,6 @@ static void __init em7210_init_machine(void)
 }
 
 MACHINE_START(EM7210, "Lanner EM7210")
-       .phys_io        = IQ31244_UART,
-       .io_pg_offst    = ((IQ31244_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = em7210_map_io,
        .init_irq       = iop32x_init_irq,
index 10384fc37cb29d4315931483151c961e63e2d033..c6b6f9c5650d11183678163dc05799c9512955d8 100644 (file)
@@ -207,8 +207,6 @@ static void __init glantank_init_machine(void)
 
 MACHINE_START(GLANTANK, "GLAN Tank")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = GLANTANK_UART,
-       .io_pg_offst    = ((GLANTANK_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = glantank_map_io,
        .init_irq       = iop32x_init_irq,
index 736afe1edd1f668c4f84850b1604a3fc98a699b2..ff9e76c09f35b28ec0c551ad107b37d27b398d20 100644 (file)
  * published by the Free Software Foundation.
  */
 
-               .macro  addruart, rx, tmp
-               mov     \rx, #0xfe000000        @ physical as well as virtual
-               orr     \rx, \rx, #0x00800000   @ location of the UART
+               .macro  addruart, rp, rv
+               mov     \rp, #0xfe000000        @ physical as well as virtual
+               orr     \rp, \rp, #0x00800000   @ location of the UART
+               mov     \rv, \rp
                .endm
 
 #define UART_SHIFT     0
index d6ac85ff109deef02935213bc33577f0be2da42a..fde962c057f0e8489ce61c074c707a562337add1 100644 (file)
@@ -313,8 +313,6 @@ __setup("force_ep80219", force_ep80219_setup);
 
 MACHINE_START(IQ31244, "Intel IQ31244")
        /* Maintainer: Intel Corp. */
-       .phys_io        = IQ31244_UART,
-       .io_pg_offst    = ((IQ31244_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
@@ -329,8 +327,6 @@ MACHINE_END
  */
 MACHINE_START(EP80219, "Intel EP80219")
        /* Maintainer: Intel Corp. */
-       .phys_io        = IQ31244_UART,
-       .io_pg_offst    = ((IQ31244_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
index c6a0e4ee9d911d1b5d311be33b0fd537f65d93c4..3a95950e8737a05095ec02a91646ea6c6bc0674f 100644 (file)
@@ -186,8 +186,6 @@ static void __init iq80321_init_machine(void)
 
 MACHINE_START(IQ80321, "Intel IQ80321")
        /* Maintainer: Intel Corp. */
-       .phys_io        = IQ80321_UART,
-       .io_pg_offst    = ((IQ80321_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = iq80321_map_io,
        .init_irq       = iop32x_init_irq,
index f108a31afc2b9f2440bc90d56d1745829d7936eb..626aa375915dcf06fb841fa90129a514bbf1aac6 100644 (file)
@@ -327,8 +327,6 @@ static void __init n2100_init_machine(void)
 
 MACHINE_START(N2100, "Thecus N2100")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = N2100_UART,
-       .io_pg_offst    = ((N2100_UART) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = n2100_map_io,
        .init_irq       = iop32x_init_irq,
index addb2da78422b0ff58df52a64dce48fe57bdd169..40c500dd1fac61ec3f520fe0fb0fab6934d43a74 100644 (file)
  * published by the Free Software Foundation.
  */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ mmu enabled?
-               moveq   \rx, #0xff000000        @ physical
-               movne   \rx, #0xfe000000        @ virtual
-               orr     \rx, \rx, #0x00ff0000
-               orr     \rx, \rx, #0x0000f700
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00ff0000
+               orr     \rp, \rp, #0x0000f700
+               orr     \rv, #0xfe000000        @ virtual
+               orr     \rp, #0xff000000        @ physical
                .endm
 
 #define UART_SHIFT     2
index c6ff5523b380f95e26fc4282d895d1e03c54614b..c565f8d1e3a46826d66c2a4d5718d3732c7bb2eb 100644 (file)
@@ -141,8 +141,6 @@ static void __init iq80331_init_machine(void)
 
 MACHINE_START(IQ80331, "Intel IQ80331")
        /* Maintainer: Intel Corp. */
-       .phys_io        = 0xfefff000,
-       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
index fbf55140939407f322af2f1c75441550edb37414..36a9efb254c25e69aa532ec70bcf6334352c33ff 100644 (file)
@@ -141,8 +141,6 @@ static void __init iq80332_init_machine(void)
 
 MACHINE_START(IQ80332, "Intel IQ80332")
        /* Maintainer: Intel Corp. */
-       .phys_io        = 0xfefff000,
-       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
index 1a557e0d055b56626e5e0b37206b032a055c4818..88663ab1d2ad949cdca45c4a1ae49e71bec35b58 100644 (file)
@@ -253,8 +253,6 @@ static void __init enp2611_init_machine(void)
 
 MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = enp2611_map_io,
        .init_irq       = ixp2000_init_irq,
index 6a827681680fe20b833c07bc1990c488d1c20dae..0ef533b209721380abef4ffbd68d5c6a94a1c140 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0xc0000000        @ Physical base
-               movne   \rx, #0xfe000000        @ virtual base
-               orrne   \rx, \rx, #0x00f00000
-               orr     \rx, \rx, #0x00030000
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00030000
 #ifdef __ARMEB__
-               orr     \rx, \rx, #0x00000003
+               orr     \rp, \rp, #0x00000003
 #endif
+               orr     \rv, \rp, #0xfe000000   @ virtual base
+               orr     \rv, \rv, #0x00f00000
+               orr     \rp, \rp, #0xc0000000   @ Physical base
                .endm
 
 #define UART_SHIFT     2
index 55e5c69352ad4de2395659e8dccc3a1e4e00a637..dfffc1e817faaa1a478653c5cba9077500237998 100644 (file)
@@ -170,8 +170,6 @@ void __init ixdp2400_init_irq(void)
 
 MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ixdp2x00_map_io,
        .init_irq       = ixdp2400_init_irq,
index 237b61a85e9a397f6d398c53a686edbd186515ac..cd4c9bcff2b512f9571af54f3734a2b790bae614 100644 (file)
@@ -285,8 +285,6 @@ void __init ixdp2800_init_irq(void)
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ixdp2x00_map_io,
        .init_irq       = ixdp2800_init_irq,
index 0369ec4242a687e61c7c4305de54fcec5d4f696b..6c121bdbe31192731948d73280f2918557c70417 100644 (file)
@@ -416,8 +416,6 @@ static void __init ixdp2x01_init_machine(void)
 #ifdef CONFIG_ARCH_IXDP2401
 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
@@ -429,8 +427,6 @@ MACHINE_END
 #ifdef CONFIG_ARCH_IXDP2801
 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
@@ -444,8 +440,6 @@ MACHINE_END
  */
 MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP2000_UART_PHYS_BASE,
-       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
index 1c06bfc5a7efc5909fe1dd1897b9bcd285388ad0..e25e5fe183ba976b319e3b2a912e13795a43caaf 100644 (file)
@@ -85,8 +85,6 @@ static void __init espresso_init(void)
 
 MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
        /* Maintainer: Lennert Buytenhek */
-       .phys_io        = IXP23XX_PERIPHERAL_PHYS,
-       .io_pg_offst    = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
        .map_io         = ixp23xx_map_io,
        .init_irq       = ixp23xx_init_irq,
        .timer          = &ixp23xx_timer,
index a82e375465e283651c4f8e96ea7913c4a77f4b35..f7c6eef7fa220d58a57b72e852002d22f14efe8f 100644 (file)
  */
 #include <mach/ixp23xx.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                         @ mmu enabled?
-               ldreq   \rx, =IXP23XX_PERIPHERAL_PHYS   @ physical
-               ldrne   \rx, =IXP23XX_PERIPHERAL_VIRT   @ virtual
+               .macro  addruart, rp, rv
+               ldr     \rp, =IXP23XX_PERIPHERAL_PHYS   @ physical
+               ldr     \rv, =IXP23XX_PERIPHERAL_VIRT   @ virtual
 #ifdef __ARMEB__
-               orr     \rx, \rx, #0x00000003
+               orr     \rp, \rp, #0x00000003
+               orr     \rv, \rv, #0x00000003
 #endif
                .endm
 
index f1b124a709abd232b63625f6ddc143fd4b17730a..664e39c2a903e81a2491ea7a8d4eab1af02c2ac8 100644 (file)
@@ -328,8 +328,6 @@ static void __init ixdp2351_init(void)
 
 MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP23XX_PERIPHERAL_PHYS,
-       .io_pg_offst    = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
        .map_io         = ixdp2351_map_io,
        .init_irq       = ixdp2351_init_irq,
        .timer          = &ixp23xx_timer,
index 6d38d769761c1b727b7a2da2a1b096bc20fe4e76..76c61ba73218778987cec85683909e70ccf897fa 100644 (file)
@@ -171,8 +171,6 @@ static void __init roadrunner_init(void)
 
 MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
        /* Maintainer: Deepak Saxena */
-       .phys_io        = IXP23XX_PERIPHERAL_PHYS,
-       .io_pg_offst    = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
        .map_io         = ixp23xx_map_io,
        .init_irq       = ixp23xx_init_irq,
        .timer          = &ixp23xx_timer,
index d8bc86d76f1d2248b0d936f5cd1413c0ce0ba469..73745ff102d5da3e20beb6451b9736a2bf20cb00 100644 (file)
@@ -164,8 +164,6 @@ static void __init avila_init(void)
 
 MACHINE_START(AVILA, "Gateworks Avila Network Platform")
        /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
@@ -181,8 +179,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_LOFT
 MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
        /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 61cd4d64b98596c7507dcaf67d069dbe22508e50..24498a932ba65b8054de5ba8229ef0e0c838dd71 100644 (file)
@@ -503,6 +503,14 @@ struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys)
        return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys);
 }
 
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+       if (mask >= SZ_64M - 1)
+               return 0;
+
+       return -EIO;
+}
+
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
 
index 31a47f6a8939d8fc1bc0ce7c0e78db0495e5b5df..355e3de3873371050a9794761def1761fd0ef34f 100644 (file)
@@ -109,8 +109,6 @@ static void __init coyote_init(void)
 #ifdef CONFIG_ARCH_ADI_COYOTE
 MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
@@ -126,8 +124,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_IXDPG425
 MACHINE_START(IXDPG425, "Intel IXDPG425")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 7c1fa54a6145a987a4d41a4910421231a62a2ea5..d398229cfaa5d40b09e13effcf660dc71e97df8f 100644 (file)
@@ -279,8 +279,6 @@ static void __init dsmg600_init(void)
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
        /* Maintainer: www.nslu2-linux.org */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
index e7f4befba4224b364c5d601ffe7359ef474fbc60..727ee39ce11c1ec786dc8cc498d7631996cc0490 100644 (file)
@@ -270,8 +270,6 @@ static void __init fsg_init(void)
 
 MACHINE_START(FSG, "Freecom FSG-3")
        /* Maintainer: www.nslu2-linux.org */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 2583b2a13174ef02959fb62b70d96c68a978073a..9dc0b4eaa65adbac3ca17e7c7c565f793c440356 100644 (file)
@@ -96,8 +96,6 @@ static void __init gateway7001_init(void)
 #ifdef CONFIG_MACH_GATEWAY7001
 MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 1c28048209c14c233407902fd86364f153fbaf9c..d0e4861ac03d5bc39c0f201d60e956f43559c28a 100644 (file)
@@ -496,8 +496,6 @@ subsys_initcall(gmlr_pci_init);
 
 MACHINE_START(GORAMO_MLR, "MultiLink")
        /* Maintainer: Krzysztof Halasa */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index c67586b79400c8a02084389e297539208dcdb5c1..77abead362277492e076f6d734a182241275314b 100644 (file)
@@ -164,8 +164,6 @@ static void __init gtwx5715_init(void)
 
 MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
        /* Maintainer: George Joseph */
-       .phys_io        = IXP4XX_UART2_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 3fc66d6d00a01f9d5b559f65ce096ebbf5576717..b974a49c0aff45a6a1ca1967b501f7d80588e757 100644 (file)
  * published by the Free Software Foundation.
 */
 
-                .macro  addruart, rx, tmp
-                mrc     p15, 0, \rx, c1, c0
-                tst     \rx, #1                 @ MMU enabled?
-                moveq   \rx, #0xc8000000
-                movne   \rx, #0xff000000
-               orrne   \rx, \rx, #0x00b00000
+                .macro  addruart, rp, rv
 #ifdef __ARMEB__
-                add     \rx,\rx,#3              @ Uart regs are at off set of 3 if
-                                               @ byte writes used - Big Endian.
+                mov     \rp, #3         @ Uart regs are at off set of 3 if
+                                       @ byte writes used - Big Endian.
+#else
+               mov     \rp, #0
 #endif
+                orr     \rv, \rp, #0xff000000  @ virtual
+               orr     \rv, \rv, #0x00b00000
+                orr     \rp, \rp, #0xc8000000  @ physical
                 .endm
 
 #define UART_SHIFT     2
index f91ca6d4fbe8a2820758d2252091a761caac377c..8138371c406e6584b8990803079c7a093cbe1964 100644 (file)
@@ -26,6 +26,8 @@
 #define PCIBIOS_MAX_MEM                0x4BFFFFFF
 #endif
 
+#define ARCH_HAS_DMA_SET_COHERENT_MASK
+
 #define pcibios_assign_all_busses()    1
 
 /* Register locations and bits */
index ea9ee4ed0a3e06a6b2f8135557b05a70c6240fbb..140783386785511a8997a8926a20a9d353bd8091 100644 (file)
@@ -257,8 +257,6 @@ static void __init ixdp425_init(void)
 #ifdef CONFIG_ARCH_IXDP425
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
@@ -270,8 +268,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_IXDP465
 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
@@ -283,8 +279,6 @@ MACHINE_END
 #ifdef CONFIG_ARCH_PRPMC1100
 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
@@ -296,8 +290,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_KIXRP435
 MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index e3ee880aa1e687ae3df927bddaf95de4206710c4..f18fee748878e961136a837755dc460d3c35574b 100644 (file)
@@ -314,8 +314,6 @@ static void __init nas100d_init(void)
 
 MACHINE_START(NAS100D, "Iomega NAS 100d")
        /* Maintainer: www.nslu2-linux.org */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
index c14e0034be4b42b134175d4614a764db59f04ec8..f79b62eb7614ec091d098b0276881a569d521d78 100644 (file)
@@ -300,8 +300,6 @@ static void __init nslu2_init(void)
 
 MACHINE_START(NSLU2, "Linksys NSLU2")
        /* Maintainer: www.nslu2-linux.org */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
index 465cc5cce687df05de98c8e926994417462aac87..4e72cfdd3c461d2dba2fc03161998645d353e7f5 100644 (file)
@@ -236,8 +236,6 @@ static void __init vulcan_init(void)
 
 MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 4dd74863daa9cb4e56c074108436abd2ea39b33d..5d148c7bc4fbd167473efb36fa2cd3e62e68aecb 100644 (file)
@@ -97,8 +97,6 @@ static void __init wg302v2_init(void)
 #ifdef CONFIG_MACH_WG302V2
 MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index cc25501b57fa8edf270752e0a719f2564965f44a..34106335c728f31527dc59dbc05d5978165ae365 100644 (file)
@@ -58,6 +58,12 @@ config MACH_TS41X
          QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
          devices.
 
+config MACH_DOCKSTAR
+       bool "Seagate FreeAgent DockStar"
+       help
+         Say 'Y' here if you want your kernel to support the
+         Seagate FreeAgent DockStar.
+
 config MACH_OPENRD
         bool
 
@@ -100,6 +106,12 @@ config MACH_NETSPACE_MAX_V2
          Say 'Y' here if you want your kernel to support the
          LaCie Network Space Max v2 NAS.
 
+config MACH_D2NET_V2
+       bool "LaCie d2 Network v2 NAS Board"
+       help
+         Say 'Y' here if you want your kernel to support the
+         LaCie d2 Network v2 NAS.
+
 config MACH_NET2BIG_V2
        bool "LaCie 2Big Network v2 NAS Board"
        help
index 295d7baa6ae11150956e004330259859ef3c4ec6..5dcaa81a2ec39f0f6b60a13438651ab381fc6eb4 100644 (file)
@@ -7,14 +7,16 @@ obj-$(CONFIG_MACH_MV88F6281GTW_GE)    += mv88f6281gtw_ge-setup.o
 obj-$(CONFIG_MACH_SHEEVAPLUG)          += sheevaplug-setup.o
 obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG)    += sheevaplug-setup.o
 obj-$(CONFIG_MACH_GURUPLUG)            += guruplug-setup.o
+obj-$(CONFIG_MACH_DOCKSTAR)            += dockstar-setup.o
 obj-$(CONFIG_MACH_TS219)               += ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)               += ts41x-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_OPENRD)              += openrd-setup.o
-obj-$(CONFIG_MACH_NETSPACE_V2)         += netspace_v2-setup.o
-obj-$(CONFIG_MACH_INETSPACE_V2)                += netspace_v2-setup.o
-obj-$(CONFIG_MACH_NETSPACE_MAX_V2)     += netspace_v2-setup.o
-obj-$(CONFIG_MACH_NET2BIG_V2)          += netxbig_v2-setup.o
-obj-$(CONFIG_MACH_NET5BIG_V2)          += netxbig_v2-setup.o
+obj-$(CONFIG_MACH_NETSPACE_V2)         += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_INETSPACE_V2)                += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NETSPACE_MAX_V2)     += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_D2NET_V2)            += d2net_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET2BIG_V2)          += netxbig_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET5BIG_V2)          += netxbig_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_T5325)               += t5325-setup.o
 
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
new file mode 100644 (file)
index 0000000..4aa86e4
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * arch/arm/mach-kirkwood/d2net_v2-setup.c
+ *
+ * LaCie d2 Network Space v2 Board Setup
+ *
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <mach/leds-ns2.h>
+#include "common.h"
+#include "mpp.h"
+#include "lacie_v2-common.h"
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data d2net_v2_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+
+static struct mv_sata_platform_data d2net_v2_sata_data = {
+       .n_ports        = 2,
+};
+
+/*****************************************************************************
+ * GPIO keys
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_PUSH_BUTTON          34
+#define D2NET_V2_GPIO_POWER_SWITCH_ON      13
+#define D2NET_V2_GPIO_POWER_SWITCH_OFF     15
+
+#define D2NET_V2_SWITCH_POWER_ON           0x1
+#define D2NET_V2_SWITCH_POWER_OFF          0x2
+
+static struct gpio_keys_button d2net_v2_buttons[] = {
+       [0] = {
+               .type           = EV_SW,
+               .code           = D2NET_V2_SWITCH_POWER_ON,
+               .gpio           = D2NET_V2_GPIO_POWER_SWITCH_ON,
+               .desc           = "Back power switch (on|auto)",
+               .active_low     = 0,
+       },
+       [1] = {
+               .type           = EV_SW,
+               .code           = D2NET_V2_SWITCH_POWER_OFF,
+               .gpio           = D2NET_V2_GPIO_POWER_SWITCH_OFF,
+               .desc           = "Back power switch (auto|off)",
+               .active_low     = 0,
+       },
+       [2] = {
+               .code           = KEY_POWER,
+               .gpio           = D2NET_V2_GPIO_PUSH_BUTTON,
+               .desc           = "Front Push Button",
+               .active_low     = 1,
+       },
+};
+
+static struct gpio_keys_platform_data d2net_v2_button_data = {
+       .buttons        = d2net_v2_buttons,
+       .nbuttons       = ARRAY_SIZE(d2net_v2_buttons),
+};
+
+static struct platform_device d2net_v2_gpio_buttons = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &d2net_v2_button_data,
+       },
+};
+
+/*****************************************************************************
+ * GPIO LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_RED_LED          12
+
+static struct gpio_led d2net_v2_gpio_led_pins[] = {
+       {
+               .name   = "d2net_v2:red:fail",
+               .gpio   = D2NET_V2_GPIO_RED_LED,
+       },
+};
+
+static struct gpio_led_platform_data d2net_v2_gpio_leds_data = {
+       .num_leds       = ARRAY_SIZE(d2net_v2_gpio_led_pins),
+       .leds           = d2net_v2_gpio_led_pins,
+};
+
+static struct platform_device d2net_v2_gpio_leds = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &d2net_v2_gpio_leds_data,
+       },
+};
+
+/*****************************************************************************
+ * Dual-GPIO CPLD LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_BLUE_LED_SLOW    29
+#define D2NET_V2_GPIO_BLUE_LED_CMD     30
+
+static struct ns2_led d2net_v2_led_pins[] = {
+       {
+               .name   = "d2net_v2:blue:sata",
+               .cmd    = D2NET_V2_GPIO_BLUE_LED_CMD,
+               .slow   = D2NET_V2_GPIO_BLUE_LED_SLOW,
+       },
+};
+
+static struct ns2_led_platform_data d2net_v2_leds_data = {
+       .num_leds       = ARRAY_SIZE(d2net_v2_led_pins),
+       .leds           = d2net_v2_led_pins,
+};
+
+static struct platform_device d2net_v2_leds = {
+       .name           = "leds-ns2",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &d2net_v2_leds_data,
+       },
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+static unsigned int d2net_v2_mpp_config[] __initdata = {
+       MPP0_SPI_SCn,
+       MPP1_SPI_MOSI,
+       MPP2_SPI_SCK,
+       MPP3_SPI_MISO,
+       MPP6_SYSRST_OUTn,
+       MPP7_GPO,               /* Request power-off */
+       MPP8_TW0_SDA,
+       MPP9_TW0_SCK,
+       MPP10_UART0_TXD,
+       MPP11_UART0_RXD,
+       MPP12_GPO,              /* Red led */
+       MPP13_GPIO,             /* Rear power switch (on|auto) */
+       MPP14_GPIO,             /* USB fuse */
+       MPP15_GPIO,             /* Rear power switch (auto|off) */
+       MPP16_GPIO,             /* SATA 0 power */
+       MPP21_SATA0_ACTn,
+       MPP24_GPIO,             /* USB mode select */
+       MPP26_GPIO,             /* USB device vbus */
+       MPP28_GPIO,             /* USB enable host vbus */
+       MPP29_GPIO,             /* Blue led (slow register) */
+       MPP30_GPIO,             /* Blue led (command register) */
+       MPP34_GPIO,             /* Power button (1 = Released, 0 = Pushed) */
+       MPP35_GPIO,             /* Inhibit power-off */
+       0
+};
+
+#define D2NET_V2_GPIO_POWER_OFF                7
+
+static void d2net_v2_power_off(void)
+{
+       gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1);
+}
+
+static void __init d2net_v2_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_init();
+       kirkwood_mpp_conf(d2net_v2_mpp_config);
+
+       lacie_v2_hdd_power_init(1);
+
+       kirkwood_ehci_init();
+       kirkwood_ge00_init(&d2net_v2_ge00_data);
+       kirkwood_sata_init(&d2net_v2_sata_data);
+       kirkwood_uart0_init();
+       lacie_v2_register_flash();
+       lacie_v2_register_i2c_devices();
+
+       platform_device_register(&d2net_v2_leds);
+       platform_device_register(&d2net_v2_gpio_leds);
+       platform_device_register(&d2net_v2_gpio_buttons);
+
+       if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 &&
+           gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0)
+               pm_power_off = d2net_v2_power_off;
+       else
+               pr_err("d2net_v2: failed to configure power-off GPIO\n");
+}
+
+MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
+       .boot_params    = 0x00000100,
+       .init_machine   = d2net_v2_init,
+       .map_io         = kirkwood_map_io,
+       .init_irq       = kirkwood_init_irq,
+       .timer          = &lacie_v2_timer,
+MACHINE_END
index 16f6691e7c685cc6af9266b56bcd0af1265a60ef..9ea71182d31ac5aea51d7a31d5e60ac98c1bc830 100644 (file)
@@ -97,8 +97,6 @@ subsys_initcall(db88f6281_pci_init);
 
 MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = db88f6281_init,
        .map_io         = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
new file mode 100644 (file)
index 0000000..433ea36
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * arch/arm/mach-kirkwood/dockstar-setup.c
+ *
+ * Seagate FreeAgent DockStar Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition dockstar_nand_parts[] = {
+       {
+               .name = "u-boot",
+               .offset = 0,
+               .size = SZ_1M
+       }, {
+               .name = "uImage",
+               .offset = MTDPART_OFS_NXTBLK,
+               .size = SZ_4M
+       }, {
+               .name = "root",
+               .offset = MTDPART_OFS_NXTBLK,
+               .size = MTDPART_SIZ_FULL
+       },
+};
+
+static struct mv643xx_eth_platform_data dockstar_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct gpio_led dockstar_led_pins[] = {
+       {
+               .name                   = "dockstar:green:health",
+               .default_trigger        = "default-on",
+               .gpio                   = 46,
+               .active_low             = 1,
+       },
+       {
+               .name                   = "dockstar:orange:misc",
+               .default_trigger        = "none",
+               .gpio                   = 47,
+               .active_low             = 1,
+       },
+};
+
+static struct gpio_led_platform_data dockstar_led_data = {
+       .leds           = dockstar_led_pins,
+       .num_leds       = ARRAY_SIZE(dockstar_led_pins),
+};
+
+static struct platform_device dockstar_leds = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &dockstar_led_data,
+       }
+};
+
+static unsigned int dockstar_mpp_config[] __initdata = {
+       MPP29_GPIO,     /* USB Power Enable */
+       MPP46_GPIO,     /* LED green */
+       MPP47_GPIO,     /* LED orange */
+       0
+};
+
+static void __init dockstar_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_init();
+
+       /* setup gpio pin select */
+       kirkwood_mpp_conf(dockstar_mpp_config);
+
+       kirkwood_uart0_init();
+       kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25);
+
+       if (gpio_request(29, "USB Power Enable") != 0 ||
+           gpio_direction_output(29, 1) != 0)
+               printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+       kirkwood_ehci_init();
+
+       kirkwood_ge00_init(&dockstar_ge00_data);
+
+       platform_device_register(&dockstar_leds);
+}
+
+MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
+       .boot_params    = 0x00000100,
+       .init_machine   = dockstar_init,
+       .map_io         = kirkwood_map_io,
+       .init_irq       = kirkwood_init_irq,
+       .timer          = &kirkwood_timer,
+MACHINE_END
index 54d07c89d4ffe2e278c501ec6e4ddda0e6171cda..8f47dc0a2feff75a9d546373f7565dc4e4585862 100644 (file)
@@ -121,8 +121,6 @@ static void __init guruplug_init(void)
 
 MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
        /* Maintainer: Siddarth Gore <gores@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = guruplug_init,
        .map_io         = kirkwood_map_io,
index d0606774dea7de3baa03e4291dd016b0825dde07..db06ae437d08c69fa126edf696b377bdca54262e 100644 (file)
@@ -8,12 +8,11 @@
 
 #include <mach/bridge-regs.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =KIRKWOOD_REGS_PHYS_BASE
-       ldrne   \rx, =KIRKWOOD_REGS_VIRT_BASE
-       orr     \rx, \rx, #0x00012000
+       .macro  addruart, rp, rv
+       ldr     \rp, =KIRKWOOD_REGS_PHYS_BASE
+       ldr     \rv, =KIRKWOOD_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
        .endm
 
 #define UART_SHIFT     2
index 93fc2ec95e7687b30b6144f2116adb0664266a4d..6e924b398919e822ca4f2bddd294358bf4008ede 100644 (file)
@@ -38,7 +38,7 @@
 
 #define KIRKWOOD_PCIE1_IO_PHYS_BASE    0xf3000000
 #define KIRKWOOD_PCIE1_IO_VIRT_BASE    0xfef00000
-#define KIRKWOOD_PCIE1_IO_BUS_BASE     0x00000000
+#define KIRKWOOD_PCIE1_IO_BUS_BASE     0x00100000
 #define KIRKWOOD_PCIE1_IO_SIZE         SZ_1M
 
 #define KIRKWOOD_PCIE_IO_PHYS_BASE     0xf2000000
diff --git a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
new file mode 100644 (file)
index 0000000..24b536e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
+ *
+ * Platform data structure for netxbig LED driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_LEDS_NETXBIG_H
+#define __MACH_LEDS_NETXBIG_H
+
+struct netxbig_gpio_ext {
+       unsigned        *addr;
+       int             num_addr;
+       unsigned        *data;
+       int             num_data;
+       unsigned        enable;
+};
+
+enum netxbig_led_mode {
+       NETXBIG_LED_OFF,
+       NETXBIG_LED_ON,
+       NETXBIG_LED_SATA,
+       NETXBIG_LED_TIMER1,
+       NETXBIG_LED_TIMER2,
+       NETXBIG_LED_MODE_NUM,
+};
+
+#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM
+
+struct netxbig_led_timer {
+       unsigned long           delay_on;
+       unsigned long           delay_off;
+       enum netxbig_led_mode   mode;
+};
+
+struct netxbig_led {
+       const char      *name;
+       const char      *default_trigger;
+       int             mode_addr;
+       int             *mode_val;
+       int             bright_addr;
+};
+
+struct netxbig_led_platform_data {
+       struct netxbig_gpio_ext *gpio_ext;
+       struct netxbig_led_timer *timer;
+       int                     num_timer;
+       struct netxbig_led      *leds;
+       int                     num_leds;
+};
+
+#endif /* __MACH_LEDS_NETXBIG_H */
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c
new file mode 100644 (file)
index 0000000..d3ea1b6
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/gpio.h>
+#include <asm/mach/time.h>
+#include <mach/kirkwood.h>
+#include <mach/irqs.h>
+#include <plat/time.h>
+#include "common.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
+ ****************************************************************************/
+
+static struct mtd_partition lacie_v2_flash_parts[] = {
+       {
+               .name = "u-boot",
+               .size = MTDPART_SIZ_FULL,
+               .offset = 0,
+               .mask_flags = MTD_WRITEABLE, /* force read-only */
+       },
+};
+
+static const struct flash_platform_data lacie_v2_flash = {
+       .type           = "mx25l4005a",
+       .name           = "spi_flash",
+       .parts          = lacie_v2_flash_parts,
+       .nr_parts       = ARRAY_SIZE(lacie_v2_flash_parts),
+};
+
+static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = {
+       {
+               .modalias       = "m25p80",
+               .platform_data  = &lacie_v2_flash,
+               .irq            = -1,
+               .max_speed_hz   = 20000000,
+               .bus_num        = 0,
+               .chip_select    = 0,
+       },
+};
+
+void __init lacie_v2_register_flash(void)
+{
+       spi_register_board_info(lacie_v2_spi_slave_info,
+                               ARRAY_SIZE(lacie_v2_spi_slave_info));
+       kirkwood_spi_init();
+}
+
+/*****************************************************************************
+ * I2C devices
+ ****************************************************************************/
+
+static struct at24_platform_data at24c04 = {
+       .byte_len       = SZ_4K / 8,
+       .page_size      = 16,
+};
+
+/*
+ * i2c addr | chip         | description
+ * 0x50     | HT24LC04     | eeprom (512B)
+ */
+
+static struct i2c_board_info __initdata lacie_v2_i2c_info[] = {
+       {
+               I2C_BOARD_INFO("24c04", 0x50),
+               .platform_data  = &at24c04,
+       }
+};
+
+void __init lacie_v2_register_i2c_devices(void)
+{
+       kirkwood_i2c_init();
+       i2c_register_board_info(0, lacie_v2_i2c_info,
+                               ARRAY_SIZE(lacie_v2_i2c_info));
+}
+
+/*****************************************************************************
+ * Hard Disk power
+ ****************************************************************************/
+
+static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
+
+void __init lacie_v2_hdd_power_init(int hdd_num)
+{
+       int i;
+       int err;
+
+       /* Power up all hard disks. */
+       for (i = 0; i < hdd_num; i++) {
+               err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL);
+               if (err == 0) {
+                       err = gpio_direction_output(
+                                       lacie_v2_gpio_hdd_power[i], 1);
+                       /* Free the HDD power GPIOs. This allow user-space to
+                        * configure them via the gpiolib sysfs interface. */
+                       gpio_free(lacie_v2_gpio_hdd_power[i]);
+               }
+               if (err)
+                       pr_err("Failed to power up HDD%d\n", i + 1);
+       }
+}
+
+/*****************************************************************************
+ * Timer
+ ****************************************************************************/
+
+static void lacie_v2_timer_init(void)
+{
+       kirkwood_tclk = 166666667;
+       orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+}
+
+struct sys_timer lacie_v2_timer = {
+       .init = lacie_v2_timer_init,
+};
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.h b/arch/arm/mach-kirkwood/lacie_v2-common.h
new file mode 100644 (file)
index 0000000..af52131
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+
+void lacie_v2_register_flash(void);
+void lacie_v2_register_i2c_devices(void);
+void lacie_v2_hdd_power_init(int hdd_num);
+
+extern struct sys_timer lacie_v2_timer;
+
+#endif
index c6b92b42eb4e5a627fcceb74b61078bc8e589f4a..1e5266f57e2a2d3e6a46d7761e8b622c5f3928ca 100644 (file)
@@ -163,8 +163,6 @@ subsys_initcall(mv88f6281gtw_ge_pci_init);
 
 MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = mv88f6281gtw_ge_init,
        .map_io         = kirkwood_map_io,
index d26bf324738bde48e5be8b5c5cf13978a9f03730..5e286441b8f45f5f571e001b48d16fe7685362ac 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
 #include <mach/kirkwood.h>
 #include <mach/leds-ns2.h>
-#include <plat/time.h>
 #include "common.h"
 #include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netspace_v2_flash_parts[] = {
-       {
-               .name = "u-boot",
-               .size = MTDPART_SIZ_FULL,
-               .offset = 0,
-               .mask_flags = MTD_WRITEABLE, /* force read-only */
-       },
-};
-
-static const struct flash_platform_data netspace_v2_flash = {
-       .type           = "mx25l4005a",
-       .name           = "spi_flash",
-       .parts          = netspace_v2_flash_parts,
-       .nr_parts       = ARRAY_SIZE(netspace_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = {
-       {
-               .modalias       = "m25p80",
-               .platform_data  = &netspace_v2_flash,
-               .irq            = -1,
-               .max_speed_hz   = 20000000,
-               .bus_num        = 0,
-               .chip_select    = 0,
-       },
-};
+#include "lacie_v2-common.h"
 
 /*****************************************************************************
  * Ethernet
@@ -83,27 +46,6 @@ static struct mv643xx_eth_platform_data netspace_v2_ge00_data = {
        .phy_addr       = MV643XX_ETH_PHY_ADDR(8),
 };
 
-/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
-       .byte_len       = SZ_4K / 8,
-       .page_size      = 16,
-};
-
-/*
- * i2c addr | chip         | description
- * 0x50     | HT24LC04     | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netspace_v2_i2c_info[] = {
-       {
-               I2C_BOARD_INFO("24c04", 0x50),
-               .platform_data  = &at24c04,
-       }
-};
-
 /*****************************************************************************
  * SATA
  ****************************************************************************/
@@ -112,35 +54,6 @@ static struct mv_sata_platform_data netspace_v2_sata_data = {
        .n_ports        = 2,
 };
 
-#define NETSPACE_V2_GPIO_SATA0_POWER   16
-#define NETSPACE_V2_GPIO_SATA1_POWER   17
-
-static void __init netspace_v2_sata_power_init(void)
-{
-       int err;
-
-       err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power");
-       if (err == 0) {
-               err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1);
-               if (err)
-                       gpio_free(NETSPACE_V2_GPIO_SATA0_POWER);
-       }
-       if (err)
-               pr_err("netspace_v2: failed to setup SATA0 power\n");
-
-       if (machine_is_netspace_max_v2()) {
-               err = gpio_request(NETSPACE_V2_GPIO_SATA1_POWER, "SATA1 power");
-               if (err == 0) {
-                       err = gpio_direction_output(
-                                       NETSPACE_V2_GPIO_SATA1_POWER, 1);
-                       if (err)
-                               gpio_free(NETSPACE_V2_GPIO_SATA1_POWER);
-               }
-               if (err)
-                       pr_err("netspace_v2: failed to setup SATA1 power\n");
-       }
-}
-
 /*****************************************************************************
  * GPIO keys
  ****************************************************************************/
@@ -223,20 +136,6 @@ static struct platform_device netspace_v2_leds = {
        },
 };
 
-/*****************************************************************************
- * Timer
- ****************************************************************************/
-
-static void netspace_v2_timer_init(void)
-{
-       kirkwood_tclk = 166666667;
-       orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
-
-struct sys_timer netspace_v2_timer = {
-       .init = netspace_v2_timer_init,
-};
-
 /*****************************************************************************
  * General Setup
  ****************************************************************************/
@@ -291,18 +190,17 @@ static void __init netspace_v2_init(void)
        kirkwood_init();
        kirkwood_mpp_conf(netspace_v2_mpp_config);
 
-       netspace_v2_sata_power_init();
+       if (machine_is_netspace_max_v2())
+               lacie_v2_hdd_power_init(2);
+       else
+               lacie_v2_hdd_power_init(1);
 
        kirkwood_ehci_init();
        kirkwood_ge00_init(&netspace_v2_ge00_data);
        kirkwood_sata_init(&netspace_v2_sata_data);
        kirkwood_uart0_init();
-       spi_register_board_info(netspace_v2_spi_slave_info,
-                               ARRAY_SIZE(netspace_v2_spi_slave_info));
-       kirkwood_spi_init();
-       kirkwood_i2c_init();
-       i2c_register_board_info(0, netspace_v2_i2c_info,
-                               ARRAY_SIZE(netspace_v2_i2c_info));
+       lacie_v2_register_flash();
+       lacie_v2_register_i2c_devices();
 
        platform_device_register(&netspace_v2_leds);
        platform_device_register(&netspace_v2_gpio_leds);
@@ -317,36 +215,30 @@ static void __init netspace_v2_init(void)
 
 #ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &netspace_v2_timer,
+       .timer          = &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_INETSPACE_V2
 MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &netspace_v2_timer,
+       .timer          = &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_NETSPACE_MAX_V2
 MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &netspace_v2_timer,
+       .timer          = &lacie_v2_timer,
 MACHINE_END
 #endif
index 2bd14c5079de7c0e7379439523aed3422173f383..a1b45d501aef57393a47e0d99e67a423ae3355fc 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
 #include <mach/kirkwood.h>
-#include <plat/time.h>
+#include <mach/leds-netxbig.h>
 #include "common.h"
 #include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netxbig_v2_flash_parts[] = {
-       {
-               .name = "u-boot",
-               .size = MTDPART_SIZ_FULL,
-               .offset = 0,
-               .mask_flags = MTD_WRITEABLE, /* force read-only */
-       },
-};
-
-static const struct flash_platform_data netxbig_v2_flash = {
-       .type           = "mx25l4005a",
-       .name           = "spi_flash",
-       .parts          = netxbig_v2_flash_parts,
-       .nr_parts       = ARRAY_SIZE(netxbig_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netxbig_v2_spi_slave_info[] = {
-       {
-               .modalias       = "m25p80",
-               .platform_data  = &netxbig_v2_flash,
-               .irq            = -1,
-               .max_speed_hz   = 20000000,
-               .bus_num        = 0,
-               .chip_select    = 0,
-       },
-};
+#include "lacie_v2-common.h"
 
 /*****************************************************************************
  * Ethernet
@@ -85,27 +49,6 @@ static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = {
        .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
 };
 
-/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
-       .byte_len       = SZ_4K / 8,
-       .page_size      = 16,
-};
-
-/*
- * i2c addr | chip         | description
- * 0x50     | HT24LC04     | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netxbig_v2_i2c_info[] = {
-       {
-               I2C_BOARD_INFO("24c04", 0x50),
-               .platform_data  = &at24c04,
-       }
-};
-
 /*****************************************************************************
  * SATA
  ****************************************************************************/
@@ -114,34 +57,6 @@ static struct mv_sata_platform_data netxbig_v2_sata_data = {
        .n_ports        = 2,
 };
 
-static int __initdata netxbig_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
-
-static void __init netxbig_v2_sata_power_init(void)
-{
-       int i;
-       int err;
-       int hdd_nb;
-
-       if (machine_is_net2big_v2())
-               hdd_nb = 2;
-       else
-               hdd_nb = 5;
-
-       /* Power up all hard disks. */
-       for (i = 0; i < hdd_nb; i++) {
-               err = gpio_request(netxbig_v2_gpio_hdd_power[i], NULL);
-               if (err == 0) {
-                       err = gpio_direction_output(
-                                       netxbig_v2_gpio_hdd_power[i], 1);
-                       /* Free the HDD power GPIOs. This allow user-space to
-                        * configure them via the gpiolib sysfs interface. */
-                       gpio_free(netxbig_v2_gpio_hdd_power[i]);
-               }
-               if (err)
-                       pr_err("netxbig_v2: failed to power up HDD%d\n", i + 1);
-       }
-}
-
 /*****************************************************************************
  * GPIO keys
  ****************************************************************************/
@@ -190,7 +105,7 @@ static struct platform_device netxbig_v2_gpio_buttons = {
 };
 
 /*****************************************************************************
- * GPIO LEDs
+ * GPIO extension LEDs
  ****************************************************************************/
 
 /*
@@ -200,19 +115,32 @@ static struct platform_device netxbig_v2_gpio_buttons = {
  * - address register : bit [0-2] -> GPIO [47-49]
  * - data register    : bit [0-2] -> GPIO [44-46]
  * - enable register  : GPIO 29
- *
+ */
+
+static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
+static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
+
+static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
+       .addr           = netxbig_v2_gpio_ext_addr,
+       .num_addr       = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
+       .data           = netxbig_v2_gpio_ext_data,
+       .num_data       = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
+       .enable         = 29,
+};
+
+/*
  * Address register selection:
  *
  * addr | register
  * ----------------------------
  *   0  | front LED
  *   1  | front LED brightness
- *   2  | HDD LED brightness
- *   3  | HDD1 LED
- *   4  | HDD2 LED
- *   5  | HDD3 LED
- *   6  | HDD4 LED
- *   7  | HDD5 LED
+ *   2  | SATA LED brightness
+ *   3  | SATA0 LED
+ *   4  | SATA1 LED
+ *   5  | SATA2 LED
+ *   6  | SATA3 LED
+ *   7  | SATA4 LED
  *
  * Data register configuration:
  *
@@ -233,30 +161,107 @@ static struct platform_device netxbig_v2_gpio_buttons = {
  *   6  | blink blue on=1 sec and red on=1 sec
  *   7  | blink blue on=0.5 sec and blue off=2.5 sec
  *
- * data | HDD LED mode
+ * data | SATA LED mode
  * -------------------------------------------------
- *   0  | fix blue on
+ *   0  | fix off
  *   1  | SATA activity blink
  *   2  | fix red on
  *   3  | blink blue on=1 sec and blue off=1 sec
  *   4  | blink red on=1 sec and red off=1 sec
  *   5  | blink blue on=2.5 sec and red on=0.5 sec
  *   6  | blink blue on=1 sec and red on=1 sec
- *   7  | blink blue on=0.5 sec and blue off=2.5 sec
+ *   7  | fix blue on
  */
 
-/*****************************************************************************
- * Timer
- ****************************************************************************/
+static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
+       [NETXBIG_LED_OFF]       = 0,
+       [NETXBIG_LED_ON]        = 2,
+       [NETXBIG_LED_SATA]      = NETXBIG_LED_INVALID_MODE,
+       [NETXBIG_LED_TIMER1]    = 4,
+       [NETXBIG_LED_TIMER2]    = NETXBIG_LED_INVALID_MODE,
+};
 
-static void netxbig_v2_timer_init(void)
-{
-       kirkwood_tclk = 166666667;
-       orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
+static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
+       [NETXBIG_LED_OFF]       = 0,
+       [NETXBIG_LED_ON]        = 1,
+       [NETXBIG_LED_SATA]      = NETXBIG_LED_INVALID_MODE,
+       [NETXBIG_LED_TIMER1]    = 3,
+       [NETXBIG_LED_TIMER2]    = 7,
+};
+
+static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
+       [NETXBIG_LED_OFF]       = 0,
+       [NETXBIG_LED_ON]        = 7,
+       [NETXBIG_LED_SATA]      = 1,
+       [NETXBIG_LED_TIMER1]    = 3,
+       [NETXBIG_LED_TIMER2]    = NETXBIG_LED_INVALID_MODE,
+};
+
+static struct netxbig_led_timer netxbig_v2_led_timer[] = {
+       [0] = {
+               .delay_on       = 500,
+               .delay_off      = 500,
+               .mode           = NETXBIG_LED_TIMER1,
+       },
+       [1] = {
+               .delay_on       = 500,
+               .delay_off      = 1000,
+               .mode           = NETXBIG_LED_TIMER2,
+       },
+};
+
+#define NETXBIG_LED(_name, maddr, mval, baddr)                 \
+       { .name         = _name,                                \
+         .mode_addr    = maddr,                                \
+         .mode_val     = mval,                                 \
+         .bright_addr  = baddr }
+
+static struct netxbig_led net2big_v2_leds_ctrl[] = {
+       NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+       NETXBIG_LED("net2big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+       NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net2big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+       NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net2big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+};
+
+static struct netxbig_led_platform_data net2big_v2_leds_data = {
+       .gpio_ext       = &netxbig_v2_gpio_ext,
+       .timer          = netxbig_v2_led_timer,
+       .num_timer      = ARRAY_SIZE(netxbig_v2_led_timer),
+       .leds           = net2big_v2_leds_ctrl,
+       .num_leds       = ARRAY_SIZE(net2big_v2_leds_ctrl),
+};
+
+static struct netxbig_led net5big_v2_leds_ctrl[] = {
+       NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+       NETXBIG_LED("net5big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+       NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net5big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+       NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net5big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+       NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net5big-v2:red:sata2",  5, netxbig_v2_red_mled,       2),
+       NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net5big-v2:red:sata3",  6, netxbig_v2_red_mled,       2),
+       NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
+       NETXBIG_LED("net5big-v2:red:sata5",  7, netxbig_v2_red_mled,       2),
+};
 
-struct sys_timer netxbig_v2_timer = {
-       .init = netxbig_v2_timer_init,
+static struct netxbig_led_platform_data net5big_v2_leds_data = {
+       .gpio_ext       = &netxbig_v2_gpio_ext,
+       .timer          = netxbig_v2_led_timer,
+       .num_timer      = ARRAY_SIZE(netxbig_v2_led_timer),
+       .leds           = net5big_v2_leds_ctrl,
+       .num_leds       = ARRAY_SIZE(net5big_v2_leds_ctrl),
+};
+
+static struct platform_device netxbig_v2_leds = {
+       .name           = "leds-netxbig",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &net2big_v2_leds_data,
+       },
 };
 
 /*****************************************************************************
@@ -284,18 +289,18 @@ static unsigned int net2big_v2_mpp_config[] __initdata = {
        MPP24_GPIO,             /* USB mode select */
        MPP26_GPIO,             /* USB device vbus */
        MPP28_GPIO,             /* USB enable host vbus */
-       MPP29_GPIO,             /* CPLD extension ALE */
+       MPP29_GPIO,             /* GPIO extension ALE */
        MPP34_GPIO,             /* Rear Push button */
        MPP35_GPIO,             /* Inhibit switch power-off */
        MPP36_GPIO,             /* SATA HDD1 presence */
        MPP37_GPIO,             /* SATA HDD2 presence */
        MPP40_GPIO,             /* eSATA presence */
-       MPP44_GPIO,             /* CPLD extension (data 0) */
-       MPP45_GPIO,             /* CPLD extension (data 1) */
-       MPP46_GPIO,             /* CPLD extension (data 2) */
-       MPP47_GPIO,             /* CPLD extension (addr 0) */
-       MPP48_GPIO,             /* CPLD extension (addr 1) */
-       MPP49_GPIO,             /* CPLD extension (addr 2) */
+       MPP44_GPIO,             /* GPIO extension (data 0) */
+       MPP45_GPIO,             /* GPIO extension (data 1) */
+       MPP46_GPIO,             /* GPIO extension (data 2) */
+       MPP47_GPIO,             /* GPIO extension (addr 0) */
+       MPP48_GPIO,             /* GPIO extension (addr 1) */
+       MPP49_GPIO,             /* GPIO extension (addr 2) */
        0
 };
 
@@ -324,7 +329,7 @@ static unsigned int net5big_v2_mpp_config[] __initdata = {
        MPP26_GE1_RXD2,
        MPP27_GE1_RXD3,
        MPP28_GPIO,             /* USB enable host vbus */
-       MPP29_GPIO,             /* CPLD extension ALE */
+       MPP29_GPIO,             /* GPIO extension ALE */
        MPP30_GE1_RXCTL,
        MPP31_GE1_RXCLK,
        MPP32_GE1_TCLKOUT,
@@ -339,12 +344,12 @@ static unsigned int net5big_v2_mpp_config[] __initdata = {
        MPP41_GPIO,             /* SATA HDD3 power */
        MPP42_GPIO,             /* SATA HDD4 power */
        MPP43_GPIO,             /* SATA HDD5 power */
-       MPP44_GPIO,             /* CPLD extension (data 0) */
-       MPP45_GPIO,             /* CPLD extension (data 1) */
-       MPP46_GPIO,             /* CPLD extension (data 2) */
-       MPP47_GPIO,             /* CPLD extension (addr 0) */
-       MPP48_GPIO,             /* CPLD extension (addr 1) */
-       MPP49_GPIO,             /* CPLD extension (addr 2) */
+       MPP44_GPIO,             /* GPIO extension (data 0) */
+       MPP45_GPIO,             /* GPIO extension (data 1) */
+       MPP46_GPIO,             /* GPIO extension (data 2) */
+       MPP47_GPIO,             /* GPIO extension (addr 0) */
+       MPP48_GPIO,             /* GPIO extension (addr 1) */
+       MPP49_GPIO,             /* GPIO extension (addr 2) */
        0
 };
 
@@ -366,7 +371,10 @@ static void __init netxbig_v2_init(void)
        else
                kirkwood_mpp_conf(net5big_v2_mpp_config);
 
-       netxbig_v2_sata_power_init();
+       if (machine_is_net2big_v2())
+               lacie_v2_hdd_power_init(2);
+       else
+               lacie_v2_hdd_power_init(5);
 
        kirkwood_ehci_init();
        kirkwood_ge00_init(&netxbig_v2_ge00_data);
@@ -374,13 +382,12 @@ static void __init netxbig_v2_init(void)
                kirkwood_ge01_init(&netxbig_v2_ge01_data);
        kirkwood_sata_init(&netxbig_v2_sata_data);
        kirkwood_uart0_init();
-       spi_register_board_info(netxbig_v2_spi_slave_info,
-                               ARRAY_SIZE(netxbig_v2_spi_slave_info));
-       kirkwood_spi_init();
-       kirkwood_i2c_init();
-       i2c_register_board_info(0, netxbig_v2_i2c_info,
-                               ARRAY_SIZE(netxbig_v2_i2c_info));
+       lacie_v2_register_flash();
+       lacie_v2_register_i2c_devices();
 
+       if (machine_is_net5big_v2())
+               netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
+       platform_device_register(&netxbig_v2_leds);
        platform_device_register(&netxbig_v2_gpio_buttons);
 
        if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 &&
@@ -392,24 +399,20 @@ static void __init netxbig_v2_init(void)
 
 #ifdef CONFIG_MACH_NET2BIG_V2
 MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = netxbig_v2_init,
        .map_io         = kirkwood_map_io,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &netxbig_v2_timer,
+       .timer          = &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_NET5BIG_V2
 MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = netxbig_v2_init,
        .map_io         = kirkwood_map_io,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &netxbig_v2_timer,
+       .timer          = &lacie_v2_timer,
 MACHINE_END
 #endif
index fd06be6188159da478ba8311dbec6f6b167e3df9..c9d77fad10ab854a517f78ec7c01adc35cf85c76 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -57,7 +58,22 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
+       MPP12_SD_CLK,
+       MPP13_SD_CMD,
+       MPP14_SD_D0,
+       MPP15_SD_D1,
+       MPP16_SD_D2,
+       MPP17_SD_D3,
+       MPP28_GPIO,
        MPP29_GPIO,
+       MPP34_GPIO,
+       0
+};
+
+/* Configure MPP for UART1 */
+static unsigned int openrd_uart1_mpp_config[] __initdata = {
+       MPP13_UART1_TXD,
+       MPP14_UART1_RXD,
        0
 };
 
@@ -67,6 +83,68 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
        },
 };
 
+static int __initdata uart1;
+
+static int __init sd_uart_selection(char *str)
+{
+       uart1 = -EINVAL;
+
+       /* Default is SD. Change if required, for UART */
+       if (!str)
+               return 0;
+
+       if (!strncmp(str, "232", 3)) {
+               uart1 = 232;
+       } else if (!strncmp(str, "485", 3)) {
+               /* OpenRD-Base doesn't have RS485. Treat is as an
+                * unknown argument & just have default setting -
+                * which is SD */
+               if (machine_is_openrd_base()) {
+                       uart1 = -ENODEV;
+                       return 1;
+               }
+
+               uart1 = 485;
+       }
+       return 1;
+}
+/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */
+__setup("kw_openrd_init_uart1=", sd_uart_selection);
+
+static int __init uart1_mpp_config(void)
+{
+       kirkwood_mpp_conf(openrd_uart1_mpp_config);
+
+       if (gpio_request(34, "SD_UART1_SEL")) {
+               printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
+                               ", gpio: 34\n");
+               return -EIO;
+       }
+
+       if (gpio_request(28, "RS232_RS485_SEL")) {
+               printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
+                               ", gpio# 28\n");
+               gpio_free(34);
+               return -EIO;
+       }
+
+       /* Select UART1
+        * Pin # 34: 0 => UART1, 1 => SD */
+       gpio_direction_output(34, 0);
+
+       /* Select RS232 OR RS485
+        * Pin # 28: 0 => RS232, 1 => RS485 */
+       if (uart1 == 232)
+               gpio_direction_output(28, 0);
+       else
+               gpio_direction_output(28, 1);
+
+       gpio_free(34);
+       gpio_free(28);
+
+       return 0;
+}
+
 static void __init openrd_init(void)
 {
        /*
@@ -90,7 +168,6 @@ static void __init openrd_init(void)
                kirkwood_ge01_init(&openrd_ge01_data);
 
        kirkwood_sata_init(&openrd_sata_data);
-       kirkwood_sdio_init(&openrd_mvsdio_data);
 
        kirkwood_i2c_init();
 
@@ -99,6 +176,28 @@ static void __init openrd_init(void)
                        ARRAY_SIZE(i2c_board_info));
                kirkwood_audio_init();
        }
+
+       if (uart1 <= 0) {
+               if (uart1 < 0)
+                       printk(KERN_ERR "Invalid kernel parameter to select "
+                               "UART1. Defaulting to SD. ERROR CODE: %d\n",
+                               uart1);
+
+               /* Select SD
+                * Pin # 34: 0 => UART1, 1 => SD */
+               if (gpio_request(34, "SD_UART1_SEL")) {
+                       printk(KERN_ERR "GPIO request failed for SD/UART1 "
+                                       "selection, gpio: 34\n");
+               } else {
+
+                       gpio_direction_output(34, 1);
+                       gpio_free(34);
+                       kirkwood_sdio_init(&openrd_mvsdio_data);
+               }
+       } else {
+               if (!uart1_mpp_config())
+                       kirkwood_uart1_init();
+       }
 }
 
 static int __init openrd_pci_init(void)
@@ -115,8 +214,6 @@ 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> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
@@ -128,8 +225,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_CLIENT
 MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
        /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
@@ -141,8 +236,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_ULTIMATE
 MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
        /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
index 55e7f00836b7cdba68a9662729119e977904a2dd..513ad3102d7c192d2fdc00229b6cdb527b002d87 100644 (file)
@@ -117,7 +117,7 @@ static void __init pcie0_ioresources_init(struct pcie_port *pp)
         * IORESOURCE_IO
         */
        pp->res[0].name = "PCIe 0 I/O Space";
-       pp->res[0].start = KIRKWOOD_PCIE_IO_PHYS_BASE;
+       pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
        pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
        pp->res[0].flags = IORESOURCE_IO;
 
@@ -139,7 +139,7 @@ static void __init pcie1_ioresources_init(struct pcie_port *pp)
         * IORESOURCE_IO
         */
        pp->res[0].name = "PCIe 1 I/O Space";
-       pp->res[0].start = KIRKWOOD_PCIE1_IO_PHYS_BASE;
+       pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE;
        pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
        pp->res[0].flags = IORESOURCE_IO;
 
index c34718c2cfe511373df10338e28c399a092c7744..0049614cd3245fc486dc785351f102b566ae61a7 100644 (file)
@@ -79,8 +79,6 @@ subsys_initcall(rd88f6192_pci_init);
 
 MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f6192_init,
        .map_io         = kirkwood_map_io,
index 3d1477135e12d8fb0edacb8067304a18f04bc111..0998a08cf42d84cd7712b545a5d0185abc61aa2d 100644 (file)
@@ -115,8 +115,6 @@ subsys_initcall(rd88f6281_pci_init);
 
 MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f6281_init,
        .map_io         = kirkwood_map_io,
index a00879d34d541500a88b1150256b9ffe246dd527..d2eec35dfe0f2ac94582709daed74373ae09a11a 100644 (file)
@@ -131,8 +131,6 @@ static void __init sheevaplug_init(void)
 #ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
        /* Maintainer: shadi Ammouri <shadi@marvell.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = sheevaplug_init,
        .map_io         = kirkwood_map_io,
@@ -143,8 +141,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
 MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = sheevaplug_init,
        .map_io         = kirkwood_map_io,
index d01bf89cedbe79bbcf453fda6a0be2c69e819d44..ce50e61aac9feee6c575107ea5fb3c567f2fa055 100644 (file)
@@ -184,8 +184,6 @@ subsys_initcall(hp_t5325_pci_init);
 
 MACHINE_START(T5325, "HP t5325 Thin Client")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = hp_t5325_init,
        .map_io         = kirkwood_map_io,
index a5bd7fde04a9429068f856070225cf816b96bb56..6710bd7773b8b0b1e603a52914dbbce5f4cd34bc 100644 (file)
@@ -120,8 +120,6 @@ subsys_initcall(ts219_pci_init);
 
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = qnap_ts219_init,
        .map_io         = kirkwood_map_io,
index 2e14afef07a2ace0708e144b98bf4ef1f2a446b1..8be09a0ce4ac724a8e5981dba3ab1a723f5e77f5 100644 (file)
@@ -149,8 +149,6 @@ subsys_initcall(ts41x_pci_init);
 
 MACHINE_START(TS41X, "QNAP TS-41x")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
-       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = qnap_ts41x_init,
        .map_io         = kirkwood_map_io,
index 9e3e5a640ad255c49eeeb199cc3323028d7efa5b..3ca4f8e6f54fd1cd1fb56f08723aa7b0668de44a 100644 (file)
@@ -223,8 +223,6 @@ static void __init acs5k_init(void)
 
 MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
        /* Maintainer: Simtec Electronics. */
-       .phys_io        = KS8695_IO_PA,
-       .io_pg_offst    = (KS8695_IO_VA >> 18) & 0xfffc,
        .boot_params    = KS8695_SDRAM_PA + 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
index 521ff0789f398eb641d3c8907fe55e1054ed66da..ada92b6bed24793aa2485ead10b1f03f03e19b63 100644 (file)
@@ -121,8 +121,6 @@ static void __init dsm320_init(void)
 
 MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
        /* Maintainer: Simtec Electronics. */
-       .phys_io        = KS8695_IO_PA,
-       .io_pg_offst    = (KS8695_IO_VA >> 18) & 0xfffc,
        .boot_params    = KS8695_SDRAM_PA + 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
index 8ceaf5ac6e2ca405bc4843b7f66fb8141807c8b3..c7ad09bd6ea21a02e6f95968f9d79625add4cd33 100644 (file)
@@ -53,8 +53,6 @@ static void __init micrel_init(void)
 
 MACHINE_START(KS8695, "KS8695 Centaur Development Board")
        /* Maintainer: Micrel Semiconductor Inc. */
-       .phys_io        = KS8695_IO_PA,
-       .io_pg_offst    = (KS8695_IO_VA >> 18) & 0xfffc,
        .boot_params    = KS8695_SDRAM_PA + 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
index cf2095da2372cddfb0e3105f1ab04ac4fc4fc61c..bf516adf19250d05eb020fac0be6b51611416e45 100644 (file)
 #include <mach/hardware.h>
 #include <mach/regs-uart.h>
 
-       .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                         @ MMU enabled?
-               ldreq   \rx, =KS8695_UART_PA            @ physical base address
-               ldrne   \rx, =KS8695_UART_VA            @ virtual base address
+       .macro  addruart, rp, rv
+               ldr     \rp, =KS8695_UART_PA            @ physical base address
+               ldr     \rv, =KS8695_UART_VA            @ virtual base address
        .endm
 
        .macro  senduart, rd, rx
diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..b0a2db7
--- /dev/null
@@ -0,0 +1,38 @@
+/* arch/arm/mach-l7200/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ *
+*/
+
+               .equ    io_virt, IO_BASE
+               .equ    io_phys, IO_START
+
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00044000        @ UART1
+@              mov     \rp, #0x00045000        @ UART2
+               add     \rv, \rp, #io_virt      @ virtual address
+               add     \rp, \rp, #io_phys      @ physical base address
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #0x0]        @ UARTDR
+               .endm
+
+               .macro  waituart,rd,rx
+1001:          ldr     \rd, [\rx, #0x18]       @ UARTFLG
+               tst     \rd, #1 << 5            @ UARTFLGUTXFF - 1 when full
+               bne     1001b
+               .endm
+
+               .macro  busyuart,rd,rx
+1001:          ldr     \rd, [\rx, #0x18]       @ UARTFLG
+               tst     \rd, #1 << 3            @ UARTFLGUBUSY - 1 when busy
+               bne     1001b
+               .endm
index 3d7bd50b9095ba30abc98130c86a0efd9ae86bfd..9088c16662e8082fefd39b9226ea814049f3dbd0 100644 (file)
@@ -111,8 +111,6 @@ void __init lh7a40x_init_board_irq (void)
 
 MACHINE_START (KEV7A400, "Sharp KEV7a400")
        /* Maintainer: Marc Singer */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((io_p2v (0x80000000))>>18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = kev7a400_map_io,
        .init_irq       = lh7a400_init_irq,
index cb15e5d321202690912bf33b184bfa5f9e2f7717..7315a569aea121506508b108a2b69f5babf1b5bf 100644 (file)
@@ -398,8 +398,6 @@ lpd7a40x_map_io(void)
 
 MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
        /* Maintainer: Marc Singer */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((io_p2v (0x80000000))>>18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = lpd7a40x_map_io,
        .init_irq       = lh7a400_init_irq,
@@ -413,8 +411,6 @@ MACHINE_END
 
 MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
        /* Maintainer: Marc Singer */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((io_p2v (0x80000000))>>18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = lpd7a40x_map_io,
        .init_irq       = lh7a404_init_irq,
index c0dcbbba22ba6f7eeb0af9893579f7aedc870879..cff33625276faa4bb4f6d78fbe9a9163cd9430d2 100644 (file)
        @ It is not known if this will be appropriate for every 40x
        @ board.
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               mov     \rx, #0x00000700        @ offset from base
-               orreq   \rx, \rx, #0x80000000   @ physical base
-               orrne   \rx, \rx, #0xf8000000   @ virtual base
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00000700        @ offset from base
+               orr     \rv, \rp, #0xf8000000   @ virtual base
+               orr     \rp, \rp, #0x80000000   @ physical base
                .endm
 
                .macro  senduart,rd,rx
index 3136c913a92c2c4886cbcd232f145f9aac2572f2..cc90d99ac76ce8419e8d12079afb9c72a4ca2618 100644 (file)
@@ -8,12 +8,11 @@
 
 #include <mach/loki.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =LOKI_REGS_PHYS_BASE
-       ldrne   \rx, =LOKI_REGS_VIRT_BASE
-       orr     \rx, \rx, #0x00012000
+       .macro  addruart, rp, rv
+       ldr     \rp, =LOKI_REGS_PHYS_BASE
+       ldr     \rv, =LOKI_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
        .endm
 
 #define UART_SHIFT     2
index 85f9c1296aa02675d7c131a85e8c12161a437919..a1e75e7fc50092d9b4e6268c5464ec4524349ded 100644 (file)
@@ -90,8 +90,6 @@ static void __init lb88rc8480_init(void)
 
 MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
        /* Maintainer: Ke Wei <kewei@marvell.com> */
-       .phys_io        = LOKI_REGS_PHYS_BASE,
-       .io_pg_offst    = ((LOKI_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = lb88rc8480_init,
        .map_io         = loki_map_io,
index 621744d6b15205954bbad0980b89a2315c343d3f..629e744aeb9e980dd1c4ad2c5b9c7ba16274ff16 100644 (file)
  * Debug output is hardcoded to standard UART 5
 */
 
-       .macro  addruart,rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                         @ MMU enabled?
-       ldreq   \rx, =0x40090000
-       ldrne   \rx, =0xF4090000
+       .macro  addruart, rp, rv
+       ldreq   \rp, =0x40090000
+       ldrne   \rv, =0xF4090000
        .endm
 
 #define UART_SHIFT     2
index bc9a42da21452b7c77cac895d2f9ab97471eb12e..7993b096778e1f49c9d44d3e2762dd58b4233678 100644 (file)
@@ -172,18 +172,12 @@ static void phy3250_spi_cs_set(u32 control)
 }
 
 static struct pl022_config_chip spi0_chip_info = {
-       .lbm                    = LOOPBACK_DISABLED,
        .com_mode               = INTERRUPT_TRANSFER,
        .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
        .hierarchy              = SSP_MASTER,
        .slave_tx_disable       = 0,
-       .endian_tx              = SSP_TX_LSB,
-       .endian_rx              = SSP_RX_LSB,
-       .data_size              = SSP_DATA_BITS_8,
        .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
        .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .clk_phase              = SSP_CLK_FIRST_EDGE,
-       .clk_pol                = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len               = SSP_BITS_8,
        .wait_state             = SSP_MWIRE_WAIT_ZERO,
        .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -239,6 +233,7 @@ static int __init phy3250_spi_board_register(void)
                        .max_speed_hz = 5000000,
                        .bus_num = 0,
                        .chip_select = 0,
+                       .mode = SPI_MODE_0,
                        .platform_data = &eeprom,
                        .controller_data = &spi0_chip_info,
                },
@@ -387,8 +382,6 @@ arch_initcall(lpc32xx_display_uid);
 
 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
        /* Maintainer: Kevin Wells, NXP Semiconductors */
-       .phys_io        = LPC32XX_UART5_BASE,
-       .io_pg_offst    = ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = lpc32xx_map_io,
        .init_irq       = lpc32xx_init_irq,
index 6ab843eaa35b507b5df31773ecc6fe5a60200b23..0711d3b620ad2286ea5aaabd035fbc1e19627e81 100644 (file)
@@ -57,6 +57,13 @@ config MACH_MARVELL_JASPER
          PXA910-based development board. Since MMP2 is compatible to
          ARMv6 architecture.
 
+config MACH_TETON_BGA
+       bool "Marvell's PXA168 Teton BGA Development Board"
+       select CPU_PXA168
+       help
+         Say 'Y' here if you want to support the Marvell PXA168-based
+         Teton BGA Development Board.
+
 endmenu
 
 config CPU_PXA168
index 8b66d06739c4d9c02ea1c03e98b1d23548894e8d..751cdbf733c852c5970e77e32013d28931b0113e 100644 (file)
@@ -17,3 +17,4 @@ obj-$(CONFIG_MACH_TAVOREVB)   += tavorevb.o
 obj-$(CONFIG_MACH_TTC_DKB)     += ttc_dkb.o
 obj-$(CONFIG_MACH_FLINT)       += flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
+obj-$(CONFIG_MACH_TETON_BGA)   += teton_bga.o
index 0629394a5fb9ad3dce6b73f0298a9ae56f52310f..06b5fa853c9325b81548378a7978a29cbe898a88 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -23,6 +24,9 @@
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
 #include <mach/gpio.h>
+#include <video/pxa168fb.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "common.h"
 
@@ -66,6 +70,43 @@ static unsigned long common_pin_config[] __initdata = {
        GPIO115_I2S_BCLK,
        GPIO116_I2S_RXD,
        GPIO117_I2S_TXD,
+
+       /* LCD */
+       GPIO56_LCD_FCLK_RD,
+       GPIO57_LCD_LCLK_A0,
+       GPIO58_LCD_PCLK_WR,
+       GPIO59_LCD_DENA_BIAS,
+       GPIO60_LCD_DD0,
+       GPIO61_LCD_DD1,
+       GPIO62_LCD_DD2,
+       GPIO63_LCD_DD3,
+       GPIO64_LCD_DD4,
+       GPIO65_LCD_DD5,
+       GPIO66_LCD_DD6,
+       GPIO67_LCD_DD7,
+       GPIO68_LCD_DD8,
+       GPIO69_LCD_DD9,
+       GPIO70_LCD_DD10,
+       GPIO71_LCD_DD11,
+       GPIO72_LCD_DD12,
+       GPIO73_LCD_DD13,
+       GPIO74_LCD_DD14,
+       GPIO75_LCD_DD15,
+       GPIO76_LCD_DD16,
+       GPIO77_LCD_DD17,
+       GPIO78_LCD_DD18,
+       GPIO79_LCD_DD19,
+       GPIO80_LCD_DD20,
+       GPIO81_LCD_DD21,
+       GPIO82_LCD_DD22,
+       GPIO83_LCD_DD23,
+
+       /* Keypad */
+       GPIO109_KP_MKIN1,
+       GPIO110_KP_MKIN0,
+       GPIO111_KP_MKOUT7,
+       GPIO112_KP_MKOUT6,
+       GPIO121_KP_MKIN4,
 };
 
 static struct smc91x_platdata smc91x_info = {
@@ -134,6 +175,51 @@ static struct i2c_board_info aspenite_i2c_info[] __initdata = {
        { I2C_BOARD_INFO("wm8753", 0x1b), },
 };
 
+static struct fb_videomode video_modes[] = {
+       [0] = {
+               .pixclock       = 30120,
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .hsync_len      = 1,
+               .left_margin    = 215,
+               .right_margin   = 40,
+               .vsync_len      = 1,
+               .upper_margin   = 34,
+               .lower_margin   = 10,
+               .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+       },
+};
+
+struct pxa168fb_mach_info aspenite_lcd_info = {
+       .id                     = "Graphic Frame",
+       .modes                  = video_modes,
+       .num_modes              = ARRAY_SIZE(video_modes),
+       .pix_fmt                = PIX_FMT_RGB565,
+       .io_pin_allocation_mode = PIN_MODE_DUMB_24,
+       .dumb_mode              = DUMB_MODE_RGB888,
+       .active                 = 1,
+       .panel_rbswap           = 0,
+       .invert_pixclock        = 0,
+};
+
+static unsigned int aspenite_matrix_key_map[] = {
+       KEY(0, 6, KEY_UP),      /* SW 4 */
+       KEY(0, 7, KEY_DOWN),    /* SW 5 */
+       KEY(1, 6, KEY_LEFT),    /* SW 6 */
+       KEY(1, 7, KEY_RIGHT),   /* SW 7 */
+       KEY(4, 6, KEY_ENTER),   /* SW 8 */
+       KEY(4, 7, KEY_ESC),     /* SW 9 */
+};
+
+static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
+       .matrix_key_rows        = 5,
+       .matrix_key_cols        = 8,
+       .matrix_key_map         = aspenite_matrix_key_map,
+       .matrix_key_map_size    = ARRAY_SIZE(aspenite_matrix_key_map),
+       .debounce_interval      = 30,
+};
+
 static void __init common_init(void)
 {
        mfp_config(ARRAY_AND_SIZE(common_pin_config));
@@ -143,24 +229,24 @@ static void __init common_init(void)
        pxa168_add_twsi(1, NULL, ARRAY_AND_SIZE(aspenite_i2c_info));
        pxa168_add_ssp(1);
        pxa168_add_nand(&aspenite_nand_info);
+       pxa168_add_fb(&aspenite_lcd_info);
+       pxa168_add_keypad(&aspenite_keypad_info);
 
        /* off-chip devices */
        platform_device_register(&smc91x_device);
 }
 
 MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
+       .nr_irqs        = IRQ_BOARD_START,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
 MACHINE_END
 
 MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
+       .nr_irqs        = IRQ_BOARD_START,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
index 69bcba11f53f94d8cd5ee6d8f4f0a67d17847a70..39f0878d64a0c39ba026c2be0f20755576d75045 100644 (file)
@@ -41,8 +41,6 @@ static void __init avengers_lite_init(void)
 }
 
 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
index 3b29fa7e9b084c1c3891aea452d1e5cda5c35a03..0ec0ca80bb3ed4e87300030484ee21fa9ac6177a 100644 (file)
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <mach/addr-map.h>
+#include <mach/cputype.h>
 
 #include "common.h"
 
+#define MMP_CHIPID     (AXI_VIRT_BASE + 0x82c00)
+
+unsigned int mmp_chip_id;
+EXPORT_SYMBOL(mmp_chip_id);
+
 static struct map_desc standard_io_desc[] __initdata = {
        {
                .pfn            = __phys_to_pfn(APB_PHYS_BASE),
@@ -34,4 +41,7 @@ static struct map_desc standard_io_desc[] __initdata = {
 void __init mmp_map_io(void)
 {
        iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+
+       /* this is early, initialize mmp_chip_id here */
+       mmp_chip_id = __raw_readl(MMP_CHIPID);
 }
index e4312d238eae3ec4e3a4b9a93564a5a265619549..bdeb6db4d49a1a143396abcaec6b7fe3552a2946 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/smc91x.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,6 +26,8 @@
 
 #include "common.h"
 
+#define FLINT_NR_IRQS  (IRQ_BOARD_START + 48)
+
 static unsigned long flint_pin_config[] __initdata = {
        /* UART1 */
        GPIO45_UART1_RXD,
@@ -113,9 +116,8 @@ static void __init flint_init(void)
 }
 
 MACHINE_START(FLINT, "Flint Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
+       .nr_irqs        = FLINT_NR_IRQS,
        .init_irq       = mmp2_init_irq,
        .timer          = &mmp2_timer,
        .init_machine   = flint_init,
index 83b18721d93305f6c9f47b0989e21b3e2006b0e5..f43a68b213f111a200e0395638e3cc538e442b3e 100644 (file)
@@ -4,36 +4,51 @@
 #include <asm/cputype.h>
 
 /*
- *  CPU   Stepping   OLD_ID       CPU_ID      CHIP_ID
+ *  CPU   Stepping   CPU_ID      CHIP_ID
  *
- * PXA168    A0    0x41159263   0x56158400   0x00A0A333
- * PXA910    Y0    0x41159262   0x56158000   0x00F0C910
- * MMP2             Z0                 0x560f5811
+ * PXA168    S0    0x56158400   0x0000C910
+ * PXA168    A0    0x56158400   0x00A0A168
+ * PXA910    Y1    0x56158400   0x00F2C920
+ * PXA910    A0    0x56158400   0x00F2C910
+ * PXA910    A1    0x56158400   0x00A0C910
+ * PXA920    Y0    0x56158400   0x00F2C920
+ * PXA920    A0    0x56158400   0x00A0C920
+ * PXA920    A1    0x56158400   0x00A1C920
+ * MMP2             Z0    0x560f5811   0x00F00410
+ * MMP2      Z1    0x560f5811   0x00E00410
+ * MMP2      A0    0x560f5811   0x00A0A610
  */
 
+extern unsigned int mmp_chip_id;
+
 #ifdef CONFIG_CPU_PXA168
-#  define __cpu_is_pxa168(id)  \
-       ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; })
+static inline int cpu_is_pxa168(void)
+{
+       return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+               ((mmp_chip_id & 0xfff) == 0x168);
+}
 #else
-#  define __cpu_is_pxa168(id)  (0)
+#define cpu_is_pxa168()        (0)
 #endif
 
+/* cpu_is_pxa910() is shared on both pxa910 and pxa920 */
 #ifdef CONFIG_CPU_PXA910
-#  define __cpu_is_pxa910(id)  \
-       ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; })
+static inline int cpu_is_pxa910(void)
+{
+       return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+               (((mmp_chip_id & 0xfff) == 0x910) ||
+                ((mmp_chip_id & 0xfff) == 0x920));
+}
 #else
-#  define __cpu_is_pxa910(id)  (0)
+#define cpu_is_pxa910()        (0)
 #endif
 
 #ifdef CONFIG_CPU_MMP2
-#  define __cpu_is_mmp2(id)    \
-       ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x58; })
+static inline int cpu_is_mmp2(void)
+{
+       return (((cpu_readid_id() >> 8) & 0xff) == 0x58);
 #else
-#  define __cpu_is_mmp2(id)    (0)
+#define cpu_is_mmp2()  (0)
 #endif
 
-#define cpu_is_pxa168()                ({ __cpu_is_pxa168(read_cpuid_id()); })
-#define cpu_is_pxa910()                ({ __cpu_is_pxa910(read_cpuid_id()); })
-#define cpu_is_mmp2()          ({ __cpu_is_mmp2(read_cpuid_id()); })
-
 #endif /* __ASM_MACH_CPUTYPE_H */
index 76deff238e1c5f394505a0a413d3fb98577d0645..7e2ebd3efc7c0ba900ced458e0268cb99c166975 100644 (file)
 
 #include <mach/addr-map.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                         @ MMU enabled?
-               ldreq   \rx, =APB_PHYS_BASE             @ physical
-               ldrne   \rx, =APB_VIRT_BASE             @ virtual
-               orr     \rx, \rx, #0x00017000
+               .macro  addruart, rp, rv
+               ldr     \rp, =APB_PHYS_BASE             @ physical
+               ldr     \rv, =APB_VIRT_BASE             @ virtual
+               orr     \rp, \rp, #0x00017000
+               orr     \rv, \rv, #0x00017000
                .endm
 
 #define UART_SHIFT     2
index b379cdec4d38410d9caeedf927b6d8cbae4c9ef6..a09d328e2ddd02087cdd7d08c68d6950b0ff6250 100644 (file)
 #define IRQ_GPIO_NUM                   192
 #define IRQ_GPIO(x)                    (IRQ_GPIO_START + (x))
 
-/* Board IRQ - 64 by default, increase if not enough */
 #define IRQ_BOARD_START                        (IRQ_GPIO_START + IRQ_GPIO_NUM)
-#define IRQ_BOARD_END                  (IRQ_BOARD_START + 64)
 
-#define NR_IRQS                                (IRQ_BOARD_END)
+#define NR_IRQS                                (IRQ_BOARD_START)
 
 #endif /* __ASM_MACH_IRQS_H */
index ded43c455ec39870dab17e0da05d2c36d5a91329..4621067c7720f457b311faff80e19dddc87ecd3e 100644 (file)
 #define GPIO86_PWM1_OUT                MFP_CFG(GPIO86, AF2)
 #define GPIO86_PWM2_OUT                MFP_CFG(GPIO86, AF3)
 
+/* Keypad */
+#define GPIO109_KP_MKIN1        MFP_CFG(GPIO109, AF7)
+#define GPIO110_KP_MKIN0        MFP_CFG(GPIO110, AF7)
+#define GPIO111_KP_MKOUT7       MFP_CFG(GPIO111, AF7)
+#define GPIO112_KP_MKOUT6       MFP_CFG(GPIO112, AF7)
+#define GPIO121_KP_MKIN4        MFP_CFG(GPIO121, AF7)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
index 27e1bc758623808cb30ed6471ca2d45fb2b40dbd..1801e420623259a6a4004dd0f8f9ba280997fc0a 100644 (file)
@@ -5,11 +5,15 @@ struct sys_timer;
 
 extern struct sys_timer pxa168_timer;
 extern void __init pxa168_init_irq(void);
+extern void pxa168_clear_keypad_wakeup(void);
 
 #include <linux/i2c.h>
 #include <mach/devices.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
+#include <video/pxa168fb.h>
+#include <plat/pxa27x_keypad.h>
+#include <mach/cputype.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
@@ -25,6 +29,8 @@ extern struct pxa_device_desc pxa168_device_ssp3;
 extern struct pxa_device_desc pxa168_device_ssp4;
 extern struct pxa_device_desc pxa168_device_ssp5;
 extern struct pxa_device_desc pxa168_device_nand;
+extern struct pxa_device_desc pxa168_device_fb;
+extern struct pxa_device_desc pxa168_device_keypad;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -97,4 +103,18 @@ static inline int pxa168_add_nand(struct pxa3xx_nand_platform_data *info)
 {
        return pxa_register_device(&pxa168_device_nand, info, sizeof(*info));
 }
+
+static inline int pxa168_add_fb(struct pxa168fb_mach_info *mi)
+{
+       return pxa_register_device(&pxa168_device_fb, mi, sizeof(*mi));
+}
+
+static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
+{
+       if (cpu_is_pxa168())
+               data->clear_wakeup_event = pxa168_clear_keypad_wakeup;
+
+       return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_PXA168_H */
index 9190305141201cf5d99aead14375420c38b7d4ca..ac4702357a6e5b026d8939bdd93fdad9c2ed2c6d 100644 (file)
 #define APMU_FNRST_DIS (1 << 1)
 #define APMU_AXIRST_DIS        (1 << 0)
 
+/* Wake Clear Register */
+#define APMU_WAKE_CLR  APMU_REG(0x07c)
+
+#define APMU_PXA168_KP_WAKE_CLR                (1 << 7)
+#define APMU_PXA168_CFI_WAKE_CLR       (1 << 6)
+#define APMU_PXA168_XD_WAKE_CLR                (1 << 5)
+#define APMU_PXA168_MSP_WAKE_CLR       (1 << 4)
+#define APMU_PXA168_SD4_WAKE_CLR       (1 << 3)
+#define APMU_PXA168_SD3_WAKE_CLR       (1 << 2)
+#define APMU_PXA168_SD2_WAKE_CLR       (1 << 1)
+#define APMU_PXA168_SD1_WAKE_CLR       (1 << 0)
+
 #endif /* __ASM_MACH_REGS_APMU_H */
index 4f5b0e0ce6cf8f87e0e843b82ce2f8b0b4cbc34c..1a8a25edb1b422ace6925e07171953390b51bc11 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __ASM_MACH_SYSTEM_H
 #define __ASM_MACH_SYSTEM_H
 
+#include <mach/cputype.h>
+
 static inline void arch_idle(void)
 {
        cpu_do_idle();
@@ -16,6 +18,9 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode, const char *cmd)
 {
-       cpu_reset(0);
+       if (cpu_is_pxa168())
+               cpu_reset(0xffff0000);
+       else
+               cpu_reset(0);
 }
 #endif /* __ASM_MACH_SYSTEM_H */
diff --git a/arch/arm/mach-mmp/include/mach/teton_bga.h b/arch/arm/mach-mmp/include/mach/teton_bga.h
new file mode 100644 (file)
index 0000000..61a539b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  linux/arch/arm/mach-mmp/include/mach/teton_bga.h
+ *
+ *  Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+#ifndef __ASM_MACH_TETON_BGA_H
+#define __ASM_MACH_TETON_BGA_H
+
+/* GPIOs */
+#define MMC_PWENA_GPIO         27
+#define USBHPENB_GPIO          55
+#define RTC_INT_GPIO           78
+#define LCD_VBLK_EN_GPIO       79
+#define LCD_DVDD_EN_GPIO       80
+#define RST_WIFI_GPIO          81
+#define CF_PWEN_GPIO           82
+#define USB_OC_GPIO            83
+#define PWM_GPIO               84
+#define USBHPENA_GPIO          85
+#define TS_INT_GPIO            86
+#define CIR_GPIO               108
+
+#endif /* __ASM_MACH_TETON_BGA_H */
index 80c3e7ab1e1700c2aa96bdb9270b0e5a57004b3f..2a684fa50773cebc8a57e1d470840f1bfd5d8d31 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/mfd/max8925.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-mmp2.h>
 #include <mach/mmp2.h>
-#include <mach/irqs.h>
 
 #include "common.h"
 
+#define JASPER_NR_IRQS         (IRQ_BOARD_START + 48)
+
 static unsigned long jasper_pin_config[] __initdata = {
        /* UART1 */
        GPIO29_UART1_RXD,
@@ -134,9 +136,8 @@ static void __init jasper_init(void)
 }
 
 MACHINE_START(MARVELL_JASPER, "Jasper Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
+       .nr_irqs        = JASPER_NR_IRQS,
        .init_irq       = mmp2_init_irq,
        .timer          = &mmp2_timer,
        .init_machine   = jasper_init,
index 652ae660634c5fcd8409972994bd3f97d20acba2..72b4e76315830e91b9dad19dfdedcdf829021559 100644 (file)
@@ -77,8 +77,10 @@ static APBC_CLK(ssp2, PXA168_SSP2, 4, 0);
 static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
 static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
 static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
+static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
 
 static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(lcd, LCD, 0x7f, 312000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
@@ -96,6 +98,8 @@ static struct clk_lookup pxa168_clkregs[] = {
        INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL),
        INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL),
        INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+       INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
+       INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
 };
 
 static int __init pxa168_init(void)
@@ -132,6 +136,16 @@ struct sys_timer pxa168_timer = {
        .init   = pxa168_timer_init,
 };
 
+void pxa168_clear_keypad_wakeup(void)
+{
+       uint32_t val;
+       uint32_t mask = APMU_PXA168_KP_WAKE_CLR;
+
+       /* wake event clear is needed in order to clear keypad interrupt */
+       val = __raw_readl(APMU_WAKE_CLR);
+       __raw_writel(val |  mask, APMU_WAKE_CLR);
+}
+
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
@@ -147,3 +161,5 @@ PXA168_DEVICE(ssp2, "pxa168-ssp", 1, SSP2, 0xd401c000, 0x40, 54, 55);
 PXA168_DEVICE(ssp3, "pxa168-ssp", 2, SSP3, 0xd401f000, 0x40, 56, 57);
 PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
 PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
+PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
+PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
index e81db7428215608ee2ade0281a755f9226983411..c296b75c4453de76f0757329baffb677b56dda5c 100644 (file)
@@ -99,8 +99,6 @@ static void __init tavorevb_init(void)
 }
 
 MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
        .init_irq       = pxa910_init_irq,
        .timer          = &pxa910_timer,
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
new file mode 100644 (file)
index 0000000..bbe4727
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  linux/arch/arm/mach-mmp/teton_bga.c
+ *
+ *  Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ *  Author: Mark F. Brown <mark.brown314@gmail.com>
+ *
+ *  This code is based on aspenite.c
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/pxa168.h>
+#include <mach/teton_bga.h>
+
+#include "common.h"
+
+static unsigned long teton_bga_pin_config[] __initdata = {
+       /* UART1 */
+       GPIO107_UART1_TXD,
+       GPIO108_UART1_RXD,
+
+       /* Keypad */
+       GPIO109_KP_MKIN1,
+       GPIO110_KP_MKIN0,
+       GPIO111_KP_MKOUT7,
+       GPIO112_KP_MKOUT6,
+
+       /* I2C Bus */
+       GPIO105_CI2C_SDA,
+       GPIO106_CI2C_SCL,
+
+       /* RTC */
+       GPIO78_GPIO,
+};
+
+static unsigned int teton_bga_matrix_key_map[] = {
+       KEY(0, 6, KEY_ESC),
+       KEY(0, 7, KEY_ENTER),
+       KEY(1, 6, KEY_LEFT),
+       KEY(1, 7, KEY_RIGHT),
+};
+
+static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
+       .matrix_key_rows        = 2,
+       .matrix_key_cols        = 8,
+       .matrix_key_map         = teton_bga_matrix_key_map,
+       .matrix_key_map_size    = ARRAY_SIZE(teton_bga_matrix_key_map),
+       .debounce_interval      = 30,
+};
+
+static struct i2c_board_info teton_bga_i2c_info[] __initdata = {
+       {
+               I2C_BOARD_INFO("ds1337", 0x68),
+               .irq = gpio_to_irq(RTC_INT_GPIO)
+       },
+};
+
+static void __init teton_bga_init(void)
+{
+       mfp_config(ARRAY_AND_SIZE(teton_bga_pin_config));
+
+       /* on-chip devices */
+       pxa168_add_uart(1);
+       pxa168_add_keypad(&teton_bga_keypad_info);
+       pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info));
+}
+
+MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
+       .map_io         = mmp_map_io,
+       .nr_irqs        = IRQ_BOARD_START,
+       .init_irq       = pxa168_init_irq,
+       .timer          = &pxa168_timer,
+       .init_machine   = teton_bga_init,
+MACHINE_END
index ee65e05f0cf15e0118461ce4a7b277e5038a77c2..e411039ea59e3f2911513ca4353c8b9ce87312ac 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -24,6 +25,8 @@
 
 #include "common.h"
 
+#define TTCDKB_NR_IRQS         (IRQ_BOARD_START + 24)
+
 static unsigned long ttc_dkb_pin_config[] __initdata = {
        /* UART2 */
        GPIO47_UART2_RXD,
@@ -122,9 +125,8 @@ static void __init ttc_dkb_init(void)
 }
 
 MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
-       .phys_io        = APB_PHYS_BASE,
-       .io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
        .map_io         = mmp_map_io,
+       .nr_irqs        = TTCDKB_NR_IRQS,
        .init_irq       = pxa910_init_irq,
        .timer          = &pxa910_timer,
        .init_machine   = ttc_dkb_init,
index 47264a76eeb31d52602ca9386960d4cbf0a012fb..3115a29dec4ea58b867cfa0dab424833ecbf7e5f 100644 (file)
@@ -10,6 +10,8 @@ config ARCH_MSM7X00A
        select MSM_SMD
        select MSM_SMD_PKG3
        select CPU_V6
+       select MSM_PROC_COMM
+       select HAS_MSM_DEBUG_UART_PHYS
 
 config ARCH_MSM7X30
        bool "MSM7x30"
@@ -18,6 +20,9 @@ config ARCH_MSM7X30
        select MSM_VIC
        select CPU_V7
        select MSM_REMOTE_SPINLOCK_DEKKERS
+       select MSM_GPIOMUX
+       select MSM_PROC_COMM
+       select HAS_MSM_DEBUG_UART_PHYS
 
 config ARCH_QSD8X50
        bool "QSD8X50"
@@ -26,6 +31,19 @@ config ARCH_QSD8X50
        select MSM_VIC
        select CPU_V7
        select MSM_REMOTE_SPINLOCK_LDREX
+       select MSM_GPIOMUX
+       select MSM_PROC_COMM
+       select HAS_MSM_DEBUG_UART_PHYS
+
+config ARCH_MSM8X60
+       bool "MSM8X60"
+       select ARM_GIC
+       select CPU_V7
+       select MSM_V2_TLMM
+       select MSM_GPIOMUX
+       select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
+                                 && !MACH_MSM8X60_FFA)
+
 endchoice
 
 config MSM_SOC_REV_A
@@ -36,6 +54,9 @@ config  ARCH_MSM_ARM11
 config  ARCH_MSM_SCORPION
        bool
 
+config HAS_MSM_DEBUG_UART_PHYS
+       bool
+
 config  MSM_VIC
        bool
 
@@ -74,6 +95,30 @@ config MACH_QSD8X50A_ST1_5
        help
          Support for the Qualcomm ST1.5.
 
+config MACH_MSM8X60_RUMI3
+       depends on ARCH_MSM8X60
+       bool "MSM8x60 RUMI3"
+       help
+         Support for the Qualcomm MSM8x60 RUMI3 emulator.
+
+config MACH_MSM8X60_SURF
+       depends on ARCH_MSM8X60
+       bool "MSM8x60 SURF"
+       help
+         Support for the Qualcomm MSM8x60 SURF eval board.
+
+config MACH_MSM8X60_SIM
+       depends on ARCH_MSM8X60
+       bool "MSM8x60 Simulator"
+       help
+         Support for the Qualcomm MSM8x60 simulator.
+
+config MACH_MSM8X60_FFA
+       depends on ARCH_MSM8X60
+       bool "MSM8x60 FFA"
+       help
+         Support for the Qualcomm MSM8x60 FFA eval board.
+
 endmenu
 
 config MSM_DEBUG_UART
@@ -82,6 +127,7 @@ config MSM_DEBUG_UART
        default 2 if MSM_DEBUG_UART2
        default 3 if MSM_DEBUG_UART3
 
+if HAS_MSM_DEBUG_UART_PHYS
 choice
        prompt "Debug UART"
 
@@ -99,11 +145,20 @@ choice
        config MSM_DEBUG_UART3
                bool "UART3"
 endchoice
+endif
 
 config MSM_SMD_PKG3
        bool
 
+config MSM_PROC_COMM
+       bool
+
 config MSM_SMD
        bool
 
+config MSM_GPIOMUX
+       bool
+
+config MSM_V2_TLMM
+       bool
 endif
index 704610648a255870d5b959899d1f1f0b3a8259d4..b5a7b07a44f53c9652048d10157f7a24745c53a2 100644 (file)
@@ -1,16 +1,20 @@
-obj-y += proc_comm.o
-obj-y += io.o idle.o timer.o dma.o
-obj-y += vreg.o
+obj-y += io.o idle.o timer.o
+ifndef CONFIG_ARCH_MSM8X60
 obj-y += acpuclock-arm11.o
-obj-y += clock.o clock-pcom.o
-obj-y += gpio.o
+obj-y += dma.o
+endif
 
 ifdef CONFIG_MSM_VIC
 obj-y += irq-vic.o
 else
+ifndef CONFIG_ARCH_MSM8X60
 obj-y += irq.o
 endif
+endif
 
+obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
+obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
+obj-$(CONFIG_MSM_PROC_COMM) += clock.o
 obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
@@ -19,4 +23,11 @@ obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o d
 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
+obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
 
+obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
+ifndef CONFIG_MSM_V2_TLMM
+obj-y  += gpio.o
+endif
index 7bd72e8f127ea39f8a7ee222241552a7b98eb2c3..59edecbe126cc5ab6df4d925ff19458a06167537 100644 (file)
@@ -95,8 +95,6 @@ static void __init halibut_map_io(void)
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = 0x10000100,
        .fixup          = halibut_fixup,
index bcbefdfe7b5e582052fb14334085567c7ef91de5..ef3ebf2f763be9c660554f4c6189aa67028a2ea0 100644 (file)
@@ -75,8 +75,6 @@ extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = 0x20000100,
        .fixup          = mahimahi_fixup,
index db9381b85bf031542e1fca1837d15b68242aa201..e7a76eff57d93c878d45294f140038e076e64be3 100644 (file)
@@ -131,8 +131,6 @@ static void __init msm7x2x_map_io(void)
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = PHYS_OFFSET + 0x100,
        .map_io         = msm7x2x_map_io,
@@ -143,8 +141,6 @@ MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = PHYS_OFFSET + 0x100,
        .map_io         = msm7x2x_map_io,
@@ -155,8 +151,6 @@ MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = PHYS_OFFSET + 0x100,
        .map_io         = msm7x2x_map_io,
@@ -167,8 +161,6 @@ MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = PHYS_OFFSET + 0x100,
        .map_io         = msm7x2x_map_io,
index e32981928c7701e2032414d69ef099fd6a1bd9db..05241df3f9b6b3a4dd829029d6b97943549b824d 100644 (file)
 
 extern struct sys_timer msm_timer;
 
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-static struct msm_gpio uart2_config_data[] = {
-       { GPIO_CFG(49, 2, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_RFR"},
-       { GPIO_CFG(50, 2, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_CTS"},
-       { GPIO_CFG(51, 2, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
-       { GPIO_CFG(52, 2, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
-};
-
-static void msm7x30_init_uart2(void)
-{
-       msm_gpios_request_enable(uart2_config_data,
-                       ARRAY_SIZE(uart2_config_data));
-
-}
-#endif
-
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
 #endif
-
+       &msm_device_smd,
 };
 
 static void __init msm7x30_init_irq(void)
@@ -70,10 +54,6 @@ static void __init msm7x30_init_irq(void)
 static void __init msm7x30_init(void)
 {
        platform_add_devices(devices, ARRAY_SIZE(devices));
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-       msm7x30_init_uart2();
-#endif
-
 }
 
 static void __init msm7x30_map_io(void)
@@ -84,8 +64,6 @@ static void __init msm7x30_map_io(void)
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io  = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = msm7x30_map_io,
@@ -96,8 +74,6 @@ MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io  = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = msm7x30_map_io,
@@ -108,8 +84,6 @@ MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io  = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = msm7x30_map_io,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
new file mode 100644 (file)
index 0000000..7486a68
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+
+void __iomem *gic_cpu_base_addr;
+
+unsigned long clk_get_max_axi_khz(void)
+{
+       return 0;
+}
+
+static void __init msm8x60_map_io(void)
+{
+       msm_map_msm8x60_io();
+}
+
+static void __init msm8x60_init_irq(void)
+{
+       unsigned int i;
+
+       gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
+       gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
+       gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+
+       /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+       writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+       /* RUMI does not adhere to GIC spec by enabling STIs by default.
+        * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
+        */
+       if (!machine_is_msm8x60_sim())
+               writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+
+       /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+        * as they are configured as level, which does not play nice with
+        * handle_percpu_irq.
+        */
+       for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+               if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+                       set_irq_handler(i, handle_percpu_irq);
+       }
+}
+
+static void __init msm8x60_init(void)
+{
+}
+
+MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+       .map_io = msm8x60_map_io,
+       .init_irq = msm8x60_init_irq,
+       .init_machine = msm8x60_init,
+       .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+       .map_io = msm8x60_map_io,
+       .init_irq = msm8x60_init_irq,
+       .init_machine = msm8x60_init,
+       .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+       .map_io = msm8x60_map_io,
+       .init_irq = msm8x60_init_irq,
+       .init_machine = msm8x60_init,
+       .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+       .map_io = msm8x60_map_io,
+       .init_irq = msm8x60_init_irq,
+       .init_machine = msm8x60_init,
+       .timer = &msm_timer,
+MACHINE_END
index e3cc80792d6c2bafbcb9bb68ce9505434d71c176..ed2af4ad97ed22db1d0829da48e2770796bcb966 100644 (file)
 
 extern struct sys_timer msm_timer;
 
-static struct msm_gpio uart3_config_data[] = {
-       { GPIO_CFG(86, 1, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
-       { GPIO_CFG(87, 1, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
+static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
+static const unsigned        qsd8x50_surf_smc91x_gpio __initdata = 156;
+
+/* Leave smc91x resources empty here, as we'll fill them in
+ * at run-time: they vary from board to board, and the true
+ * configuration won't be known until boot.
+ */
+static struct resource smc91x_resources[] __initdata = {
+       [0] = {
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .flags = IORESOURCE_IRQ,
+       },
 };
 
-static struct platform_device *devices[] __initdata = {
-       &msm_device_uart3,
+static struct platform_device smc91x_device __initdata = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
 };
 
-static void msm8x50_init_uart3(void)
+static int __init msm_init_smc91x(void)
 {
-       msm_gpios_request_enable(uart3_config_data,
-                               ARRAY_SIZE(uart3_config_data));
+       if (machine_is_qsd8x50_surf()) {
+               smc91x_resources[0].start = qsd8x50_surf_smc91x_base;
+               smc91x_resources[0].end   = qsd8x50_surf_smc91x_base + 0xff;
+               smc91x_resources[1].start =
+                       gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+               smc91x_resources[1].end   =
+                       gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+               platform_device_register(&smc91x_device);
+       }
+
+       return 0;
 }
+module_init(msm_init_smc91x);
+
+static struct platform_device *devices[] __initdata = {
+       &msm_device_uart3,
+       &msm_device_smd,
+};
 
 static void __init qsd8x50_map_io(void)
 {
@@ -64,14 +93,11 @@ static void __init qsd8x50_init_irq(void)
 
 static void __init qsd8x50_init(void)
 {
-       msm8x50_init_uart3();
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io  = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = qsd8x50_map_io,
@@ -82,8 +108,6 @@ MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io  = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = qsd8x50_map_io,
index 2bc1b9d5623e4e1871d2ab81d9e3e0faf5573218..8919ffb1719600bfbd954d93d8c1eb2d7369261b 100644 (file)
@@ -106,8 +106,6 @@ static void __init sapphire_map_io(void)
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = PHYS_OFFSET + 0x100,
        .fixup          = sapphire_fixup,
index 469e0be3499dbe9b69a1ec8e39995b4c604aa953..73f146066542198f111330b602eb3978bd34fa4b 100644 (file)
@@ -93,8 +93,6 @@ static void __init trout_map_io(void)
 
 MACHINE_START(TROUT, "HTC Dream")
 #ifdef CONFIG_MSM_DEBUG_UART
-       .phys_io        = MSM_DEBUG_UART_PHYS,
-       .io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
        .boot_params    = 0x10000100,
        .fixup          = trout_fixup,
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
new file mode 100644 (file)
index 0000000..1250d22
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+       return -ENOENT;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return -ENOENT;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
index b449e8ad2904c36905043e5bf951510052d89790..7fcf2e3b7698d5ef329a6483eefc29b7be432075 100644 (file)
@@ -51,6 +51,11 @@ struct platform_device msm_device_uart2 = {
        .resource       = resources_uart2,
 };
 
+struct platform_device msm_device_smd = {
+       .name   = "msm_smd",
+       .id     = -1,
+};
+
 struct clk msm_clocks_7x30[] = {
        CLK_PCOM("adm_clk",     ADM_CLK,        NULL, 0),
        CLK_PCOM("adsp_clk",    ADSP_CLK,       NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
new file mode 100644 (file)
index 0000000..89b9d44
--- /dev/null
@@ -0,0 +1,883 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <mach/msm_iomap-8x60.h>
+#include <mach/irqs-8x60.h>
+#include <mach/iommu.h>
+
+static struct resource msm_iommu_jpegd_resources[] = {
+       {
+               .start = MSM_IOMMU_JPEGD_PHYS,
+               .end   = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+               .end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_vpe_resources[] = {
+       {
+               .start = MSM_IOMMU_VPE_PHYS,
+               .end   = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_VPE_CB_SC_SECURE_IRQ,
+               .end   = SMMU_VPE_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_mdp0_resources[] = {
+       {
+               .start = MSM_IOMMU_MDP0_PHYS,
+               .end   = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_MDP0_CB_SC_SECURE_IRQ,
+               .end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_mdp1_resources[] = {
+       {
+               .start = MSM_IOMMU_MDP1_PHYS,
+               .end   = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_MDP1_CB_SC_SECURE_IRQ,
+               .end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_rot_resources[] = {
+       {
+               .start = MSM_IOMMU_ROT_PHYS,
+               .end   = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_ROT_CB_SC_SECURE_IRQ,
+               .end   = SMMU_ROT_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_ijpeg_resources[] = {
+       {
+               .start = MSM_IOMMU_IJPEG_PHYS,
+               .end   = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+               .end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_vfe_resources[] = {
+       {
+               .start = MSM_IOMMU_VFE_PHYS,
+               .end   = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_VFE_CB_SC_SECURE_IRQ,
+               .end   = SMMU_VFE_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_vcodec_a_resources[] = {
+       {
+               .start = MSM_IOMMU_VCODEC_A_PHYS,
+               .end   = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+               .end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_vcodec_b_resources[] = {
+       {
+               .start = MSM_IOMMU_VCODEC_B_PHYS,
+               .end   = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+               .end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_gfx3d_resources[] = {
+       {
+               .start = MSM_IOMMU_GFX3D_PHYS,
+               .end   = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+               .end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msm_iommu_gfx2d0_resources[] = {
+       {
+               .start = MSM_IOMMU_GFX2D0_PHYS,
+               .end   = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1,
+               .name  = "physbase",
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "nonsecure_irq",
+               .start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+               .end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "secure_irq",
+               .start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+               .end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device msm_root_iommu_dev = {
+       .name = "msm_iommu",
+       .id = -1,
+};
+
+static struct msm_iommu_dev jpegd_smmu = {
+       .name = "jpegd",
+       .clk_rate = -1
+};
+
+static struct msm_iommu_dev vpe_smmu = {
+       .name = "vpe"
+};
+
+static struct msm_iommu_dev mdp0_smmu = {
+       .name = "mdp0"
+};
+
+static struct msm_iommu_dev mdp1_smmu = {
+       .name = "mdp1"
+};
+
+static struct msm_iommu_dev rot_smmu = {
+       .name = "rot"
+};
+
+static struct msm_iommu_dev ijpeg_smmu = {
+       .name = "ijpeg"
+};
+
+static struct msm_iommu_dev vfe_smmu = {
+       .name = "vfe",
+       .clk_rate = -1
+};
+
+static struct msm_iommu_dev vcodec_a_smmu = {
+       .name = "vcodec_a"
+};
+
+static struct msm_iommu_dev vcodec_b_smmu = {
+       .name = "vcodec_b"
+};
+
+static struct msm_iommu_dev gfx3d_smmu = {
+       .name = "gfx3d",
+       .clk_rate = 27000000
+};
+
+static struct msm_iommu_dev gfx2d0_smmu = {
+       .name = "gfx2d0",
+       .clk_rate = 27000000
+};
+
+static struct platform_device msm_device_smmu_jpegd = {
+       .name = "msm_iommu",
+       .id = 0,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
+       .resource = msm_iommu_jpegd_resources,
+};
+
+static struct platform_device msm_device_smmu_vpe = {
+       .name = "msm_iommu",
+       .id = 1,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
+       .resource = msm_iommu_vpe_resources,
+};
+
+static struct platform_device msm_device_smmu_mdp0 = {
+       .name = "msm_iommu",
+       .id = 2,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
+       .resource = msm_iommu_mdp0_resources,
+};
+
+static struct platform_device msm_device_smmu_mdp1 = {
+       .name = "msm_iommu",
+       .id = 3,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
+       .resource = msm_iommu_mdp1_resources,
+};
+
+static struct platform_device msm_device_smmu_rot = {
+       .name = "msm_iommu",
+       .id = 4,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
+       .resource = msm_iommu_rot_resources,
+};
+
+static struct platform_device msm_device_smmu_ijpeg = {
+       .name = "msm_iommu",
+       .id = 5,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
+       .resource = msm_iommu_ijpeg_resources,
+};
+
+static struct platform_device msm_device_smmu_vfe = {
+       .name = "msm_iommu",
+       .id = 6,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
+       .resource = msm_iommu_vfe_resources,
+};
+
+static struct platform_device msm_device_smmu_vcodec_a = {
+       .name = "msm_iommu",
+       .id = 7,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
+       .resource = msm_iommu_vcodec_a_resources,
+};
+
+static struct platform_device msm_device_smmu_vcodec_b = {
+       .name = "msm_iommu",
+       .id = 8,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
+       .resource = msm_iommu_vcodec_b_resources,
+};
+
+static struct platform_device msm_device_smmu_gfx3d = {
+       .name = "msm_iommu",
+       .id = 9,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
+       .resource = msm_iommu_gfx3d_resources,
+};
+
+static struct platform_device msm_device_smmu_gfx2d0 = {
+       .name = "msm_iommu",
+       .id = 10,
+       .dev = {
+               .parent = &msm_root_iommu_dev.dev,
+       },
+       .num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
+       .resource = msm_iommu_gfx2d0_resources,
+};
+
+static struct msm_iommu_ctx_dev jpegd_src_ctx = {
+       .name = "jpegd_src",
+       .num = 0,
+       .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
+       .name = "jpegd_dst",
+       .num = 1,
+       .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_src_ctx = {
+       .name = "vpe_src",
+       .num = 0,
+       .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_dst_ctx = {
+       .name = "vpe_dst",
+       .num = 1,
+       .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
+       .name = "mdp_vg1",
+       .num = 0,
+       .mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
+       .name = "mdp_rgb1",
+       .num = 1,
+       .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
+       .name = "mdp_vg2",
+       .num = 0,
+       .mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
+       .name = "mdp_rgb2",
+       .num = 1,
+       .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_src_ctx = {
+       .name = "rot_src",
+       .num = 0,
+       .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_dst_ctx = {
+       .name = "rot_dst",
+       .num = 1,
+       .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
+       .name = "ijpeg_src",
+       .num = 0,
+       .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
+       .name = "ijpeg_dst",
+       .num = 1,
+       .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
+       .name = "vfe_imgwr",
+       .num = 0,
+       .mids = {2, 3, 4, 5, 6, 7, 8, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_misc_ctx = {
+       .name = "vfe_misc",
+       .num = 1,
+       .mids = {0, 1, 9, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
+       .name = "vcodec_a_stream",
+       .num = 0,
+       .mids = {2, 5, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
+       .name = "vcodec_a_mm1",
+       .num = 1,
+       .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
+       .name = "vcodec_b_mm2",
+       .num = 0,
+       .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_rbpa_ctx = {
+       .name = "gfx3d_rbpa",
+       .num = 0,
+       .mids = {-1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = {
+       .name = "gfx3d_cpvgttc",
+       .num = 1,
+       .mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = {
+       .name = "gfx3d_smmu",
+       .num = 2,
+       .mids = {8, 9, 10, 11, 12, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
+       .name = "gfx2d0_pixv1_smmu",
+       .num = 0,
+       .mids = {0, 3, 4, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
+       .name = "gfx2d0_texv3_smmu",
+       .num = 1,
+       .mids = {1, 6, 7, -1}
+};
+
+static struct platform_device msm_device_jpegd_src_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 0,
+       .dev = {
+               .parent = &msm_device_smmu_jpegd.dev,
+       },
+};
+
+static struct platform_device msm_device_jpegd_dst_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 1,
+       .dev = {
+               .parent = &msm_device_smmu_jpegd.dev,
+       },
+};
+
+static struct platform_device msm_device_vpe_src_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 2,
+       .dev = {
+               .parent = &msm_device_smmu_vpe.dev,
+       },
+};
+
+static struct platform_device msm_device_vpe_dst_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 3,
+       .dev = {
+               .parent = &msm_device_smmu_vpe.dev,
+       },
+};
+
+static struct platform_device msm_device_mdp_vg1_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 4,
+       .dev = {
+               .parent = &msm_device_smmu_mdp0.dev,
+       },
+};
+
+static struct platform_device msm_device_mdp_rgb1_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 5,
+       .dev = {
+               .parent = &msm_device_smmu_mdp0.dev,
+       },
+};
+
+static struct platform_device msm_device_mdp_vg2_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 6,
+       .dev = {
+               .parent = &msm_device_smmu_mdp1.dev,
+       },
+};
+
+static struct platform_device msm_device_mdp_rgb2_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 7,
+       .dev = {
+               .parent = &msm_device_smmu_mdp1.dev,
+       },
+};
+
+static struct platform_device msm_device_rot_src_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 8,
+       .dev = {
+               .parent = &msm_device_smmu_rot.dev,
+       },
+};
+
+static struct platform_device msm_device_rot_dst_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 9,
+       .dev = {
+               .parent = &msm_device_smmu_rot.dev,
+       },
+};
+
+static struct platform_device msm_device_ijpeg_src_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 10,
+       .dev = {
+               .parent = &msm_device_smmu_ijpeg.dev,
+       },
+};
+
+static struct platform_device msm_device_ijpeg_dst_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 11,
+       .dev = {
+               .parent = &msm_device_smmu_ijpeg.dev,
+       },
+};
+
+static struct platform_device msm_device_vfe_imgwr_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 12,
+       .dev = {
+               .parent = &msm_device_smmu_vfe.dev,
+       },
+};
+
+static struct platform_device msm_device_vfe_misc_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 13,
+       .dev = {
+               .parent = &msm_device_smmu_vfe.dev,
+       },
+};
+
+static struct platform_device msm_device_vcodec_a_stream_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 14,
+       .dev = {
+               .parent = &msm_device_smmu_vcodec_a.dev,
+       },
+};
+
+static struct platform_device msm_device_vcodec_a_mm1_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 15,
+       .dev = {
+               .parent = &msm_device_smmu_vcodec_a.dev,
+       },
+};
+
+static struct platform_device msm_device_vcodec_b_mm2_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 16,
+       .dev = {
+               .parent = &msm_device_smmu_vcodec_b.dev,
+       },
+};
+
+static struct platform_device msm_device_gfx3d_rbpa_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 17,
+       .dev = {
+               .parent = &msm_device_smmu_gfx3d.dev,
+       },
+};
+
+static struct platform_device msm_device_gfx3d_cpvgttc_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 18,
+       .dev = {
+               .parent = &msm_device_smmu_gfx3d.dev,
+       },
+};
+
+static struct platform_device msm_device_gfx3d_smmu_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 19,
+       .dev = {
+               .parent = &msm_device_smmu_gfx3d.dev,
+       },
+};
+
+static struct platform_device msm_device_gfx2d0_pixv1_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 20,
+       .dev = {
+               .parent = &msm_device_smmu_gfx2d0.dev,
+       },
+};
+
+static struct platform_device msm_device_gfx2d0_texv3_ctx = {
+       .name = "msm_iommu_ctx",
+       .id = 21,
+       .dev = {
+               .parent = &msm_device_smmu_gfx2d0.dev,
+       },
+};
+
+static struct platform_device *msm_iommu_devs[] = {
+       &msm_device_smmu_jpegd,
+       &msm_device_smmu_vpe,
+       &msm_device_smmu_mdp0,
+       &msm_device_smmu_mdp1,
+       &msm_device_smmu_rot,
+       &msm_device_smmu_ijpeg,
+       &msm_device_smmu_vfe,
+       &msm_device_smmu_vcodec_a,
+       &msm_device_smmu_vcodec_b,
+       &msm_device_smmu_gfx3d,
+       &msm_device_smmu_gfx2d0,
+};
+
+static struct msm_iommu_dev *msm_iommu_data[] = {
+       &jpegd_smmu,
+       &vpe_smmu,
+       &mdp0_smmu,
+       &mdp1_smmu,
+       &rot_smmu,
+       &ijpeg_smmu,
+       &vfe_smmu,
+       &vcodec_a_smmu,
+       &vcodec_b_smmu,
+       &gfx3d_smmu,
+       &gfx2d0_smmu,
+};
+
+static struct platform_device *msm_iommu_ctx_devs[] = {
+       &msm_device_jpegd_src_ctx,
+       &msm_device_jpegd_dst_ctx,
+       &msm_device_vpe_src_ctx,
+       &msm_device_vpe_dst_ctx,
+       &msm_device_mdp_vg1_ctx,
+       &msm_device_mdp_rgb1_ctx,
+       &msm_device_mdp_vg2_ctx,
+       &msm_device_mdp_rgb2_ctx,
+       &msm_device_rot_src_ctx,
+       &msm_device_rot_dst_ctx,
+       &msm_device_ijpeg_src_ctx,
+       &msm_device_ijpeg_dst_ctx,
+       &msm_device_vfe_imgwr_ctx,
+       &msm_device_vfe_misc_ctx,
+       &msm_device_vcodec_a_stream_ctx,
+       &msm_device_vcodec_a_mm1_ctx,
+       &msm_device_vcodec_b_mm2_ctx,
+       &msm_device_gfx3d_rbpa_ctx,
+       &msm_device_gfx3d_cpvgttc_ctx,
+       &msm_device_gfx3d_smmu_ctx,
+       &msm_device_gfx2d0_pixv1_ctx,
+       &msm_device_gfx2d0_texv3_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
+       &jpegd_src_ctx,
+       &jpegd_dst_ctx,
+       &vpe_src_ctx,
+       &vpe_dst_ctx,
+       &mdp_vg1_ctx,
+       &mdp_rgb1_ctx,
+       &mdp_vg2_ctx,
+       &mdp_rgb2_ctx,
+       &rot_src_ctx,
+       &rot_dst_ctx,
+       &ijpeg_src_ctx,
+       &ijpeg_dst_ctx,
+       &vfe_imgwr_ctx,
+       &vfe_misc_ctx,
+       &vcodec_a_stream_ctx,
+       &vcodec_a_mm1_ctx,
+       &vcodec_b_mm2_ctx,
+       &gfx3d_rbpa_ctx,
+       &gfx3d_cpvgttc_ctx,
+       &gfx3d_smmu_ctx,
+       &gfx2d0_pixv1_ctx,
+       &gfx2d0_texv3_ctx,
+};
+
+static int msm8x60_iommu_init(void)
+{
+       int ret, i;
+
+       ret = platform_device_register(&msm_root_iommu_dev);
+       if (ret != 0) {
+               pr_err("Failed to register root IOMMU device!\n");
+               goto failure;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
+               ret = platform_device_add_data(msm_iommu_devs[i],
+                                              msm_iommu_data[i],
+                                              sizeof(struct msm_iommu_dev));
+               if (ret != 0) {
+                       pr_err("platform_device_add_data failed, "
+                              "i = %d\n", i);
+                       goto failure_unwind;
+               }
+
+               ret = platform_device_register(msm_iommu_devs[i]);
+
+               if (ret != 0) {
+                       pr_err("platform_device_register smmu failed, "
+                              "i = %d\n", i);
+                       goto failure_unwind;
+               }
+       }
+
+       for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
+               ret = platform_device_add_data(msm_iommu_ctx_devs[i],
+                                              msm_iommu_ctx_data[i],
+                                              sizeof(*msm_iommu_ctx_devs[i]));
+               if (ret != 0) {
+                       pr_err("platform_device_add_data smmu failed, "
+                              "i = %d\n", i);
+                       goto failure_unwind2;
+               }
+
+               ret = platform_device_register(msm_iommu_ctx_devs[i]);
+               if (ret != 0) {
+                       pr_err("platform_device_register ctx failed, "
+                              "i = %d\n", i);
+                       goto failure_unwind2;
+               }
+       }
+       return 0;
+
+failure_unwind2:
+       while (--i >= 0)
+               platform_device_unregister(msm_iommu_ctx_devs[i]);
+failure_unwind:
+       while (--i >= 0)
+               platform_device_unregister(msm_iommu_devs[i]);
+
+       platform_device_unregister(&msm_root_iommu_dev);
+failure:
+       return ret;
+}
+
+static void msm8x60_iommu_exit(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
+               platform_device_unregister(msm_iommu_ctx_devs[i]);
+
+       for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
+               platform_device_unregister(msm_iommu_devs[i]);
+
+       platform_device_unregister(&msm_root_iommu_dev);
+}
+
+subsys_initcall(msm8x60_iommu_init);
+module_exit(msm8x60_iommu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
index 4d4a50785e344914ffee947cf64fae3664125a56..6fe67c5d1ae0aa3e7286f659b67acb8d11dd12fb 100644 (file)
@@ -48,6 +48,11 @@ struct platform_device msm_device_uart3 = {
        .resource       = resources_uart3,
 };
 
+struct platform_device msm_device_smd = {
+       .name   = "msm_smd",
+       .id     = -1,
+};
+
 struct clk msm_clocks_8x50[] = {
        CLK_PCOM("adm_clk",     ADM_CLK,        NULL, 0),
        CLK_PCOM("ebi1_clk",    EBI1_CLK,       NULL, CLK_MIN),
index bc32c845c7b0e4f777e3366fd4f418daa44c700e..33051b509e88a18679876840a6a5a4a12a4bfdc1 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/gpio.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  *
  */
 
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/module.h>
-#include <mach/gpio.h>
-#include "proc_comm.h"
-
-int gpio_tlmm_config(unsigned config, unsigned disable)
-{
-       return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable);
-}
-EXPORT_SYMBOL(gpio_tlmm_config);
-
-int msm_gpios_enable(const struct msm_gpio *table, int size)
-{
-       int rc;
-       int i;
-       const struct msm_gpio *g;
-       for (i = 0; i < size; i++) {
-               g = table + i;
-               rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE);
-               if (rc) {
-                       pr_err("gpio_tlmm_config(0x%08x, GPIO_ENABLE)"
-                              " <%s> failed: %d\n",
-                              g->gpio_cfg, g->label ?: "?", rc);
-                       pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
-                              GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
-                              GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
-                              GPIO_DRVSTR(g->gpio_cfg));
-                       goto err;
-               }
+#include "gpio_hw.h"
+#include "gpiomux.h"
+
+#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
+
+#define MSM_GPIO_BANK(bank, first, last)                               \
+       {                                                               \
+               .regs = {                                               \
+                       .out =         MSM_GPIO_OUT_##bank,             \
+                       .in =          MSM_GPIO_IN_##bank,              \
+                       .int_status =  MSM_GPIO_INT_STATUS_##bank,      \
+                       .int_clear =   MSM_GPIO_INT_CLEAR_##bank,       \
+                       .int_en =      MSM_GPIO_INT_EN_##bank,          \
+                       .int_edge =    MSM_GPIO_INT_EDGE_##bank,        \
+                       .int_pos =     MSM_GPIO_INT_POS_##bank,         \
+                       .oe =          MSM_GPIO_OE_##bank,              \
+               },                                                      \
+               .chip = {                                               \
+                       .base = (first),                                \
+                       .ngpio = (last) - (first) + 1,                  \
+                       .get = msm_gpio_get,                            \
+                       .set = msm_gpio_set,                            \
+                       .direction_input = msm_gpio_direction_input,    \
+                       .direction_output = msm_gpio_direction_output,  \
+                       .to_irq = msm_gpio_to_irq,                      \
+                       .request = msm_gpio_request,                    \
+                       .free = msm_gpio_free,                          \
+               }                                                       \
        }
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+struct msm_gpio_regs {
+       void __iomem *out;
+       void __iomem *in;
+       void __iomem *int_status;
+       void __iomem *int_clear;
+       void __iomem *int_en;
+       void __iomem *int_edge;
+       void __iomem *int_pos;
+       void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+       spinlock_t              lock;
+       struct gpio_chip        chip;
+       struct msm_gpio_regs    regs;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       unsigned                int_status_copy;
+#endif
+       unsigned int            both_edge_detect;
+       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
+                         unsigned offset, unsigned on)
+{
+       unsigned mask = BIT(offset);
+       unsigned val;
+
+       val = readl(msm_chip->regs.out);
+       if (on)
+               writel(val | mask, msm_chip->regs.out);
+       else
+               writel(val & ~mask, msm_chip->regs.out);
        return 0;
-err:
-       msm_gpios_disable(table, i);
-       return rc;
-}
-EXPORT_SYMBOL(msm_gpios_enable);
-
-void msm_gpios_disable(const struct msm_gpio *table, int size)
-{
-       int rc;
-       int i;
-       const struct msm_gpio *g;
-       for (i = size-1; i >= 0; i--) {
-               g = table + i;
-               rc = gpio_tlmm_config(g->gpio_cfg, GPIO_DISABLE);
-               if (rc) {
-                       pr_err("gpio_tlmm_config(0x%08x, GPIO_DISABLE)"
-                              " <%s> failed: %d\n",
-                              g->gpio_cfg, g->label ?: "?", rc);
-                       pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
-                              GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
-                              GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
-                              GPIO_DRVSTR(g->gpio_cfg));
-               }
+}
+
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
+{
+       int loop_limit = 100;
+       unsigned pol, val, val2, intstat;
+       do {
+               val = readl(msm_chip->regs.in);
+               pol = readl(msm_chip->regs.int_pos);
+               pol = (pol & ~msm_chip->both_edge_detect) |
+                     (~val & msm_chip->both_edge_detect);
+               writel(pol, msm_chip->regs.int_pos);
+               intstat = readl(msm_chip->regs.int_status);
+               val2 = readl(msm_chip->regs.in);
+               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+                       return;
+       } while (loop_limit-- > 0);
+       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
+              "failed to reach stable state %x != %x\n", val, val2);
+}
+
+static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
+                                       unsigned offset)
+{
+       unsigned bit = BIT(offset);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       /* Save interrupts that already triggered before we loose them. */
+       /* Any interrupt that triggers between the read of int_status */
+       /* and the write to int_clear will still be lost though. */
+       msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+       msm_chip->int_status_copy &= ~bit;
+#endif
+       writel(bit, msm_chip->regs.int_clear);
+       msm_gpio_update_both_edge_detect(msm_chip);
+       return 0;
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int
+msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+#ifdef CONFIG_MSM_GPIOMUX
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       msm_gpiomux_put(chip->base + offset);
+}
+#else
+#define msm_gpio_request NULL
+#define msm_gpio_free NULL
+#endif
+
+struct msm_gpio_chip msm_gpio_chips[] = {
+#if defined(CONFIG_ARCH_MSM7X00A)
+       MSM_GPIO_BANK(0,   0,  15),
+       MSM_GPIO_BANK(1,  16,  42),
+       MSM_GPIO_BANK(2,  43,  67),
+       MSM_GPIO_BANK(3,  68,  94),
+       MSM_GPIO_BANK(4,  95, 106),
+       MSM_GPIO_BANK(5, 107, 121),
+#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
+       MSM_GPIO_BANK(0,   0,  15),
+       MSM_GPIO_BANK(1,  16,  42),
+       MSM_GPIO_BANK(2,  43,  67),
+       MSM_GPIO_BANK(3,  68,  94),
+       MSM_GPIO_BANK(4,  95, 106),
+       MSM_GPIO_BANK(5, 107, 132),
+#elif defined(CONFIG_ARCH_MSM7X30)
+       MSM_GPIO_BANK(0,   0,  15),
+       MSM_GPIO_BANK(1,  16,  43),
+       MSM_GPIO_BANK(2,  44,  67),
+       MSM_GPIO_BANK(3,  68,  94),
+       MSM_GPIO_BANK(4,  95, 106),
+       MSM_GPIO_BANK(5, 107, 133),
+       MSM_GPIO_BANK(6, 134, 150),
+       MSM_GPIO_BANK(7, 151, 181),
+#elif defined(CONFIG_ARCH_QSD8X50)
+       MSM_GPIO_BANK(0,   0,  15),
+       MSM_GPIO_BANK(1,  16,  42),
+       MSM_GPIO_BANK(2,  43,  67),
+       MSM_GPIO_BANK(3,  68,  94),
+       MSM_GPIO_BANK(4,  95, 103),
+       MSM_GPIO_BANK(5, 104, 121),
+       MSM_GPIO_BANK(6, 122, 152),
+       MSM_GPIO_BANK(7, 153, 164),
+#endif
+};
+
+static void msm_gpio_irq_ack(unsigned int irq)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_clear_detect_status(msm_chip,
+                                    irq - gpio_to_irq(msm_chip->chip.base));
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(unsigned int irq)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+       unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] &= ~BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(unsigned int irq)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+       unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] |= BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+       unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+       if (on)
+               msm_chip->int_enable[1] |= BIT(offset);
+       else
+               msm_chip->int_enable[1] &= ~BIT(offset);
+
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+       unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+       unsigned val, mask = BIT(offset);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       val = readl(msm_chip->regs.int_edge);
+       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+               writel(val | mask, msm_chip->regs.int_edge);
+               irq_desc[irq].handle_irq = handle_edge_irq;
+       } else {
+               writel(val & ~mask, msm_chip->regs.int_edge);
+               irq_desc[irq].handle_irq = handle_level_irq;
+       }
+       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               msm_chip->both_edge_detect |= mask;
+               msm_gpio_update_both_edge_detect(msm_chip);
+       } else {
+               msm_chip->both_edge_detect &= ~mask;
+               val = readl(msm_chip->regs.int_pos);
+               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+                       writel(val | mask, msm_chip->regs.int_pos);
+               else
+                       writel(val & ~mask, msm_chip->regs.int_pos);
        }
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
 }
-EXPORT_SYMBOL(msm_gpios_disable);
 
-int msm_gpios_request_enable(const struct msm_gpio *table, int size)
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       int rc = msm_gpios_enable(table, size);
-       return rc;
+       int i, j, mask;
+       unsigned val;
+
+       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+               val = readl(msm_chip->regs.int_status);
+               val &= msm_chip->int_enable[0];
+               while (val) {
+                       mask = val & -val;
+                       j = fls(mask) - 1;
+                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
+                               __func__, v, m, j, msm_chip->chip.start + j,
+                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
+                       val &= ~mask;
+                       generic_handle_irq(FIRST_GPIO_IRQ +
+                                          msm_chip->chip.base + j);
+               }
+       }
+       desc->chip->ack(irq);
 }
-EXPORT_SYMBOL(msm_gpios_request_enable);
 
-void msm_gpios_disable_free(const struct msm_gpio *table, int size)
+static struct irq_chip msm_gpio_irq_chip = {
+       .name      = "msmgpio",
+       .ack       = msm_gpio_irq_ack,
+       .mask      = msm_gpio_irq_mask,
+       .unmask    = msm_gpio_irq_unmask,
+       .set_wake  = msm_gpio_irq_set_wake,
+       .set_type  = msm_gpio_irq_set_type,
+};
+
+static int __init msm_init_gpio(void)
 {
-       msm_gpios_disable(table, size);
+       int i, j = 0;
+
+       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+               if (i - FIRST_GPIO_IRQ >=
+                       msm_gpio_chips[j].chip.base +
+                       msm_gpio_chips[j].chip.ngpio)
+                       j++;
+               set_irq_chip_data(i, &msm_gpio_chips[j]);
+               set_irq_chip(i, &msm_gpio_irq_chip);
+               set_irq_handler(i, handle_edge_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+               spin_lock_init(&msm_gpio_chips[i].lock);
+               writel(0, msm_gpio_chips[i].regs.int_en);
+               gpiochip_add(&msm_gpio_chips[i].chip);
+       }
+
+       set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+       set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+       set_irq_wake(INT_GPIO_GROUP1, 1);
+       set_irq_wake(INT_GPIO_GROUP2, 2);
+       return 0;
 }
-EXPORT_SYMBOL(msm_gpios_disable_free);
+
+postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
new file mode 100644 (file)
index 0000000..6b50660
--- /dev/null
@@ -0,0 +1,278 @@
+/* arch/arm/mach-msm/gpio_hw.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
+#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
+
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
+#else
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
+    defined(CONFIG_ARCH_MSM7X27)
+
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0  */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16 */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43 */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68 */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 106-95 */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)  /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
+
+#endif
+
+#if defined(CONFIG_ARCH_QSD8X50)
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0   */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16  */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43  */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68  */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 103-95  */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x10)  /* gpio 121-104 */
+#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0x14)  /* gpio 152-122 */
+#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x18)  /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x20)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x24)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x28)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x2C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x30)
+#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x38)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x50)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x58)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x5C)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xC4)
+#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xE4)
+#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xF0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xF4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xF8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xFC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0x100)
+#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0x104)
+#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x108)
+
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X30)
+
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
+#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
+#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0xC8)
+#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x218)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
+#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0xCC)
+#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x21C)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x240)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0x228)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0x22C)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0x230)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x234)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c
new file mode 100644 (file)
index 0000000..6ce41c5
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+       [49] = { /* UART2 RFR */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+       },
+       [50] = { /* UART2 CTS */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+       },
+       [51] = { /* UART2 RX */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+       },
+       [52] = { /* UART2 TX */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+       },
+#endif
+};
diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c
new file mode 100644 (file)
index 0000000..4406e0f
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+       [86] = { /* UART3 RX */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+       },
+       [87] = { /* UART3 TX */
+               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+                            GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+       },
+};
diff --git a/arch/arm/mach-msm/gpiomux-8x60.c b/arch/arm/mach-msm/gpiomux-8x60.c
new file mode 100644 (file)
index 0000000..7b380b3
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};
diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c
new file mode 100644 (file)
index 0000000..27de2ab
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/kernel.h>
+#include "gpiomux.h"
+#include "proc_comm.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+       unsigned tlmm_config  = (val & ~GPIOMUX_CTL_MASK) |
+                               ((gpio & 0x3ff) << 4);
+       unsigned tlmm_disable = 0;
+       int rc;
+
+       rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
+                          &tlmm_config, &tlmm_disable);
+       if (rc)
+               pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
+                      __func__, rc, tlmm_config, tlmm_disable);
+}
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
new file mode 100644 (file)
index 0000000..71d86fe
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define GPIOMUX_NGPIOS 182
+#elif defined(CONFIG_ARCH_QSD8X50)
+#define GPIOMUX_NGPIOS 165
+#else
+#define GPIOMUX_NGPIOS 133
+#endif
+
+typedef u32 gpiomux_config_t;
+
+enum {
+       GPIOMUX_DRV_2MA  = 0UL << 17,
+       GPIOMUX_DRV_4MA  = 1UL << 17,
+       GPIOMUX_DRV_6MA  = 2UL << 17,
+       GPIOMUX_DRV_8MA  = 3UL << 17,
+       GPIOMUX_DRV_10MA = 4UL << 17,
+       GPIOMUX_DRV_12MA = 5UL << 17,
+       GPIOMUX_DRV_14MA = 6UL << 17,
+       GPIOMUX_DRV_16MA = 7UL << 17,
+};
+
+enum {
+       GPIOMUX_FUNC_GPIO = 0UL,
+       GPIOMUX_FUNC_1    = 1UL,
+       GPIOMUX_FUNC_2    = 2UL,
+       GPIOMUX_FUNC_3    = 3UL,
+       GPIOMUX_FUNC_4    = 4UL,
+       GPIOMUX_FUNC_5    = 5UL,
+       GPIOMUX_FUNC_6    = 6UL,
+       GPIOMUX_FUNC_7    = 7UL,
+       GPIOMUX_FUNC_8    = 8UL,
+       GPIOMUX_FUNC_9    = 9UL,
+       GPIOMUX_FUNC_A    = 10UL,
+       GPIOMUX_FUNC_B    = 11UL,
+       GPIOMUX_FUNC_C    = 12UL,
+       GPIOMUX_FUNC_D    = 13UL,
+       GPIOMUX_FUNC_E    = 14UL,
+       GPIOMUX_FUNC_F    = 15UL,
+};
+
+enum {
+       GPIOMUX_PULL_NONE   = 0UL << 15,
+       GPIOMUX_PULL_DOWN   = 1UL << 15,
+       GPIOMUX_PULL_KEEPER = 2UL << 15,
+       GPIOMUX_PULL_UP     = 3UL << 15,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c
new file mode 100644 (file)
index 0000000..273396d
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/io.h>
+#include <mach/msm_iomap.h>
+#include "gpiomux.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+       writel(val & ~GPIOMUX_CTL_MASK,
+              MSM_TLMM_BASE + 0x1000 + (0x10 * gpio));
+}
diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h
new file mode 100644 (file)
index 0000000..3bf10e7
--- /dev/null
@@ -0,0 +1,61 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+
+#define GPIOMUX_NGPIOS 173
+
+typedef u16 gpiomux_config_t;
+
+enum {
+       GPIOMUX_DRV_2MA  = 0UL << 6,
+       GPIOMUX_DRV_4MA  = 1UL << 6,
+       GPIOMUX_DRV_6MA  = 2UL << 6,
+       GPIOMUX_DRV_8MA  = 3UL << 6,
+       GPIOMUX_DRV_10MA = 4UL << 6,
+       GPIOMUX_DRV_12MA = 5UL << 6,
+       GPIOMUX_DRV_14MA = 6UL << 6,
+       GPIOMUX_DRV_16MA = 7UL << 6,
+};
+
+enum {
+       GPIOMUX_FUNC_GPIO = 0UL  << 2,
+       GPIOMUX_FUNC_1    = 1UL  << 2,
+       GPIOMUX_FUNC_2    = 2UL  << 2,
+       GPIOMUX_FUNC_3    = 3UL  << 2,
+       GPIOMUX_FUNC_4    = 4UL  << 2,
+       GPIOMUX_FUNC_5    = 5UL  << 2,
+       GPIOMUX_FUNC_6    = 6UL  << 2,
+       GPIOMUX_FUNC_7    = 7UL  << 2,
+       GPIOMUX_FUNC_8    = 8UL  << 2,
+       GPIOMUX_FUNC_9    = 9UL  << 2,
+       GPIOMUX_FUNC_A    = 10UL << 2,
+       GPIOMUX_FUNC_B    = 11UL << 2,
+       GPIOMUX_FUNC_C    = 12UL << 2,
+       GPIOMUX_FUNC_D    = 13UL << 2,
+       GPIOMUX_FUNC_E    = 14UL << 2,
+       GPIOMUX_FUNC_F    = 15UL << 2,
+};
+
+enum {
+       GPIOMUX_PULL_NONE   = 0UL,
+       GPIOMUX_PULL_DOWN   = 1UL,
+       GPIOMUX_PULL_KEEPER = 2UL,
+       GPIOMUX_PULL_UP     = 3UL,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
new file mode 100644 (file)
index 0000000..53af21a
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "gpiomux.h"
+
+static DEFINE_SPINLOCK(gpiomux_lock);
+
+int msm_gpiomux_write(unsigned gpio,
+                     gpiomux_config_t active,
+                     gpiomux_config_t suspended)
+{
+       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+       unsigned long irq_flags;
+       gpiomux_config_t setting;
+
+       if (gpio >= GPIOMUX_NGPIOS)
+               return -EINVAL;
+
+       spin_lock_irqsave(&gpiomux_lock, irq_flags);
+
+       if (active & GPIOMUX_VALID)
+               cfg->active = active;
+
+       if (suspended & GPIOMUX_VALID)
+               cfg->suspended = suspended;
+
+       setting = cfg->ref ? active : suspended;
+       if (setting & GPIOMUX_VALID)
+               __msm_gpiomux_write(gpio, setting);
+
+       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+       return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_write);
+
+int msm_gpiomux_get(unsigned gpio)
+{
+       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+       unsigned long irq_flags;
+
+       if (gpio >= GPIOMUX_NGPIOS)
+               return -EINVAL;
+
+       spin_lock_irqsave(&gpiomux_lock, irq_flags);
+       if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
+               __msm_gpiomux_write(gpio, cfg->active);
+       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+       return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_get);
+
+int msm_gpiomux_put(unsigned gpio)
+{
+       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+       unsigned long irq_flags;
+
+       if (gpio >= GPIOMUX_NGPIOS)
+               return -EINVAL;
+
+       spin_lock_irqsave(&gpiomux_lock, irq_flags);
+       BUG_ON(cfg->ref == 0);
+       if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
+               __msm_gpiomux_write(gpio, cfg->suspended);
+       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+       return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_put);
+
+static int __init gpiomux_init(void)
+{
+       unsigned n;
+
+       for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
+               msm_gpiomux_configs[n].ref = 0;
+               if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
+                       continue;
+               __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+       }
+       return 0;
+}
+postcore_initcall(gpiomux_init);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
new file mode 100644 (file)
index 0000000..b178d9c
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+
+#if defined(CONFIG_MSM_V2_TLMM)
+#include "gpiomux-v2.h"
+#else
+#include "gpiomux-v1.h"
+#endif
+
+/**
+ * struct msm_gpiomux_config: gpiomux settings for one gpio line.
+ *
+ * A complete gpiomux config is the bitwise-or of a drive-strength,
+ * function, and pull.  For functions other than GPIO, the OE
+ * is hard-wired according to the function.  For GPIO mode,
+ * OE is controlled by gpiolib.
+ *
+ * Available settings differ by target; see the gpiomux header
+ * specific to your target arch for available configurations.
+ *
+ * @active: The configuration to be installed when the line is
+ * active, or its reference count is > 0.
+ * @suspended: The configuration to be installed when the line
+ * is suspended, or its reference count is 0.
+ * @ref: The reference count of the line.  For internal use of
+ * the gpiomux framework only.
+ */
+struct msm_gpiomux_config {
+       gpiomux_config_t active;
+       gpiomux_config_t suspended;
+       unsigned         ref;
+};
+
+/**
+ * @GPIOMUX_VALID:     If set, the config field contains 'good data'.
+ *                      The absence of this bit will prevent the gpiomux
+ *                     system from applying the configuration under all
+ *                     circumstances.
+ */
+enum {
+       GPIOMUX_VALID    = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1),
+       GPIOMUX_CTL_MASK = GPIOMUX_VALID,
+};
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Each architecture must provide its own instance of this table.
+ * To avoid having gpiomux manage any given gpio, one or both of
+ * the entries can avoid setting GPIOMUX_VALID - the absence
+ * of that flag will prevent the configuration from being applied
+ * during state transitions.
+ */
+extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+/* Install a new configuration to the gpio line.  To avoid overwriting
+ * a configuration, leave the VALID bit out.
+ */
+int msm_gpiomux_write(unsigned gpio,
+                     gpiomux_config_t active,
+                     gpiomux_config_t suspended);
+
+/* Architecture-internal function for use by the framework only.
+ * This function can assume the following:
+ * - the gpio value has passed a bounds-check
+ * - the gpiomux spinlock has been obtained
+ *
+ * This function is not for public consumption.  External users
+ * should use msm_gpiomux_write.
+ */
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
+#else
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int msm_gpiomux_write(unsigned gpio,
+                                   gpiomux_config_t active,
+                                   gpiomux_config_t suspended)
+{
+       return -ENOSYS;
+}
+#endif
+#endif
index 5a79bcf5041367894d876ece1a86f20f5948bb97..6abf4a6eadc19be578b7888c21bfd3ec534291f6 100644 (file)
@@ -33,6 +33,8 @@ struct msm_acpu_clock_platform_data
 
 struct clk;
 
+extern struct sys_timer msm_timer;
+
 /* common init routines for use by arch/arm/mach-msm/board-*.c */
 
 void __init msm_add_devices(void);
index 528750f307e9428433c97101153be1933d495ba8..fbd5d90dcc8ce36ec411e8b8d1be04613a2742f0 100644 (file)
 #include <mach/hardware.h>
 #include <mach/msm_iomap.h>
 
-#ifdef CONFIG_MSM_DEBUG_UART
-       .macro  addruart, rx, tmp
-       @ see if the MMU is enabled and select appropriate base address
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1
-       ldreq   \rx, =MSM_DEBUG_UART_PHYS
-       ldrne   \rx, =MSM_DEBUG_UART_BASE
+#ifdef CONFIG_HAS_MSM_DEBUG_UART_PHYS
+       .macro  addruart, rp, rv
+       ldr     \rp, =MSM_DEBUG_UART_PHYS
+       ldr     \rv, =MSM_DEBUG_UART_BASE
        .endm
 
        .macro  senduart,rd,rx
        tst     \rd, #0x04
        beq     1001b
        .endm
-#else
-       .macro  addruart, rx, tmp
-       .endm
-
-       .macro  senduart,rd,rx
-       .endm
-
-       .macro  waituart,rd,rx
-       .endm
-#endif
 
        .macro  busyuart,rd,rx
        .endm
+#endif
index 00f9bbfadbe6052972e5c5a183e312f7b800c233..05583f569524449ed2b61ea52ecd42544a959416 100644 (file)
@@ -32,10 +32,18 @@ struct msm_dmov_cmd {
        void *data;
 };
 
+#ifndef CONFIG_ARCH_MSM8X60
 void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
 void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
 int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
-
+#else
+static inline
+void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
+static inline
+void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
+static inline
+int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
+#endif
 
 
 #define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
new file mode 100644 (file)
index 0000000..4dc99aa
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Low-level IRQ helper macros
+ *
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_preamble, base, tmp
+       ldr     \base, =gic_cpu_base_addr
+       ldr     \base, [\base]
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
+       /*
+        * The interrupt numbering scheme is defined in the
+        * interrupt controller spec.  To wit:
+        *
+        * Migrated the code from ARM MP port to be more consistant
+        * with interrupt processing , the following still holds true
+        * however, all interrupts are treated the same regardless of
+        * if they are local IPI or PPI
+        *
+        * Interrupts 0-15 are IPI
+        * 16-31 are PPI
+        *   (16-18 are the timers)
+        * 32-1020 are global
+        * 1021-1022 are reserved
+        * 1023 is "spurious" (no interrupt)
+        *
+        * A simple read from the controller will tell us the number of the
+        * highest priority enabled interrupt.  We then just need to check
+        * whether it is in the valid range for an IRQ (0-1020 inclusive).
+        *
+        * Base ARM code assumes that the local (private) peripheral interrupts
+        * are not valid, we treat them differently, in that the privates are
+        * handled like normal shared interrupts with the exception that only
+        * one processor can register the interrupt and the handler must be
+        * the same for all processors.
+        */
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+       ldr  \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
+                                                  9-0 =int # */
+
+       bic     \irqnr, \irqstat, #0x1c00       @mask src
+       cmp     \irqnr, #15
+       ldr             \tmp, =1021
+       cmpcc   \irqnr, \irqnr
+       cmpne   \irqnr, \tmp
+       cmpcs   \irqnr, \irqnr
+
+       .endm
+
+       /* We assume that irqstat (the raw value of the IRQ acknowledge
+        * register) is preserved from the macro above.
+        * If there is an IPI, we immediately signal end of interrupt on the
+        * controller, since this requires the original irqstat value which
+        * we won't easily be able to recreate later.
+        */
+       .macro test_for_ipi, irqnr, irqstat, base, tmp
+    bic \irqnr, \irqstat, #0x1c00
+    cmp \irqnr, #16
+    strcc   \irqstat, [\base, #GIC_CPU_EOI]
+    cmpcs   \irqnr, \irqnr
+       .endm
+
+       /* As above, this assumes that irqstat and base are preserved.. */
+
+       .macro test_for_ltirq, irqnr, irqstat, base, tmp
+    bic \irqnr, \irqstat, #0x1c00
+    mov     \tmp, #0
+    cmp \irqnr, #16
+    moveq   \tmp, #1
+    streq   \irqstat, [\base, #GIC_CPU_EOI]
+    cmp \tmp, #0
+       .endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-vic.S b/arch/arm/mach-msm/include/mach/entry-macro-vic.S
new file mode 100644 (file)
index 0000000..70563ed
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <mach/msm_iomap.h>
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_preamble, base, tmp
+       @ enable imprecise aborts
+       cpsie   a
+       mov     \base, #MSM_VIC_BASE
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       @ 0xD0 has irq# or old irq# if the irq has been handled
+       @ 0xD4 has irq# or -1 if none pending *but* if you just
+       @ read 0xD4 you never get the first irq for some reason
+       ldr     \irqnr, [\base, #0xD0]
+       ldr     \irqnr, [\base, #0xD4]
+       cmp     \irqnr, #0xffffffff
+       .endm
index d2259486bcb1588175df8a9f5fcdd76c5efe4aae..b16f082eeb6f7c092f8a041f3ba302fae5fcf163 100644 (file)
@@ -1,38 +1,23 @@
-/* arch/arm/mach-msm7200/include/mach/entry-macro.S
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
  */
 
-#include <mach/msm_iomap.h>
-
-       .macro  disable_fiq
-       .endm
-
-       .macro  get_irqnr_preamble, base, tmp
-       @ enable imprecise aborts
-       cpsie   a
-       mov     \base, #MSM_VIC_BASE
-       .endm
-
-       .macro  arch_ret_to_user, tmp1, tmp2
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       @ 0xD0 has irq# or old irq# if the irq has been handled
-       @ 0xD4 has irq# or -1 if none pending *but* if you just
-       @ read 0xD4 you never get the first irq for some reason
-       ldr     \irqnr, [\base, #0xD0]
-       ldr     \irqnr, [\base, #0xD4]
-       cmp     \irqnr, #0xffffffff
-       .endm
+#if defined(CONFIG_ARM_GIC)
+#include <mach/entry-macro-qgic.S>
+#else
+#include <mach/entry-macro-vic.S>
+#endif
index 83e47c0d5c2e451de5f459653053684beb786ee8..36ad50d3bfaa8e03e9f0333c05ed655d9ebf4adb 100644 (file)
 #define gpio_cansleep   __gpio_cansleep
 #define gpio_to_irq     __gpio_to_irq
 
-/**
- * struct msm_gpio - GPIO pin description
- * @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
- * @label - textual label
- *
- * Usually, GPIO's are operated by sets.
- * This struct accumulate all GPIO information in single source
- * and facilitete group operations provided by msm_gpios_xxx()
- */
-struct msm_gpio {
-       u32 gpio_cfg;
-       const char *label;
-};
-
-/**
- * msm_gpios_request_enable() - request and enable set of GPIOs
- *
- * Request and configure set of GPIO's
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_request_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable_free() - disable and free set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_disable_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_request() - request set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_request(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_free() - free set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_enable() - enable set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable() - disable set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_disable(const struct msm_gpio *table, int size);
-
-/* GPIO TLMM (Top Level Multiplexing) Definitions */
-
-/* GPIO TLMM: Function -- GPIO specific */
-
-/* GPIO TLMM: Direction */
-enum {
-       GPIO_INPUT,
-       GPIO_OUTPUT,
-};
-
-/* GPIO TLMM: Pullup/Pulldown */
-enum {
-       GPIO_NO_PULL,
-       GPIO_PULL_DOWN,
-       GPIO_KEEPER,
-       GPIO_PULL_UP,
-};
-
-/* GPIO TLMM: Drive Strength */
-enum {
-       GPIO_2MA,
-       GPIO_4MA,
-       GPIO_6MA,
-       GPIO_8MA,
-       GPIO_10MA,
-       GPIO_12MA,
-       GPIO_14MA,
-       GPIO_16MA,
-};
-
-enum {
-       GPIO_ENABLE,
-       GPIO_DISABLE,
-};
-
-#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
-       ((((gpio) & 0x3FF) << 4)        |         \
-        ((func) & 0xf)                  |        \
-        (((dir) & 0x1) << 14)           |        \
-        (((pull) & 0x3) << 15)          |        \
-        (((drvstr) & 0xF) << 17))
-
-/**
- * extract GPIO pin from bit-field used for gpio_tlmm_config
- */
-#define GPIO_PIN(gpio_cfg)    (((gpio_cfg) >>  4) & 0x3ff)
-#define GPIO_FUNC(gpio_cfg)   (((gpio_cfg) >>  0) & 0xf)
-#define GPIO_DIR(gpio_cfg)    (((gpio_cfg) >> 14) & 0x1)
-#define GPIO_PULL(gpio_cfg)   (((gpio_cfg) >> 15) & 0x3)
-#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
-
-int gpio_tlmm_config(unsigned config, unsigned disable);
-
 #endif /* __ASM_ARCH_MSM_GPIO_H */
index c35b29f9ac0fb615180344f7edb0bb3440bc1b7b..7386e732baad9d380914fd923404cb7a5e2e1931 100644 (file)
@@ -28,6 +28,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int m
 
 void msm_map_qsd8x50_io(void);
 void msm_map_msm7x30_io(void);
+void msm_map_msm8x60_io(void);
 
 extern unsigned int msm_shared_ram_phys;
 
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
new file mode 100644 (file)
index 0000000..218ef57
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef MSM_IOMMU_H
+#define MSM_IOMMU_H
+
+#include <linux/interrupt.h>
+
+/* Maximum number of Machine IDs that we are allowing to be mapped to the same
+ * context bank. The number of MIDs mapped to the same CB does not affect
+ * performance, but there is a practical limit on how many distinct MIDs may
+ * be present. These mappings are typically determined at design time and are
+ * not expected to change at run time.
+ */
+#define MAX_NUM_MIDS   16
+
+/**
+ * struct msm_iommu_dev - a single IOMMU hardware instance
+ * name                Human-readable name given to this IOMMU HW instance
+ * clk_rate    Rate to set for this IOMMU's clock, if applicable to this
+ *             particular IOMMU. 0 means don't set a rate.
+ *             -1 means it is an AXI clock with no valid rate
+ *
+ */
+struct msm_iommu_dev {
+       const char *name;
+       int clk_rate;
+};
+
+/**
+ * struct msm_iommu_ctx_dev - an IOMMU context bank instance
+ * name                Human-readable name given to this context bank
+ * num         Index of this context bank within the hardware
+ * mids                List of Machine IDs that are to be mapped into this context
+ *             bank, terminated by -1. The MID is a set of signals on the
+ *             AXI bus that identifies the function associated with a specific
+ *             memory request. (See ARM spec).
+ */
+struct msm_iommu_ctx_dev {
+       const char *name;
+       int num;
+       int mids[MAX_NUM_MIDS];
+};
+
+
+/**
+ * struct msm_iommu_drvdata - A single IOMMU hardware instance
+ * @base:      IOMMU config port base address (VA)
+ * @irq:       Interrupt number
+  *
+ * A msm_iommu_drvdata holds the global driver data about a single piece
+ * of an IOMMU hardware instance.
+ */
+struct msm_iommu_drvdata {
+       void __iomem *base;
+       int irq;
+};
+
+/**
+ * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
+ * @num:               Hardware context number of this context
+ * @pdev:              Platform device associated wit this HW instance
+ * @attached_elm:      List element for domains to track which devices are
+ *                     attached to them
+ *
+ * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
+ * within each IOMMU hardware instance
+ */
+struct msm_iommu_ctx_drvdata {
+       int num;
+       struct platform_device *pdev;
+       struct list_head attached_elm;
+};
+
+/*
+ * Look up an IOMMU context device by its context name. NULL if none found.
+ * Useful for testing and drivers that do not yet fully have IOMMU stuff in
+ * their platform devices.
+ */
+struct device *msm_iommu_get_ctx(const char *ctx_name);
+
+/*
+ * Interrupt handler for the IOMMU context fault interrupt. Hooking the
+ * interrupt is not supported in the API yet, but this will print an error
+ * message and dump useful IOMMU registers.
+ */
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
new file mode 100644 (file)
index 0000000..f9386d3
--- /dev/null
@@ -0,0 +1,1871 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+
+#define CTX_SHIFT 12
+
+#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg)))
+#define GET_CTX_REG(reg, base, ctx) \
+                               (readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg)))
+
+#define SET_CTX_REG(reg, base, ctx, val) \
+                       writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+/* Wrappers for numbered registers */
+#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
+#define GET_GLOBAL_REG_N(b, n, r)    GET_GLOBAL_REG(b, ((r) + (n << 2)))
+
+/* Field wrappers */
+#define GET_GLOBAL_FIELD(b, r, F)    GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT)
+#define GET_CONTEXT_FIELD(b, c, r, F)  \
+       GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
+
+#define SET_GLOBAL_FIELD(b, r, F, v) \
+       SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
+#define SET_CONTEXT_FIELD(b, c, r, F, v)       \
+       SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
+
+#define GET_FIELD(addr, mask, shift)  ((readl(addr) >> (shift)) & (mask))
+
+#define SET_FIELD(addr, mask, shift, v) \
+do { \
+       int t = readl(addr); \
+       writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+} while (0)
+
+
+#define NUM_FL_PTE     4096
+#define NUM_SL_PTE     256
+
+/* First-level page table bits */
+#define FL_BASE_MASK           0xFFFFFC00
+#define FL_TYPE_TABLE          (1 << 0)
+#define FL_TYPE_SECT           (2 << 0)
+#define FL_SUPERSECTION                (1 << 18)
+#define FL_AP_WRITE            (1 << 10)
+#define FL_AP_READ             (1 << 11)
+#define FL_SHARED              (1 << 16)
+#define FL_OFFSET(va)          (((va) & 0xFFF00000) >> 20)
+
+/* Second-level page table bits */
+#define SL_BASE_MASK_LARGE     0xFFFF0000
+#define SL_BASE_MASK_SMALL     0xFFFFF000
+#define SL_TYPE_LARGE          (1 << 0)
+#define SL_TYPE_SMALL          (2 << 0)
+#define SL_AP0                 (1 << 4)
+#define SL_AP1                 (2 << 4)
+#define SL_SHARED              (1 << 10)
+#define SL_OFFSET(va)          (((va) & 0xFF000) >> 12)
+
+/* Global register setters / getters */
+#define SET_M2VCBR_N(b, N, v)   SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
+#define SET_CBACR_N(b, N, v)    SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
+#define SET_TLBRSW(b, v)        SET_GLOBAL_REG(TLBRSW, (b), (v))
+#define SET_TLBTR0(b, v)        SET_GLOBAL_REG(TLBTR0, (b), (v))
+#define SET_TLBTR1(b, v)        SET_GLOBAL_REG(TLBTR1, (b), (v))
+#define SET_TLBTR2(b, v)        SET_GLOBAL_REG(TLBTR2, (b), (v))
+#define SET_TESTBUSCR(b, v)     SET_GLOBAL_REG(TESTBUSCR, (b), (v))
+#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
+#define SET_TLBIVMID(b, v)      SET_GLOBAL_REG(TLBIVMID, (b), (v))
+#define SET_CR(b, v)            SET_GLOBAL_REG(CR, (b), (v))
+#define SET_EAR(b, v)           SET_GLOBAL_REG(EAR, (b), (v))
+#define SET_ESR(b, v)           SET_GLOBAL_REG(ESR, (b), (v))
+#define SET_ESRRESTORE(b, v)    SET_GLOBAL_REG(ESRRESTORE, (b), (v))
+#define SET_ESYNR0(b, v)        SET_GLOBAL_REG(ESYNR0, (b), (v))
+#define SET_ESYNR1(b, v)        SET_GLOBAL_REG(ESYNR1, (b), (v))
+#define SET_RPU_ACR(b, v)       SET_GLOBAL_REG(RPU_ACR, (b), (v))
+
+#define GET_M2VCBR_N(b, N)      GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
+#define GET_CBACR_N(b, N)       GET_GLOBAL_REG_N(CBACR_N, N, (b))
+#define GET_TLBTR0(b)           GET_GLOBAL_REG(TLBTR0, (b))
+#define GET_TLBTR1(b)           GET_GLOBAL_REG(TLBTR1, (b))
+#define GET_TLBTR2(b)           GET_GLOBAL_REG(TLBTR2, (b))
+#define GET_TESTBUSCR(b)        GET_GLOBAL_REG(TESTBUSCR, (b))
+#define GET_GLOBAL_TLBIALL(b)   GET_GLOBAL_REG(GLOBAL_TLBIALL, (b))
+#define GET_TLBIVMID(b)                 GET_GLOBAL_REG(TLBIVMID, (b))
+#define GET_CR(b)               GET_GLOBAL_REG(CR, (b))
+#define GET_EAR(b)              GET_GLOBAL_REG(EAR, (b))
+#define GET_ESR(b)              GET_GLOBAL_REG(ESR, (b))
+#define GET_ESRRESTORE(b)       GET_GLOBAL_REG(ESRRESTORE, (b))
+#define GET_ESYNR0(b)           GET_GLOBAL_REG(ESYNR0, (b))
+#define GET_ESYNR1(b)           GET_GLOBAL_REG(ESYNR1, (b))
+#define GET_REV(b)              GET_GLOBAL_REG(REV, (b))
+#define GET_IDR(b)              GET_GLOBAL_REG(IDR, (b))
+#define GET_RPU_ACR(b)          GET_GLOBAL_REG(RPU_ACR, (b))
+
+
+/* Context register setters/getters */
+#define SET_SCTLR(b, c, v)      SET_CTX_REG(SCTLR, (b), (c), (v))
+#define SET_ACTLR(b, c, v)      SET_CTX_REG(ACTLR, (b), (c), (v))
+#define SET_CONTEXTIDR(b, c, v)         SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
+#define SET_TTBR0(b, c, v)      SET_CTX_REG(TTBR0, (b), (c), (v))
+#define SET_TTBR1(b, c, v)      SET_CTX_REG(TTBR1, (b), (c), (v))
+#define SET_TTBCR(b, c, v)      SET_CTX_REG(TTBCR, (b), (c), (v))
+#define SET_PAR(b, c, v)        SET_CTX_REG(PAR, (b), (c), (v))
+#define SET_FSR(b, c, v)        SET_CTX_REG(FSR, (b), (c), (v))
+#define SET_FSRRESTORE(b, c, v)         SET_CTX_REG(FSRRESTORE, (b), (c), (v))
+#define SET_FAR(b, c, v)        SET_CTX_REG(FAR, (b), (c), (v))
+#define SET_FSYNR0(b, c, v)     SET_CTX_REG(FSYNR0, (b), (c), (v))
+#define SET_FSYNR1(b, c, v)     SET_CTX_REG(FSYNR1, (b), (c), (v))
+#define SET_PRRR(b, c, v)       SET_CTX_REG(PRRR, (b), (c), (v))
+#define SET_NMRR(b, c, v)       SET_CTX_REG(NMRR, (b), (c), (v))
+#define SET_TLBLKCR(b, c, v)    SET_CTX_REG(TLBLCKR, (b), (c), (v))
+#define SET_V2PSR(b, c, v)      SET_CTX_REG(V2PSR, (b), (c), (v))
+#define SET_TLBFLPTER(b, c, v)  SET_CTX_REG(TLBFLPTER, (b), (c), (v))
+#define SET_TLBSLPTER(b, c, v)  SET_CTX_REG(TLBSLPTER, (b), (c), (v))
+#define SET_BFBCR(b, c, v)      SET_CTX_REG(BFBCR, (b), (c), (v))
+#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
+#define SET_TLBIASID(b, c, v)   SET_CTX_REG(TLBIASID, (b), (c), (v))
+#define SET_TLBIVA(b, c, v)     SET_CTX_REG(TLBIVA, (b), (c), (v))
+#define SET_TLBIVAA(b, c, v)    SET_CTX_REG(TLBIVAA, (b), (c), (v))
+#define SET_V2PPR(b, c, v)      SET_CTX_REG(V2PPR, (b), (c), (v))
+#define SET_V2PPW(b, c, v)      SET_CTX_REG(V2PPW, (b), (c), (v))
+#define SET_V2PUR(b, c, v)      SET_CTX_REG(V2PUR, (b), (c), (v))
+#define SET_V2PUW(b, c, v)      SET_CTX_REG(V2PUW, (b), (c), (v))
+#define SET_RESUME(b, c, v)     SET_CTX_REG(RESUME, (b), (c), (v))
+
+#define GET_SCTLR(b, c)                 GET_CTX_REG(SCTLR, (b), (c))
+#define GET_ACTLR(b, c)                 GET_CTX_REG(ACTLR, (b), (c))
+#define GET_CONTEXTIDR(b, c)    GET_CTX_REG(CONTEXTIDR, (b), (c))
+#define GET_TTBR0(b, c)                 GET_CTX_REG(TTBR0, (b), (c))
+#define GET_TTBR1(b, c)                 GET_CTX_REG(TTBR1, (b), (c))
+#define GET_TTBCR(b, c)                 GET_CTX_REG(TTBCR, (b), (c))
+#define GET_PAR(b, c)           GET_CTX_REG(PAR, (b), (c))
+#define GET_FSR(b, c)           GET_CTX_REG(FSR, (b), (c))
+#define GET_FSRRESTORE(b, c)    GET_CTX_REG(FSRRESTORE, (b), (c))
+#define GET_FAR(b, c)           GET_CTX_REG(FAR, (b), (c))
+#define GET_FSYNR0(b, c)        GET_CTX_REG(FSYNR0, (b), (c))
+#define GET_FSYNR1(b, c)        GET_CTX_REG(FSYNR1, (b), (c))
+#define GET_PRRR(b, c)          GET_CTX_REG(PRRR, (b), (c))
+#define GET_NMRR(b, c)          GET_CTX_REG(NMRR, (b), (c))
+#define GET_TLBLCKR(b, c)       GET_CTX_REG(TLBLCKR, (b), (c))
+#define GET_V2PSR(b, c)                 GET_CTX_REG(V2PSR, (b), (c))
+#define GET_TLBFLPTER(b, c)     GET_CTX_REG(TLBFLPTER, (b), (c))
+#define GET_TLBSLPTER(b, c)     GET_CTX_REG(TLBSLPTER, (b), (c))
+#define GET_BFBCR(b, c)                 GET_CTX_REG(BFBCR, (b), (c))
+#define GET_CTX_TLBIALL(b, c)   GET_CTX_REG(CTX_TLBIALL, (b), (c))
+#define GET_TLBIASID(b, c)      GET_CTX_REG(TLBIASID, (b), (c))
+#define GET_TLBIVA(b, c)        GET_CTX_REG(TLBIVA, (b), (c))
+#define GET_TLBIVAA(b, c)       GET_CTX_REG(TLBIVAA, (b), (c))
+#define GET_V2PPR(b, c)                 GET_CTX_REG(V2PPR, (b), (c))
+#define GET_V2PPW(b, c)                 GET_CTX_REG(V2PPW, (b), (c))
+#define GET_V2PUR(b, c)                 GET_CTX_REG(V2PUR, (b), (c))
+#define GET_V2PUW(b, c)                 GET_CTX_REG(V2PUW, (b), (c))
+#define GET_RESUME(b, c)        GET_CTX_REG(RESUME, (b), (c))
+
+
+/* Global field setters / getters */
+/* Global Field Setters: */
+/* CBACR_N */
+#define SET_RWVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v)
+#define SET_RWE(b, n, v)      SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v)
+#define SET_RWGE(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v)
+#define SET_CBVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v)
+#define SET_IRPTNDX(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v)
+
+
+/* M2VCBR_N */
+#define SET_VMID(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v)
+#define SET_CBNDX(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v)
+#define SET_BYPASSD(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v)
+#define SET_BPRCOSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v)
+#define SET_BPRCISH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v)
+#define SET_BPRCNSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v)
+#define SET_BPSHCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v)
+#define SET_NSCFG(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v)
+#define SET_BPMTCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v)
+#define SET_BPMEMTYPE(b, n, v) \
+       SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v)
+
+
+/* CR */
+#define SET_RPUE(b, v)          SET_GLOBAL_FIELD(b, CR, RPUE, v)
+#define SET_RPUERE(b, v)        SET_GLOBAL_FIELD(b, CR, RPUERE, v)
+#define SET_RPUEIE(b, v)        SET_GLOBAL_FIELD(b, CR, RPUEIE, v)
+#define SET_DCDEE(b, v)                 SET_GLOBAL_FIELD(b, CR, DCDEE, v)
+#define SET_CLIENTPD(b, v)       SET_GLOBAL_FIELD(b, CR, CLIENTPD, v)
+#define SET_STALLD(b, v)        SET_GLOBAL_FIELD(b, CR, STALLD, v)
+#define SET_TLBLKCRWE(b, v)      SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v)
+#define SET_CR_TLBIALLCFG(b, v)  SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v)
+#define SET_TLBIVMIDCFG(b, v)    SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v)
+#define SET_CR_HUME(b, v)        SET_GLOBAL_FIELD(b, CR, CR_HUME, v)
+
+
+/* ESR */
+#define SET_CFG(b, v)           SET_GLOBAL_FIELD(b, ESR, CFG, v)
+#define SET_BYPASS(b, v)        SET_GLOBAL_FIELD(b, ESR, BYPASS, v)
+#define SET_ESR_MULTI(b, v)      SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v)
+
+
+/* ESYNR0 */
+#define SET_ESYNR0_AMID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v)
+#define SET_ESYNR0_APID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v)
+#define SET_ESYNR0_ABID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v)
+#define SET_ESYNR0_AVMID(b, v)   SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v)
+#define SET_ESYNR0_ATID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v)
+
+
+/* ESYNR1 */
+#define SET_ESYNR1_AMEMTYPE(b, v) \
+                       SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v)
+#define SET_ESYNR1_ASHARED(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v)
+#define SET_ESYNR1_AINNERSHARED(b, v) \
+                       SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v)
+#define SET_ESYNR1_APRIV(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v)
+#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v)
+#define SET_ESYNR1_AINST(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v)
+#define SET_ESYNR1_AWRITE(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v)
+#define SET_ESYNR1_ABURST(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v)
+#define SET_ESYNR1_ALEN(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v)
+#define SET_ESYNR1_ASIZE(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v)
+#define SET_ESYNR1_ALOCK(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v)
+#define SET_ESYNR1_AOOO(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v)
+#define SET_ESYNR1_AFULL(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v)
+#define SET_ESYNR1_AC(b, v)      SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v)
+#define SET_ESYNR1_DCD(b, v)     SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v)
+
+
+/* TESTBUSCR */
+#define SET_TBE(b, v)           SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v)
+#define SET_SPDMBE(b, v)        SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v)
+#define SET_WGSEL(b, v)                 SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v)
+#define SET_TBLSEL(b, v)        SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v)
+#define SET_TBHSEL(b, v)        SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v)
+#define SET_SPDM0SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v)
+#define SET_SPDM1SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v)
+#define SET_SPDM2SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v)
+#define SET_SPDM3SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v)
+
+
+/* TLBIVMID */
+#define SET_TLBIVMID_VMID(b, v)  SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v)
+
+
+/* TLBRSW */
+#define SET_TLBRSW_INDEX(b, v)   SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v)
+#define SET_TLBBFBS(b, v)       SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v)
+
+
+/* TLBTR0 */
+#define SET_PR(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, PR, v)
+#define SET_PW(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, PW, v)
+#define SET_UR(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, UR, v)
+#define SET_UW(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, UW, v)
+#define SET_XN(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, XN, v)
+#define SET_NSDESC(b, v)        SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v)
+#define SET_ISH(b, v)           SET_GLOBAL_FIELD(b, TLBTR0, ISH, v)
+#define SET_SH(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, SH, v)
+#define SET_MT(b, v)            SET_GLOBAL_FIELD(b, TLBTR0, MT, v)
+#define SET_DPSIZR(b, v)        SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v)
+#define SET_DPSIZC(b, v)        SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v)
+
+
+/* TLBTR1 */
+#define SET_TLBTR1_VMID(b, v)    SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v)
+#define SET_TLBTR1_PA(b, v)      SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v)
+
+
+/* TLBTR2 */
+#define SET_TLBTR2_ASID(b, v)    SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v)
+#define SET_TLBTR2_V(b, v)       SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v)
+#define SET_TLBTR2_NSTID(b, v)   SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v)
+#define SET_TLBTR2_NV(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v)
+#define SET_TLBTR2_VA(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v)
+
+
+/* Global Field Getters */
+/* CBACR_N */
+#define GET_RWVMID(b, n)        GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID)
+#define GET_RWE(b, n)           GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE)
+#define GET_RWGE(b, n)          GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE)
+#define GET_CBVMID(b, n)        GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID)
+#define GET_IRPTNDX(b, n)       GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX)
+
+
+/* M2VCBR_N */
+#define GET_VMID(b, n)       GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID)
+#define GET_CBNDX(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX)
+#define GET_BYPASSD(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD)
+#define GET_BPRCOSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH)
+#define GET_BPRCISH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH)
+#define GET_BPRCNSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH)
+#define GET_BPSHCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG)
+#define GET_NSCFG(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG)
+#define GET_BPMTCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG)
+#define GET_BPMEMTYPE(b, n)  GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE)
+
+
+/* CR */
+#define GET_RPUE(b)             GET_GLOBAL_FIELD(b, CR, RPUE)
+#define GET_RPUERE(b)           GET_GLOBAL_FIELD(b, CR, RPUERE)
+#define GET_RPUEIE(b)           GET_GLOBAL_FIELD(b, CR, RPUEIE)
+#define GET_DCDEE(b)            GET_GLOBAL_FIELD(b, CR, DCDEE)
+#define GET_CLIENTPD(b)                 GET_GLOBAL_FIELD(b, CR, CLIENTPD)
+#define GET_STALLD(b)           GET_GLOBAL_FIELD(b, CR, STALLD)
+#define GET_TLBLKCRWE(b)        GET_GLOBAL_FIELD(b, CR, TLBLKCRWE)
+#define GET_CR_TLBIALLCFG(b)    GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG)
+#define GET_TLBIVMIDCFG(b)      GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG)
+#define GET_CR_HUME(b)          GET_GLOBAL_FIELD(b, CR, CR_HUME)
+
+
+/* ESR */
+#define GET_CFG(b)              GET_GLOBAL_FIELD(b, ESR, CFG)
+#define GET_BYPASS(b)           GET_GLOBAL_FIELD(b, ESR, BYPASS)
+#define GET_ESR_MULTI(b)        GET_GLOBAL_FIELD(b, ESR, ESR_MULTI)
+
+
+/* ESYNR0 */
+#define GET_ESYNR0_AMID(b)      GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID)
+#define GET_ESYNR0_APID(b)      GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID)
+#define GET_ESYNR0_ABID(b)      GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID)
+#define GET_ESYNR0_AVMID(b)     GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID)
+#define GET_ESYNR0_ATID(b)      GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID)
+
+
+/* ESYNR1 */
+#define GET_ESYNR1_AMEMTYPE(b)   GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE)
+#define GET_ESYNR1_ASHARED(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED)
+#define GET_ESYNR1_AINNERSHARED(b) \
+                       GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED)
+#define GET_ESYNR1_APRIV(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV)
+#define GET_ESYNR1_APROTNS(b)   GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS)
+#define GET_ESYNR1_AINST(b)     GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST)
+#define GET_ESYNR1_AWRITE(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE)
+#define GET_ESYNR1_ABURST(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST)
+#define GET_ESYNR1_ALEN(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN)
+#define GET_ESYNR1_ASIZE(b)     GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE)
+#define GET_ESYNR1_ALOCK(b)     GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK)
+#define GET_ESYNR1_AOOO(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO)
+#define GET_ESYNR1_AFULL(b)     GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL)
+#define GET_ESYNR1_AC(b)        GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC)
+#define GET_ESYNR1_DCD(b)       GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD)
+
+
+/* IDR */
+#define GET_NM2VCBMT(b)                 GET_GLOBAL_FIELD(b, IDR, NM2VCBMT)
+#define GET_HTW(b)              GET_GLOBAL_FIELD(b, IDR, HTW)
+#define GET_HUM(b)              GET_GLOBAL_FIELD(b, IDR, HUM)
+#define GET_TLBSIZE(b)          GET_GLOBAL_FIELD(b, IDR, TLBSIZE)
+#define GET_NCB(b)              GET_GLOBAL_FIELD(b, IDR, NCB)
+#define GET_NIRPT(b)            GET_GLOBAL_FIELD(b, IDR, NIRPT)
+
+
+/* REV */
+#define GET_MAJOR(b)            GET_GLOBAL_FIELD(b, REV, MAJOR)
+#define GET_MINOR(b)            GET_GLOBAL_FIELD(b, REV, MINOR)
+
+
+/* TESTBUSCR */
+#define GET_TBE(b)              GET_GLOBAL_FIELD(b, TESTBUSCR, TBE)
+#define GET_SPDMBE(b)           GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE)
+#define GET_WGSEL(b)            GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL)
+#define GET_TBLSEL(b)           GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL)
+#define GET_TBHSEL(b)           GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL)
+#define GET_SPDM0SEL(b)                 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL)
+#define GET_SPDM1SEL(b)                 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL)
+#define GET_SPDM2SEL(b)                 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL)
+#define GET_SPDM3SEL(b)                 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL)
+
+
+/* TLBIVMID */
+#define GET_TLBIVMID_VMID(b)    GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID)
+
+
+/* TLBTR0 */
+#define GET_PR(b)               GET_GLOBAL_FIELD(b, TLBTR0, PR)
+#define GET_PW(b)               GET_GLOBAL_FIELD(b, TLBTR0, PW)
+#define GET_UR(b)               GET_GLOBAL_FIELD(b, TLBTR0, UR)
+#define GET_UW(b)               GET_GLOBAL_FIELD(b, TLBTR0, UW)
+#define GET_XN(b)               GET_GLOBAL_FIELD(b, TLBTR0, XN)
+#define GET_NSDESC(b)           GET_GLOBAL_FIELD(b, TLBTR0, NSDESC)
+#define GET_ISH(b)              GET_GLOBAL_FIELD(b, TLBTR0, ISH)
+#define GET_SH(b)               GET_GLOBAL_FIELD(b, TLBTR0, SH)
+#define GET_MT(b)               GET_GLOBAL_FIELD(b, TLBTR0, MT)
+#define GET_DPSIZR(b)           GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR)
+#define GET_DPSIZC(b)           GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC)
+
+
+/* TLBTR1 */
+#define GET_TLBTR1_VMID(b)      GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID)
+#define GET_TLBTR1_PA(b)        GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA)
+
+
+/* TLBTR2 */
+#define GET_TLBTR2_ASID(b)      GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID)
+#define GET_TLBTR2_V(b)                 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V)
+#define GET_TLBTR2_NSTID(b)     GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID)
+#define GET_TLBTR2_NV(b)        GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV)
+#define GET_TLBTR2_VA(b)        GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA)
+
+
+/* Context Register setters / getters */
+/* Context Register setters */
+/* ACTLR */
+#define SET_CFERE(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v)
+#define SET_CFEIE(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v)
+#define SET_PTSHCFG(b, c, v)    SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v)
+#define SET_RCOSH(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v)
+#define SET_RCISH(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v)
+#define SET_RCNSH(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v)
+#define SET_PRIVCFG(b, c, v)    SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v)
+#define SET_DNA(b, c, v)        SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v)
+#define SET_DNLV2PA(b, c, v)    SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v)
+#define SET_TLBMCFG(b, c, v)    SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v)
+#define SET_CFCFG(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v)
+#define SET_TIPCF(b, c, v)      SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v)
+#define SET_V2PCFG(b, c, v)     SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v)
+#define SET_HUME(b, c, v)       SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v)
+#define SET_PTMTCFG(b, c, v)    SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v)
+#define SET_PTMEMTYPE(b, c, v)  SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v)
+
+
+/* BFBCR */
+#define SET_BFBDFE(b, c, v)     SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v)
+#define SET_BFBSFE(b, c, v)     SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v)
+#define SET_SFVS(b, c, v)       SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v)
+#define SET_FLVIC(b, c, v)      SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v)
+#define SET_SLVIC(b, c, v)      SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v)
+
+
+/* CONTEXTIDR */
+#define SET_CONTEXTIDR_ASID(b, c, v)   \
+               SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v)
+#define SET_CONTEXTIDR_PROCID(b, c, v) \
+               SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v)
+
+
+/* FSR */
+#define SET_TF(b, c, v)                 SET_CONTEXT_FIELD(b, c, FSR, TF, v)
+#define SET_AFF(b, c, v)        SET_CONTEXT_FIELD(b, c, FSR, AFF, v)
+#define SET_APF(b, c, v)        SET_CONTEXT_FIELD(b, c, FSR, APF, v)
+#define SET_TLBMF(b, c, v)      SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v)
+#define SET_HTWDEEF(b, c, v)    SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v)
+#define SET_HTWSEEF(b, c, v)    SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v)
+#define SET_MHF(b, c, v)        SET_CONTEXT_FIELD(b, c, FSR, MHF, v)
+#define SET_SL(b, c, v)                 SET_CONTEXT_FIELD(b, c, FSR, SL, v)
+#define SET_SS(b, c, v)                 SET_CONTEXT_FIELD(b, c, FSR, SS, v)
+#define SET_MULTI(b, c, v)      SET_CONTEXT_FIELD(b, c, FSR, MULTI, v)
+
+
+/* FSYNR0 */
+#define SET_AMID(b, c, v)       SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v)
+#define SET_APID(b, c, v)       SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v)
+#define SET_ABID(b, c, v)       SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v)
+#define SET_ATID(b, c, v)       SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v)
+
+
+/* FSYNR1 */
+#define SET_AMEMTYPE(b, c, v)   SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v)
+#define SET_ASHARED(b, c, v)    SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v)
+#define SET_AINNERSHARED(b, c, v)  \
+                               SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v)
+#define SET_APRIV(b, c, v)      SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v)
+#define SET_APROTNS(b, c, v)    SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v)
+#define SET_AINST(b, c, v)      SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v)
+#define SET_AWRITE(b, c, v)     SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v)
+#define SET_ABURST(b, c, v)     SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v)
+#define SET_ALEN(b, c, v)       SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v)
+#define SET_FSYNR1_ASIZE(b, c, v) \
+                               SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v)
+#define SET_ALOCK(b, c, v)      SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v)
+#define SET_AFULL(b, c, v)      SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v)
+
+
+/* NMRR */
+#define SET_ICPC0(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v)
+#define SET_ICPC1(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v)
+#define SET_ICPC2(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v)
+#define SET_ICPC3(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v)
+#define SET_ICPC4(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v)
+#define SET_ICPC5(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v)
+#define SET_ICPC6(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v)
+#define SET_ICPC7(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v)
+#define SET_OCPC0(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v)
+#define SET_OCPC1(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v)
+#define SET_OCPC2(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v)
+#define SET_OCPC3(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v)
+#define SET_OCPC4(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v)
+#define SET_OCPC5(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v)
+#define SET_OCPC6(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v)
+#define SET_OCPC7(b, c, v)      SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v)
+
+
+/* PAR */
+#define SET_FAULT(b, c, v)      SET_CONTEXT_FIELD(b, c, PAR, FAULT, v)
+
+#define SET_FAULT_TF(b, c, v)   SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v)
+#define SET_FAULT_AFF(b, c, v)  SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v)
+#define SET_FAULT_APF(b, c, v)  SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v)
+#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v)
+#define SET_FAULT_HTWDEEF(b, c, v) \
+                               SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v)
+#define SET_FAULT_HTWSEEF(b, c, v) \
+                               SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v)
+#define SET_FAULT_MHF(b, c, v)  SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v)
+#define SET_FAULT_SL(b, c, v)   SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v)
+#define SET_FAULT_SS(b, c, v)   SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v)
+
+#define SET_NOFAULT_SS(b, c, v)         SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v)
+#define SET_NOFAULT_MT(b, c, v)         SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v)
+#define SET_NOFAULT_SH(b, c, v)         SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v)
+#define SET_NOFAULT_NS(b, c, v)         SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v)
+#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v)
+#define SET_NPFAULT_PA(b, c, v)         SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v)
+
+
+/* PRRR */
+#define SET_MTC0(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v)
+#define SET_MTC1(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v)
+#define SET_MTC2(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v)
+#define SET_MTC3(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v)
+#define SET_MTC4(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v)
+#define SET_MTC5(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v)
+#define SET_MTC6(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v)
+#define SET_MTC7(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v)
+#define SET_SHDSH0(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v)
+#define SET_SHDSH1(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v)
+#define SET_SHNMSH0(b, c, v)    SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v)
+#define SET_SHNMSH1(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v)
+#define SET_NOS0(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v)
+#define SET_NOS1(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v)
+#define SET_NOS2(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v)
+#define SET_NOS3(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v)
+#define SET_NOS4(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v)
+#define SET_NOS5(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v)
+#define SET_NOS6(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v)
+#define SET_NOS7(b, c, v)       SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v)
+
+
+/* RESUME */
+#define SET_TNR(b, c, v)        SET_CONTEXT_FIELD(b, c, RESUME, TNR, v)
+
+
+/* SCTLR */
+#define SET_M(b, c, v)          SET_CONTEXT_FIELD(b, c, SCTLR, M, v)
+#define SET_TRE(b, c, v)        SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v)
+#define SET_AFE(b, c, v)        SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v)
+#define SET_HAF(b, c, v)        SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v)
+#define SET_BE(b, c, v)                 SET_CONTEXT_FIELD(b, c, SCTLR, BE, v)
+#define SET_AFFD(b, c, v)       SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v)
+
+
+/* TLBLKCR */
+#define SET_LKE(b, c, v)          SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v)
+#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \
+                       SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v)
+#define SET_TLBIASIDCFG(b, c, v) \
+                       SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v)
+#define SET_TLBIVAACFG(b, c, v)        SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v)
+#define SET_FLOOR(b, c, v)     SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v)
+#define SET_VICTIM(b, c, v)    SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v)
+
+
+/* TTBCR */
+#define SET_N(b, c, v)          SET_CONTEXT_FIELD(b, c, TTBCR, N, v)
+#define SET_PD0(b, c, v)        SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v)
+#define SET_PD1(b, c, v)        SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v)
+
+
+/* TTBR0 */
+#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v)
+#define SET_TTBR0_SH(b, c, v)   SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v)
+#define SET_TTBR0_ORGN(b, c, v)         SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v)
+#define SET_TTBR0_NOS(b, c, v)  SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v)
+#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v)
+#define SET_TTBR0_PA(b, c, v)   SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v)
+
+
+/* TTBR1 */
+#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v)
+#define SET_TTBR1_SH(b, c, v)   SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v)
+#define SET_TTBR1_ORGN(b, c, v)         SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v)
+#define SET_TTBR1_NOS(b, c, v)  SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v)
+#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v)
+#define SET_TTBR1_PA(b, c, v)   SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v)
+
+
+/* V2PSR */
+#define SET_HIT(b, c, v)        SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v)
+#define SET_INDEX(b, c, v)      SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
+
+
+/* V2Pxx UW UR PW PR */
+#define SET_V2PUW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX, v)
+#define SET_V2PUW_VA(b, c, v)   SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA, v)
+
+#define SET_V2PUR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX, v)
+#define SET_V2PUR_VA(b, c, v)   SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA, v)
+
+#define SET_V2PPW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX, v)
+#define SET_V2PPW_VA(b, c, v)   SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA, v)
+
+#define SET_V2PPR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX, v)
+#define SET_V2PPR_VA(b, c, v)   SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA, v)
+
+
+/* Context Register getters */
+/* ACTLR */
+#define GET_CFERE(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
+#define GET_CFEIE(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE)
+#define GET_PTSHCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG)
+#define GET_RCOSH(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH)
+#define GET_RCISH(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, RCISH)
+#define GET_RCNSH(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH)
+#define GET_PRIVCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG)
+#define GET_DNA(b, c)          GET_CONTEXT_FIELD(b, c, ACTLR, DNA)
+#define GET_DNLV2PA(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA)
+#define GET_TLBMCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG)
+#define GET_CFCFG(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG)
+#define GET_TIPCF(b, c)                GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF)
+#define GET_V2PCFG(b, c)        GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG)
+#define GET_HUME(b, c)         GET_CONTEXT_FIELD(b, c, ACTLR, HUME)
+#define GET_PTMTCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG)
+#define GET_PTMEMTYPE(b, c)     GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE)
+
+/* BFBCR */
+#define GET_BFBDFE(b, c)       GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE)
+#define GET_BFBSFE(b, c)       GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE)
+#define GET_SFVS(b, c)         GET_CONTEXT_FIELD(b, c, BFBCR, SFVS)
+#define GET_FLVIC(b, c)                GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC)
+#define GET_SLVIC(b, c)                GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC)
+
+
+/* CONTEXTIDR */
+#define GET_CONTEXTIDR_ASID(b, c) \
+                       GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID)
+#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID)
+
+
+/* FSR */
+#define GET_TF(b, c)           GET_CONTEXT_FIELD(b, c, FSR, TF)
+#define GET_AFF(b, c)          GET_CONTEXT_FIELD(b, c, FSR, AFF)
+#define GET_APF(b, c)          GET_CONTEXT_FIELD(b, c, FSR, APF)
+#define GET_TLBMF(b, c)                GET_CONTEXT_FIELD(b, c, FSR, TLBMF)
+#define GET_HTWDEEF(b, c)      GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF)
+#define GET_HTWSEEF(b, c)      GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF)
+#define GET_MHF(b, c)          GET_CONTEXT_FIELD(b, c, FSR, MHF)
+#define GET_SL(b, c)           GET_CONTEXT_FIELD(b, c, FSR, SL)
+#define GET_SS(b, c)           GET_CONTEXT_FIELD(b, c, FSR, SS)
+#define GET_MULTI(b, c)                GET_CONTEXT_FIELD(b, c, FSR, MULTI)
+
+
+/* FSYNR0 */
+#define GET_AMID(b, c)         GET_CONTEXT_FIELD(b, c, FSYNR0, AMID)
+#define GET_APID(b, c)         GET_CONTEXT_FIELD(b, c, FSYNR0, APID)
+#define GET_ABID(b, c)         GET_CONTEXT_FIELD(b, c, FSYNR0, ABID)
+#define GET_ATID(b, c)         GET_CONTEXT_FIELD(b, c, FSYNR0, ATID)
+
+
+/* FSYNR1 */
+#define GET_AMEMTYPE(b, c)     GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE)
+#define GET_ASHARED(b, c)      GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED)
+#define GET_AINNERSHARED(b, c)  GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED)
+#define GET_APRIV(b, c)                GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV)
+#define GET_APROTNS(b, c)      GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS)
+#define GET_AINST(b, c)                GET_CONTEXT_FIELD(b, c, FSYNR1, AINST)
+#define GET_AWRITE(b, c)       GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE)
+#define GET_ABURST(b, c)       GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST)
+#define GET_ALEN(b, c)         GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN)
+#define GET_FSYNR1_ASIZE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE)
+#define GET_ALOCK(b, c)                GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK)
+#define GET_AFULL(b, c)                GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL)
+
+
+/* NMRR */
+#define GET_ICPC0(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC0)
+#define GET_ICPC1(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC1)
+#define GET_ICPC2(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC2)
+#define GET_ICPC3(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC3)
+#define GET_ICPC4(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC4)
+#define GET_ICPC5(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC5)
+#define GET_ICPC6(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC6)
+#define GET_ICPC7(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, ICPC7)
+#define GET_OCPC0(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC0)
+#define GET_OCPC1(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC1)
+#define GET_OCPC2(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC2)
+#define GET_OCPC3(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC3)
+#define GET_OCPC4(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC4)
+#define GET_OCPC5(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
+#define GET_OCPC6(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
+#define GET_OCPC7(b, c)                GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
+
+
+/* PAR */
+#define GET_FAULT(b, c)                GET_CONTEXT_FIELD(b, c, PAR, FAULT)
+
+#define GET_FAULT_TF(b, c)     GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF)
+#define GET_FAULT_AFF(b, c)    GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF)
+#define GET_FAULT_APF(b, c)    GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF)
+#define GET_FAULT_TLBMF(b, c)   GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF)
+#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF)
+#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF)
+#define GET_FAULT_MHF(b, c)    GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF)
+#define GET_FAULT_SL(b, c)     GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL)
+#define GET_FAULT_SS(b, c)     GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS)
+
+#define GET_NOFAULT_SS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS)
+#define GET_NOFAULT_MT(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT)
+#define GET_NOFAULT_SH(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH)
+#define GET_NOFAULT_NS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS)
+#define GET_NOFAULT_NOS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS)
+#define GET_NPFAULT_PA(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA)
+
+
+/* PRRR */
+#define GET_MTC0(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC0)
+#define GET_MTC1(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC1)
+#define GET_MTC2(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC2)
+#define GET_MTC3(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC3)
+#define GET_MTC4(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC4)
+#define GET_MTC5(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC5)
+#define GET_MTC6(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC6)
+#define GET_MTC7(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, MTC7)
+#define GET_SHDSH0(b, c)       GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0)
+#define GET_SHDSH1(b, c)       GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1)
+#define GET_SHNMSH0(b, c)      GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0)
+#define GET_SHNMSH1(b, c)      GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1)
+#define GET_NOS0(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS0)
+#define GET_NOS1(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS1)
+#define GET_NOS2(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS2)
+#define GET_NOS3(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS3)
+#define GET_NOS4(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS4)
+#define GET_NOS5(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
+#define GET_NOS6(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
+#define GET_NOS7(b, c)         GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
+
+
+/* RESUME */
+#define GET_TNR(b, c)          GET_CONTEXT_FIELD(b, c, RESUME, TNR)
+
+
+/* SCTLR */
+#define GET_M(b, c)            GET_CONTEXT_FIELD(b, c, SCTLR, M)
+#define GET_TRE(b, c)          GET_CONTEXT_FIELD(b, c, SCTLR, TRE)
+#define GET_AFE(b, c)          GET_CONTEXT_FIELD(b, c, SCTLR, AFE)
+#define GET_HAF(b, c)          GET_CONTEXT_FIELD(b, c, SCTLR, HAF)
+#define GET_BE(b, c)           GET_CONTEXT_FIELD(b, c, SCTLR, BE)
+#define GET_AFFD(b, c)         GET_CONTEXT_FIELD(b, c, SCTLR, AFFD)
+
+
+/* TLBLKCR */
+#define GET_LKE(b, c)          GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE)
+#define GET_TLBLCKR_TLBIALLCFG(b, c) \
+                       GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG)
+#define GET_TLBIASIDCFG(b, c)   GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG)
+#define GET_TLBIVAACFG(b, c)   GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG)
+#define GET_FLOOR(b, c)                GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR)
+#define GET_VICTIM(b, c)       GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM)
+
+
+/* TTBCR */
+#define GET_N(b, c)            GET_CONTEXT_FIELD(b, c, TTBCR, N)
+#define GET_PD0(b, c)          GET_CONTEXT_FIELD(b, c, TTBCR, PD0)
+#define GET_PD1(b, c)          GET_CONTEXT_FIELD(b, c, TTBCR, PD1)
+
+
+/* TTBR0 */
+#define GET_TTBR0_IRGNH(b, c)  GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH)
+#define GET_TTBR0_SH(b, c)     GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH)
+#define GET_TTBR0_ORGN(b, c)   GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN)
+#define GET_TTBR0_NOS(b, c)    GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS)
+#define GET_TTBR0_IRGNL(b, c)  GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL)
+#define GET_TTBR0_PA(b, c)     GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA)
+
+
+/* TTBR1 */
+#define GET_TTBR1_IRGNH(b, c)  GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH)
+#define GET_TTBR1_SH(b, c)     GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH)
+#define GET_TTBR1_ORGN(b, c)   GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN)
+#define GET_TTBR1_NOS(b, c)    GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS)
+#define GET_TTBR1_IRGNL(b, c)  GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL)
+#define GET_TTBR1_PA(b, c)     GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA)
+
+
+/* V2PSR */
+#define GET_HIT(b, c)          GET_CONTEXT_FIELD(b, c, V2PSR, HIT)
+#define GET_INDEX(b, c)                GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
+
+
+/* V2Pxx UW UR PW PR */
+#define GET_V2PUW_INDEX(b, c)  GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX)
+#define GET_V2PUW_VA(b, c)     GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA)
+
+#define GET_V2PUR_INDEX(b, c)  GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX)
+#define GET_V2PUR_VA(b, c)     GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA)
+
+#define GET_V2PPW_INDEX(b, c)  GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX)
+#define GET_V2PPW_VA(b, c)     GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA)
+
+#define GET_V2PPR_INDEX(b, c)  GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX)
+#define GET_V2PPR_VA(b, c)     GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA)
+
+
+/* Global Registers */
+#define M2VCBR_N       (0xFF000)
+#define CBACR_N                (0xFF800)
+#define TLBRSW         (0xFFE00)
+#define TLBTR0         (0xFFE80)
+#define TLBTR1         (0xFFE84)
+#define TLBTR2         (0xFFE88)
+#define TESTBUSCR      (0xFFE8C)
+#define GLOBAL_TLBIALL (0xFFF00)
+#define TLBIVMID       (0xFFF04)
+#define CR             (0xFFF80)
+#define EAR            (0xFFF84)
+#define ESR            (0xFFF88)
+#define ESRRESTORE     (0xFFF8C)
+#define ESYNR0         (0xFFF90)
+#define ESYNR1         (0xFFF94)
+#define REV            (0xFFFF4)
+#define IDR            (0xFFFF8)
+#define RPU_ACR                (0xFFFFC)
+
+
+/* Context Bank Registers */
+#define SCTLR          (0x000)
+#define ACTLR          (0x004)
+#define CONTEXTIDR     (0x008)
+#define TTBR0          (0x010)
+#define TTBR1          (0x014)
+#define TTBCR          (0x018)
+#define PAR            (0x01C)
+#define FSR            (0x020)
+#define FSRRESTORE     (0x024)
+#define FAR            (0x028)
+#define FSYNR0         (0x02C)
+#define FSYNR1         (0x030)
+#define PRRR           (0x034)
+#define NMRR           (0x038)
+#define TLBLCKR                (0x03C)
+#define V2PSR          (0x040)
+#define TLBFLPTER      (0x044)
+#define TLBSLPTER      (0x048)
+#define BFBCR          (0x04C)
+#define CTX_TLBIALL    (0x800)
+#define TLBIASID       (0x804)
+#define TLBIVA         (0x808)
+#define TLBIVAA                (0x80C)
+#define V2PPR          (0x810)
+#define V2PPW          (0x814)
+#define V2PUR          (0x818)
+#define V2PUW          (0x81C)
+#define RESUME         (0x820)
+
+
+/* Global Register Fields */
+/* CBACRn */
+#define RWVMID        (RWVMID_MASK       << RWVMID_SHIFT)
+#define RWE           (RWE_MASK          << RWE_SHIFT)
+#define RWGE          (RWGE_MASK         << RWGE_SHIFT)
+#define CBVMID        (CBVMID_MASK       << CBVMID_SHIFT)
+#define IRPTNDX       (IRPTNDX_MASK      << IRPTNDX_SHIFT)
+
+
+/* CR */
+#define RPUE          (RPUE_MASK          << RPUE_SHIFT)
+#define RPUERE        (RPUERE_MASK        << RPUERE_SHIFT)
+#define RPUEIE        (RPUEIE_MASK        << RPUEIE_SHIFT)
+#define DCDEE         (DCDEE_MASK         << DCDEE_SHIFT)
+#define CLIENTPD      (CLIENTPD_MASK      << CLIENTPD_SHIFT)
+#define STALLD        (STALLD_MASK        << STALLD_SHIFT)
+#define TLBLKCRWE     (TLBLKCRWE_MASK     << TLBLKCRWE_SHIFT)
+#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT)
+#define TLBIVMIDCFG   (TLBIVMIDCFG_MASK   << TLBIVMIDCFG_SHIFT)
+#define CR_HUME       (CR_HUME_MASK       << CR_HUME_SHIFT)
+
+
+/* ESR */
+#define CFG           (CFG_MASK          << CFG_SHIFT)
+#define BYPASS        (BYPASS_MASK       << BYPASS_SHIFT)
+#define ESR_MULTI     (ESR_MULTI_MASK    << ESR_MULTI_SHIFT)
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID   (ESYNR0_AMID_MASK  << ESYNR0_AMID_SHIFT)
+#define ESYNR0_APID   (ESYNR0_APID_MASK  << ESYNR0_APID_SHIFT)
+#define ESYNR0_ABID   (ESYNR0_ABID_MASK  << ESYNR0_ABID_SHIFT)
+#define ESYNR0_AVMID  (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT)
+#define ESYNR0_ATID   (ESYNR0_ATID_MASK  << ESYNR0_ATID_SHIFT)
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE      (ESYNR1_AMEMTYPE_MASK    << ESYNR1_AMEMTYPE_SHIFT)
+#define ESYNR1_ASHARED       (ESYNR1_ASHARED_MASK     << ESYNR1_ASHARED_SHIFT)
+#define ESYNR1_AINNERSHARED  (ESYNR1_AINNERSHARED_MASK<< \
+                                               ESYNR1_AINNERSHARED_SHIFT)
+#define ESYNR1_APRIV         (ESYNR1_APRIV_MASK       << ESYNR1_APRIV_SHIFT)
+#define ESYNR1_APROTNS       (ESYNR1_APROTNS_MASK     << ESYNR1_APROTNS_SHIFT)
+#define ESYNR1_AINST         (ESYNR1_AINST_MASK       << ESYNR1_AINST_SHIFT)
+#define ESYNR1_AWRITE        (ESYNR1_AWRITE_MASK      << ESYNR1_AWRITE_SHIFT)
+#define ESYNR1_ABURST        (ESYNR1_ABURST_MASK      << ESYNR1_ABURST_SHIFT)
+#define ESYNR1_ALEN          (ESYNR1_ALEN_MASK        << ESYNR1_ALEN_SHIFT)
+#define ESYNR1_ASIZE         (ESYNR1_ASIZE_MASK       << ESYNR1_ASIZE_SHIFT)
+#define ESYNR1_ALOCK         (ESYNR1_ALOCK_MASK       << ESYNR1_ALOCK_SHIFT)
+#define ESYNR1_AOOO          (ESYNR1_AOOO_MASK        << ESYNR1_AOOO_SHIFT)
+#define ESYNR1_AFULL         (ESYNR1_AFULL_MASK       << ESYNR1_AFULL_SHIFT)
+#define ESYNR1_AC            (ESYNR1_AC_MASK          << ESYNR1_AC_SHIFT)
+#define ESYNR1_DCD           (ESYNR1_DCD_MASK         << ESYNR1_DCD_SHIFT)
+
+
+/* IDR */
+#define NM2VCBMT      (NM2VCBMT_MASK     << NM2VCBMT_SHIFT)
+#define HTW           (HTW_MASK          << HTW_SHIFT)
+#define HUM           (HUM_MASK          << HUM_SHIFT)
+#define TLBSIZE       (TLBSIZE_MASK      << TLBSIZE_SHIFT)
+#define NCB           (NCB_MASK          << NCB_SHIFT)
+#define NIRPT         (NIRPT_MASK        << NIRPT_SHIFT)
+
+
+/* M2VCBRn */
+#define VMID          (VMID_MASK         << VMID_SHIFT)
+#define CBNDX         (CBNDX_MASK        << CBNDX_SHIFT)
+#define BYPASSD       (BYPASSD_MASK      << BYPASSD_SHIFT)
+#define BPRCOSH       (BPRCOSH_MASK      << BPRCOSH_SHIFT)
+#define BPRCISH       (BPRCISH_MASK      << BPRCISH_SHIFT)
+#define BPRCNSH       (BPRCNSH_MASK      << BPRCNSH_SHIFT)
+#define BPSHCFG       (BPSHCFG_MASK      << BPSHCFG_SHIFT)
+#define NSCFG         (NSCFG_MASK        << NSCFG_SHIFT)
+#define BPMTCFG       (BPMTCFG_MASK      << BPMTCFG_SHIFT)
+#define BPMEMTYPE     (BPMEMTYPE_MASK    << BPMEMTYPE_SHIFT)
+
+
+/* REV */
+#define IDR_MINOR     (MINOR_MASK        << MINOR_SHIFT)
+#define IDR_MAJOR     (MAJOR_MASK        << MAJOR_SHIFT)
+
+
+/* TESTBUSCR */
+#define TBE           (TBE_MASK          << TBE_SHIFT)
+#define SPDMBE        (SPDMBE_MASK       << SPDMBE_SHIFT)
+#define WGSEL         (WGSEL_MASK        << WGSEL_SHIFT)
+#define TBLSEL        (TBLSEL_MASK       << TBLSEL_SHIFT)
+#define TBHSEL        (TBHSEL_MASK       << TBHSEL_SHIFT)
+#define SPDM0SEL      (SPDM0SEL_MASK     << SPDM0SEL_SHIFT)
+#define SPDM1SEL      (SPDM1SEL_MASK     << SPDM1SEL_SHIFT)
+#define SPDM2SEL      (SPDM2SEL_MASK     << SPDM2SEL_SHIFT)
+#define SPDM3SEL      (SPDM3SEL_MASK     << SPDM3SEL_SHIFT)
+
+
+/* TLBIVMID */
+#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT)
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX  (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT)
+#define TLBBFBS       (TLBBFBS_MASK      << TLBBFBS_SHIFT)
+
+
+/* TLBTR0 */
+#define PR            (PR_MASK           << PR_SHIFT)
+#define PW            (PW_MASK           << PW_SHIFT)
+#define UR            (UR_MASK           << UR_SHIFT)
+#define UW            (UW_MASK           << UW_SHIFT)
+#define XN            (XN_MASK           << XN_SHIFT)
+#define NSDESC        (NSDESC_MASK       << NSDESC_SHIFT)
+#define ISH           (ISH_MASK          << ISH_SHIFT)
+#define SH            (SH_MASK           << SH_SHIFT)
+#define MT            (MT_MASK           << MT_SHIFT)
+#define DPSIZR        (DPSIZR_MASK       << DPSIZR_SHIFT)
+#define DPSIZC        (DPSIZC_MASK       << DPSIZC_SHIFT)
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID   (TLBTR1_VMID_MASK  << TLBTR1_VMID_SHIFT)
+#define TLBTR1_PA     (TLBTR1_PA_MASK    << TLBTR1_PA_SHIFT)
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID   (TLBTR2_ASID_MASK  << TLBTR2_ASID_SHIFT)
+#define TLBTR2_V      (TLBTR2_V_MASK     << TLBTR2_V_SHIFT)
+#define TLBTR2_NSTID  (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT)
+#define TLBTR2_NV     (TLBTR2_NV_MASK    << TLBTR2_NV_SHIFT)
+#define TLBTR2_VA     (TLBTR2_VA_MASK    << TLBTR2_VA_SHIFT)
+
+
+/* Context Register Fields */
+/* ACTLR */
+#define CFERE              (CFERE_MASK              << CFERE_SHIFT)
+#define CFEIE              (CFEIE_MASK              << CFEIE_SHIFT)
+#define PTSHCFG            (PTSHCFG_MASK            << PTSHCFG_SHIFT)
+#define RCOSH              (RCOSH_MASK              << RCOSH_SHIFT)
+#define RCISH              (RCISH_MASK              << RCISH_SHIFT)
+#define RCNSH              (RCNSH_MASK              << RCNSH_SHIFT)
+#define PRIVCFG            (PRIVCFG_MASK            << PRIVCFG_SHIFT)
+#define DNA                (DNA_MASK                << DNA_SHIFT)
+#define DNLV2PA            (DNLV2PA_MASK            << DNLV2PA_SHIFT)
+#define TLBMCFG            (TLBMCFG_MASK            << TLBMCFG_SHIFT)
+#define CFCFG              (CFCFG_MASK              << CFCFG_SHIFT)
+#define TIPCF              (TIPCF_MASK              << TIPCF_SHIFT)
+#define V2PCFG             (V2PCFG_MASK             << V2PCFG_SHIFT)
+#define HUME               (HUME_MASK               << HUME_SHIFT)
+#define PTMTCFG            (PTMTCFG_MASK            << PTMTCFG_SHIFT)
+#define PTMEMTYPE          (PTMEMTYPE_MASK          << PTMEMTYPE_SHIFT)
+
+
+/* BFBCR */
+#define BFBDFE             (BFBDFE_MASK             << BFBDFE_SHIFT)
+#define BFBSFE             (BFBSFE_MASK             << BFBSFE_SHIFT)
+#define SFVS               (SFVS_MASK               << SFVS_SHIFT)
+#define FLVIC              (FLVIC_MASK              << FLVIC_SHIFT)
+#define SLVIC              (SLVIC_MASK              << SLVIC_SHIFT)
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID    (CONTEXTIDR_ASID_MASK    << CONTEXTIDR_ASID_SHIFT)
+#define PROCID             (PROCID_MASK             << PROCID_SHIFT)
+
+
+/* FSR */
+#define TF                 (TF_MASK                 << TF_SHIFT)
+#define AFF                (AFF_MASK                << AFF_SHIFT)
+#define APF                (APF_MASK                << APF_SHIFT)
+#define TLBMF              (TLBMF_MASK              << TLBMF_SHIFT)
+#define HTWDEEF            (HTWDEEF_MASK            << HTWDEEF_SHIFT)
+#define HTWSEEF            (HTWSEEF_MASK            << HTWSEEF_SHIFT)
+#define MHF                (MHF_MASK                << MHF_SHIFT)
+#define SL                 (SL_MASK                 << SL_SHIFT)
+#define SS                 (SS_MASK                 << SS_SHIFT)
+#define MULTI              (MULTI_MASK              << MULTI_SHIFT)
+
+
+/* FSYNR0 */
+#define AMID               (AMID_MASK               << AMID_SHIFT)
+#define APID               (APID_MASK               << APID_SHIFT)
+#define ABID               (ABID_MASK               << ABID_SHIFT)
+#define ATID               (ATID_MASK               << ATID_SHIFT)
+
+
+/* FSYNR1 */
+#define AMEMTYPE           (AMEMTYPE_MASK           << AMEMTYPE_SHIFT)
+#define ASHARED            (ASHARED_MASK            << ASHARED_SHIFT)
+#define AINNERSHARED       (AINNERSHARED_MASK       << AINNERSHARED_SHIFT)
+#define APRIV              (APRIV_MASK              << APRIV_SHIFT)
+#define APROTNS            (APROTNS_MASK            << APROTNS_SHIFT)
+#define AINST              (AINST_MASK              << AINST_SHIFT)
+#define AWRITE             (AWRITE_MASK             << AWRITE_SHIFT)
+#define ABURST             (ABURST_MASK             << ABURST_SHIFT)
+#define ALEN               (ALEN_MASK               << ALEN_SHIFT)
+#define FSYNR1_ASIZE       (FSYNR1_ASIZE_MASK       << FSYNR1_ASIZE_SHIFT)
+#define ALOCK              (ALOCK_MASK              << ALOCK_SHIFT)
+#define AFULL              (AFULL_MASK              << AFULL_SHIFT)
+
+
+/* NMRR */
+#define ICPC0              (ICPC0_MASK              << ICPC0_SHIFT)
+#define ICPC1              (ICPC1_MASK              << ICPC1_SHIFT)
+#define ICPC2              (ICPC2_MASK              << ICPC2_SHIFT)
+#define ICPC3              (ICPC3_MASK              << ICPC3_SHIFT)
+#define ICPC4              (ICPC4_MASK              << ICPC4_SHIFT)
+#define ICPC5              (ICPC5_MASK              << ICPC5_SHIFT)
+#define ICPC6              (ICPC6_MASK              << ICPC6_SHIFT)
+#define ICPC7              (ICPC7_MASK              << ICPC7_SHIFT)
+#define OCPC0              (OCPC0_MASK              << OCPC0_SHIFT)
+#define OCPC1              (OCPC1_MASK              << OCPC1_SHIFT)
+#define OCPC2              (OCPC2_MASK              << OCPC2_SHIFT)
+#define OCPC3              (OCPC3_MASK              << OCPC3_SHIFT)
+#define OCPC4              (OCPC4_MASK              << OCPC4_SHIFT)
+#define OCPC5              (OCPC5_MASK              << OCPC5_SHIFT)
+#define OCPC6              (OCPC6_MASK              << OCPC6_SHIFT)
+#define OCPC7              (OCPC7_MASK              << OCPC7_SHIFT)
+
+
+/* PAR */
+#define FAULT              (FAULT_MASK              << FAULT_SHIFT)
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF           (FAULT_TF_MASK           << FAULT_TF_SHIFT)
+#define FAULT_AFF          (FAULT_AFF_MASK          << FAULT_AFF_SHIFT)
+#define FAULT_APF          (FAULT_APF_MASK          << FAULT_APF_SHIFT)
+#define FAULT_TLBMF        (FAULT_TLBMF_MASK        << FAULT_TLBMF_SHIFT)
+#define FAULT_HTWDEEF      (FAULT_HTWDEEF_MASK      << FAULT_HTWDEEF_SHIFT)
+#define FAULT_HTWSEEF      (FAULT_HTWSEEF_MASK      << FAULT_HTWSEEF_SHIFT)
+#define FAULT_MHF          (FAULT_MHF_MASK          << FAULT_MHF_SHIFT)
+#define FAULT_SL           (FAULT_SL_MASK           << FAULT_SL_SHIFT)
+#define FAULT_SS           (FAULT_SS_MASK           << FAULT_SS_SHIFT)
+
+/* If NO fault is present, the following fields are in effect */
+/* (FAULT remains as before) */
+#define PAR_NOFAULT_SS     (PAR_NOFAULT_SS_MASK     << PAR_NOFAULT_SS_SHIFT)
+#define PAR_NOFAULT_MT     (PAR_NOFAULT_MT_MASK     << PAR_NOFAULT_MT_SHIFT)
+#define PAR_NOFAULT_SH     (PAR_NOFAULT_SH_MASK     << PAR_NOFAULT_SH_SHIFT)
+#define PAR_NOFAULT_NS     (PAR_NOFAULT_NS_MASK     << PAR_NOFAULT_NS_SHIFT)
+#define PAR_NOFAULT_NOS    (PAR_NOFAULT_NOS_MASK    << PAR_NOFAULT_NOS_SHIFT)
+#define PAR_NPFAULT_PA     (PAR_NPFAULT_PA_MASK     << PAR_NPFAULT_PA_SHIFT)
+
+
+/* PRRR */
+#define MTC0               (MTC0_MASK               << MTC0_SHIFT)
+#define MTC1               (MTC1_MASK               << MTC1_SHIFT)
+#define MTC2               (MTC2_MASK               << MTC2_SHIFT)
+#define MTC3               (MTC3_MASK               << MTC3_SHIFT)
+#define MTC4               (MTC4_MASK               << MTC4_SHIFT)
+#define MTC5               (MTC5_MASK               << MTC5_SHIFT)
+#define MTC6               (MTC6_MASK               << MTC6_SHIFT)
+#define MTC7               (MTC7_MASK               << MTC7_SHIFT)
+#define SHDSH0             (SHDSH0_MASK             << SHDSH0_SHIFT)
+#define SHDSH1             (SHDSH1_MASK             << SHDSH1_SHIFT)
+#define SHNMSH0            (SHNMSH0_MASK            << SHNMSH0_SHIFT)
+#define SHNMSH1            (SHNMSH1_MASK            << SHNMSH1_SHIFT)
+#define NOS0               (NOS0_MASK               << NOS0_SHIFT)
+#define NOS1               (NOS1_MASK               << NOS1_SHIFT)
+#define NOS2               (NOS2_MASK               << NOS2_SHIFT)
+#define NOS3               (NOS3_MASK               << NOS3_SHIFT)
+#define NOS4               (NOS4_MASK               << NOS4_SHIFT)
+#define NOS5               (NOS5_MASK               << NOS5_SHIFT)
+#define NOS6               (NOS6_MASK               << NOS6_SHIFT)
+#define NOS7               (NOS7_MASK               << NOS7_SHIFT)
+
+
+/* RESUME */
+#define TNR                (TNR_MASK                << TNR_SHIFT)
+
+
+/* SCTLR */
+#define M                  (M_MASK                  << M_SHIFT)
+#define TRE                (TRE_MASK                << TRE_SHIFT)
+#define AFE                (AFE_MASK                << AFE_SHIFT)
+#define HAF                (HAF_MASK                << HAF_SHIFT)
+#define BE                 (BE_MASK                 << BE_SHIFT)
+#define AFFD               (AFFD_MASK               << AFFD_SHIFT)
+
+
+/* TLBIASID */
+#define TLBIASID_ASID      (TLBIASID_ASID_MASK      << TLBIASID_ASID_SHIFT)
+
+
+/* TLBIVA */
+#define TLBIVA_ASID        (TLBIVA_ASID_MASK        << TLBIVA_ASID_SHIFT)
+#define TLBIVA_VA          (TLBIVA_VA_MASK          << TLBIVA_VA_SHIFT)
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA         (TLBIVAA_VA_MASK         << TLBIVAA_VA_SHIFT)
+
+
+/* TLBLCKR */
+#define LKE                (LKE_MASK                << LKE_SHIFT)
+#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT)
+#define TLBIASIDCFG        (TLBIASIDCFG_MASK        << TLBIASIDCFG_SHIFT)
+#define TLBIVAACFG         (TLBIVAACFG_MASK         << TLBIVAACFG_SHIFT)
+#define FLOOR              (FLOOR_MASK              << FLOOR_SHIFT)
+#define VICTIM             (VICTIM_MASK             << VICTIM_SHIFT)
+
+
+/* TTBCR */
+#define N                  (N_MASK                  << N_SHIFT)
+#define PD0                (PD0_MASK                << PD0_SHIFT)
+#define PD1                (PD1_MASK                << PD1_SHIFT)
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH        (TTBR0_IRGNH_MASK        << TTBR0_IRGNH_SHIFT)
+#define TTBR0_SH           (TTBR0_SH_MASK           << TTBR0_SH_SHIFT)
+#define TTBR0_ORGN         (TTBR0_ORGN_MASK         << TTBR0_ORGN_SHIFT)
+#define TTBR0_NOS          (TTBR0_NOS_MASK          << TTBR0_NOS_SHIFT)
+#define TTBR0_IRGNL        (TTBR0_IRGNL_MASK        << TTBR0_IRGNL_SHIFT)
+#define TTBR0_PA           (TTBR0_PA_MASK           << TTBR0_PA_SHIFT)
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH        (TTBR1_IRGNH_MASK        << TTBR1_IRGNH_SHIFT)
+#define TTBR1_SH           (TTBR1_SH_MASK           << TTBR1_SH_SHIFT)
+#define TTBR1_ORGN         (TTBR1_ORGN_MASK         << TTBR1_ORGN_SHIFT)
+#define TTBR1_NOS          (TTBR1_NOS_MASK          << TTBR1_NOS_SHIFT)
+#define TTBR1_IRGNL        (TTBR1_IRGNL_MASK        << TTBR1_IRGNL_SHIFT)
+#define TTBR1_PA           (TTBR1_PA_MASK           << TTBR1_PA_SHIFT)
+
+
+/* V2PSR */
+#define HIT                (HIT_MASK                << HIT_SHIFT)
+#define INDEX              (INDEX_MASK              << INDEX_SHIFT)
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX        (V2Pxx_INDEX_MASK        << V2Pxx_INDEX_SHIFT)
+#define V2Pxx_VA           (V2Pxx_VA_MASK           << V2Pxx_VA_SHIFT)
+
+
+/* Global Register Masks */
+/* CBACRn */
+#define RWVMID_MASK               0x1F
+#define RWE_MASK                  0x01
+#define RWGE_MASK                 0x01
+#define CBVMID_MASK               0x1F
+#define IRPTNDX_MASK              0xFF
+
+
+/* CR */
+#define RPUE_MASK                 0x01
+#define RPUERE_MASK               0x01
+#define RPUEIE_MASK               0x01
+#define DCDEE_MASK                0x01
+#define CLIENTPD_MASK             0x01
+#define STALLD_MASK               0x01
+#define TLBLKCRWE_MASK            0x01
+#define CR_TLBIALLCFG_MASK        0x01
+#define TLBIVMIDCFG_MASK          0x01
+#define CR_HUME_MASK              0x01
+
+
+/* ESR */
+#define CFG_MASK                  0x01
+#define BYPASS_MASK               0x01
+#define ESR_MULTI_MASK            0x01
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_MASK          0xFF
+#define ESYNR0_APID_MASK          0x1F
+#define ESYNR0_ABID_MASK          0x07
+#define ESYNR0_AVMID_MASK         0x1F
+#define ESYNR0_ATID_MASK          0xFF
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_MASK             0x07
+#define ESYNR1_ASHARED_MASK              0x01
+#define ESYNR1_AINNERSHARED_MASK         0x01
+#define ESYNR1_APRIV_MASK                0x01
+#define ESYNR1_APROTNS_MASK              0x01
+#define ESYNR1_AINST_MASK                0x01
+#define ESYNR1_AWRITE_MASK               0x01
+#define ESYNR1_ABURST_MASK               0x01
+#define ESYNR1_ALEN_MASK                 0x0F
+#define ESYNR1_ASIZE_MASK                0x01
+#define ESYNR1_ALOCK_MASK                0x03
+#define ESYNR1_AOOO_MASK                 0x01
+#define ESYNR1_AFULL_MASK                0x01
+#define ESYNR1_AC_MASK                   0x01
+#define ESYNR1_DCD_MASK                  0x01
+
+
+/* IDR */
+#define NM2VCBMT_MASK             0x1FF
+#define HTW_MASK                  0x01
+#define HUM_MASK                  0x01
+#define TLBSIZE_MASK              0x0F
+#define NCB_MASK                  0xFF
+#define NIRPT_MASK                0xFF
+
+
+/* M2VCBRn */
+#define VMID_MASK                 0x1F
+#define CBNDX_MASK                0xFF
+#define BYPASSD_MASK              0x01
+#define BPRCOSH_MASK              0x01
+#define BPRCISH_MASK              0x01
+#define BPRCNSH_MASK              0x01
+#define BPSHCFG_MASK              0x03
+#define NSCFG_MASK                0x03
+#define BPMTCFG_MASK              0x01
+#define BPMEMTYPE_MASK            0x07
+
+
+/* REV */
+#define MINOR_MASK                0x0F
+#define MAJOR_MASK                0x0F
+
+
+/* TESTBUSCR */
+#define TBE_MASK                  0x01
+#define SPDMBE_MASK               0x01
+#define WGSEL_MASK                0x03
+#define TBLSEL_MASK               0x03
+#define TBHSEL_MASK               0x03
+#define SPDM0SEL_MASK             0x0F
+#define SPDM1SEL_MASK             0x0F
+#define SPDM2SEL_MASK             0x0F
+#define SPDM3SEL_MASK             0x0F
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_MASK        0x1F
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_MASK         0xFF
+#define TLBBFBS_MASK              0x03
+
+
+/* TLBTR0 */
+#define PR_MASK                   0x01
+#define PW_MASK                   0x01
+#define UR_MASK                   0x01
+#define UW_MASK                   0x01
+#define XN_MASK                   0x01
+#define NSDESC_MASK               0x01
+#define ISH_MASK                  0x01
+#define SH_MASK                   0x01
+#define MT_MASK                   0x07
+#define DPSIZR_MASK               0x07
+#define DPSIZC_MASK               0x07
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_MASK          0x1F
+#define TLBTR1_PA_MASK            0x000FFFFF
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_MASK          0xFF
+#define TLBTR2_V_MASK             0x01
+#define TLBTR2_NSTID_MASK         0x01
+#define TLBTR2_NV_MASK            0x01
+#define TLBTR2_VA_MASK            0x000FFFFF
+
+
+/* Global Register Shifts */
+/* CBACRn */
+#define RWVMID_SHIFT             0
+#define RWE_SHIFT                8
+#define RWGE_SHIFT               9
+#define CBVMID_SHIFT             16
+#define IRPTNDX_SHIFT            24
+
+
+/* CR */
+#define RPUE_SHIFT               0
+#define RPUERE_SHIFT             1
+#define RPUEIE_SHIFT             2
+#define DCDEE_SHIFT              3
+#define CLIENTPD_SHIFT           4
+#define STALLD_SHIFT             5
+#define TLBLKCRWE_SHIFT          6
+#define CR_TLBIALLCFG_SHIFT      7
+#define TLBIVMIDCFG_SHIFT        8
+#define CR_HUME_SHIFT            9
+
+
+/* ESR */
+#define CFG_SHIFT                0
+#define BYPASS_SHIFT             1
+#define ESR_MULTI_SHIFT          31
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_SHIFT        0
+#define ESYNR0_APID_SHIFT        8
+#define ESYNR0_ABID_SHIFT        13
+#define ESYNR0_AVMID_SHIFT       16
+#define ESYNR0_ATID_SHIFT        24
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_SHIFT           0
+#define ESYNR1_ASHARED_SHIFT            3
+#define ESYNR1_AINNERSHARED_SHIFT       4
+#define ESYNR1_APRIV_SHIFT              5
+#define ESYNR1_APROTNS_SHIFT            6
+#define ESYNR1_AINST_SHIFT              7
+#define ESYNR1_AWRITE_SHIFT             8
+#define ESYNR1_ABURST_SHIFT             10
+#define ESYNR1_ALEN_SHIFT               12
+#define ESYNR1_ASIZE_SHIFT              16
+#define ESYNR1_ALOCK_SHIFT              20
+#define ESYNR1_AOOO_SHIFT               22
+#define ESYNR1_AFULL_SHIFT              24
+#define ESYNR1_AC_SHIFT                 30
+#define ESYNR1_DCD_SHIFT                31
+
+
+/* IDR */
+#define NM2VCBMT_SHIFT           0
+#define HTW_SHIFT                9
+#define HUM_SHIFT                10
+#define TLBSIZE_SHIFT            12
+#define NCB_SHIFT                16
+#define NIRPT_SHIFT              24
+
+
+/* M2VCBRn */
+#define VMID_SHIFT               0
+#define CBNDX_SHIFT              8
+#define BYPASSD_SHIFT            16
+#define BPRCOSH_SHIFT            17
+#define BPRCISH_SHIFT            18
+#define BPRCNSH_SHIFT            19
+#define BPSHCFG_SHIFT            20
+#define NSCFG_SHIFT              22
+#define BPMTCFG_SHIFT            24
+#define BPMEMTYPE_SHIFT          25
+
+
+/* REV */
+#define MINOR_SHIFT              0
+#define MAJOR_SHIFT              4
+
+
+/* TESTBUSCR */
+#define TBE_SHIFT                0
+#define SPDMBE_SHIFT             1
+#define WGSEL_SHIFT              8
+#define TBLSEL_SHIFT             12
+#define TBHSEL_SHIFT             14
+#define SPDM0SEL_SHIFT           16
+#define SPDM1SEL_SHIFT           20
+#define SPDM2SEL_SHIFT           24
+#define SPDM3SEL_SHIFT           28
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_SHIFT      0
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_SHIFT       0
+#define TLBBFBS_SHIFT            8
+
+
+/* TLBTR0 */
+#define PR_SHIFT                 0
+#define PW_SHIFT                 1
+#define UR_SHIFT                 2
+#define UW_SHIFT                 3
+#define XN_SHIFT                 4
+#define NSDESC_SHIFT             6
+#define ISH_SHIFT                7
+#define SH_SHIFT                 8
+#define MT_SHIFT                 9
+#define DPSIZR_SHIFT             16
+#define DPSIZC_SHIFT             20
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_SHIFT        0
+#define TLBTR1_PA_SHIFT          12
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_SHIFT        0
+#define TLBTR2_V_SHIFT           8
+#define TLBTR2_NSTID_SHIFT       9
+#define TLBTR2_NV_SHIFT          10
+#define TLBTR2_VA_SHIFT          12
+
+
+/* Context Register Masks */
+/* ACTLR */
+#define CFERE_MASK                       0x01
+#define CFEIE_MASK                       0x01
+#define PTSHCFG_MASK                     0x03
+#define RCOSH_MASK                       0x01
+#define RCISH_MASK                       0x01
+#define RCNSH_MASK                       0x01
+#define PRIVCFG_MASK                     0x03
+#define DNA_MASK                         0x01
+#define DNLV2PA_MASK                     0x01
+#define TLBMCFG_MASK                     0x03
+#define CFCFG_MASK                       0x01
+#define TIPCF_MASK                       0x01
+#define V2PCFG_MASK                      0x03
+#define HUME_MASK                        0x01
+#define PTMTCFG_MASK                     0x01
+#define PTMEMTYPE_MASK                   0x07
+
+
+/* BFBCR */
+#define BFBDFE_MASK                      0x01
+#define BFBSFE_MASK                      0x01
+#define SFVS_MASK                        0x01
+#define FLVIC_MASK                       0x0F
+#define SLVIC_MASK                       0x0F
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_MASK             0xFF
+#define PROCID_MASK                      0x00FFFFFF
+
+
+/* FSR */
+#define TF_MASK                          0x01
+#define AFF_MASK                         0x01
+#define APF_MASK                         0x01
+#define TLBMF_MASK                       0x01
+#define HTWDEEF_MASK                     0x01
+#define HTWSEEF_MASK                     0x01
+#define MHF_MASK                         0x01
+#define SL_MASK                          0x01
+#define SS_MASK                          0x01
+#define MULTI_MASK                       0x01
+
+
+/* FSYNR0 */
+#define AMID_MASK                        0xFF
+#define APID_MASK                        0x1F
+#define ABID_MASK                        0x07
+#define ATID_MASK                        0xFF
+
+
+/* FSYNR1 */
+#define AMEMTYPE_MASK                    0x07
+#define ASHARED_MASK                     0x01
+#define AINNERSHARED_MASK                0x01
+#define APRIV_MASK                       0x01
+#define APROTNS_MASK                     0x01
+#define AINST_MASK                       0x01
+#define AWRITE_MASK                      0x01
+#define ABURST_MASK                      0x01
+#define ALEN_MASK                        0x0F
+#define FSYNR1_ASIZE_MASK                0x07
+#define ALOCK_MASK                       0x03
+#define AFULL_MASK                       0x01
+
+
+/* NMRR */
+#define ICPC0_MASK                       0x03
+#define ICPC1_MASK                       0x03
+#define ICPC2_MASK                       0x03
+#define ICPC3_MASK                       0x03
+#define ICPC4_MASK                       0x03
+#define ICPC5_MASK                       0x03
+#define ICPC6_MASK                       0x03
+#define ICPC7_MASK                       0x03
+#define OCPC0_MASK                       0x03
+#define OCPC1_MASK                       0x03
+#define OCPC2_MASK                       0x03
+#define OCPC3_MASK                       0x03
+#define OCPC4_MASK                       0x03
+#define OCPC5_MASK                       0x03
+#define OCPC6_MASK                       0x03
+#define OCPC7_MASK                       0x03
+
+
+/* PAR */
+#define FAULT_MASK                       0x01
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_MASK                    0x01
+#define FAULT_AFF_MASK                   0x01
+#define FAULT_APF_MASK                   0x01
+#define FAULT_TLBMF_MASK                 0x01
+#define FAULT_HTWDEEF_MASK               0x01
+#define FAULT_HTWSEEF_MASK               0x01
+#define FAULT_MHF_MASK                   0x01
+#define FAULT_SL_MASK                    0x01
+#define FAULT_SS_MASK                    0x01
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_MASK              0x01
+#define PAR_NOFAULT_MT_MASK              0x07
+#define PAR_NOFAULT_SH_MASK              0x01
+#define PAR_NOFAULT_NS_MASK              0x01
+#define PAR_NOFAULT_NOS_MASK             0x01
+#define PAR_NPFAULT_PA_MASK              0x000FFFFF
+
+
+/* PRRR */
+#define MTC0_MASK                        0x03
+#define MTC1_MASK                        0x03
+#define MTC2_MASK                        0x03
+#define MTC3_MASK                        0x03
+#define MTC4_MASK                        0x03
+#define MTC5_MASK                        0x03
+#define MTC6_MASK                        0x03
+#define MTC7_MASK                        0x03
+#define SHDSH0_MASK                      0x01
+#define SHDSH1_MASK                      0x01
+#define SHNMSH0_MASK                     0x01
+#define SHNMSH1_MASK                     0x01
+#define NOS0_MASK                        0x01
+#define NOS1_MASK                        0x01
+#define NOS2_MASK                        0x01
+#define NOS3_MASK                        0x01
+#define NOS4_MASK                        0x01
+#define NOS5_MASK                        0x01
+#define NOS6_MASK                        0x01
+#define NOS7_MASK                        0x01
+
+
+/* RESUME */
+#define TNR_MASK                         0x01
+
+
+/* SCTLR */
+#define M_MASK                           0x01
+#define TRE_MASK                         0x01
+#define AFE_MASK                         0x01
+#define HAF_MASK                         0x01
+#define BE_MASK                          0x01
+#define AFFD_MASK                        0x01
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_MASK               0xFF
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_MASK                 0xFF
+#define TLBIVA_VA_MASK                   0x000FFFFF
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_MASK                  0x000FFFFF
+
+
+/* TLBLCKR */
+#define LKE_MASK                         0x01
+#define TLBLCKR_TLBIALLCFG_MASK          0x01
+#define TLBIASIDCFG_MASK                 0x01
+#define TLBIVAACFG_MASK                  0x01
+#define FLOOR_MASK                       0xFF
+#define VICTIM_MASK                      0xFF
+
+
+/* TTBCR */
+#define N_MASK                           0x07
+#define PD0_MASK                         0x01
+#define PD1_MASK                         0x01
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_MASK                 0x01
+#define TTBR0_SH_MASK                    0x01
+#define TTBR0_ORGN_MASK                  0x03
+#define TTBR0_NOS_MASK                   0x01
+#define TTBR0_IRGNL_MASK                 0x01
+#define TTBR0_PA_MASK                    0x0003FFFF
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_MASK                 0x01
+#define TTBR1_SH_MASK                    0x01
+#define TTBR1_ORGN_MASK                  0x03
+#define TTBR1_NOS_MASK                   0x01
+#define TTBR1_IRGNL_MASK                 0x01
+#define TTBR1_PA_MASK                    0x0003FFFF
+
+
+/* V2PSR */
+#define HIT_MASK                         0x01
+#define INDEX_MASK                       0xFF
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_MASK                 0xFF
+#define V2Pxx_VA_MASK                    0x000FFFFF
+
+
+/* Context Register Shifts */
+/* ACTLR */
+#define CFERE_SHIFT                    0
+#define CFEIE_SHIFT                    1
+#define PTSHCFG_SHIFT                  2
+#define RCOSH_SHIFT                    4
+#define RCISH_SHIFT                    5
+#define RCNSH_SHIFT                    6
+#define PRIVCFG_SHIFT                  8
+#define DNA_SHIFT                      10
+#define DNLV2PA_SHIFT                  11
+#define TLBMCFG_SHIFT                  12
+#define CFCFG_SHIFT                    14
+#define TIPCF_SHIFT                    15
+#define V2PCFG_SHIFT                   16
+#define HUME_SHIFT                     18
+#define PTMTCFG_SHIFT                  20
+#define PTMEMTYPE_SHIFT                21
+
+
+/* BFBCR */
+#define BFBDFE_SHIFT                   0
+#define BFBSFE_SHIFT                   1
+#define SFVS_SHIFT                     2
+#define FLVIC_SHIFT                    4
+#define SLVIC_SHIFT                    8
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_SHIFT          0
+#define PROCID_SHIFT                   8
+
+
+/* FSR */
+#define TF_SHIFT                       1
+#define AFF_SHIFT                      2
+#define APF_SHIFT                      3
+#define TLBMF_SHIFT                    4
+#define HTWDEEF_SHIFT                  5
+#define HTWSEEF_SHIFT                  6
+#define MHF_SHIFT                      7
+#define SL_SHIFT                       16
+#define SS_SHIFT                       30
+#define MULTI_SHIFT                    31
+
+
+/* FSYNR0 */
+#define AMID_SHIFT                     0
+#define APID_SHIFT                     8
+#define ABID_SHIFT                     13
+#define ATID_SHIFT                     24
+
+
+/* FSYNR1 */
+#define AMEMTYPE_SHIFT                 0
+#define ASHARED_SHIFT                  3
+#define AINNERSHARED_SHIFT             4
+#define APRIV_SHIFT                    5
+#define APROTNS_SHIFT                  6
+#define AINST_SHIFT                    7
+#define AWRITE_SHIFT                   8
+#define ABURST_SHIFT                   10
+#define ALEN_SHIFT                     12
+#define FSYNR1_ASIZE_SHIFT             16
+#define ALOCK_SHIFT                    20
+#define AFULL_SHIFT                    24
+
+
+/* NMRR */
+#define ICPC0_SHIFT                    0
+#define ICPC1_SHIFT                    2
+#define ICPC2_SHIFT                    4
+#define ICPC3_SHIFT                    6
+#define ICPC4_SHIFT                    8
+#define ICPC5_SHIFT                    10
+#define ICPC6_SHIFT                    12
+#define ICPC7_SHIFT                    14
+#define OCPC0_SHIFT                    16
+#define OCPC1_SHIFT                    18
+#define OCPC2_SHIFT                    20
+#define OCPC3_SHIFT                    22
+#define OCPC4_SHIFT                    24
+#define OCPC5_SHIFT                    26
+#define OCPC6_SHIFT                    28
+#define OCPC7_SHIFT                    30
+
+
+/* PAR */
+#define FAULT_SHIFT                    0
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_SHIFT                 1
+#define FAULT_AFF_SHIFT                2
+#define FAULT_APF_SHIFT                3
+#define FAULT_TLBMF_SHIFT              4
+#define FAULT_HTWDEEF_SHIFT            5
+#define FAULT_HTWSEEF_SHIFT            6
+#define FAULT_MHF_SHIFT                7
+#define FAULT_SL_SHIFT                 16
+#define FAULT_SS_SHIFT                 30
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_SHIFT           1
+#define PAR_NOFAULT_MT_SHIFT           4
+#define PAR_NOFAULT_SH_SHIFT           7
+#define PAR_NOFAULT_NS_SHIFT           9
+#define PAR_NOFAULT_NOS_SHIFT          10
+#define PAR_NPFAULT_PA_SHIFT           12
+
+
+/* PRRR */
+#define MTC0_SHIFT                     0
+#define MTC1_SHIFT                     2
+#define MTC2_SHIFT                     4
+#define MTC3_SHIFT                     6
+#define MTC4_SHIFT                     8
+#define MTC5_SHIFT                     10
+#define MTC6_SHIFT                     12
+#define MTC7_SHIFT                     14
+#define SHDSH0_SHIFT                   16
+#define SHDSH1_SHIFT                   17
+#define SHNMSH0_SHIFT                  18
+#define SHNMSH1_SHIFT                  19
+#define NOS0_SHIFT                     24
+#define NOS1_SHIFT                     25
+#define NOS2_SHIFT                     26
+#define NOS3_SHIFT                     27
+#define NOS4_SHIFT                     28
+#define NOS5_SHIFT                     29
+#define NOS6_SHIFT                     30
+#define NOS7_SHIFT                     31
+
+
+/* RESUME */
+#define TNR_SHIFT                      0
+
+
+/* SCTLR */
+#define M_SHIFT                        0
+#define TRE_SHIFT                      1
+#define AFE_SHIFT                      2
+#define HAF_SHIFT                      3
+#define BE_SHIFT                       4
+#define AFFD_SHIFT                     5
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_SHIFT            0
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_SHIFT              0
+#define TLBIVA_VA_SHIFT                12
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_SHIFT               12
+
+
+/* TLBLCKR */
+#define LKE_SHIFT                      0
+#define TLBLCKR_TLBIALLCFG_SHIFT       1
+#define TLBIASIDCFG_SHIFT              2
+#define TLBIVAACFG_SHIFT               3
+#define FLOOR_SHIFT                    8
+#define VICTIM_SHIFT                   8
+
+
+/* TTBCR */
+#define N_SHIFT                        3
+#define PD0_SHIFT                      4
+#define PD1_SHIFT                      5
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_SHIFT              0
+#define TTBR0_SH_SHIFT                 1
+#define TTBR0_ORGN_SHIFT               3
+#define TTBR0_NOS_SHIFT                5
+#define TTBR0_IRGNL_SHIFT              6
+#define TTBR0_PA_SHIFT                 14
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_SHIFT              0
+#define TTBR1_SH_SHIFT                 1
+#define TTBR1_ORGN_SHIFT               3
+#define TTBR1_NOS_SHIFT                5
+#define TTBR1_IRGNL_SHIFT              6
+#define TTBR1_PA_SHIFT                 14
+
+
+/* V2PSR */
+#define HIT_SHIFT                      0
+#define INDEX_SHIFT                    8
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_SHIFT              0
+#define V2Pxx_VA_SHIFT                 12
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
new file mode 100644 (file)
index 0000000..36074cf
--- /dev/null
@@ -0,0 +1,253 @@
+/* Copyright (c) 2010 Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8X60_H
+#define __ASM_ARCH_MSM_IRQS_8X60_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/* 0-15:  STI/SGI (software triggered/generated interrupts)
+ * 16-31: PPI (private peripheral interrupts)
+ * 32+:   SPI (shared peripheral interrupts)
+ */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define INT_DEBUG_TIMER_EXP                    (GIC_PPI_START + 0)
+#define INT_GP_TIMER_EXP                       (GIC_PPI_START + 1)
+#define INT_GP_TIMER2_EXP                      (GIC_PPI_START + 2)
+#define WDT0_ACCSCSSNBARK_INT                  (GIC_PPI_START + 3)
+#define WDT1_ACCSCSSNBARK_INT                  (GIC_PPI_START + 4)
+#define AVS_SVICINT                            (GIC_PPI_START + 5)
+#define AVS_SVICINTSWDONE                      (GIC_PPI_START + 6)
+#define CPU_DBGCPUXCOMMRXFULL                  (GIC_PPI_START + 7)
+#define CPU_DBGCPUXCOMMTXEMPTY                 (GIC_PPI_START + 8)
+#define CPU_SICCPUXPERFMONIRPTREQ              (GIC_PPI_START + 9)
+#define SC_AVSCPUXDOWN                         (GIC_PPI_START + 10)
+#define SC_AVSCPUXUP                           (GIC_PPI_START + 11)
+#define SC_SICCPUXACGIRPTREQ                   (GIC_PPI_START + 12)
+/* PPI 13 to 15 are unused */
+
+
+#define SC_SICMPUIRPTREQ                       (GIC_SPI_START + 0)
+#define SC_SICL2IRPTREQ                                (GIC_SPI_START + 1)
+#define SC_SICL2ACGIRPTREQ                     (GIC_SPI_START + 2)
+#define NC                                     (GIC_SPI_START + 3)
+#define TLMM_SCSS_DIR_CONN_IRQ_0               (GIC_SPI_START + 4)
+#define TLMM_SCSS_DIR_CONN_IRQ_1               (GIC_SPI_START + 5)
+#define TLMM_SCSS_DIR_CONN_IRQ_2               (GIC_SPI_START + 6)
+#define TLMM_SCSS_DIR_CONN_IRQ_3               (GIC_SPI_START + 7)
+#define TLMM_SCSS_DIR_CONN_IRQ_4               (GIC_SPI_START + 8)
+#define TLMM_SCSS_DIR_CONN_IRQ_5               (GIC_SPI_START + 9)
+#define TLMM_SCSS_DIR_CONN_IRQ_6               (GIC_SPI_START + 10)
+#define TLMM_SCSS_DIR_CONN_IRQ_7               (GIC_SPI_START + 11)
+#define TLMM_SCSS_DIR_CONN_IRQ_8               (GIC_SPI_START + 12)
+#define TLMM_SCSS_DIR_CONN_IRQ_9               (GIC_SPI_START + 13)
+#define PM8058_SEC_IRQ_N                       (GIC_SPI_START + 14)
+#define PM8901_SEC_IRQ_N                       (GIC_SPI_START + 15)
+#define TLMM_SCSS_SUMMARY_IRQ                  (GIC_SPI_START + 16)
+#define SPDM_RT_1_IRQ                          (GIC_SPI_START + 17)
+#define SPDM_DIAG_IRQ                          (GIC_SPI_START + 18)
+#define RPM_SCSS_CPU0_GP_HIGH_IRQ              (GIC_SPI_START + 19)
+#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ            (GIC_SPI_START + 20)
+#define RPM_SCSS_CPU0_GP_LOW_IRQ               (GIC_SPI_START + 21)
+#define RPM_SCSS_CPU0_WAKE_UP_IRQ              (GIC_SPI_START + 22)
+#define RPM_SCSS_CPU1_GP_HIGH_IRQ              (GIC_SPI_START + 23)
+#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ            (GIC_SPI_START + 24)
+#define RPM_SCSS_CPU1_GP_LOW_IRQ               (GIC_SPI_START + 25)
+#define RPM_SCSS_CPU1_WAKE_UP_IRQ              (GIC_SPI_START + 26)
+#define SSBI2_2_SC_CPU0_SECURE_INT             (GIC_SPI_START + 27)
+#define SSBI2_2_SC_CPU0_NON_SECURE_INT         (GIC_SPI_START + 28)
+#define SSBI2_1_SC_CPU0_SECURE_INT             (GIC_SPI_START + 29)
+#define SSBI2_1_SC_CPU0_NON_SECURE_INT         (GIC_SPI_START + 30)
+#define MSMC_SC_SEC_CE_IRQ                     (GIC_SPI_START + 31)
+#define MSMC_SC_PRI_CE_IRQ                     (GIC_SPI_START + 32)
+#define MARM_FIQ                               (GIC_SPI_START + 33)
+#define MARM_IRQ                               (GIC_SPI_START + 34)
+#define MARM_L2CC_IRQ                          (GIC_SPI_START + 35)
+#define MARM_WDOG_EXPIRED                      (GIC_SPI_START + 36)
+#define MARM_SCSS_GP_IRQ_0                     (GIC_SPI_START + 37)
+#define MARM_SCSS_GP_IRQ_1                     (GIC_SPI_START + 38)
+#define MARM_SCSS_GP_IRQ_2                     (GIC_SPI_START + 39)
+#define MARM_SCSS_GP_IRQ_3                     (GIC_SPI_START + 40)
+#define MARM_SCSS_GP_IRQ_4                     (GIC_SPI_START + 41)
+#define MARM_SCSS_GP_IRQ_5                     (GIC_SPI_START + 42)
+#define MARM_SCSS_GP_IRQ_6                     (GIC_SPI_START + 43)
+#define MARM_SCSS_GP_IRQ_7                     (GIC_SPI_START + 44)
+#define MARM_SCSS_GP_IRQ_8                     (GIC_SPI_START + 45)
+#define MARM_SCSS_GP_IRQ_9                     (GIC_SPI_START + 46)
+#define VPE_IRQ                                        (GIC_SPI_START + 47)
+#define VFE_IRQ                                        (GIC_SPI_START + 48)
+#define VCODEC_IRQ                             (GIC_SPI_START + 49)
+#define TV_ENC_IRQ                             (GIC_SPI_START + 50)
+#define SMMU_VPE_CB_SC_SECURE_IRQ              (GIC_SPI_START + 51)
+#define SMMU_VPE_CB_SC_NON_SECURE_IRQ          (GIC_SPI_START + 52)
+#define SMMU_VFE_CB_SC_SECURE_IRQ              (GIC_SPI_START + 53)
+#define SMMU_VFE_CB_SC_NON_SECURE_IRQ          (GIC_SPI_START + 54)
+#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ         (GIC_SPI_START + 55)
+#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ     (GIC_SPI_START + 56)
+#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ         (GIC_SPI_START + 57)
+#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ     (GIC_SPI_START + 58)
+#define SMMU_ROT_CB_SC_SECURE_IRQ              (GIC_SPI_START + 59)
+#define SMMU_ROT_CB_SC_NON_SECURE_IRQ          (GIC_SPI_START + 60)
+#define SMMU_MDP1_CB_SC_SECURE_IRQ             (GIC_SPI_START + 61)
+#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ         (GIC_SPI_START + 62)
+#define SMMU_MDP0_CB_SC_SECURE_IRQ             (GIC_SPI_START + 63)
+#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ         (GIC_SPI_START + 64)
+#define SMMU_JPEGD_CB_SC_SECURE_IRQ            (GIC_SPI_START + 65)
+#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ                (GIC_SPI_START + 66)
+#define SMMU_IJPEG_CB_SC_SECURE_IRQ            (GIC_SPI_START + 67)
+#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ                (GIC_SPI_START + 68)
+#define SMMU_GFX3D_CB_SC_SECURE_IRQ            (GIC_SPI_START + 69)
+#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ                (GIC_SPI_START + 70)
+#define SMMU_GFX2D0_CB_SC_SECURE_IRQ           (GIC_SPI_START + 71)
+#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ       (GIC_SPI_START + 72)
+#define ROT_IRQ                                        (GIC_SPI_START + 73)
+#define MMSS_FABRIC_IRQ                                (GIC_SPI_START + 74)
+#define MDP_IRQ                                        (GIC_SPI_START + 75)
+#define JPEGD_IRQ                              (GIC_SPI_START + 76)
+#define JPEG_IRQ                               (GIC_SPI_START + 77)
+#define MMSS_IMEM_IRQ                          (GIC_SPI_START + 78)
+#define HDMI_IRQ                               (GIC_SPI_START + 79)
+#define GFX3D_IRQ                              (GIC_SPI_START + 80)
+#define GFX2D0_IRQ                             (GIC_SPI_START + 81)
+#define DSI_IRQ                                        (GIC_SPI_START + 82)
+#define CSI_1_IRQ                              (GIC_SPI_START + 83)
+#define CSI_0_IRQ                              (GIC_SPI_START + 84)
+#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ           (GIC_SPI_START + 85)
+#define LPASS_SCSS_MIDI_IRQ                    (GIC_SPI_START + 86)
+#define LPASS_Q6SS_WDOG_EXPIRED                        (GIC_SPI_START + 87)
+#define LPASS_SCSS_GP_LOW_IRQ                  (GIC_SPI_START + 88)
+#define LPASS_SCSS_GP_MEDIUM_IRQ               (GIC_SPI_START + 89)
+#define LPASS_SCSS_GP_HIGH_IRQ                 (GIC_SPI_START + 90)
+#define TOP_IMEM_IRQ                           (GIC_SPI_START + 91)
+#define FABRIC_SYS_IRQ                         (GIC_SPI_START + 92)
+#define FABRIC_APPS_IRQ                                (GIC_SPI_START + 93)
+#define USB1_HS_BAM_IRQ                                (GIC_SPI_START + 94)
+#define SDC4_BAM_IRQ                           (GIC_SPI_START + 95)
+#define SDC3_BAM_IRQ                           (GIC_SPI_START + 96)
+#define SDC2_BAM_IRQ                           (GIC_SPI_START + 97)
+#define SDC1_BAM_IRQ                           (GIC_SPI_START + 98)
+#define FABRIC_SPS_IRQ                         (GIC_SPI_START + 99)
+#define USB1_HS_IRQ                            (GIC_SPI_START + 100)
+#define SDC4_IRQ_0                             (GIC_SPI_START + 101)
+#define SDC3_IRQ_0                             (GIC_SPI_START + 102)
+#define SDC2_IRQ_0                             (GIC_SPI_START + 103)
+#define SDC1_IRQ_0                             (GIC_SPI_START + 104)
+#define SPS_BAM_DMA_IRQ                                (GIC_SPI_START + 105)
+#define SPS_SEC_VIOL_IRQ                       (GIC_SPI_START + 106)
+#define SPS_MTI_0                              (GIC_SPI_START + 107)
+#define SPS_MTI_1                              (GIC_SPI_START + 108)
+#define SPS_MTI_2                              (GIC_SPI_START + 109)
+#define SPS_MTI_3                              (GIC_SPI_START + 110)
+#define SPS_MTI_4                              (GIC_SPI_START + 111)
+#define SPS_MTI_5                              (GIC_SPI_START + 112)
+#define SPS_MTI_6                              (GIC_SPI_START + 113)
+#define SPS_MTI_7                              (GIC_SPI_START + 114)
+#define SPS_MTI_8                              (GIC_SPI_START + 115)
+#define SPS_MTI_9                              (GIC_SPI_START + 116)
+#define SPS_MTI_10                             (GIC_SPI_START + 117)
+#define SPS_MTI_11                             (GIC_SPI_START + 118)
+#define SPS_MTI_12                             (GIC_SPI_START + 119)
+#define SPS_MTI_13                             (GIC_SPI_START + 120)
+#define SPS_MTI_14                             (GIC_SPI_START + 121)
+#define SPS_MTI_15                             (GIC_SPI_START + 122)
+#define SPS_MTI_16                             (GIC_SPI_START + 123)
+#define SPS_MTI_17                             (GIC_SPI_START + 124)
+#define SPS_MTI_18                             (GIC_SPI_START + 125)
+#define SPS_MTI_19                             (GIC_SPI_START + 126)
+#define SPS_MTI_20                             (GIC_SPI_START + 127)
+#define SPS_MTI_21                             (GIC_SPI_START + 128)
+#define SPS_MTI_22                             (GIC_SPI_START + 129)
+#define SPS_MTI_23                             (GIC_SPI_START + 130)
+#define SPS_MTI_24                             (GIC_SPI_START + 131)
+#define SPS_MTI_25                             (GIC_SPI_START + 132)
+#define SPS_MTI_26                             (GIC_SPI_START + 133)
+#define SPS_MTI_27                             (GIC_SPI_START + 134)
+#define SPS_MTI_28                             (GIC_SPI_START + 135)
+#define SPS_MTI_29                             (GIC_SPI_START + 136)
+#define SPS_MTI_30                             (GIC_SPI_START + 137)
+#define SPS_MTI_31                             (GIC_SPI_START + 138)
+#define UXMC_EBI2_WR_ER_DONE_IRQ               (GIC_SPI_START + 139)
+#define UXMC_EBI2_OP_DONE_IRQ                  (GIC_SPI_START + 140)
+#define USB2_IRQ                               (GIC_SPI_START + 141)
+#define USB1_IRQ                               (GIC_SPI_START + 142)
+#define TSSC_SSBI_IRQ                          (GIC_SPI_START + 143)
+#define TSSC_SAMPLE_IRQ                                (GIC_SPI_START + 144)
+#define TSSC_PENUP_IRQ                         (GIC_SPI_START + 145)
+#define INT_UART1DM_IRQ                                (GIC_SPI_START + 146)
+#define GSBI1_QUP_IRQ                          (GIC_SPI_START + 147)
+#define INT_UART2DM_IRQ                                (GIC_SPI_START + 148)
+#define GSBI2_QUP_IRQ                          (GIC_SPI_START + 149)
+#define INT_UART3DM_IRQ                                (GIC_SPI_START + 150)
+#define GSBI3_QUP_IRQ                          (GIC_SPI_START + 151)
+#define INT_UART4DM_IRQ                                (GIC_SPI_START + 152)
+#define GSBI4_QUP_IRQ                          (GIC_SPI_START + 153)
+#define INT_UART5DM_IRQ                                (GIC_SPI_START + 154)
+#define GSBI5_QUP_IRQ                          (GIC_SPI_START + 155)
+#define INT_UART6DM_IRQ                                (GIC_SPI_START + 156)
+#define GSBI6_QUP_IRQ                          (GIC_SPI_START + 157)
+#define INT_UART7DM_IRQ                                (GIC_SPI_START + 158)
+#define GSBI7_QUP_IRQ                          (GIC_SPI_START + 159)
+#define INT_UART8DM_IRQ                                (GIC_SPI_START + 160)
+#define GSBI8_QUP_IRQ                          (GIC_SPI_START + 161)
+#define TSIF_TSPP_IRQ                          (GIC_SPI_START + 162)
+#define TSIF_BAM_IRQ                           (GIC_SPI_START + 163)
+#define TSIF2_IRQ                              (GIC_SPI_START + 164)
+#define TSIF1_IRQ                              (GIC_SPI_START + 165)
+#define INT_ADM1_MASTER                                (GIC_SPI_START + 166)
+#define INT_ADM1_AARM                          (GIC_SPI_START + 167)
+#define INT_ADM1_SD2                           (GIC_SPI_START + 168)
+#define INT_ADM1_SD3                           (GIC_SPI_START + 169)
+#define INT_ADM0_MASTER                                (GIC_SPI_START + 170)
+#define INT_ADM0_AARM                          (GIC_SPI_START + 171)
+#define INT_ADM0_SD2                           (GIC_SPI_START + 172)
+#define INT_ADM0_SD3                           (GIC_SPI_START + 173)
+#define CC_SCSS_WDT1CPU1BITEEXPIRED            (GIC_SPI_START + 174)
+#define CC_SCSS_WDT1CPU0BITEEXPIRED            (GIC_SPI_START + 175)
+#define CC_SCSS_WDT0CPU1BITEEXPIRED            (GIC_SPI_START + 176)
+#define CC_SCSS_WDT0CPU0BITEEXPIRED            (GIC_SPI_START + 177)
+#define TSENS_UPPER_LOWER_INT                  (GIC_SPI_START + 178)
+#define SSBI2_2_SC_CPU1_SECURE_INT             (GIC_SPI_START + 179)
+#define SSBI2_2_SC_CPU1_NON_SECURE_INT         (GIC_SPI_START + 180)
+#define SSBI2_1_SC_CPU1_SECURE_INT             (GIC_SPI_START + 181)
+#define SSBI2_1_SC_CPU1_NON_SECURE_INT         (GIC_SPI_START + 182)
+#define XPU_SUMMARY_IRQ                                (GIC_SPI_START + 183)
+#define BUS_EXCEPTION_SUMMARY_IRQ              (GIC_SPI_START + 184)
+#define HSDDRX_SMICH0_IRQ                      (GIC_SPI_START + 185)
+#define HSDDRX_EBI1_IRQ                                (GIC_SPI_START + 186)
+#define SDC5_BAM_IRQ                           (GIC_SPI_START + 187)
+#define SDC5_IRQ_0                             (GIC_SPI_START + 188)
+#define INT_UART9DM_IRQ                                (GIC_SPI_START + 189)
+#define GSBI9_QUP_IRQ                          (GIC_SPI_START + 190)
+#define INT_UART10DM_IRQ                       (GIC_SPI_START + 191)
+#define GSBI10_QUP_IRQ                         (GIC_SPI_START + 192)
+#define INT_UART11DM_IRQ                       (GIC_SPI_START + 193)
+#define GSBI11_QUP_IRQ                         (GIC_SPI_START + 194)
+#define INT_UART12DM_IRQ                       (GIC_SPI_START + 195)
+#define GSBI12_QUP_IRQ                         (GIC_SPI_START + 196)
+/*SPI 197 to 216 arent used in 8x60*/
+#define SMPSS_SPARE_1                          (GIC_SPI_START + 217)
+#define SMPSS_SPARE_2                          (GIC_SPI_START + 218)
+#define SMPSS_SPARE_3                          (GIC_SPI_START + 219)
+#define SMPSS_SPARE_4                          (GIC_SPI_START + 220)
+#define SMPSS_SPARE_5                          (GIC_SPI_START + 221)
+#define SMPSS_SPARE_6                          (GIC_SPI_START + 222)
+#define SMPSS_SPARE_7                          (GIC_SPI_START + 223)
+
+#define NR_GPIO_IRQS 173
+#define NR_MSM_IRQS 256
+#define NR_BOARD_IRQS 0
+
+#endif
index 164d355c96ea99d5a9b884de18b201f4461054f4..8679a45647447c213902c297efd953aabba7ecba 100644 (file)
@@ -24,6 +24,8 @@
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "irqs-8x50.h"
 #include "sirc.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "irqs-8x60.h"
 #elif defined(CONFIG_ARCH_MSM_ARM11)
 #include "irqs-7x00.h"
 #else
index 50c7847e6002d3311b265c514f471ee39ad371ce..070e17d237f1926916391a56822d2cc6b8c3d444 100644 (file)
@@ -23,6 +23,8 @@
 #define PHYS_OFFSET            UL(0x20000000)
 #elif defined(CONFIG_ARCH_MSM7X30)
 #define PHYS_OFFSET            UL(0x00200000)
+#elif defined(CONFIG_ARCH_MSM8X60)
+#define PHYS_OFFSET            UL(0x40200000)
 #else
 #define PHYS_OFFSET            UL(0x10000000)
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
new file mode 100644 (file)
index 0000000..45bab50
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ *
+ * The MSM peripherals are spread all over across 768MB of physical
+ * space, which makes just having a simple IO_ADDRESS macro to slide
+ * them into the right virtual location rough.  Instead, we will
+ * provide a master phys->virt mapping for peripherals here.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H
+#define __ASM_ARCH_MSM_IOMAP_8X60_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * MSM_VIC_BASE must be an value that can be loaded via a "mov"
+ * instruction, otherwise entry-macro.S will not compile.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSM_QGIC_DIST_BASE     IOMEM(0xF0000000)
+#define MSM_QGIC_DIST_PHYS     0x02080000
+#define MSM_QGIC_DIST_SIZE     SZ_4K
+
+#define MSM_QGIC_CPU_BASE      IOMEM(0xF0001000)
+#define MSM_QGIC_CPU_PHYS      0x02081000
+#define MSM_QGIC_CPU_SIZE      SZ_4K
+
+#define MSM_ACC_BASE           IOMEM(0xF0002000)
+#define MSM_ACC_PHYS           0x02001000
+#define MSM_ACC_SIZE           SZ_4K
+
+#define MSM_GCC_BASE           IOMEM(0xF0003000)
+#define MSM_GCC_PHYS           0x02082000
+#define MSM_GCC_SIZE           SZ_4K
+
+#define MSM_TLMM_BASE          IOMEM(0xF0004000)
+#define MSM_TLMM_PHYS          0x00800000
+#define MSM_TLMM_SIZE          SZ_16K
+
+#define MSM_SHARED_RAM_BASE    IOMEM(0xF0100000)
+#define MSM_SHARED_RAM_SIZE    SZ_1M
+
+#define MSM_TMR_BASE           IOMEM(0xF0200000)
+#define MSM_TMR_PHYS           0x02000000
+#define MSM_TMR_SIZE           (SZ_1M)
+
+#define MSM_GPT_BASE           (MSM_TMR_BASE + 0x4)
+#define MSM_DGT_BASE           (MSM_TMR_BASE + 0x24)
+
+#define MSM_IOMMU_JPEGD_PHYS   0x07300000
+#define MSM_IOMMU_JPEGD_SIZE   SZ_1M
+
+#define MSM_IOMMU_VPE_PHYS     0x07400000
+#define MSM_IOMMU_VPE_SIZE     SZ_1M
+
+#define MSM_IOMMU_MDP0_PHYS    0x07500000
+#define MSM_IOMMU_MDP0_SIZE    SZ_1M
+
+#define MSM_IOMMU_MDP1_PHYS    0x07600000
+#define MSM_IOMMU_MDP1_SIZE    SZ_1M
+
+#define MSM_IOMMU_ROT_PHYS     0x07700000
+#define MSM_IOMMU_ROT_SIZE     SZ_1M
+
+#define MSM_IOMMU_IJPEG_PHYS   0x07800000
+#define MSM_IOMMU_IJPEG_SIZE   SZ_1M
+
+#define MSM_IOMMU_VFE_PHYS     0x07900000
+#define MSM_IOMMU_VFE_SIZE     SZ_1M
+
+#define MSM_IOMMU_VCODEC_A_PHYS        0x07A00000
+#define MSM_IOMMU_VCODEC_A_SIZE        SZ_1M
+
+#define MSM_IOMMU_VCODEC_B_PHYS        0x07B00000
+#define MSM_IOMMU_VCODEC_B_SIZE        SZ_1M
+
+#define MSM_IOMMU_GFX3D_PHYS   0x07C00000
+#define MSM_IOMMU_GFX3D_SIZE   SZ_1M
+
+#define MSM_IOMMU_GFX2D0_PHYS  0x07D00000
+#define MSM_IOMMU_GFX2D0_SIZE  SZ_1M
+
+#endif
index e6b1821cc4ea130e0266d83191e95195694ee9d4..8e24dd8121397871de5bc3f8ee4a5d5769bca8f6 100644 (file)
 #include "msm_iomap-7x30.h"
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
 #else
 #include "msm_iomap-7x00.h"
 #endif
 
+
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h
new file mode 100644 (file)
index 0000000..3ff7bf5
--- /dev/null
@@ -0,0 +1,39 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_SMP_H
+#define __ASM_ARCH_MSM_SMP_H
+
+#include <asm/hardware/gic.h>
+
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+       gic_raise_softirq(mask, 1);
+}
+
+#endif
index 05f81fd8623c2534a680a2be78bf824e3673e43b..31a32ad062dcd7eee3c280aa91e63c55ea11cf64 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef __ASM_ARCH_MSM_VMALLOC_H
 #define __ASM_ARCH_MSM_VMALLOC_H
 
-#define VMALLOC_END      (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END      0xd0000000
 
 #endif
 
index 1c05060b5f3b40545dce99453d97f55500c69f6d..d36b61074146eb35aa862f9c0ff46c619840c9bf 100644 (file)
@@ -100,6 +100,21 @@ void __init msm_map_qsd8x50_io(void)
 }
 #endif /* CONFIG_ARCH_QSD8X50 */
 
+#ifdef CONFIG_ARCH_MSM8X60
+static struct map_desc msm8x60_io_desc[] __initdata = {
+       MSM_DEVICE(QGIC_DIST),
+       MSM_DEVICE(QGIC_CPU),
+       MSM_DEVICE(TMR),
+       MSM_DEVICE(ACC),
+       MSM_DEVICE(GCC),
+};
+
+void __init msm_map_msm8x60_io(void)
+{
+       iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8X60 */
+
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
new file mode 100644 (file)
index 0000000..f71747d
--- /dev/null
@@ -0,0 +1,597 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sizes.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+DEFINE_SPINLOCK(msm_iommu_lock);
+
+struct msm_priv {
+       unsigned long *pgtable;
+       struct list_head list_attached;
+};
+
+static void __flush_iotlb(struct iommu_domain *domain)
+{
+       struct msm_priv *priv = domain->priv;
+       struct msm_iommu_drvdata *iommu_drvdata;
+       struct msm_iommu_ctx_drvdata *ctx_drvdata;
+
+#ifndef CONFIG_IOMMU_PGTABLES_L2
+       unsigned long *fl_table = priv->pgtable;
+       int i;
+
+       dmac_flush_range(fl_table, fl_table + SZ_16K);
+
+       for (i = 0; i < NUM_FL_PTE; i++)
+               if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
+                       void *sl_table = __va(fl_table[i] & FL_BASE_MASK);
+                       dmac_flush_range(sl_table, sl_table + SZ_4K);
+               }
+#endif
+
+       list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
+               if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
+                       BUG();
+
+               iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+               SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+       }
+}
+
+static void __reset_context(void __iomem *base, int ctx)
+{
+       SET_BPRCOSH(base, ctx, 0);
+       SET_BPRCISH(base, ctx, 0);
+       SET_BPRCNSH(base, ctx, 0);
+       SET_BPSHCFG(base, ctx, 0);
+       SET_BPMTCFG(base, ctx, 0);
+       SET_ACTLR(base, ctx, 0);
+       SET_SCTLR(base, ctx, 0);
+       SET_FSRRESTORE(base, ctx, 0);
+       SET_TTBR0(base, ctx, 0);
+       SET_TTBR1(base, ctx, 0);
+       SET_TTBCR(base, ctx, 0);
+       SET_BFBCR(base, ctx, 0);
+       SET_PAR(base, ctx, 0);
+       SET_FAR(base, ctx, 0);
+       SET_CTX_TLBIALL(base, ctx, 0);
+       SET_TLBFLPTER(base, ctx, 0);
+       SET_TLBSLPTER(base, ctx, 0);
+       SET_TLBLKCR(base, ctx, 0);
+       SET_PRRR(base, ctx, 0);
+       SET_NMRR(base, ctx, 0);
+       SET_CONTEXTIDR(base, ctx, 0);
+}
+
+static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+{
+       __reset_context(base, ctx);
+
+       /* Set up HTW mode */
+       /* TLB miss configuration: perform HTW on miss */
+       SET_TLBMCFG(base, ctx, 0x3);
+
+       /* V2P configuration: HTW for access */
+       SET_V2PCFG(base, ctx, 0x3);
+
+       SET_TTBCR(base, ctx, 0);
+       SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+
+       /* Invalidate the TLB for this context */
+       SET_CTX_TLBIALL(base, ctx, 0);
+
+       /* Set interrupt number to "secure" interrupt */
+       SET_IRPTNDX(base, ctx, 0);
+
+       /* Enable context fault interrupt */
+       SET_CFEIE(base, ctx, 1);
+
+       /* Stall access on a context fault and let the handler deal with it */
+       SET_CFCFG(base, ctx, 1);
+
+       /* Redirect all cacheable requests to L2 slave port. */
+       SET_RCISH(base, ctx, 1);
+       SET_RCOSH(base, ctx, 1);
+       SET_RCNSH(base, ctx, 1);
+
+       /* Turn on TEX Remap */
+       SET_TRE(base, ctx, 1);
+
+       /* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
+        * TEX class 0 for everything until attributes are properly worked out
+        */
+       SET_PRRR(base, ctx, 0);
+       SET_NMRR(base, ctx, 0);
+
+       /* Turn on BFB prefetch */
+       SET_BFBDFE(base, ctx, 1);
+
+#ifdef CONFIG_IOMMU_PGTABLES_L2
+       /* Configure page tables as inner-cacheable and shareable to reduce
+        * the TLB miss penalty.
+        */
+       SET_TTBR0_SH(base, ctx, 1);
+       SET_TTBR1_SH(base, ctx, 1);
+
+       SET_TTBR0_NOS(base, ctx, 1);
+       SET_TTBR1_NOS(base, ctx, 1);
+
+       SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
+       SET_TTBR0_IRGNL(base, ctx, 1);
+
+       SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
+       SET_TTBR1_IRGNL(base, ctx, 1);
+
+       SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
+       SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
+#endif
+
+       /* Enable the MMU */
+       SET_M(base, ctx, 1);
+}
+
+static int msm_iommu_domain_init(struct iommu_domain *domain)
+{
+       struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+       if (!priv)
+               goto fail_nomem;
+
+       INIT_LIST_HEAD(&priv->list_attached);
+       priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+                                                         get_order(SZ_16K));
+
+       if (!priv->pgtable)
+               goto fail_nomem;
+
+       memset(priv->pgtable, 0, SZ_16K);
+       domain->priv = priv;
+       return 0;
+
+fail_nomem:
+       kfree(priv);
+       return -ENOMEM;
+}
+
+static void msm_iommu_domain_destroy(struct iommu_domain *domain)
+{
+       struct msm_priv *priv;
+       unsigned long flags;
+       unsigned long *fl_table;
+       int i;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+       priv = domain->priv;
+       domain->priv = NULL;
+
+       if (priv) {
+               fl_table = priv->pgtable;
+
+               for (i = 0; i < NUM_FL_PTE; i++)
+                       if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
+                               free_page((unsigned long) __va(((fl_table[i]) &
+                                                               FL_BASE_MASK)));
+
+               free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
+               priv->pgtable = NULL;
+       }
+
+       kfree(priv);
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+       struct msm_priv *priv;
+       struct msm_iommu_ctx_dev *ctx_dev;
+       struct msm_iommu_drvdata *iommu_drvdata;
+       struct msm_iommu_ctx_drvdata *ctx_drvdata;
+       struct msm_iommu_ctx_drvdata *tmp_drvdata;
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+
+       priv = domain->priv;
+
+       if (!priv || !dev) {
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       iommu_drvdata = dev_get_drvdata(dev->parent);
+       ctx_drvdata = dev_get_drvdata(dev);
+       ctx_dev = dev->platform_data;
+
+       if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
+               if (tmp_drvdata == ctx_drvdata) {
+                       ret = -EBUSY;
+                       goto fail;
+               }
+
+       __program_context(iommu_drvdata->base, ctx_dev->num,
+                         __pa(priv->pgtable));
+
+       list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
+       __flush_iotlb(domain);
+
+fail:
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+       return ret;
+}
+
+static void msm_iommu_detach_dev(struct iommu_domain *domain,
+                                struct device *dev)
+{
+       struct msm_priv *priv;
+       struct msm_iommu_ctx_dev *ctx_dev;
+       struct msm_iommu_drvdata *iommu_drvdata;
+       struct msm_iommu_ctx_drvdata *ctx_drvdata;
+       unsigned long flags;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+       priv = domain->priv;
+
+       if (!priv || !dev)
+               goto fail;
+
+       iommu_drvdata = dev_get_drvdata(dev->parent);
+       ctx_drvdata = dev_get_drvdata(dev);
+       ctx_dev = dev->platform_data;
+
+       if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
+               goto fail;
+
+       __flush_iotlb(domain);
+       __reset_context(iommu_drvdata->base, ctx_dev->num);
+       list_del_init(&ctx_drvdata->attached_elm);
+
+fail:
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+                        phys_addr_t pa, int order, int prot)
+{
+       struct msm_priv *priv;
+       unsigned long flags;
+       unsigned long *fl_table;
+       unsigned long *fl_pte;
+       unsigned long fl_offset;
+       unsigned long *sl_table;
+       unsigned long *sl_pte;
+       unsigned long sl_offset;
+       size_t len = 0x1000UL << order;
+       int ret = 0;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+       priv = domain->priv;
+
+       if (!priv) {
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       fl_table = priv->pgtable;
+
+       if (len != SZ_16M && len != SZ_1M &&
+           len != SZ_64K && len != SZ_4K) {
+               pr_debug("Bad size: %d\n", len);
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       if (!fl_table) {
+               pr_debug("Null page table\n");
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       fl_offset = FL_OFFSET(va);      /* Upper 12 bits */
+       fl_pte = fl_table + fl_offset;  /* int pointers, 4 bytes */
+
+       if (len == SZ_16M) {
+               int i = 0;
+               for (i = 0; i < 16; i++)
+                       *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
+                                 FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
+                                 FL_SHARED;
+       }
+
+       if (len == SZ_1M)
+               *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
+                                               FL_TYPE_SECT | FL_SHARED;
+
+       /* Need a 2nd level table */
+       if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
+               unsigned long *sl;
+               sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
+                                                       get_order(SZ_4K));
+
+               if (!sl) {
+                       pr_debug("Could not allocate second level table\n");
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               memset(sl, 0, SZ_4K);
+               *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
+       }
+
+       sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+       sl_offset = SL_OFFSET(va);
+       sl_pte = sl_table + sl_offset;
+
+
+       if (len == SZ_4K)
+               *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
+                                         SL_SHARED | SL_TYPE_SMALL;
+
+       if (len == SZ_64K) {
+               int i;
+
+               for (i = 0; i < 16; i++)
+                       *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
+                                           SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
+       }
+
+       __flush_iotlb(domain);
+fail:
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+       return ret;
+}
+
+static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
+                           int order)
+{
+       struct msm_priv *priv;
+       unsigned long flags;
+       unsigned long *fl_table;
+       unsigned long *fl_pte;
+       unsigned long fl_offset;
+       unsigned long *sl_table;
+       unsigned long *sl_pte;
+       unsigned long sl_offset;
+       size_t len = 0x1000UL << order;
+       int i, ret = 0;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+
+       priv = domain->priv;
+
+       if (!priv) {
+               ret = -ENODEV;
+               goto fail;
+       }
+
+       fl_table = priv->pgtable;
+
+       if (len != SZ_16M && len != SZ_1M &&
+           len != SZ_64K && len != SZ_4K) {
+               pr_debug("Bad length: %d\n", len);
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       if (!fl_table) {
+               pr_debug("Null page table\n");
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       fl_offset = FL_OFFSET(va);      /* Upper 12 bits */
+       fl_pte = fl_table + fl_offset;  /* int pointers, 4 bytes */
+
+       if (*fl_pte == 0) {
+               pr_debug("First level PTE is 0\n");
+               ret = -ENODEV;
+               goto fail;
+       }
+
+       /* Unmap supersection */
+       if (len == SZ_16M)
+               for (i = 0; i < 16; i++)
+                       *(fl_pte+i) = 0;
+
+       if (len == SZ_1M)
+               *fl_pte = 0;
+
+       sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+       sl_offset = SL_OFFSET(va);
+       sl_pte = sl_table + sl_offset;
+
+       if (len == SZ_64K) {
+               for (i = 0; i < 16; i++)
+                       *(sl_pte+i) = 0;
+       }
+
+       if (len == SZ_4K)
+               *sl_pte = 0;
+
+       if (len == SZ_4K || len == SZ_64K) {
+               int used = 0;
+
+               for (i = 0; i < NUM_SL_PTE; i++)
+                       if (sl_table[i])
+                               used = 1;
+               if (!used) {
+                       free_page((unsigned long)sl_table);
+                       *fl_pte = 0;
+               }
+       }
+
+       __flush_iotlb(domain);
+fail:
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+       return ret;
+}
+
+static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
+                                         unsigned long va)
+{
+       struct msm_priv *priv;
+       struct msm_iommu_drvdata *iommu_drvdata;
+       struct msm_iommu_ctx_drvdata *ctx_drvdata;
+       unsigned int par;
+       unsigned long flags;
+       void __iomem *base;
+       phys_addr_t ret = 0;
+       int ctx;
+
+       spin_lock_irqsave(&msm_iommu_lock, flags);
+
+       priv = domain->priv;
+       if (list_empty(&priv->list_attached))
+               goto fail;
+
+       ctx_drvdata = list_entry(priv->list_attached.next,
+                                struct msm_iommu_ctx_drvdata, attached_elm);
+       iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+
+       base = iommu_drvdata->base;
+       ctx = ctx_drvdata->num;
+
+       /* Invalidate context TLB */
+       SET_CTX_TLBIALL(base, ctx, 0);
+       SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
+
+       if (GET_FAULT(base, ctx))
+               goto fail;
+
+       par = GET_PAR(base, ctx);
+
+       /* We are dealing with a supersection */
+       if (GET_NOFAULT_SS(base, ctx))
+               ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
+       else    /* Upper 20 bits from PAR, lower 12 from VA */
+               ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
+
+fail:
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+       return ret;
+}
+
+static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
+                                   unsigned long cap)
+{
+       return 0;
+}
+
+static void print_ctx_regs(void __iomem *base, int ctx)
+{
+       unsigned int fsr = GET_FSR(base, ctx);
+       pr_err("FAR    = %08x    PAR    = %08x\n",
+              GET_FAR(base, ctx), GET_PAR(base, ctx));
+       pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
+                       (fsr & 0x02) ? "TF " : "",
+                       (fsr & 0x04) ? "AFF " : "",
+                       (fsr & 0x08) ? "APF " : "",
+                       (fsr & 0x10) ? "TLBMF " : "",
+                       (fsr & 0x20) ? "HTWDEEF " : "",
+                       (fsr & 0x40) ? "HTWSEEF " : "",
+                       (fsr & 0x80) ? "MHF " : "",
+                       (fsr & 0x10000) ? "SL " : "",
+                       (fsr & 0x40000000) ? "SS " : "",
+                       (fsr & 0x80000000) ? "MULTI " : "");
+
+       pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
+              GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
+       pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
+              GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
+       pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
+              GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
+       pr_err("PRRR   = %08x    NMRR   = %08x\n",
+              GET_PRRR(base, ctx), GET_NMRR(base, ctx));
+}
+
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
+{
+       struct msm_iommu_drvdata *drvdata = dev_id;
+       void __iomem *base;
+       unsigned int fsr = 0;
+       int ncb = 0, i = 0;
+
+       spin_lock(&msm_iommu_lock);
+
+       if (!drvdata) {
+               pr_err("Invalid device ID in context interrupt handler\n");
+               goto fail;
+       }
+
+       base = drvdata->base;
+
+       pr_err("===== WOAH! =====\n");
+       pr_err("Unexpected IOMMU page fault!\n");
+       pr_err("base = %08x\n", (unsigned int) base);
+
+       ncb = GET_NCB(base)+1;
+       for (i = 0; i < ncb; i++) {
+               fsr = GET_FSR(base, i);
+               if (fsr) {
+                       pr_err("Fault occurred in context %d.\n", i);
+                       pr_err("Interesting registers:\n");
+                       print_ctx_regs(base, i);
+                       SET_FSR(base, i, 0x4000000F);
+               }
+       }
+fail:
+       spin_unlock(&msm_iommu_lock);
+       return 0;
+}
+
+static struct iommu_ops msm_iommu_ops = {
+       .domain_init = msm_iommu_domain_init,
+       .domain_destroy = msm_iommu_domain_destroy,
+       .attach_dev = msm_iommu_attach_dev,
+       .detach_dev = msm_iommu_detach_dev,
+       .map = msm_iommu_map,
+       .unmap = msm_iommu_unmap,
+       .iova_to_phys = msm_iommu_iova_to_phys,
+       .domain_has_cap = msm_iommu_domain_has_cap
+};
+
+static int msm_iommu_init(void)
+{
+       register_iommu(&msm_iommu_ops);
+       return 0;
+}
+
+subsys_initcall(msm_iommu_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
new file mode 100644 (file)
index 0000000..c33ae78
--- /dev/null
@@ -0,0 +1,374 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/iommu.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+struct iommu_ctx_iter_data {
+       /* input */
+       const char *name;
+
+       /* output */
+       struct device *dev;
+};
+
+static struct platform_device *msm_iommu_root_dev;
+
+static int each_iommu_ctx(struct device *dev, void *data)
+{
+       struct iommu_ctx_iter_data *res = data;
+       struct msm_iommu_ctx_dev *c = dev->platform_data;
+
+       if (!res || !c || !c->name || !res->name)
+               return -EINVAL;
+
+       if (!strcmp(res->name, c->name)) {
+               res->dev = dev;
+               return 1;
+       }
+       return 0;
+}
+
+static int each_iommu(struct device *dev, void *data)
+{
+       return device_for_each_child(dev, data, each_iommu_ctx);
+}
+
+struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+       struct iommu_ctx_iter_data r;
+       int found;
+
+       if (!msm_iommu_root_dev) {
+               pr_err("No root IOMMU device.\n");
+               goto fail;
+       }
+
+       r.name = ctx_name;
+       found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
+
+       if (!found) {
+               pr_err("Could not find context <%s>\n", ctx_name);
+               goto fail;
+       }
+
+       return r.dev;
+fail:
+       return NULL;
+}
+EXPORT_SYMBOL(msm_iommu_get_ctx);
+
+static void msm_iommu_reset(void __iomem *base)
+{
+       int ctx, ncb;
+
+       SET_RPUE(base, 0);
+       SET_RPUEIE(base, 0);
+       SET_ESRRESTORE(base, 0);
+       SET_TBE(base, 0);
+       SET_CR(base, 0);
+       SET_SPDMBE(base, 0);
+       SET_TESTBUSCR(base, 0);
+       SET_TLBRSW(base, 0);
+       SET_GLOBAL_TLBIALL(base, 0);
+       SET_RPU_ACR(base, 0);
+       SET_TLBLKCRWE(base, 1);
+       ncb = GET_NCB(base)+1;
+
+       for (ctx = 0; ctx < ncb; ctx++) {
+               SET_BPRCOSH(base, ctx, 0);
+               SET_BPRCISH(base, ctx, 0);
+               SET_BPRCNSH(base, ctx, 0);
+               SET_BPSHCFG(base, ctx, 0);
+               SET_BPMTCFG(base, ctx, 0);
+               SET_ACTLR(base, ctx, 0);
+               SET_SCTLR(base, ctx, 0);
+               SET_FSRRESTORE(base, ctx, 0);
+               SET_TTBR0(base, ctx, 0);
+               SET_TTBR1(base, ctx, 0);
+               SET_TTBCR(base, ctx, 0);
+               SET_BFBCR(base, ctx, 0);
+               SET_PAR(base, ctx, 0);
+               SET_FAR(base, ctx, 0);
+               SET_CTX_TLBIALL(base, ctx, 0);
+               SET_TLBFLPTER(base, ctx, 0);
+               SET_TLBSLPTER(base, ctx, 0);
+               SET_TLBLKCR(base, ctx, 0);
+               SET_PRRR(base, ctx, 0);
+               SET_NMRR(base, ctx, 0);
+               SET_CONTEXTIDR(base, ctx, 0);
+       }
+}
+
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+       struct resource *r;
+       struct clk *iommu_clk;
+       struct msm_iommu_drvdata *drvdata;
+       struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
+       void __iomem *regs_base;
+       resource_size_t len;
+       int ret = 0, ncb, nm2v, irq;
+
+       if (pdev->id != -1) {
+               drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+
+               if (!drvdata) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               if (!iommu_dev) {
+                       ret = -ENODEV;
+                       goto fail;
+               }
+
+               if (iommu_dev->clk_rate != 0) {
+                       iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+                       if (IS_ERR(iommu_clk)) {
+                               ret = -ENODEV;
+                               goto fail;
+                       }
+
+                       if (iommu_dev->clk_rate > 0) {
+                               ret = clk_set_rate(iommu_clk,
+                                                       iommu_dev->clk_rate);
+                               if (ret) {
+                                       clk_put(iommu_clk);
+                                       goto fail;
+                               }
+                       }
+
+                       ret = clk_enable(iommu_clk);
+                       if (ret) {
+                               clk_put(iommu_clk);
+                               goto fail;
+                       }
+                       clk_put(iommu_clk);
+               }
+
+               r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                "physbase");
+               if (!r) {
+                       ret = -ENODEV;
+                       goto fail;
+               }
+
+               len = r->end - r->start + 1;
+
+               r = request_mem_region(r->start, len, r->name);
+               if (!r) {
+                       pr_err("Could not request memory region: "
+                       "start=%p, len=%d\n", (void *) r->start, len);
+                       ret = -EBUSY;
+                       goto fail;
+               }
+
+               regs_base = ioremap(r->start, len);
+
+               if (!regs_base) {
+                       pr_err("Could not ioremap: start=%p, len=%d\n",
+                                (void *) r->start, len);
+                       ret = -EBUSY;
+                       goto fail;
+               }
+
+               irq = platform_get_irq_byname(pdev, "secure_irq");
+               if (irq < 0) {
+                       ret = -ENODEV;
+                       goto fail;
+               }
+
+               mb();
+
+               if (GET_IDR(regs_base) == 0) {
+                       pr_err("Invalid IDR value detected\n");
+                       ret = -ENODEV;
+                       goto fail;
+               }
+
+               ret = request_irq(irq, msm_iommu_fault_handler, 0,
+                               "msm_iommu_secure_irpt_handler", drvdata);
+               if (ret) {
+                       pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+                       goto fail;
+               }
+
+               msm_iommu_reset(regs_base);
+               drvdata->base = regs_base;
+               drvdata->irq = irq;
+
+               nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+               ncb = GET_NCB((unsigned long) regs_base);
+
+               pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+                       iommu_dev->name, regs_base, irq, ncb+1);
+
+               platform_set_drvdata(pdev, drvdata);
+       } else
+               msm_iommu_root_dev = pdev;
+
+       return 0;
+
+fail:
+       kfree(drvdata);
+       return ret;
+}
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+       struct msm_iommu_drvdata *drv = NULL;
+
+       drv = platform_get_drvdata(pdev);
+       if (drv) {
+               memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+               kfree(drv);
+               platform_set_drvdata(pdev, NULL);
+       }
+       return 0;
+}
+
+static int msm_iommu_ctx_probe(struct platform_device *pdev)
+{
+       struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
+       struct msm_iommu_drvdata *drvdata;
+       struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
+       int i, ret = 0;
+       if (!c || !pdev->dev.parent) {
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       drvdata = dev_get_drvdata(pdev->dev.parent);
+
+       if (!drvdata) {
+               ret = -ENODEV;
+               goto fail;
+       }
+
+       ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
+       if (!ctx_drvdata) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+       ctx_drvdata->num = c->num;
+       ctx_drvdata->pdev = pdev;
+
+       INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
+       platform_set_drvdata(pdev, ctx_drvdata);
+
+       /* Program the M2V tables for this context */
+       for (i = 0; i < MAX_NUM_MIDS; i++) {
+               int mid = c->mids[i];
+               if (mid == -1)
+                       break;
+
+               SET_M2VCBR_N(drvdata->base, mid, 0);
+               SET_CBACR_N(drvdata->base, c->num, 0);
+
+               /* Set VMID = MID */
+               SET_VMID(drvdata->base, mid, mid);
+
+               /* Set the context number for that MID to this context */
+               SET_CBNDX(drvdata->base, mid, c->num);
+
+               /* Set MID associated with this context bank */
+               SET_CBVMID(drvdata->base, c->num, mid);
+
+               /* Set security bit override to be Non-secure */
+               SET_NSCFG(drvdata->base, mid, 3);
+       }
+
+       pr_info("context device %s with bank index %d\n", c->name, c->num);
+
+       return 0;
+fail:
+       kfree(ctx_drvdata);
+       return ret;
+}
+
+static int msm_iommu_ctx_remove(struct platform_device *pdev)
+{
+       struct msm_iommu_ctx_drvdata *drv = NULL;
+       drv = platform_get_drvdata(pdev);
+       if (drv) {
+               memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
+               kfree(drv);
+               platform_set_drvdata(pdev, NULL);
+       }
+       return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+       .driver = {
+               .name   = "msm_iommu",
+       },
+       .probe          = msm_iommu_probe,
+       .remove         = msm_iommu_remove,
+};
+
+static struct platform_driver msm_iommu_ctx_driver = {
+       .driver = {
+               .name   = "msm_iommu_ctx",
+       },
+       .probe          = msm_iommu_ctx_probe,
+       .remove         = msm_iommu_ctx_remove,
+};
+
+static int msm_iommu_driver_init(void)
+{
+       int ret;
+       ret = platform_driver_register(&msm_iommu_driver);
+       if (ret != 0) {
+               pr_err("Failed to register IOMMU driver\n");
+               goto error;
+       }
+
+       ret = platform_driver_register(&msm_iommu_ctx_driver);
+       if (ret != 0) {
+               pr_err("Failed to register IOMMU context driver\n");
+               goto error;
+       }
+
+error:
+       return ret;
+}
+
+static void msm_iommu_driver_exit(void)
+{
+       platform_driver_unregister(&msm_iommu_ctx_driver);
+       platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
index b64ba5a98686a2ad8fe85ffdb971d51725b192f5..1e243f46a9699341b9e35310632fcd6ed25fa3b4 100644 (file)
@@ -48,7 +48,8 @@ static ssize_t last_radio_log_read(struct file *file, char __user *buf,
 }
 
 static struct file_operations last_radio_log_fops = {
-       .read = last_radio_log_read
+       .read = last_radio_log_read,
+       .llseek = default_llseek,
 };
 
 void msm_init_last_radio_log(struct module *owner)
index 3b2dd717b788feb315d36cc5ec34cad57b3ebf1b..f91c3b7bc6558f89e918f76e7a790fe28d6d89b9 100644 (file)
@@ -212,6 +212,7 @@ static int debug_open(struct inode *inode, struct file *file)
 static const struct file_operations debug_ops = {
        .read = debug_read,
        .open = debug_open,
+       .llseek = default_llseek,
 };
 
 static void debug_create(const char *name, mode_t mode,
index dec5ca622d7daf6963450f612d7062109cae6e92..7689848ec680d28a322040e9bf8e9c7764de27ac 100644 (file)
@@ -28,7 +28,6 @@
 #ifndef MSM_DGT_BASE
 #define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
 #endif
-#define MSM_DGT_SHIFT (5)
 
 #define TIMER_MATCH_VAL         0x0000
 #define TIMER_COUNT_VAL         0x0004
 #define TIMER_ENABLE_CLR_ON_MATCH_EN    2
 #define TIMER_ENABLE_EN                 1
 #define TIMER_CLEAR             0x000C
-
+#define DGT_CLK_CTL             0x0034
+enum {
+       DGT_CLK_CTL_DIV_1 = 0,
+       DGT_CLK_CTL_DIV_2 = 1,
+       DGT_CLK_CTL_DIV_3 = 2,
+       DGT_CLK_CTL_DIV_4 = 3,
+};
 #define CSR_PROTECTION          0x0020
 #define CSR_PROTECTION_EN               1
 
 #define GPT_HZ 32768
+
+#if defined(CONFIG_ARCH_QSD8X50)
+#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
+#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#else
 #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
+#define MSM_DGT_SHIFT (5)
+#endif
 
 struct msm_clock {
        struct clock_event_device   clockevent;
@@ -170,6 +185,10 @@ static void __init msm_timer_init(void)
        int i;
        int res;
 
+#ifdef CONFIG_ARCH_MSM8X60
+       writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+#endif
+
        for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
                struct msm_clock *clock = &msm_clocks[i];
                struct clock_event_device *ce = &clock->clockevent;
index 61e5e583603b10f009f5a7ec6b6207806a0d29f4..29e390e89ff41b57c9c887d3acfeb917210b817e 100644 (file)
@@ -145,8 +145,6 @@ subsys_initcall(wxl_pci_init);
 
 MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
        /* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
-       .phys_io        = MV78XX0_REGS_PHYS_BASE,
-       .io_pg_offst    = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = wxl_init,
        .map_io         = mv78xx0_map_io,
index efdabe04c69ef80bad21f5a5ad3a661741cbae79..207c95e403b95c04593a73d490db07570d65b93c 100644 (file)
@@ -93,8 +93,6 @@ subsys_initcall(db78x00_pci_init);
 
 MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = MV78XX0_REGS_PHYS_BASE,
-       .io_pg_offst    = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = db78x00_init,
        .map_io         = mv78xx0_map_io,
index cd81689c4621dad5bfa9b08d2b1a35bed5049b8a..04891428e48bcd9d4cc164679a8fbc0a77fff900 100644 (file)
@@ -8,12 +8,11 @@
 
 #include <mach/mv78xx0.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =MV78XX0_REGS_PHYS_BASE
-       ldrne   \rx, =MV78XX0_REGS_VIRT_BASE
-       orr     \rx, \rx, #0x00012000
+       .macro  addruart, rp, rv
+       ldr     \rp, =MV78XX0_REGS_PHYS_BASE
+       ldr     \rv, =MV78XX0_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
        .endm
 
 #define UART_SHIFT     2
index e136b7a03355bc445c74cd626969acb73cedcc89..3511ad4d973b7218a6a9fa3669c8def6d649fc56 100644 (file)
@@ -78,8 +78,6 @@ subsys_initcall(rd78x00_pci_init);
 
 MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = MV78XX0_REGS_PHYS_BASE,
-       .io_pg_offst    = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = rd78x00_masa_init,
        .map_io         = mv78xx0_map_io,
index c71a7bc19284bf64b14f939f3094bfc501631240..aa57e35ce3cd2c097cd0af5bb8f56d75480c87bd 100644 (file)
@@ -12,6 +12,8 @@ config MACH_EUKREA_CPUIMX25
        select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_FLEXCAN
+       select IMX_HAVE_PLATFORM_ESDHC
        select MXC_ULPI if USB_ULPI
 
 choice
@@ -20,8 +22,8 @@ choice
        default MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD25_BASEBOARD
-       prompt "Eukrea MBIMXSD development board"
-       bool
+       bool "Eukrea MBIMXSD development board"
+       select IMX_HAVE_PLATFORM_IMX_SSI
        help
          This adds board specific devices that can be found on Eukrea's
          MBIMXSD evaluation board.
index 40c7cc41cee372c906e3339f5da50f9e709f36df..9e4a5578c2fb9dc6a392aa07b5fb085dde900651 100644 (file)
@@ -72,7 +72,7 @@ unsigned long get_rate_arm(struct clk *clk)
        unsigned long rate = get_rate_mpll();
 
        if (cctl & (1 << 14))
-               rate = (rate * 3) >> 1;
+               rate = (rate * 3) >> 2;
 
        return rate / ((cctl >> 30) + 1);
 }
@@ -99,7 +99,7 @@ static unsigned long get_rate_per(int per)
        if (readl(CRM_BASE + 0x64) & (1 << per))
                fref = get_rate_upll();
        else
-               fref = get_rate_ipg(NULL);
+               fref = get_rate_ahb(NULL);
 
        return fref / (val + 1);
 }
@@ -139,6 +139,16 @@ static unsigned long get_rate_lcdc(struct clk *clk)
        return get_rate_per(7);
 }
 
+static unsigned long get_rate_esdhc1(struct clk *clk)
+{
+       return get_rate_per(3);
+}
+
+static unsigned long get_rate_esdhc2(struct clk *clk)
+{
+       return get_rate_per(4);
+}
+
 static unsigned long get_rate_csi(struct clk *clk)
 {
        return get_rate_per(0);
@@ -213,6 +223,12 @@ DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1,         NULL, NULL);
+DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0,  3, get_rate_esdhc1,         NULL,
+               &esdhc1_ahb_clk);
+DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2,         NULL, NULL);
+DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0,  4, get_rate_esdhc2,         NULL,
+               &esdhc2_ahb_clk);
 DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,       NULL, NULL);
 DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,      NULL, NULL);
 DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,      NULL, &lcdc_ahb_clk);
@@ -238,10 +254,14 @@ DEFINE_CLOCK(lcdc_clk,     0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
 DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
 DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
 DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
+DEFINE_CLOCK(esdhc1_clk,  0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
+               &esdhc1_per_clk);
+DEFINE_CLOCK(esdhc2_clk,  1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
+               &esdhc2_per_clk);
 DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
 DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
 DEFINE_CLOCK(can1_clk,  0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(can2_clk,  0, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(can2_clk,  1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)       \
        {                               \
@@ -261,9 +281,9 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
-       _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-       _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-       _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+       _REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
+       _REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
+       _REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
        _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
        _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
        _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
@@ -279,6 +299,8 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx-wdt.0", NULL, wdt_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
        _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
        _REGISTER_CLOCK(NULL, "audmux", audmux_clk)
        _REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
index d86a7c3ca8b0cf64c7b7cb69af2e7dc883194df0..93afa10b13cf929de543f5f3eea3b51dead77629 100644 (file)
@@ -9,35 +9,46 @@
 #include <mach/mx25.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_fec_data imx25_fec_data __initconst;
+#define imx25_add_fec(pdata)   \
+       imx_add_fec(&imx25_fec_data, pdata)
+
 #define imx25_add_flexcan0(pdata)      \
        imx_add_flexcan(0, MX25_CAN1_BASE_ADDR, SZ_16K, MX25_INT_CAN1, pdata)
 #define imx25_add_flexcan1(pdata)      \
        imx_add_flexcan(1, MX25_CAN2_BASE_ADDR, SZ_16K, MX25_INT_CAN2, pdata)
 
-#define imx25_add_imx_i2c0(pdata)      \
-       imx_add_imx_i2c(0, MX25_I2C1_BASE_ADDR, SZ_16K, MX25_INT_I2C1, pdata)
-#define imx25_add_imx_i2c1(pdata)      \
-       imx_add_imx_i2c(1, MX25_I2C2_BASE_ADDR, SZ_16K, MX25_INT_I2C2, pdata)
-#define imx25_add_imx_i2c2(pdata)      \
-       imx_add_imx_i2c(2, MX25_I2C3_BASE_ADDR, SZ_16K, MX25_INT_I2C3, pdata)
-
-#define imx25_add_imx_uart0(pdata)     \
-       imx_add_imx_uart_1irq(0, MX25_UART1_BASE_ADDR, SZ_16K, MX25_INT_UART1, pdata)
-#define imx25_add_imx_uart1(pdata)     \
-       imx_add_imx_uart_1irq(1, MX25_UART2_BASE_ADDR, SZ_16K, MX25_INT_UART2, pdata)
-#define imx25_add_imx_uart2(pdata)     \
-       imx_add_imx_uart_1irq(2, MX25_UART3_BASE_ADDR, SZ_16K, MX25_INT_UART3, pdata)
-#define imx25_add_imx_uart3(pdata)     \
-       imx_add_imx_uart_1irq(3, MX25_UART4_BASE_ADDR, SZ_16K, MX25_INT_UART4, pdata)
-#define imx25_add_imx_uart4(pdata)     \
-       imx_add_imx_uart_1irq(4, MX25_UART5_BASE_ADDR, SZ_16K, MX25_INT_UART5, pdata)
+extern const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst;
+#define imx25_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
+#define imx25_add_imx_i2c0(pdata)      imx25_add_imx_i2c(0, pdata)
+#define imx25_add_imx_i2c1(pdata)      imx25_add_imx_i2c(1, pdata)
+#define imx25_add_imx_i2c2(pdata)      imx25_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst;
+#define imx25_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst;
+#define imx25_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
+#define imx25_add_imx_uart0(pdata)     imx25_add_imx_uart(0, pdata)
+#define imx25_add_imx_uart1(pdata)     imx25_add_imx_uart(1, pdata)
+#define imx25_add_imx_uart2(pdata)     imx25_add_imx_uart(2, pdata)
+#define imx25_add_imx_uart3(pdata)     imx25_add_imx_uart(3, pdata)
+#define imx25_add_imx_uart4(pdata)     imx25_add_imx_uart(4, pdata)
 
+extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
 #define imx25_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand_v21(MX25_NFC_BASE_ADDR, MX25_INT_NANDFC, pdata)
-
-#define imx25_add_spi_imx0(pdata)      \
-       imx_add_spi_imx(0, MX25_CSPI1_BASE_ADDR, SZ_16K, MX25_INT_CSPI1, pdata)
-#define imx25_add_spi_imx1(pdata)      \
-       imx_add_spi_imx(1, MX25_CSPI2_BASE_ADDR, SZ_16K, MX25_INT_CSPI2, pdata)
-#define imx25_add_spi_imx2(pdata)      \
-       imx_add_spi_imx(2, MX25_CSPI3_BASE_ADDR, SZ_16K, MX25_INT_CSPI3, pdata)
+       imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx25_spi_imx_data[] __initconst;
+#define imx25_add_spi_imx(id, pdata)   \
+       imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+#define imx25_add_spi_imx0(pdata)      imx25_add_spi_imx(0, pdata)
+#define imx25_add_spi_imx1(pdata)      imx25_add_spi_imx(1, pdata)
+#define imx25_add_spi_imx2(pdata)      imx25_add_spi_imx(2, pdata)
+
+extern const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst;
+#define imx25_add_esdhc(id, pdata)     \
+       imx_add_esdhc(&imx25_esdhc_data[id], pdata)
index 3468eb15b2367fd1a4c197bf76d3b59af4b3372a..1d0eb3e85941030d091fc6094bc955ae40035128 100644 (file)
@@ -208,26 +208,6 @@ int __init imx25_register_gpios(void)
        return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
 }
 
-static struct resource mx25_fec_resources[] = {
-       {
-               .start  = MX25_FEC_BASE_ADDR,
-               .end    = MX25_FEC_BASE_ADDR + 0xfff,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = MX25_INT_FEC,
-               .end    = MX25_INT_FEC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mx25_fec_device = {
-       .name   = "fec",
-       .id     = 0,
-       .num_resources  = ARRAY_SIZE(mx25_fec_resources),
-       .resource       = mx25_fec_resources,
-};
-
 static struct resource mx25_rtc_resources[] = {
        {
                .start  = MX25_DRYICE_BASE_ADDR,
@@ -305,44 +285,6 @@ struct platform_device mx25_kpp_device = {
        .resource       = mx25_kpp_resources,
 };
 
-static struct resource imx_ssi_resources0[] = {
-       {
-               .start  = MX25_SSI1_BASE_ADDR,
-               .end    = MX25_SSI1_BASE_ADDR + 0x3fff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = MX25_INT_SSI1,
-               .end    = MX25_INT_SSI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct resource imx_ssi_resources1[] = {
-       {
-               .start  = MX25_SSI2_BASE_ADDR,
-               .end    = MX25_SSI2_BASE_ADDR + 0x3fff,
-               .flags  = IORESOURCE_MEM
-       }, {
-               .start  = MX25_INT_SSI2,
-               .end    = MX25_INT_SSI2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device imx_ssi_device0 = {
-       .name = "imx-ssi",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(imx_ssi_resources0),
-       .resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
-       .name = "imx-ssi",
-       .id = 1,
-       .num_resources = ARRAY_SIZE(imx_ssi_resources1),
-       .resource = imx_ssi_resources1,
-};
-
 static struct resource mx25_csi_resources[] = {
        {
                .start  = MX25_CSI_BASE_ADDR,
index 4aceb68e35a77003e11505dfb3eca338006263fb..7b70a43c3a4be3bccf692c4dea2e62f2af1615f5 100644 (file)
@@ -6,11 +6,8 @@ extern struct platform_device mxc_pwm_device1;
 extern struct platform_device mxc_pwm_device2;
 extern struct platform_device mxc_pwm_device3;
 extern struct platform_device mxc_keypad_device;
-extern struct platform_device mx25_fec_device;
 extern struct platform_device mx25_rtc_device;
 extern struct platform_device mx25_fb_device;
 extern struct platform_device mxc_wdt;
 extern struct platform_device mx25_kpp_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device mx25_csi_device;
index 91931dcb068997d540dd2a133001eed458cbc81b..e765ac5d9a08ad7c501d10e3e61682bfb45ead78 100644 (file)
@@ -34,7 +34,6 @@
 #include <mach/mx25.h>
 #include <mach/imx-uart.h>
 #include <mach/imxfb.h>
-#include <mach/ssi.h>
 #include <mach/audmux.h>
 
 #include "devices-imx25.h"
@@ -90,6 +89,9 @@ static struct pad_desc eukrea_mbimxsd_pads[] = {
        MX25_PAD_KPP_COL2__AUD5_TXC,
        MX25_PAD_KPP_COL1__AUD5_RXD,
        MX25_PAD_KPP_COL0__AUD5_TXD,
+       /* CAN */
+       MX25_PAD_GPIO_D__CAN2_RX,
+       MX25_PAD_GPIO_C__CAN2_TX,
 };
 
 #define GPIO_LED1      83
@@ -114,6 +116,38 @@ static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
                },
                .bpp    = 16,
                .pcr    = 0xCAD08B80,
+       }, {
+               .mode = {
+                       .name           = "DVI-VGA",
+                       .refresh        = 60,
+                       .xres           = 640,
+                       .yres           = 480,
+                       .pixclock       = 32000,
+                       .hsync_len      = 7,
+                       .left_margin    = 100,
+                       .right_margin   = 100,
+                       .vsync_len      = 7,
+                       .upper_margin   = 7,
+                       .lower_margin   = 100,
+               },
+               .pcr            = 0xFA208B80,
+               .bpp            = 16,
+       }, {
+               .mode = {
+                       .name           = "DVI-SVGA",
+                       .refresh        = 60,
+                       .xres           = 800,
+                       .yres           = 600,
+                       .pixclock       = 25000,
+                       .hsync_len      = 7,
+                       .left_margin    = 75,
+                       .right_margin   = 75,
+                       .vsync_len      = 7,
+                       .upper_margin   = 7,
+                       .lower_margin   = 75,
+               },
+               .pcr            = 0xFA208B80,
+               .bpp            = 16,
        },
 };
 
@@ -205,7 +239,8 @@ static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
        },
 };
 
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
        .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -215,7 +250,7 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
  * Add platform devices present on this baseboard and init
  * them from CPU side as far as required to use them later on
  */
-void __init eukrea_mbimxsd_baseboard_init(void)
+void __init eukrea_mbimxsd25_baseboard_init(void)
 {
        if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
                        ARRAY_SIZE(eukrea_mbimxsd_pads)))
@@ -239,7 +274,10 @@ void __init eukrea_mbimxsd_baseboard_init(void)
 
        imx25_add_imx_uart1(&uart_pdata);
        mxc_register_device(&mx25_fb_device, &eukrea_mximxsd_fb_pdata);
-       mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+       imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+       imx25_add_flexcan1(NULL);
+       imx25_add_esdhc(0, NULL);
 
        gpio_request(GPIO_LED1, "LED1");
        gpio_direction_output(GPIO_LED1, 1);
index 56b2e26d23b4eda6a178e6ee633eae2526bd3186..f6f9ad60c25e37f724217c0e5f7a05393992812c 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/fec.h>
 #include <linux/platform_device.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -41,7 +40,6 @@
 #include <mach/mxc_nand.h>
 #include <mach/imxfb.h>
 #include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
 #include <mach/iomux-mx25.h>
 
 #include "devices-imx25.h"
@@ -67,7 +65,7 @@ static struct pad_desc eukrea_cpuimx25_pads[] = {
        MX25_PAD_I2C1_DAT__I2C1_DAT,
 };
 
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
        .phy    = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -129,26 +127,21 @@ static void __init eukrea_cpuimx25_init(void)
        imx25_add_imx_uart0(&uart_pdata);
        imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
        mxc_register_device(&mx25_rtc_device, NULL);
-       mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+       imx25_add_fec(&mx25_fec_pdata);
 
        i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
                                ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
        imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
 
-#if defined(CONFIG_USB_ULPI)
-       if (otg_mode_host) {
-               otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-
+       if (otg_mode_host)
                mxc_register_device(&mxc_otg, &otg_pdata);
-       }
-       mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-#endif
-       if (!otg_mode_host)
+       else
                mxc_register_device(&otg_udc_device, &otg_device_pdata);
 
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD_BASEBOARD
-       eukrea_mbimxsd_baseboard_init();
+       mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
+       eukrea_mbimxsd25_baseboard_init();
 #endif
 }
 
@@ -163,8 +156,6 @@ static struct sys_timer eukrea_cpuimx25_timer = {
 
 MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
        /* Maintainer: Eukrea Electromatique */
-       .phys_io        = MX25_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX25_PHYS_OFFSET + 0x100,
        .map_io         = mx25_map_io,
        .init_irq       = mx25_init_irq,
index 62bc21f11a714aa46df5e439d4965f340d59460a..80805107a73eb74bbf7b18d2e22fd7b18e194965 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/fec.h>
 #include <linux/platform_device.h>
 #include <linux/input/matrix_keypad.h>
 
@@ -99,7 +98,7 @@ static struct pad_desc mx25pdk_pads[] = {
        MX25_PAD_KPP_COL3__KPP_COL3,
 };
 
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
         .phy    = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -192,7 +191,7 @@ static void __init mx25pdk_init(void)
        mxc_register_device(&mxc_wdt, NULL);
 
        mx25pdk_fec_reset();
-       mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+       imx25_add_fec(&mx25_fec_pdata);
        mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data);
 }
 
@@ -207,8 +206,6 @@ static struct sys_timer mx25pdk_timer = {
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX25_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX25_PHYS_OFFSET + 0x100,
        .map_io         = mx25_map_io,
        .init_irq       = mx25_init_irq,
index 85beece802aab702a71331f63fd6ff7065adb7bb..096fd33f8ab9ad6b77c4689361be00172f3bd327 100644 (file)
@@ -9,6 +9,7 @@ config ARCH_MX35
        bool
        select ARCH_MXC_IOMUX_V3
        select ARCH_MXC_AUDMUX_V2
+       select HAVE_EPIT
 
 comment "MX3 platforms:"
 
@@ -16,6 +17,7 @@ config MACH_MX31ADS
        bool "Support MX31ADS platforms"
        select ARCH_MX31
        select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_UART
        default y
        help
@@ -117,9 +119,11 @@ config MACH_PCM043
        bool "Support Phytec pcm043 (i.MX35) platforms"
        select ARCH_MX35
        select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_FLEXCAN
+       select IMX_HAVE_PLATFORM_ESDHC
        select MXC_ULPI if USB_ULPI
        help
          Include support for Phytec pcm043 platform. This includes
@@ -140,6 +144,7 @@ config MACH_MX35_3DS
        bool "Support MX35PDK platform"
        select ARCH_MX35
        select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_NAND
        default n
        help
          Include support for MX35PDK platform. This includes specific
@@ -159,6 +164,8 @@ config MACH_EUKREA_CPUIMX35
        select IMX_HAVE_PLATFORM_IMX_UART
        select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_FLEXCAN
+       select IMX_HAVE_PLATFORM_ESDHC
        select MXC_ULPI if USB_ULPI
        help
          Include support for Eukrea CPUIMX35 platform. This includes
@@ -170,8 +177,8 @@ choice
        default MACH_EUKREA_MBIMXSD35_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD35_BASEBOARD
-       prompt "Eukrea MBIMXSD development board"
-       bool
+       bool "Eukrea MBIMXSD development board"
+       select IMX_HAVE_PLATFORM_IMX_SSI
        help
          This adds board specific devices that can be found on Eukrea's
          MBIMXSD evaluation board.
index 2bd7beceb99182879a7100d14e6d54dd5cdac6a2..8a182d0a3fcf9d11aa6307c9410c94ee27541924 100644 (file)
@@ -7,7 +7,6 @@
 obj-y                          := mm.o devices.o cpu.o
 CFLAGS_mm.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
 CFLAGS_devices.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
-CFLAGS_cpu.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
 obj-$(CONFIG_ARCH_MX31)                += clock-imx31.o iomux-imx31.o
 obj-$(CONFIG_ARCH_MX35)                += clock-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)     += mach-mx31ads.o
index 9a9eb6de6127efd0b7a6241a17a5f9d88b4e09e1..109e98f323e0568a299d46f1481ee3a31116476e 100644 (file)
@@ -477,7 +477,7 @@ DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
@@ -525,9 +525,9 @@ DEFINE_CLOCK(ipg_clk,     0, NULL,          0, ipg_get_rate, NULL, &ahb_clk);
 
 static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "emi", emi_clk)
-       _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-       _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-       _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+       _REGISTER_CLOCK("imx31-cspi.0", NULL, cspi1_clk)
+       _REGISTER_CLOCK("imx31-cspi.1", NULL, cspi2_clk)
+       _REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
        _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
        _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
@@ -564,7 +564,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "ata", ata_clk)
        _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
        _REGISTER_CLOCK(NULL, "rng", rng_clk)
-       _REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
        _REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
        _REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
        _REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
index d3af0fdf8475f7ef0d67b3afbb080df739c36431..61e4a318980a2bc9fe4fa25c7de02a08a7b89bb8 100644 (file)
@@ -155,7 +155,7 @@ static unsigned long get_rate_arm(void)
 
        aad = &clk_consumer[(pdr0 >> 16) & 0xf];
        if (aad->sel)
-               fref = fref * 2 / 3;
+               fref = fref * 3 / 4;
 
        return fref / aad->arm;
 }
@@ -164,7 +164,7 @@ static unsigned long get_rate_ahb(struct clk *clk)
 {
        unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
        struct arm_ahb_div *aad;
-       unsigned long fref = get_rate_mpll();
+       unsigned long fref = get_rate_arm();
 
        aad = &clk_consumer[(pdr0 >> 16) & 0xf];
 
@@ -176,16 +176,11 @@ static unsigned long get_rate_ipg(struct clk *clk)
        return get_rate_ahb(NULL) >> 1;
 }
 
-static unsigned long get_3_3_div(unsigned long in)
-{
-       return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1);
-}
-
 static unsigned long get_rate_uart(struct clk *clk)
 {
        unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3);
        unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
-       unsigned long div = get_3_3_div(pdr4 >> 10);
+       unsigned long div = ((pdr4 >> 10) & 0x3f) + 1;
 
        if (pdr3 & (1 << 14))
                return get_rate_arm() / div;
@@ -216,7 +211,7 @@ static unsigned long get_rate_sdhc(struct clk *clk)
                break;
        }
 
-       return rate / get_3_3_div(div);
+       return rate / (div + 1);
 }
 
 static unsigned long get_rate_mshc(struct clk *clk)
@@ -270,7 +265,7 @@ static unsigned long get_rate_csi(struct clk *clk)
        else
                rate = get_rate_ppll();
 
-       return rate / get_3_3_div((pdr2 >> 16) & 0x3f);
+       return rate / (((pdr2 >> 16) & 0x3f) + 1);
 }
 
 static unsigned long get_rate_otg(struct clk *clk)
@@ -283,25 +278,51 @@ static unsigned long get_rate_otg(struct clk *clk)
        else
                rate = get_rate_ppll();
 
-       return rate / get_3_3_div((pdr4 >> 22) & 0x3f);
+       return rate / (((pdr4 >> 22) & 0x3f) + 1);
 }
 
 static unsigned long get_rate_ipg_per(struct clk *clk)
 {
        unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
        unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
-       unsigned long div1, div2;
+       unsigned long div;
 
        if (pdr0 & (1 << 26)) {
-               div1 = (pdr4 >> 19) & 0x7;
-               div2 = (pdr4 >> 16) & 0x7;
-               return get_rate_arm() / ((div1 + 1) * (div2 + 1));
+               div = (pdr4 >> 16) & 0x3f;
+               return get_rate_arm() / (div + 1);
        } else {
-               div1 = (pdr0 >> 12) & 0x7;
-               return get_rate_ahb(NULL) / div1;
+               div = (pdr0 >> 12) & 0x7;
+               return get_rate_ahb(NULL) / (div + 1);
        }
 }
 
+static unsigned long get_rate_hsp(struct clk *clk)
+{
+       unsigned long hsp_podf = (__raw_readl(CCM_BASE + CCM_PDR0) >> 20) & 0x03;
+       unsigned long fref = get_rate_mpll();
+
+       if (fref > 400 * 1000 * 1000) {
+               switch (hsp_podf) {
+               case 0:
+                       return fref >> 2;
+               case 1:
+                       return fref >> 3;
+               case 2:
+                       return fref / 3;
+               }
+       } else {
+               switch (hsp_podf) {
+               case 0:
+               case 2:
+                       return fref / 3;
+               case 1:
+                       return fref / 6;
+               }
+       }
+
+       return 0;
+}
+
 static int clk_cgr_enable(struct clk *clk)
 {
        u32 reg;
@@ -343,8 +364,8 @@ DEFINE_CLOCK(cspi2_clk,  1, CCM_CGR0, 12, get_rate_ipg, NULL);
 DEFINE_CLOCK(ect_clk,    0, CCM_CGR0, 14, get_rate_ipg, NULL);
 DEFINE_CLOCK(edio_clk,   0, CCM_CGR0, 16, NULL, NULL);
 DEFINE_CLOCK(emi_clk,    0, CCM_CGR0, 18, get_rate_ipg, NULL);
-DEFINE_CLOCK(epit1_clk,  0, CCM_CGR0, 20, get_rate_ipg_per, NULL);
-DEFINE_CLOCK(epit2_clk,  1, CCM_CGR0, 22, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(epit1_clk,  0, CCM_CGR0, 20, get_rate_ipg, NULL);
+DEFINE_CLOCK(epit2_clk,  1, CCM_CGR0, 22, get_rate_ipg, NULL);
 DEFINE_CLOCK(esai_clk,   0, CCM_CGR0, 24, NULL, NULL);
 DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL);
 DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL);
@@ -359,7 +380,7 @@ DEFINE_CLOCK(i2c1_clk,   0, CCM_CGR1, 10, get_rate_ipg_per, NULL);
 DEFINE_CLOCK(i2c2_clk,   1, CCM_CGR1, 12, get_rate_ipg_per, NULL);
 DEFINE_CLOCK(i2c3_clk,   2, CCM_CGR1, 14, get_rate_ipg_per, NULL);
 DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL);
-DEFINE_CLOCK(ipu_clk,    0, CCM_CGR1, 18, get_rate_ahb, NULL);
+DEFINE_CLOCK(ipu_clk,    0, CCM_CGR1, 18, get_rate_hsp, NULL);
 DEFINE_CLOCK(kpp_clk,    0, CCM_CGR1, 20, get_rate_ipg, NULL);
 DEFINE_CLOCK(mlb_clk,    0, CCM_CGR1, 22, get_rate_ahb, NULL);
 DEFINE_CLOCK(mshc_clk,   0, CCM_CGR1, 24, get_rate_mshc, NULL);
@@ -430,17 +451,17 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "ata", ata_clk)
        _REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
        _REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
-       _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-       _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+       _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
+       _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
        _REGISTER_CLOCK(NULL, "ect", ect_clk)
        _REGISTER_CLOCK(NULL, "edio", edio_clk)
        _REGISTER_CLOCK(NULL, "emi", emi_clk)
-       _REGISTER_CLOCK(NULL, "epit", epit1_clk)
-       _REGISTER_CLOCK(NULL, "epit", epit2_clk)
+       _REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
+       _REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
        _REGISTER_CLOCK(NULL, "esai", esai_clk)
-       _REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk)
-       _REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk)
-       _REGISTER_CLOCK(NULL, "sdhc", esdhc3_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
        _REGISTER_CLOCK("fec.0", NULL, fec_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
@@ -461,7 +482,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
        _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
        _REGISTER_CLOCK(NULL, "scc", scc_clk)
-       _REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
        _REGISTER_CLOCK(NULL, "spba", spba_clk)
        _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
@@ -485,10 +506,10 @@ static struct clk_lookup lookups[] = {
 
 int __init mx35_clocks_init()
 {
-       unsigned int ll = 0;
+       unsigned int cgr2 = 3 << 26, cgr3 = 0;
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
-       ll = (3 << 16);
+       cgr2 |= 3 << 16;
 #endif
 
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
@@ -499,11 +520,31 @@ int __init mx35_clocks_init()
        __raw_writel((3 << 18), CCM_BASE + CCM_CGR0);
        __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
                        CCM_BASE + CCM_CGR1);
-       __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2);
-       __raw_writel(0, CCM_BASE + CCM_CGR3);
 
+       /*
+        * Check if we came up in internal boot mode. If yes, we need some
+        * extra clocks turned on, otherwise the MX35 boot ROM code will
+        * hang after a watchdog reset.
+        */
+       if (!(__raw_readl(CCM_BASE + CCM_RCSR) & (3 << 10))) {
+               /* Additionally turn on UART1, SCC, and IIM clocks */
+               cgr2 |= 3 << 16 | 3 << 4;
+               cgr3 |= 3 << 2;
+       }
+
+       __raw_writel(cgr2, CCM_BASE + CCM_CGR2);
+       __raw_writel(cgr3, CCM_BASE + CCM_CGR3);
+
+       clk_enable(&iim_clk);
+       mx35_read_cpu_rev();
+
+#ifdef CONFIG_MXC_USE_EPIT
+       epit_timer_init(&epit1_clk,
+                       MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
+#else
        mxc_timer_init(&gpt_clk,
                        MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
+#endif
 
        return 0;
 }
index 861afe0fe3ad6217edfa46fd25d4e9985b5ce1b2..d00a75457812eebc3f23eab759140a057ad6f8f8 100644 (file)
@@ -25,15 +25,15 @@ struct mx3_cpu_type {
 };
 
 static struct mx3_cpu_type mx31_cpu_type[] __initdata = {
-       { .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = CHIP_REV_1_0   },
-       { .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = CHIP_REV_1_1   },
-       { .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = CHIP_REV_1_1   },
-       { .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = CHIP_REV_1_1   },
-       { .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = CHIP_REV_1_1   },
-       { .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = CHIP_REV_1_2   },
-       { .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = CHIP_REV_1_2   },
-       { .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = CHIP_REV_2_0   },
-       { .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = CHIP_REV_2_0   },
+       { .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = MX3x_CHIP_REV_1_0 },
+       { .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
+       { .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
+       { .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+       { .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+       { .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
+       { .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
+       { .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
+       { .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
 };
 
 void __init mx31_read_cpu_rev(void)
@@ -41,7 +41,7 @@ void __init mx31_read_cpu_rev(void)
        u32 i, srev;
 
        /* read SREV register from IIM module */
-       srev = __raw_readl(IO_ADDRESS(IIM_BASE_ADDR + MXC_IIMSREV));
+       srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
 
        for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
                if (srev == mx31_cpu_type[i].srev) {
@@ -55,3 +55,30 @@ void __init mx31_read_cpu_rev(void)
 
        printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
 }
+
+unsigned int mx35_cpu_rev;
+EXPORT_SYMBOL(mx35_cpu_rev);
+
+void __init mx35_read_cpu_rev(void)
+{
+       u32 rev;
+       char *srev = "unknown";
+
+       rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
+       switch (rev) {
+       case 0x00:
+               mx35_cpu_rev = MX3x_CHIP_REV_1_0;
+               srev = "1.0";
+               break;
+       case 0x10:
+               mx35_cpu_rev = MX3x_CHIP_REV_2_0;
+               srev = "2.0";
+               break;
+       case 0x11:
+               mx35_cpu_rev = MX3x_CHIP_REV_2_1;
+               srev = "2.1";
+               break;
+       }
+
+       printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+}
index 3b1a44a20585560935e34698d3c333659300717e..de9598590eba71e43f83339e5d53a64d1740345c 100644 (file)
@@ -9,30 +9,33 @@
 #include <mach/mx31.h>
 #include <mach/devices-common.h>
 
-#define imx31_add_imx_i2c0(pdata)      \
-       imx_add_imx_i2c(0, MX31_I2C1_BASE_ADDR, SZ_4K, MX31_INT_I2C1, pdata)
-#define imx31_add_imx_i2c1(pdata)      \
-       imx_add_imx_i2c(1, MX31_I2C2_BASE_ADDR, SZ_4K, MX31_INT_I2C2, pdata)
-#define imx31_add_imx_i2c2(pdata)      \
-       imx_add_imx_i2c(2, MX31_I2C3_BASE_ADDR, SZ_4K, MX31_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst;
+#define imx31_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx31_imx_i2c_data[id], pdata)
+#define imx31_add_imx_i2c0(pdata)      imx31_add_imx_i2c(0, pdata)
+#define imx31_add_imx_i2c1(pdata)      imx31_add_imx_i2c(1, pdata)
+#define imx31_add_imx_i2c2(pdata)      imx31_add_imx_i2c(2, pdata)
 
-#define imx31_add_imx_uart0(pdata)     \
-       imx_add_imx_uart_1irq(0, MX31_UART1_BASE_ADDR, SZ_16K, MX31_INT_UART1, pdata)
-#define imx31_add_imx_uart1(pdata)     \
-       imx_add_imx_uart_1irq(1, MX31_UART2_BASE_ADDR, SZ_16K, MX31_INT_UART2, pdata)
-#define imx31_add_imx_uart2(pdata)     \
-       imx_add_imx_uart_1irq(2, MX31_UART3_BASE_ADDR, SZ_16K, MX31_INT_UART3, pdata)
-#define imx31_add_imx_uart3(pdata)     \
-       imx_add_imx_uart_1irq(3, MX31_UART4_BASE_ADDR, SZ_16K, MX31_INT_UART4, pdata)
-#define imx31_add_imx_uart4(pdata)     \
-       imx_add_imx_uart_1irq(4, MX31_UART5_BASE_ADDR, SZ_16K, MX31_INT_UART5, pdata)
+extern const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst;
+#define imx31_add_imx_ssi(id, pdata)    \
+       imx_add_imx_ssi(&imx31_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst;
+#define imx31_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx31_imx_uart_data[id], pdata)
+#define imx31_add_imx_uart0(pdata)     imx31_add_imx_uart(0, pdata)
+#define imx31_add_imx_uart1(pdata)     imx31_add_imx_uart(1, pdata)
+#define imx31_add_imx_uart2(pdata)     imx31_add_imx_uart(2, pdata)
+#define imx31_add_imx_uart3(pdata)     imx31_add_imx_uart(3, pdata)
+#define imx31_add_imx_uart4(pdata)     imx31_add_imx_uart(4, pdata)
+
+extern const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst;
 #define imx31_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand_v1(MX31_NFC_BASE_ADDR, MX31_INT_NANDFC, pdata)
+       imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
 
-#define imx31_add_spi_imx0(pdata)      \
-       imx_add_spi_imx(0, MX31_CSPI1_BASE_ADDR, SZ_4K, MX31_INT_CSPI1, pdata)
-#define imx31_add_spi_imx1(pdata)      \
-       imx_add_spi_imx(1, MX31_CSPI2_BASE_ADDR, SZ_4K, MX31_INT_CSPI2, pdata)
-#define imx31_add_spi_imx2(pdata)      \
-       imx_add_spi_imx(2, MX31_CSPI3_BASE_ADDR, SZ_4K, MX31_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx31_cspi_data[] __initconst;
+#define imx31_add_cspi(id, pdata)      \
+       imx_add_spi_imx(&imx31_cspi_data[id], pdata)
+#define imx31_add_spi_imx0(pdata)      imx31_add_cspi(0, pdata)
+#define imx31_add_spi_imx1(pdata)      imx31_add_cspi(1, pdata)
+#define imx31_add_spi_imx2(pdata)      imx31_add_cspi(2, pdata)
index f6a431a4c3d2ebdf45c82ed6f54afcdbaccd73e1..5eb917b638d0b40ea14ef260bdc414298cb17db8 100644 (file)
@@ -9,29 +9,43 @@
 #include <mach/mx35.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_fec_data imx35_fec_data __initconst;
+#define imx35_add_fec(pdata)   \
+       imx_add_fec(&imx35_fec_data, pdata)
+
 #define imx35_add_flexcan0(pdata)      \
        imx_add_flexcan(0, MX35_CAN1_BASE_ADDR, SZ_16K, MX35_INT_CAN1, pdata)
 #define imx35_add_flexcan1(pdata)      \
        imx_add_flexcan(1, MX35_CAN2_BASE_ADDR, SZ_16K, MX35_INT_CAN2, pdata)
 
-#define imx35_add_imx_i2c0(pdata)      \
-       imx_add_imx_i2c(0, MX35_I2C1_BASE_ADDR, SZ_4K, MX35_INT_I2C1, pdata)
-#define imx35_add_imx_i2c1(pdata)      \
-       imx_add_imx_i2c(1, MX35_I2C2_BASE_ADDR, SZ_4K, MX35_INT_I2C2, pdata)
-#define imx35_add_imx_i2c2(pdata)      \
-       imx_add_imx_i2c(2, MX35_I2C3_BASE_ADDR, SZ_4K, MX35_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst;
+#define imx35_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx35_imx_i2c_data[id], pdata)
+#define imx35_add_imx_i2c0(pdata)      imx35_add_imx_i2c(0, pdata)
+#define imx35_add_imx_i2c1(pdata)      imx35_add_imx_i2c(1, pdata)
+#define imx35_add_imx_i2c2(pdata)      imx35_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
+#define imx35_add_imx_ssi(id, pdata)    \
+       imx_add_imx_ssi(&imx35_imx_ssi_data[id], pdata)
 
-#define imx35_add_imx_uart0(pdata)     \
-       imx_add_imx_uart_1irq(0, MX35_UART1_BASE_ADDR, SZ_16K, MX35_INT_UART1, pdata)
-#define imx35_add_imx_uart1(pdata)     \
-       imx_add_imx_uart_1irq(1, MX35_UART2_BASE_ADDR, SZ_16K, MX35_INT_UART2, pdata)
-#define imx35_add_imx_uart2(pdata)     \
-       imx_add_imx_uart_1irq(2, MX35_UART3_BASE_ADDR, SZ_16K, MX35_INT_UART3, pdata)
+extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst;
+#define imx35_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx35_imx_uart_data[id], pdata)
+#define imx35_add_imx_uart0(pdata)     imx35_add_imx_uart(0, pdata)
+#define imx35_add_imx_uart1(pdata)     imx35_add_imx_uart(1, pdata)
+#define imx35_add_imx_uart2(pdata)     imx35_add_imx_uart(2, pdata)
 
+extern const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst;
 #define imx35_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand_v21(MX35_NFC_BASE_ADDR, MX35_INT_NANDFC, pdata)
+       imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx35_cspi_data[] __initconst;
+#define imx35_add_cspi(id, pdata)      \
+       imx_add_spi_imx(&imx35_cspi_data[id], pdata)
+#define imx35_add_spi_imx0(pdata)      imx35_add_cspi(0, pdata)
+#define imx35_add_spi_imx1(pdata)      imx35_add_cspi(1, pdata)
 
-#define imx35_add_spi_imx0(pdata)      \
-       imx_add_spi_imx(0, MX35_CSPI1_BASE_ADDR, SZ_4K, MX35_INT_CSPI1, pdata)
-#define imx35_add_spi_imx1(pdata)      \
-       imx_add_spi_imx(1, MX35_CSPI2_BASE_ADDR, SZ_4K, MX35_INT_CSPI2, pdata)
+extern const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst;
+#define imx35_add_esdhc(id, pdata)     \
+       imx_add_esdhc(&imx35_esdhc_data[id], pdata)
index a4fd1a26fc91982d200d76c7a152eb5c62610a7b..f4dff11aaee7a68aa58fb9a07a43aca9662f6856 100644 (file)
@@ -281,65 +281,6 @@ struct platform_device mxc_usbh2 = {
        .num_resources = ARRAY_SIZE(mxc_usbh2_resources),
 };
 
-#if defined(CONFIG_ARCH_MX35)
-static struct resource mxc_fec_resources[] = {
-       {
-               .start  = MXC_FEC_BASE_ADDR,
-               .end    = MXC_FEC_BASE_ADDR + 0xfff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = MXC_INT_FEC,
-               .end    = MXC_INT_FEC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_fec_device = {
-       .name = "fec",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(mxc_fec_resources),
-       .resource = mxc_fec_resources,
-};
-#endif
-
-static struct resource imx_ssi_resources0[] = {
-       {
-               .start  = SSI1_BASE_ADDR,
-               .end    = SSI1_BASE_ADDR + 0xfff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = MX31_INT_SSI1,
-               .end    = MX31_INT_SSI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct resource imx_ssi_resources1[] = {
-       {
-               .start  = SSI2_BASE_ADDR,
-               .end    = SSI2_BASE_ADDR + 0xfff,
-               .flags  = IORESOURCE_MEM
-       }, {
-               .start  = MX31_INT_SSI2,
-               .end    = MX31_INT_SSI2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device imx_ssi_device0 = {
-       .name = "imx-ssi",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(imx_ssi_resources0),
-       .resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
-       .name = "imx-ssi",
-       .id = 1,
-       .num_resources = ARRAY_SIZE(imx_ssi_resources1),
-       .resource = imx_ssi_resources1,
-};
-
 static struct resource imx_wdt_resources[] = {
        {
                .flags = IORESOURCE_MEM,
@@ -410,10 +351,6 @@ static int __init mx3_devices_init(void)
                mxc_usbh1_resources[0].end = MX35_OTG_BASE_ADDR + 0x5ff;
                mxc_usbh1_resources[1].start = MXC_INT_USBHS;
                mxc_usbh1_resources[1].end = MXC_INT_USBHS;
-               imx_ssi_resources0[1].start = MX35_INT_SSI1;
-               imx_ssi_resources0[1].end = MX35_INT_SSI1;
-               imx_ssi_resources1[1].start = MX35_INT_SSI2;
-               imx_ssi_resources1[1].end = MX35_INT_SSI2;
                imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
                imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
        }
index e5535234839f5e1ae8159d0513e8bf9c0952d7c7..585f814473d5f7b857426b8f549bf1512002e9da 100644 (file)
@@ -2,7 +2,6 @@ extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mx3_ipu;
 extern struct platform_device mx3_fb;
 extern struct platform_device mx3_camera;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxcsdhc_device0;
 extern struct platform_device mxcsdhc_device1;
 extern struct platform_device mxc_otg_udc_device;
@@ -10,9 +9,6 @@ extern struct platform_device mxc_otg_host;
 extern struct platform_device mxc_usbh1;
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mxc_rnga_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device imx_wdt_device0;
 extern struct platform_device imx_rtc_device0;
 extern struct platform_device imx_kpp_device;
index 1dc5004df866d4e9df7d817aca27e658573f8c6c..1abc10d5292217db60b714de87e689491e05a4fe 100644 (file)
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
 
 static const struct fb_videomode fb_modedb[] = {
        {
-               .name           = "CMO_QVGA",
+               .name           = "CMO-QVGA",
                .refresh        = 60,
                .xres           = 320,
                .yres           = 240,
@@ -65,6 +64,40 @@ static const struct fb_videomode fb_modedb[] = {
                .vmode          = FB_VMODE_NONINTERLACED,
                .flag           = 0,
        },
+       {
+               .name           = "DVI-VGA",
+               .refresh        = 60,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 32000,
+               .left_margin    = 100,
+               .right_margin   = 100,
+               .upper_margin   = 7,
+               .lower_margin   = 100,
+               .hsync_len      = 7,
+               .vsync_len      = 7,
+               .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+                                 FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+               .flag           = 0,
+       },
+       {
+               .name           = "DVI-SVGA",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 600,
+               .pixclock       = 25000,
+               .left_margin    = 75,
+               .right_margin   = 75,
+               .upper_margin   = 7,
+               .lower_margin   = 75,
+               .hsync_len      = 7,
+               .vsync_len      = 7,
+               .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+                                 FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+               .flag           = 0,
+       },
 };
 
 static struct ipu_platform_data mx3_ipu_data = {
@@ -73,7 +106,7 @@ static struct ipu_platform_data mx3_ipu_data = {
 
 static struct mx3fb_platform_data mx3fb_pdata = {
        .dma_dev        = &mx3_ipu.dev,
-       .name           = "CMO_QVGA",
+       .name           = "CMO-QVGA",
        .mode           = fb_modedb,
        .num_modes      = ARRAY_SIZE(fb_modedb),
 };
@@ -120,6 +153,16 @@ static struct pad_desc eukrea_mbimxsd_pads[] = {
        MX35_PAD_STXD4__AUDMUX_AUD4_TXD,
        MX35_PAD_SRXD4__AUDMUX_AUD4_RXD,
        MX35_PAD_SCK4__AUDMUX_AUD4_TXC,
+       /* CAN2 */
+       MX35_PAD_TX5_RX0__CAN2_TXCAN,
+       MX35_PAD_TX4_RX1__CAN2_RXCAN,
+       /* SDCARD */
+       MX35_PAD_SD1_CMD__ESDHC1_CMD,
+       MX35_PAD_SD1_CLK__ESDHC1_CLK,
+       MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
 };
 
 #define GPIO_LED1      (2 * 32 + 29)
@@ -206,7 +249,8 @@ static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
        },
 };
 
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
        .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -216,7 +260,7 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
  * Add platform devices present on this baseboard and init
  * them from CPU side as far as required to use them later on
  */
-void __init eukrea_mbimxsd_baseboard_init(void)
+void __init eukrea_mbimxsd35_baseboard_init(void)
 {
        if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
                        ARRAY_SIZE(eukrea_mbimxsd_pads)))
@@ -242,7 +286,10 @@ void __init eukrea_mbimxsd_baseboard_init(void)
        mxc_register_device(&mx3_ipu, &mx3_ipu_data);
        mxc_register_device(&mx3_fb, &mx3fb_pdata);
 
-       mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+       imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+       imx35_add_flexcan1(NULL);
+       imx35_add_esdhc(0, NULL);
 
        gpio_request(GPIO_LED1, "LED1");
        gpio_direction_output(GPIO_LED1, 1);
@@ -254,7 +301,7 @@ void __init eukrea_mbimxsd_baseboard_init(void)
 
        gpio_request(GPIO_LCDPWR, "LCDPWR");
        gpio_direction_output(GPIO_LCDPWR, 1);
-       gpio_free(GPIO_SWITCH1);
+       gpio_free(GPIO_LCDPWR);
 
        i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
                                ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
index 68879c996a55d0db79b84f94952ed8efc6c0cf7a..aaa30fe18f8593639e9f4ffa8752c52b4932de5f 100644 (file)
@@ -571,8 +571,6 @@ static struct sys_timer armadillo5x0_timer = {
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
        /* Maintainer: Alberto Panizzo  */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index 63f970f340a2cc28482ea1484a248fade05098e8..8533bf04284a1fc682db1a7fc15897a097a61e2d 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -43,7 +44,6 @@
 #include <mach/iomux-mx35.h>
 #include <mach/mxc_nand.h>
 #include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -53,39 +53,16 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 };
 
 static const struct imxi2c_platform_data
-eukrea_cpuimx35_i2c0_data __initconst = {
-       .bitrate = 50000,
+               eukrea_cpuimx35_i2c0_data __initconst = {
+       .bitrate =              100000,
 };
 
-#define TSC2007_IRQGPIO                (2 * 32 + 2)
-static int ts_get_pendown_state(void)
-{
-       int val = 0;
-       gpio_free(TSC2007_IRQGPIO);
-       gpio_request(TSC2007_IRQGPIO, NULL);
-       gpio_direction_input(TSC2007_IRQGPIO);
-
-       val = gpio_get_value(TSC2007_IRQGPIO);
-
-       gpio_free(TSC2007_IRQGPIO);
-       gpio_request(TSC2007_IRQGPIO, NULL);
-
-       return val ? 0 : 1;
-}
-
-static int ts_init(void)
-{
-       gpio_request(TSC2007_IRQGPIO, NULL);
-       return 0;
-}
-
 static struct tsc2007_platform_data tsc2007_info = {
        .model                  = 2007,
        .x_plate_ohms           = 180,
-       .get_pendown_state      = ts_get_pendown_state,
-       .init_platform_hw       = ts_init,
 };
 
+#define TSC2007_IRQGPIO                (2 * 32 + 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
        {
                I2C_BOARD_INFO("pcf8563", 0x51),
@@ -98,7 +75,6 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 };
 
 static struct platform_device *devices[] __initdata = {
-       &mxc_fec_device,
        &imx_wdt_device0,
 };
 
@@ -135,18 +111,18 @@ static struct pad_desc eukrea_cpuimx35_pads[] = {
 };
 
 static const struct mxc_nand_platform_data
-eukrea_cpuimx35_nand_board_info __initconst = {
+               eukrea_cpuimx35_nand_board_info __initconst = {
        .width          = 1,
        .hw_ecc         = 1,
        .flash_bbt      = 1,
 };
 
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused otg_pdata = {
        .portsc = MXC_EHCI_MODE_UTMI,
        .flags  = MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused usbh1_pdata = {
        .portsc = MXC_EHCI_MODE_SERIAL,
        .flags  = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
                  MXC_EHCI_IPPUE_DOWN,
@@ -180,6 +156,7 @@ static void __init mxc_board_init(void)
        mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
                        ARRAY_SIZE(eukrea_cpuimx35_pads));
 
+       imx35_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx35_add_imx_uart0(&uart_pdata);
@@ -189,20 +166,15 @@ static void __init mxc_board_init(void)
                        ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
        imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
 
-#if defined(CONFIG_USB_ULPI)
-       if (otg_mode_host) {
-               otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-
+       if (otg_mode_host)
                mxc_register_device(&mxc_otg_host, &otg_pdata);
-       }
-       mxc_register_device(&mxc_usbh1, &usbh1_pdata);
-#endif
-       if (!otg_mode_host)
+       else
                mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
 
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD_BASEBOARD
-       eukrea_mbimxsd_baseboard_init();
+       mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD
+       eukrea_mbimxsd35_baseboard_init();
 #endif
 }
 
@@ -217,8 +189,6 @@ struct sys_timer eukrea_cpuimx35_timer = {
 
 MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35")
        /* Maintainer: Eukrea Electromatique */
-       .phys_io        = MX35_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx35_map_io,
        .init_irq       = mx35_init_irq,
index 5b23e416d6c704c904385895f4bbf82dabfba56e..042cd5655e17b46d548a39a72b2780881af91bb4 100644 (file)
@@ -274,8 +274,6 @@ static struct sys_timer kzm_timer = {
  * initialize __mach_desc_KZM_ARM11_01 data structure.
  */
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = kzm_map_io,
        .init_irq       = mx31_init_irq,
index 6fe69e124d30faa27d23a239ba903f0a76cb1c15..5c1d0e86c91e16fd22e0ed2f4d1c190eb87f3a58 100644 (file)
@@ -301,8 +301,6 @@ static struct sys_timer mx31_3ds_timer = {
  */
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_3ds_map_io,
        .init_irq       = mx31_init_irq,
index 94b3e7c4240408451aa08446c9b991ad179be699..b993b9bf61793c4bfb765abfa1b7ef1caaaa0f42 100644 (file)
 #include <linux/i2c.h>
 #include <linux/irq.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 #include <mach/common.h>
+#include <mach/board-mx31ads.h>
 #include <mach/iomux-mx3.h>
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 #include "devices-imx31.h"
 #include "devices.h"
 
-/* Base address of PBC controller */
-#define PBC_BASE_ADDRESS        MX31_CS4_BASE_ADDR_VIRT
-/* Offsets for the PBC Controller register */
-
 /* PBC Board interrupt status register */
 #define PBC_INTSTATUS           0x000016
 
@@ -67,7 +63,6 @@
 #define PBC_INTMASK_CLEAR_REG  (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
 #define EXPIO_PARENT_INT       IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
 
-#define MXC_EXP_IO_BASE                (MXC_BOARD_IRQ_START)
 #define MXC_IRQ_TO_EXPIO(irq)  ((irq) - MXC_EXP_IO_BASE)
 
 #define EXPIO_INT_XUART_INTA   (MXC_EXP_IO_BASE + 10)
@@ -517,7 +512,7 @@ static unsigned int ssi_pins[] = {
 
 static void mxc_init_audio(void)
 {
-       mxc_register_device(&imx_ssi_device0, NULL);
+       imx31_add_imx_ssi(0, NULL);
        mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
 }
 
@@ -574,8 +569,6 @@ static struct sys_timer mx31ads_timer = {
  */
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31ads_map_io,
        .init_irq       = mx31ads_init_irq,
index 7c37daabb757351e559a81da063b4f78562cb6db..42f47faa6fd6c7e3aef760e86c948d04b058eccc 100644 (file)
@@ -348,8 +348,6 @@ static struct sys_timer mx31lilly_timer = {
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index f66a9576d8c242ed691583f9762d6acaa15b433c..b93895814cdfcc321134be0e4359a01a8d78ffe5 100644 (file)
@@ -282,8 +282,6 @@ struct sys_timer mx31lite_timer = {
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31lite_map_io,
        .init_irq       = mx31_init_irq,
index 7a075e8bf2d4767d2eb7b8b724b5e960edde0de1..eb5f426df224b8f1e3ef2e5feaf424be83b6c48a 100644 (file)
@@ -560,8 +560,6 @@ struct sys_timer mx31moboard_timer = {
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
        /* Maintainer: Valentin Longchamp, EPFL Mobots group */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index 1c30d7212f17901a6703cb33d687ddab926ad3cd..05f628d907250b5118c4e1ecb2df4e2e40a3c33c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
  *
  * Author: Fabio Estevam <fabio.estevam@freescale.com>
  *
@@ -27,6 +28,8 @@
 #include <linux/gpio.h>
 #include <linux/fsl_devices.h>
 
+#include <linux/mtd/physmap.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -35,6 +38,7 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
+#include <mach/mxc_ehci.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -43,8 +47,34 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
+static struct physmap_flash_data mx35pdk_flash_data = {
+       .width  = 2,
+};
+
+static struct resource mx35pdk_flash_resource = {
+       .start  = MX35_CS0_BASE_ADDR,
+       .end    = MX35_CS0_BASE_ADDR + SZ_64M - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device mx35pdk_flash = {
+       .name   = "physmap-flash",
+       .id     = 0,
+       .dev    = {
+               .platform_data  = &mx35pdk_flash_data,
+       },
+       .resource = &mx35pdk_flash_resource,
+       .num_resources = 1,
+};
+
+static const struct mxc_nand_platform_data mx35pdk_nand_board_info __initconst = {
+       .width = 1,
+       .hw_ecc = 1,
+       .flash_bbt = 1,
+};
+
 static struct platform_device *devices[] __initdata = {
-       &mxc_fec_device,
+       &mx35pdk_flash,
 };
 
 static struct pad_desc mx35pdk_pads[] = {
@@ -75,14 +105,24 @@ static struct pad_desc mx35pdk_pads[] = {
        /* USBOTG */
        MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
        MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+       /* USBH1 */
+       MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR,
+       MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC,
 };
 
 /* OTG config */
-static struct fsl_usb2_platform_data usb_pdata = {
+static struct fsl_usb2_platform_data usb_otg_pdata = {
        .operating_mode = FSL_USB2_DR_DEVICE,
        .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
 };
 
+/* USB HOST config */
+static struct mxc_usbh_platform_data usb_host_pdata = {
+       .portsc         = MXC_EHCI_MODE_SERIAL,
+       .flags          = MXC_EHCI_INTERFACE_SINGLE_UNI |
+                         MXC_EHCI_INTERNAL_PHY,
+};
+
 /*
  * Board specific initialization.
  */
@@ -90,11 +130,16 @@ static void __init mxc_board_init(void)
 {
        mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
+       imx35_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx35_add_imx_uart0(&uart_pdata);
 
-       mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+       mxc_register_device(&mxc_otg_udc_device, &usb_otg_pdata);
+
+       mxc_register_device(&mxc_usbh1, &usb_host_pdata);
+
+       imx35_add_mxc_nand(&mx35pdk_nand_board_info);
 }
 
 static void __init mx35pdk_timer_init(void)
@@ -108,8 +153,6 @@ struct sys_timer mx35pdk_timer = {
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
        /* Maintainer: Freescale Semiconductor, Inc */
-       .phys_io        = MX35_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx35_map_io,
        .init_irq       = mx35_init_irq,
index 214de11b20b919ece5a33c0041d8f8a62571f5e9..86e86c1300d5525352ed8d2b3dee50162eef89d9 100644 (file)
@@ -680,8 +680,6 @@ struct sys_timer pcm037_timer = {
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
        /* Maintainer: Pengutronix */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index c8b98218efeec9d32882333faa52c41458ce2f37..99e0894e07db320f3e4bbd668768b24803b62f1c 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "pcm037.h"
 #include "devices.h"
+#include "devices-imx31.h"
 
 static unsigned int pcm037_eet_pins[] = {
        /* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
@@ -181,7 +182,7 @@ static int eet_init_devices(void)
        /* SPI */
        spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
 #if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
-       imx35_add_spi_imx0(&pcm037_spi1_pdata);
+       imx31_add_spi_imx0(&pcm037_spi1_pdata);
 #endif
 
        platform_device_register(&pcm037_gpio_keys_device);
index 28886f0e62f97de762c015e5d9db2fdf4f84f400..4e1de87995d48da64c76bb558abf3bbab815919f 100644 (file)
@@ -42,7 +42,6 @@
 #include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -141,7 +140,6 @@ static struct i2c_board_info pcm043_i2c_devices[] = {
 
 static struct platform_device *devices[] __initdata = {
        &pcm043_flash,
-       &mxc_fec_device,
        &imx_wdt_device0,
 };
 
@@ -217,6 +215,13 @@ static struct pad_desc pcm043_pads[] = {
        /* CAN2 */
        MX35_PAD_TX5_RX0__CAN2_TXCAN,
        MX35_PAD_TX4_RX1__CAN2_RXCAN,
+       /* esdhc */
+       MX35_PAD_SD1_CMD__ESDHC1_CMD,
+       MX35_PAD_SD1_CLK__ESDHC1_CLK,
+       MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
 };
 
 #define AC97_GPIO_TXFS (1 * 32 + 31)
@@ -293,7 +298,7 @@ err1:
        mdelay(1);
 }
 
-static struct imx_ssi_platform_data pcm043_ssi_pdata = {
+static const struct imx_ssi_platform_data pcm043_ssi_pdata __initconst = {
        .ac97_reset = pcm043_ac97_cold_reset,
        .ac97_warm_reset = pcm043_ac97_warm_reset,
        .flags = IMX_SSI_USE_AC97,
@@ -357,11 +362,12 @@ static void __init mxc_board_init(void)
                        MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
                        MXC_AUDMUX_V2_PDCR_RXDSEL(3));
 
+       imx35_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&pcm037_nand_board_info);
-       mxc_register_device(&imx_ssi_device0, &pcm043_ssi_pdata);
+       imx35_add_imx_ssi(0, &pcm043_ssi_pdata);
 
        imx35_add_imx_uart1(&uart_pdata);
 
@@ -389,6 +395,7 @@ static void __init mxc_board_init(void)
                mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
 
        imx35_add_flexcan1(NULL);
+       imx35_add_esdhc(0, NULL);
 }
 
 static void __init pcm043_timer_init(void)
@@ -402,8 +409,6 @@ struct sys_timer pcm043_timer = {
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
        /* Maintainer: Pengutronix */
-       .phys_io        = MX35_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx35_map_io,
        .init_irq       = mx35_init_irq,
index c8c380eef74c7d9f4ac6d3ef5b4d7dd38343f9eb..fd1050c40964cac1d42d450026f810fd0ae25af4 100644 (file)
@@ -270,8 +270,6 @@ static struct sys_timer qong_timer = {
 
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
        /* Maintainer: DENX Software Engineering GmbH */
-       .phys_io        = MX31_AIPS1_BASE_ADDR,
-       .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index 20e48c0195c4f8533c7d43113f0ce3965c0ef143..b4ffc531a82c41894d5eaff063765b0319a08a2e 100644 (file)
@@ -110,6 +110,24 @@ void __init mx35_init_irq(void)
 static int mxc_init_l2x0(void)
 {
        void __iomem *l2x0_base;
+       void __iomem *clkctl_base;
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value
+ */
+#define L2_MEM_VAL 0x10
+
+       clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+       if (clkctl_base != NULL) {
+               writel(0x00000515, clkctl_base + L2_MEM_VAL);
+               iounmap(clkctl_base);
+       } else {
+               pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+       }
 
        l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
        if (IS_ERR(l2x0_base)) {
index 0848db5dd364dd5bb5b90ae03f3accf6eeb711aa..a2df9ac379964944ca12cd8e81d750d6f2073ddd 100644 (file)
@@ -5,11 +5,14 @@ config ARCH_MX51
        default y
        select MXC_TZIC
        select ARCH_MXC_IOMUX_V3
+       select ARCH_MXC_AUDMUX_V2
 
 comment "MX5 platforms:"
 
 config MACH_MX51_BABBAGE
        bool "Support MX51 BABBAGE platforms"
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
        help
          Include support for MX51 Babbage platform, also known as MX51EVK in
          u-boot. This includes specific configurations for the board and its
@@ -17,6 +20,8 @@ config MACH_MX51_BABBAGE
 
 config MACH_MX51_3DS
        bool "Support MX51PDK (3DS)"
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SPI_IMX
        select MXC_DEBUG_BOARD
        help
          Include support for MX51PDK (3DS) platform. This includes specific
@@ -24,6 +29,10 @@ config MACH_MX51_3DS
 
 config MACH_EUKREA_CPUIMX51
        bool "Support Eukrea CPUIMX51 module"
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_SPI_IMX
        help
          Include support for Eukrea CPUIMX51 platform. This includes
          specific configurations for the module and its peripherals.
@@ -36,10 +45,43 @@ choice
 config MACH_EUKREA_MBIMX51_BASEBOARD
        prompt "Eukrea MBIMX51 development board"
        bool
+       select IMX_HAVE_PLATFORM_ESDHC
        help
          This adds board specific devices that can be found on Eukrea's
          MBIMX51 evaluation board.
 
 endchoice
 
+config MACH_EUKREA_CPUIMX51SD
+       bool "Support Eukrea CPUIMX51SD module"
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_NAND
+       help
+         Include support for Eukrea CPUIMX51SD platform. This includes
+         specific configurations for the module and its peripherals.
+
+choice
+       prompt "Baseboard"
+       depends on MACH_EUKREA_CPUIMX51SD
+       default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+       prompt "Eukrea MBIMXSD development board"
+       bool
+       select IMX_HAVE_PLATFORM_ESDHC
+       help
+         This adds board specific devices that can be found on Eukrea's
+         MBIMXSD evaluation board.
+
+endchoice
+
+config MACH_MX51_EFIKAMX
+       bool "Support MX51 Genesi Efika MX nettop"
+       select IMX_HAVE_PLATFORM_IMX_UART
+       help
+         Include support for Genesi Efika MX nettop. This includes specific
+         configurations for the board and its peripherals.
+
 endif
index 86c66e7f52f3dc0855509587703e6972de2c483e..1769c161a60d48dc3db84277fb0c80be7d931152 100644 (file)
@@ -9,3 +9,6 @@ obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
index 623607a20f57c19c331629e5761fb23aca7cb842..6a9792fd0a763ed6b2d281e98b5cfc3bf3d67562 100644 (file)
@@ -28,9 +28,7 @@
 #include <mach/eukrea-baseboards.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/imx-uart.h>
 #include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
 #include <mach/mxc_ehci.h>
 
 #include <asm/irq.h>
@@ -39,6 +37,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define CPUIMX51_USBH1_STP     (0*32 + 27)
@@ -109,7 +108,6 @@ static struct platform_device serial_device = {
 #endif
 
 static struct platform_device *devices[] __initdata = {
-       &mxc_fec_device,
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
        &serial_device,
 #endif
@@ -148,11 +146,19 @@ static struct pad_desc eukrea_cpuimx51_pads[] = {
        MX51_PAD_USBH1_STP__USBH1_STP,
 };
 
-static struct imxuart_platform_data uart_pdata = {
+static const struct mxc_nand_platform_data
+               eukrea_cpuimx51_nand_board_info __initconst = {
+       .width          = 1,
+       .hw_ecc         = 1,
+       .flash_bbt      = 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct imxi2c_platform_data eukrea_cpuimx51_i2c_data = {
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
        .bitrate = 100000,
 };
 
@@ -239,7 +245,9 @@ static void __init eukrea_cpuimx51_init(void)
        mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
                                        ARRAY_SIZE(eukrea_cpuimx51_pads));
 
-       mxc_register_device(&mxc_uart_device0, &uart_pdata);
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
        gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
        gpio_direction_input(CPUIMX51_QUARTA_GPIO);
        gpio_free(CPUIMX51_QUARTA_GPIO);
@@ -253,9 +261,10 @@ static void __init eukrea_cpuimx51_init(void)
        gpio_direction_input(CPUIMX51_QUARTD_GPIO);
        gpio_free(CPUIMX51_QUARTD_GPIO);
 
+       imx51_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
-       mxc_register_device(&mxc_i2c_device1, &eukrea_cpuimx51_i2c_data);
+       imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
        i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
                                ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
 
@@ -283,8 +292,6 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
        /* Maintainer: Eric Bénard <eric@eukrea.com> */
-       .phys_io = MX51_AIPS1_BASE_ADDR,
-       .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = mx51_map_io,
        .init_irq = mx51_init_irq,
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
new file mode 100644 (file)
index 0000000..4b3a611
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define USBH1_RST              (1*32 + 28)
+#define ETH_RST                        (1*32 + 31)
+#define TSC2007_IRQGPIO                (2*32 + 12)
+#define CAN_IRQGPIO            (0*32 + 1)
+#define CAN_RST                        (3*32 + 15)
+#define CAN_NCS                        (3*32 + 24)
+#define CAN_RXOBF              (0*32 + 4)
+#define CAN_RX1BF              (0*32 + 6)
+#define CAN_TXORTS             (0*32 + 7)
+#define CAN_TX1RTS             (0*32 + 8)
+#define CAN_TX2RTS             (0*32 + 9)
+#define I2C_SCL                        (3*32 + 16)
+#define I2C_SDA                        (3*32 + 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET         0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN   (1 << 25)
+
+#define        MX51_USB_PLLDIV_12_MHZ          0x00
+#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
+#define        MX51_USB_PLL_DIV_24_MHZ         0x02
+
+#define CPUIMX51SD_GPIO_3_12 IOMUX_PAD(0x57C, 0x194, 3, 0x0, 0, \
+                               MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_cpuimx51sd_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* USB HOST1 */
+       MX51_PAD_USBH1_CLK__USBH1_CLK,
+       MX51_PAD_USBH1_DIR__USBH1_DIR,
+       MX51_PAD_USBH1_NXT__USBH1_NXT,
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+       MX51_PAD_USBH1_STP__USBH1_STP,
+       MX51_PAD_EIM_CS3__GPIO_2_28,            /* PHY nRESET */
+
+       /* FEC */
+       MX51_PAD_EIM_DTACK__GPIO_2_31,          /* PHY nRESET */
+
+       /* HSI2C */
+       MX51_PAD_I2C1_CLK__GPIO_4_16,
+       MX51_PAD_I2C1_DAT__GPIO_4_17,
+
+       /* CAN */
+       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+       MX51_PAD_CSPI1_SS0__GPIO_4_24,          /* nCS */
+       MX51_PAD_CSI2_PIXCLK__GPIO_4_15,        /* nReset */
+       MX51_PAD_GPIO_1_1__GPIO_1_1,            /* IRQ */
+       MX51_PAD_GPIO_1_4__GPIO_1_4,            /* Control signals */
+       MX51_PAD_GPIO_1_6__GPIO_1_6,
+       MX51_PAD_GPIO_1_7__GPIO_1_7,
+       MX51_PAD_GPIO_1_8__GPIO_1_8,
+       MX51_PAD_GPIO_1_9__GPIO_1_9,
+
+       /* Touchscreen */
+       CPUIMX51SD_GPIO_3_12,                   /* IRQ */
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int ts_get_pendown_state(void)
+{
+       return gpio_get_value(TSC2007_IRQGPIO) ? 0 : 1;
+}
+
+static struct tsc2007_platform_data tsc2007_info = {
+       .model                  = 2007,
+       .x_plate_ohms           = 180,
+       .get_pendown_state      = ts_get_pendown_state,
+};
+
+static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("pcf8563", 0x51),
+       }, {
+               I2C_BOARD_INFO("tsc2007", 0x49),
+               .type           = "tsc2007",
+               .platform_data  = &tsc2007_info,
+               .irq            = gpio_to_irq(TSC2007_IRQGPIO),
+       },
+};
+
+static const struct mxc_nand_platform_data
+               eukrea_cpuimx51sd_nand_board_info __initconst = {
+       .width          = 1,
+       .hw_ecc         = 1,
+       .flash_bbt      = 1,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_19_2_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+       return 0;
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* The clock for the USBH1 ULPI port will come from the PHY. */
+       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+                       usbother_base + MX51_USB_CTRL_1_OFFSET);
+       iounmap(usb_base);
+       return 0;
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+       .init           = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+       .flags  = MXC_EHCI_INTERNAL_PHY,
+};
+
+static struct fsl_usb2_platform_data usb_pdata = {
+       .operating_mode = FSL_USB2_DR_DEVICE,
+       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static struct mxc_usbh_platform_data usbh1_config = {
+       .init           = initialize_usbh1_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+       .flags  = (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+       if (!strcmp(options, "host"))
+               otg_mode_host = 1;
+       else if (!strcmp(options, "device"))
+               otg_mode_host = 0;
+       else
+               pr_info("otg_mode neither \"host\" nor \"device\". "
+                       "Defaulting to device\n");
+       return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+       .sda_pin                = I2C_SDA,
+       .sda_is_open_drain      = 0,
+       .scl_pin                = I2C_SCL,
+       .scl_is_open_drain      = 0,
+       .udelay                 = 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+       .name                   = "i2c-gpio",
+       .id                     = 0,
+       .dev.platform_data      = &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+       .oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+       {
+               .modalias        = "mcp2515",
+               .max_speed_hz    = 6500000,
+               .bus_num         = 0,
+               .mode           = SPI_MODE_0,
+               .chip_select     = 0,
+               .platform_data   = &mcp251x_info,
+               .irq             = gpio_to_irq(0 * 32 + 1)
+       },
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+       CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+       .chipselect     = cpuimx51sd_spi1_cs,
+       .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+       &hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+                                       ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+       gpio_request(ETH_RST, "eth_rst");
+       gpio_set_value(ETH_RST, 1);
+       imx51_add_fec(NULL);
+
+       gpio_request(CAN_IRQGPIO, "can_irq");
+       gpio_direction_input(CAN_IRQGPIO);
+       gpio_free(CAN_IRQGPIO);
+       gpio_request(CAN_NCS, "can_ncs");
+       gpio_direction_output(CAN_NCS, 1);
+       gpio_free(CAN_NCS);
+       gpio_request(CAN_RST, "can_rst");
+       gpio_direction_output(CAN_RST, 0);
+       msleep(20);
+       gpio_set_value(CAN_RST, 1);
+       imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+       spi_register_board_info(cpuimx51sd_spi_device,
+                               ARRAY_SIZE(cpuimx51sd_spi_device));
+
+       gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+       gpio_direction_input(TSC2007_IRQGPIO);
+       gpio_free(TSC2007_IRQGPIO);
+
+       i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+                       ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+       if (otg_mode_host)
+               mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+       else {
+               initialize_otg_port(NULL);
+               mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+       }
+
+       gpio_request(USBH1_RST, "usb_rst");
+       gpio_direction_output(USBH1_RST, 0);
+       msleep(20);
+       gpio_set_value(USBH1_RST, 1);
+       mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+       eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+       .init   = eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+       /* Maintainer: Eric Bénard <eric@eukrea.com> */
+       .boot_params = PHYS_OFFSET + 0x100,
+       .map_io = mx51_map_io,
+       .init_irq = mx51_init_irq,
+       .init_machine = eukrea_cpuimx51sd_init,
+       .timer = &mxc_timer,
+MACHINE_END
index f95c2fd94667c25ee97a5be10c95782d26cb5095..79ce8dcf3cda5bd26829be57a7b647c032b3ecad 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx51.h>
-#include <mach/imx-uart.h>
 #include <mach/3ds_debugboard.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define EXPIO_PARENT_INT       (MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
+#define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
 
 static struct pad_desc mx51_3ds_pads[] = {
        /* UART1 */
@@ -61,19 +63,25 @@ static struct pad_desc mx51_3ds_pads[] = {
        MX51_PAD_KEY_COL3__KEY_COL3,
        MX51_PAD_KEY_COL4__KEY_COL4,
        MX51_PAD_KEY_COL5__KEY_COL5,
+
+       /* eCSPI2 */
+       MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+       MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+       MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+       MX51_PAD_NANDF_D12__GPIO_3_28,
 };
 
 /* Serial ports */
 #if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
 static inline void mxc_init_imx_uart(void)
 {
-       mxc_register_device(&mxc_uart_device0, &uart_pdata);
-       mxc_register_device(&mxc_uart_device1, &uart_pdata);
-       mxc_register_device(&mxc_uart_device2, &uart_pdata);
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_imx_uart(1, &uart_pdata);
+       imx51_add_imx_uart(2, &uart_pdata);
 }
 #else /* !SERIAL_IMX */
 static inline void mxc_init_imx_uart(void)
@@ -127,6 +135,26 @@ static inline void mxc_init_keypad(void)
 }
 #endif
 
+static int mx51_3ds_spi2_cs[] = {
+       MXC_SPI_CS(0),
+       MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+       .chipselect     = mx51_3ds_spi2_cs,
+       .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+       {
+        .modalias = "m25p80",
+        .max_speed_hz = 25000000,      /* max spi clock (SCK) speed in HZ */
+        .bus_num = 1,
+        .chip_select = 1,
+        .mode = SPI_MODE_0,
+        .platform_data = NULL,},
+};
+
 /*
  * Board specific initialization.
  */
@@ -136,6 +164,10 @@ static void __init mxc_board_init(void)
                                        ARRAY_SIZE(mx51_3ds_pads));
        mxc_init_imx_uart();
 
+       imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+       spi_register_board_info(mx51_3ds_spi_nor_device,
+                               ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
        if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
                printk(KERN_WARNING "Init of the debugboard failed, all "
                                    "devices on the board are unusable.\n");
@@ -154,8 +186,6 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .phys_io = MX51_AIPS1_BASE_ADDR,
-       .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params = PHYS_OFFSET + 0x100,
        .map_io = mx51_map_io,
        .init_irq = mx51_init_irq,
index 6e384d92e625d107279c14228964553525aa6c53..0821fe9b3b27c01afe9942a9137e1a0627fe46d9 100644 (file)
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
+#include <linux/fec.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/imx-uart.h>
 #include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
 #include <mach/mxc_ehci.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define BABBAGE_USB_HUB_RESET  (0*32 + 7)      /* GPIO_1_7 */
 #define BABBAGE_USBH1_STP      (0*32 + 27)     /* GPIO_1_27 */
-#define BABBAGE_PHY_RESET (1*32 +5)    /* GPIO_2_5 */
+#define BABBAGE_PHY_RESET      (1*32 + 5)      /* GPIO_2_5 */
+#define BABBAGE_FEC_PHY_RESET  (1*32 + 14)     /* GPIO_2_14 */
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET                 0x10
 #define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
 #define        MX51_USB_PLL_DIV_24_MHZ 0x02
 
-static struct platform_device *devices[] __initdata = {
-       &mxc_fec_device,
-};
-
 static struct pad_desc mx51babbage_pads[] = {
        /* UART1 */
        MX51_PAD_UART1_RXD__UART1_RXD,
@@ -93,19 +90,41 @@ static struct pad_desc mx51babbage_pads[] = {
 
        /* USB HUB reset line*/
        MX51_PAD_GPIO_1_7__GPIO_1_7,
+
+       /* FEC */
+       MX51_PAD_EIM_EB2__FEC_MDIO,
+       MX51_PAD_EIM_EB3__FEC_RDAT1,
+       MX51_PAD_EIM_CS2__FEC_RDAT2,
+       MX51_PAD_EIM_CS3__FEC_RDAT3,
+       MX51_PAD_EIM_CS4__FEC_RX_ER,
+       MX51_PAD_EIM_CS5__FEC_CRS,
+       MX51_PAD_NANDF_RB2__FEC_COL,
+       MX51_PAD_NANDF_RB3__FEC_RXCLK,
+       MX51_PAD_NANDF_RB6__FEC_RDAT0,
+       MX51_PAD_NANDF_RB7__FEC_TDAT0,
+       MX51_PAD_NANDF_CS2__FEC_TX_ER,
+       MX51_PAD_NANDF_CS3__FEC_MDC,
+       MX51_PAD_NANDF_CS4__FEC_TDAT1,
+       MX51_PAD_NANDF_CS5__FEC_TDAT2,
+       MX51_PAD_NANDF_CS6__FEC_TDAT3,
+       MX51_PAD_NANDF_CS7__FEC_TX_EN,
+       MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+       /* FEC PHY reset line */
+       MX51_PAD_EIM_A20__GPIO_2_14,
 };
 
 /* Serial ports */
 #if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
 static inline void mxc_init_imx_uart(void)
 {
-       mxc_register_device(&mxc_uart_device0, &uart_pdata);
-       mxc_register_device(&mxc_uart_device1, &uart_pdata);
-       mxc_register_device(&mxc_uart_device2, &uart_pdata);
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_imx_uart(1, &uart_pdata);
+       imx51_add_imx_uart(2, &uart_pdata);
 }
 #else /* !SERIAL_IMX */
 static inline void mxc_init_imx_uart(void)
@@ -113,7 +132,7 @@ static inline void mxc_init_imx_uart(void)
 }
 #endif /* SERIAL_IMX */
 
-static struct imxi2c_platform_data babbage_i2c_data = {
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
        .bitrate = 100000,
 };
 
@@ -171,6 +190,22 @@ static inline void babbage_usbhub_reset(void)
        gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
 }
 
+static inline void babbage_fec_reset(void)
+{
+       int ret;
+
+       /* reset FEC PHY */
+       ret = gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+               return;
+       }
+       gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0);
+       gpio_set_value(BABBAGE_FEC_PHY_RESET, 0);
+       msleep(1);
+       gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
 /* This function is board specific as the bit mask for the plldiv will also
 be different for other Freescale SoCs, thus a common bitmask is not
 possible and cannot get place in /plat-mxc/ehci.c.*/
@@ -178,7 +213,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 {
        u32 v;
        void __iomem *usb_base;
-       u32 usbother_base;
+       void __iomem *usbother_base;
 
        usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
        usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -196,7 +231,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 {
        u32 v;
        void __iomem *usb_base;
-       u32 usbother_base;
+       void __iomem *usbother_base;
 
        usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
        usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -250,10 +285,11 @@ static void __init mxc_board_init(void)
        mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
                                        ARRAY_SIZE(mx51babbage_pads));
        mxc_init_imx_uart();
-       platform_add_devices(devices, ARRAY_SIZE(devices));
+       babbage_fec_reset();
+       imx51_add_fec(NULL);
 
-       mxc_register_device(&mxc_i2c_device0, &babbage_i2c_data);
-       mxc_register_device(&mxc_i2c_device1, &babbage_i2c_data);
+       imx51_add_imx_i2c(0, &babbage_i2c_data);
+       imx51_add_imx_i2c(1, &babbage_i2c_data);
        mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
 
        if (otg_mode_host)
@@ -281,9 +317,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
        /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-       .phys_io = MX51_AIPS1_BASE_ADDR,
-       .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-       .boot_params = PHYS_OFFSET + 0x100,
+       .boot_params = MX51_PHYS_OFFSET + 0x100,
        .map_io = mx51_map_io,
        .init_irq = mx51_init_irq,
        .init_machine = mxc_board_init,
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
new file mode 100644 (file)
index 0000000..6e623bd
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define        MX51_USB_PLL_DIV_24_MHZ 0x01
+
+static struct pad_desc mx51efikamx_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+};
+
+/* Serial ports */
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static const struct imxuart_platform_data uart_pdata = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_imx_uart(1, &uart_pdata);
+       imx51_add_imx_uart(2, &uart_pdata);
+}
+#else /* !SERIAL_IMX */
+static inline void mxc_init_imx_uart(void)
+{
+}
+#endif /* SERIAL_IMX */
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+       usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+       usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_24_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+       return 0;
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+       .init   = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+       .flags  = MXC_EHCI_INTERNAL_PHY,
+};
+
+static void __init mxc_board_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+                                       ARRAY_SIZE(mx51efikamx_pads));
+       mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+       mxc_init_imx_uart();
+}
+
+static void __init mx51_efikamx_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mxc_timer = {
+       .init   = mx51_efikamx_timer_init,
+};
+
+MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
+       /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .map_io = mx51_map_io,
+       .init_irq = mx51_init_irq,
+       .init_machine =  mxc_board_init,
+       .timer = &mxc_timer,
+MACHINE_END
index 6af69def357f92d2f177d19d8fc7bce330ff5666..f2aae92cf0e261992c1a8afb4bc3de15f0014c88 100644 (file)
@@ -41,34 +41,66 @@ static struct clk usboh3_clk;
 
 #define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
 
-static int _clk_ccgr_enable(struct clk *clk)
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+       u32 max_pre, u32 max_post)
 {
-       u32 reg;
+       if (div >= max_pre * max_post) {
+               *pre = max_pre;
+               *post = max_post;
+       } else if (div >= max_pre) {
+               u32 min_pre, temp_pre, old_err, err;
+               min_pre = DIV_ROUND_UP(div, max_post);
+               old_err = max_pre;
+               for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+                       err = div % temp_pre;
+                       if (err == 0) {
+                               *pre = temp_pre;
+                               break;
+                       }
+                       err = temp_pre - err;
+                       if (err < old_err) {
+                               old_err = err;
+                               *pre = temp_pre;
+                       }
+               }
+               *post = DIV_ROUND_UP(div, *pre);
+       } else {
+               *pre = div;
+               *post = 1;
+       }
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+       u32 reg = __raw_readl(clk->enable_reg);
+
+       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+       reg |= mode << clk->enable_shift;
 
-       reg = __raw_readl(clk->enable_reg);
-       reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
        __raw_writel(reg, clk->enable_reg);
+}
 
+static int _clk_ccgr_enable(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
        return 0;
 }
 
 static void _clk_ccgr_disable(struct clk *clk)
 {
-       u32 reg;
-       reg = __raw_readl(clk->enable_reg);
-       reg &= ~(MXC_CCM_CCGRx_MOD_OFF << clk->enable_shift);
-       __raw_writel(reg, clk->enable_reg);
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
 
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+       return 0;
 }
 
 static void _clk_ccgr_disable_inwait(struct clk *clk)
 {
-       u32 reg;
-
-       reg = __raw_readl(clk->enable_reg);
-       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-       reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
-       __raw_writel(reg, clk->enable_reg);
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
 }
 
 /*
@@ -542,60 +574,60 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
-static unsigned long clk_uart_get_rate(struct clk *clk)
-{
-       u32 reg, prediv, podf;
-       unsigned long parent_rate;
+#define clk_nfc_set_parent     NULL
 
-       parent_rate = clk_get_rate(clk->parent);
-
-       reg = __raw_readl(MXC_CCM_CSCDR1);
-       prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
-                 MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
-       podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
-               MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+       u32 reg, div;
 
-       return parent_rate / (prediv * podf);
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+              MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+       rate = clk_get_rate(clk->parent) / div;
+       WARN_ON(rate == 0);
+       return rate;
 }
 
-static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+                                               unsigned long rate)
 {
-       u32 reg, mux;
+       u32 div;
+       unsigned long parent_rate = clk_get_rate(clk->parent);
 
-       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-                      &lp_apm_clk);
-       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
-       reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
+       if (!rate)
+               return -EINVAL;
 
-       return 0;
-}
+       div = parent_rate / rate;
 
-static unsigned long clk_usboh3_get_rate(struct clk *clk)
-{
-       u32 reg, prediv, podf;
-       unsigned long parent_rate;
+       if (parent_rate % rate)
+               div++;
 
-       parent_rate = clk_get_rate(clk->parent);
+       if (div > 8)
+               return -EINVAL;
 
-       reg = __raw_readl(MXC_CCM_CSCDR1);
-       prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
-                 MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
-       podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
-               MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
+       return parent_rate / div;
 
-       return parent_rate / (prediv * podf);
 }
 
-static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 reg, mux;
+       u32 reg, div;
+
+       div = clk_get_rate(clk->parent) / rate;
+       if (div == 0)
+               div++;
+       if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
 
-       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-                      &lp_apm_clk);
-       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
-       reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
+       while (__raw_readl(MXC_CCM_CDHIPR) &
+                       MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+       }
 
        return 0;
 }
@@ -620,6 +652,17 @@ static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
        return ckih2_reference;
 }
 
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+              MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
 /* External high frequency clock */
 static struct clk ckih_clk = {
        .get_rate = get_high_reference_clock_rate,
@@ -715,18 +758,6 @@ static struct clk ipg_perclk = {
        .set_parent = _clk_ipg_per_set_parent,
 };
 
-static struct clk uart_root_clk = {
-       .parent = &pll2_sw_clk,
-       .get_rate = clk_uart_get_rate,
-       .set_parent = _clk_uart_set_parent,
-};
-
-static struct clk usboh3_clk = {
-       .parent = &pll2_sw_clk,
-       .get_rate = clk_usboh3_get_rate,
-       .set_parent = _clk_usboh3_set_parent,
-};
-
 static struct clk ahb_max_clk = {
        .parent = &ahb_clk,
        .enable_reg = MXC_CCM_CCGR0,
@@ -762,45 +793,183 @@ static struct clk kpp_clk = {
        .id = 0,
 };
 
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)    \
+static struct clk emi_slow_clk = {
+       .parent = &pll2_sw_clk,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+       .get_rate = clk_emi_slow_get_rate,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)  \
        static struct clk name = {                      \
                .id             = i,                    \
                .enable_reg     = er,                   \
                .enable_shift   = es,                   \
-               .get_rate       = gr,                   \
-               .set_rate       = sr,                   \
+               .get_rate       = pfx##_get_rate,       \
+               .set_rate       = pfx##_set_rate,       \
+               .round_rate     = pfx##_round_rate,     \
+               .set_parent     = pfx##_set_parent,     \
                .enable         = _clk_ccgr_enable,     \
                .disable        = _clk_ccgr_disable,    \
                .parent         = p,                    \
                .secondary      = s,                    \
        }
 
-/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
-   get_rate, set_rate, parent, secondary); */
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)   \
+       static struct clk name = {                      \
+               .id             = i,                    \
+               .enable_reg     = er,                   \
+               .enable_shift   = es,                   \
+               .get_rate       = pfx##_get_rate,       \
+               .set_rate       = pfx##_set_rate,       \
+               .set_parent     = pfx##_set_parent,     \
+               .enable         = _clk_max_enable,      \
+               .disable        = _clk_max_disable,     \
+               .parent         = p,                    \
+               .secondary      = s,                    \
+       }
+
+#define CLK_GET_RATE(name, nr, bitsname)                               \
+static unsigned long clk_##name##_get_rate(struct clk *clk)            \
+{                                                                      \
+       u32 reg, pred, podf;                                            \
+                                                                       \
+       reg = __raw_readl(MXC_CCM_CSCDR##nr);                           \
+       pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)   \
+               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;    \
+       podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)   \
+               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;    \
+                                                                       \
+       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),             \
+                       (pred + 1) * (podf + 1));                       \
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)                             \
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)        \
+{                                                                      \
+       u32 reg, mux;                                                   \
+                                                                       \
+       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,              \
+                       &pll3_sw_clk, &lp_apm_clk);                     \
+       reg = __raw_readl(MXC_CCM_CSCMR##nr) &                          \
+               ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;         \
+       reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;  \
+       __raw_writel(reg, MXC_CCM_CSCMR##nr);                           \
+                                                                       \
+       return 0;                                                       \
+}
+
+#define CLK_SET_RATE(name, nr, bitsname)                               \
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)  \
+{                                                                      \
+       u32 reg, div, parent_rate;                                      \
+       u32 pre = 0, post = 0;                                          \
+                                                                       \
+       parent_rate = clk_get_rate(clk->parent);                        \
+       div = parent_rate / rate;                                       \
+                                                                       \
+       if ((parent_rate / div) != rate)                                \
+               return -EINVAL;                                         \
+                                                                       \
+       __calc_pre_post_dividers(div, &pre, &post,                      \
+               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>      \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,  \
+               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>      \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+                                                                       \
+       /* Set sdhc1 clock divider */                                   \
+       reg = __raw_readl(MXC_CCM_CSCDR##nr) &                          \
+               ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK        \
+               | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);      \
+       reg |= (post - 1) <<                                            \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;       \
+       reg |= (pre - 1) <<                                             \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;       \
+       __raw_writel(reg, MXC_CCM_CSCDR##nr);                           \
+                                                                       \
+       return 0;                                                       \
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+       .parent = &pll2_sw_clk,
+       .get_rate = clk_uart_get_rate,
+       .set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+       .parent = &pll2_sw_clk,
+       .get_rate = clk_usboh3_get_rate,
+       .set_parent = clk_usboh3_set_parent,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+       .parent = &pll3_sw_clk,
+       .get_rate = clk_ecspi_get_rate,
+       .set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)         \
+       static struct clk name = {                                      \
+               .id             = i,                                    \
+               .enable_reg     = er,                                   \
+               .enable_shift   = es,                                   \
+               .get_rate       = gr,                                   \
+               .set_rate       = sr,                                   \
+               .enable         = e,                                    \
+               .disable        = d,                                    \
+               .parent         = p,                                    \
+               .secondary      = s,                                    \
+       }
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)                    \
+       DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
 
 /* Shared peripheral bus arbiter */
 DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
        NULL,  NULL, &ipg_clk, NULL);
 
 /* UART */
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-       NULL,  NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL,  NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL,  NULL, &uart_root_clk, NULL);
 DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
        NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
        NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
        NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
 
 /* GPT */
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
-       NULL,  NULL, &ipg_clk, NULL);
 DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
        NULL,  NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+       NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -814,6 +983,52 @@ DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
 DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
        NULL,  NULL, &ipg_clk, NULL);
 
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+       clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+               &ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+               NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+               &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+               NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+               NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+               NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+               NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+       clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+       clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
                .dev_id = d, \
@@ -837,6 +1052,18 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
        _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
+       _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+       _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+       _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+       _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+       _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+       _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+       _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
 };
 
 static void clk_tree_init(void)
@@ -880,6 +1107,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
        /* set the usboh3_clk parent to pll2_sw_clk */
        clk_set_parent(&usboh3_clk, &pll2_sw_clk);
 
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+       clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+       /* set SDHC root clock as 166.25MHZ*/
+       clk_set_rate(&esdhc1_clk, 166250000);
+       clk_set_rate(&esdhc2_clk, 166250000);
+
        /* System timer */
        mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
                MX51_MXC_INT_GPT);
index 2d37785e3857d32575a5948f36574e4770a0b917..eaacb6e9b5d0b417d0b78d56a8ebb406cb8ee9cd 100644 (file)
@@ -70,6 +70,25 @@ int mx51_revision(void)
 }
 EXPORT_SYMBOL(mx51_revision);
 
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+static int __init mx51_neon_fixup(void)
+{
+       if (mx51_revision() < MX51_CHIP_REV_3_0 && (elf_hwcap & HWCAP_NEON)) {
+               elf_hwcap &= ~HWCAP_NEON;
+               pr_info("Turning off NEON support, detected broken NEON implementation\n");
+       }
+       return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
 static int __init post_cpu_init(void)
 {
        unsigned int reg;
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
new file mode 100644 (file)
index 0000000..5cc910e
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data __initconst;
+#define imx51_add_fec(pdata)   \
+       imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst;
+#define imx51_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst;
+#define imx51_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst;
+#define imx51_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst;
+#define imx51_add_mxc_nand(pdata)      \
+       imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
+#define imx51_add_cspi(pdata)  \
+       imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
+#define imx51_add_ecspi(id, pdata)     \
+       imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst;
+#define imx51_add_esdhc(id, pdata)     \
+       imx_add_esdhc(&imx51_esdhc_data[id], pdata)
index 1920ff4963b211376822d2021d4e4bded6b268f1..4c7be87a7c9d17e57857e0376ce2ddc9fd53a6e7 100644 (file)
 #include <mach/imx-uart.h>
 #include <mach/irqs.h>
 
-static struct resource uart0[] = {
-       {
-               .start = MX51_UART1_BASE_ADDR,
-               .end = MX51_UART1_BASE_ADDR + 0xfff,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX51_MXC_INT_UART1,
-               .end = MX51_MXC_INT_UART1,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_uart_device0 = {
-       .name = "imx-uart",
-       .id = 0,
-       .resource = uart0,
-       .num_resources = ARRAY_SIZE(uart0),
-};
-
-static struct resource uart1[] = {
-       {
-               .start = MX51_UART2_BASE_ADDR,
-               .end = MX51_UART2_BASE_ADDR + 0xfff,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX51_MXC_INT_UART2,
-               .end = MX51_MXC_INT_UART2,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_uart_device1 = {
-       .name = "imx-uart",
-       .id = 1,
-       .resource = uart1,
-       .num_resources = ARRAY_SIZE(uart1),
-};
-
-static struct resource uart2[] = {
-       {
-               .start = MX51_UART3_BASE_ADDR,
-               .end = MX51_UART3_BASE_ADDR + 0xfff,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX51_MXC_INT_UART3,
-               .end = MX51_MXC_INT_UART3,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_uart_device2 = {
-       .name = "imx-uart",
-       .id = 2,
-       .resource = uart2,
-       .num_resources = ARRAY_SIZE(uart2),
-};
-
-static struct resource mxc_fec_resources[] = {
-       {
-               .start  = MX51_MXC_FEC_BASE_ADDR,
-               .end    = MX51_MXC_FEC_BASE_ADDR + 0xfff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = MX51_MXC_INT_FEC,
-               .end    = MX51_MXC_INT_FEC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_fec_device = {
-       .name = "fec",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(mxc_fec_resources),
-       .resource = mxc_fec_resources,
-};
-
-static struct resource mxc_i2c0_resources[] = {
-       {
-               .start = MX51_I2C1_BASE_ADDR,
-               .end = MX51_I2C1_BASE_ADDR + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX51_MXC_INT_I2C1,
-               .end = MX51_MXC_INT_I2C1,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_i2c_device0 = {
-       .name = "imx-i2c",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(mxc_i2c0_resources),
-       .resource = mxc_i2c0_resources,
-};
-
-static struct resource mxc_i2c1_resources[] = {
-       {
-               .start = MX51_I2C2_BASE_ADDR,
-               .end = MX51_I2C2_BASE_ADDR + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       }, {
-               .start = MX51_MXC_INT_I2C2,
-               .end = MX51_MXC_INT_I2C2,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device mxc_i2c_device1 = {
-       .name = "imx-i2c",
-       .id = 1,
-       .num_resources = ARRAY_SIZE(mxc_i2c1_resources),
-       .resource = mxc_i2c1_resources,
-};
-
 static struct resource mxc_hsi2c_resources[] = {
        {
                .start = MX51_HSI2C_DMA_BASE_ADDR,
index e509cfaad1d466b4209fd36a5b01d9b4464a3d1a..af1d07c0bbc171822034146034eb1720015e0d3d 100644 (file)
@@ -1,12 +1,6 @@
-extern struct platform_device mxc_uart_device0;
-extern struct platform_device mxc_uart_device1;
-extern struct platform_device mxc_uart_device2;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxc_usbdr_host_device;
 extern struct platform_device mxc_usbh1_device;
 extern struct platform_device mxc_usbdr_udc_device;
 extern struct platform_device mxc_wdt;
-extern struct platform_device mxc_i2c_device0;
-extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_hsi2c_device;
 extern struct platform_device mxc_keypad_device;
index ffa93d1d6ef8e30eca983fc2d11f7487ce570c61..a2e6e8c39d257da751549f67f110979c29fdde29 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <asm/mach/arch.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO   (2*32 + 30)
@@ -112,9 +113,25 @@ static struct pad_desc mbimx51_pads[] = {
        MX51_PAD_KEY_COL1__KEY_COL1,
        MX51_PAD_KEY_COL2__KEY_COL2,
        MX51_PAD_KEY_COL3__KEY_COL3,
+
+       /* SD 1 */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+       /* SD 2 */
+       MX51_PAD_SD2_CMD__SD2_CMD,
+       MX51_PAD_SD2_CLK__SD2_CLK,
+       MX51_PAD_SD2_DATA0__SD2_DATA0,
+       MX51_PAD_SD2_DATA1__SD2_DATA1,
+       MX51_PAD_SD2_DATA2__SD2_DATA2,
+       MX51_PAD_SD2_DATA3__SD2_DATA3,
 };
 
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
@@ -158,9 +175,11 @@ struct tsc2007_platform_data tsc2007_data = {
 
 static struct i2c_board_info mbimx51_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("tsc2007", 0x48),
+               I2C_BOARD_INFO("tsc2007", 0x49),
                .irq  = MBIMX51_TSC2007_IRQ,
                .platform_data = &tsc2007_data,
+       }, {
+               I2C_BOARD_INFO("tlv320aic23", 0x1a),
        },
 };
 
@@ -172,8 +191,8 @@ void __init eukrea_mbimx51_baseboard_init(void)
        mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
                                        ARRAY_SIZE(mbimx51_pads));
 
-       mxc_register_device(&mxc_uart_device1, NULL);
-       mxc_register_device(&mxc_uart_device2, &uart_pdata);
+       imx51_add_imx_uart(1, NULL);
+       imx51_add_imx_uart(2, &uart_pdata);
 
        gpio_request(MBIMX51_LED0, "LED0");
        gpio_direction_output(MBIMX51_LED0, 1);
@@ -197,4 +216,7 @@ void __init eukrea_mbimx51_baseboard_init(void)
        set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
        i2c_register_board_info(1, mbimx51_i2c_devices,
                                ARRAY_SIZE(mbimx51_i2c_devices));
+
+       imx51_add_esdhc(0, NULL);
+       imx51_add_esdhc(1, NULL);
 }
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
new file mode 100644 (file)
index 0000000..2b48f51
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define MBIMXSD_GPIO_3_31 IOMUX_PAD(0x554, 0x16C, 3, 0x0, 0, \
+                               MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_mbimxsd_pads[] = {
+       /* LED */
+       MX51_PAD_NANDF_D10__GPIO_3_30,
+       /* SWITCH */
+       MBIMXSD_GPIO_3_31,
+       /* UART2 */
+       MX51_PAD_UART2_RXD__UART2_RXD,
+       MX51_PAD_UART2_TXD__UART2_TXD,
+       /* UART 3 */
+       MX51_PAD_UART3_RXD__UART3_RXD,
+       MX51_PAD_UART3_TXD__UART3_TXD,
+       MX51_PAD_KEY_COL4__UART3_RTS,
+       MX51_PAD_KEY_COL5__UART3_CTS,
+       /* SD */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+};
+
+#define GPIO_LED1      (2 * 32 + 30)
+#define GPIO_SWITCH1   (2 * 32 + 31)
+
+static struct gpio_led eukrea_mbimxsd_leds[] = {
+       {
+               .name                   = "led1",
+               .default_trigger        = "heartbeat",
+               .active_low             = 1,
+               .gpio                   = GPIO_LED1,
+       },
+};
+
+static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+       .leds           = eukrea_mbimxsd_leds,
+       .num_leds       = ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct platform_device eukrea_mbimxsd_leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &eukrea_mbimxsd_led_info,
+       },
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+       {
+               .gpio           = GPIO_SWITCH1,
+               .code           = BTN_0,
+               .desc           = "BP1",
+               .active_low     = 1,
+               .wakeup         = 1,
+       },
+};
+
+static struct gpio_keys_platform_data eukrea_mbimxsd_button_data = {
+       .buttons        = eukrea_mbimxsd_gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static struct platform_device eukrea_mbimxsd_button_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .num_resources  = 0,
+       .dev            = {
+               .platform_data  = &eukrea_mbimxsd_button_data,
+       }
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+       &eukrea_mbimxsd_leds_gpio,
+       &eukrea_mbimxsd_button_device,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("tlv320aic23", 0x1a),
+       },
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+       if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+                       ARRAY_SIZE(eukrea_mbimxsd_pads)))
+               printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+       imx51_add_imx_uart(1, NULL);
+       imx51_add_imx_uart(2, &uart_pdata);
+
+       imx51_add_esdhc(0, NULL);
+
+       gpio_request(GPIO_LED1, "LED1");
+       gpio_direction_output(GPIO_LED1, 1);
+       gpio_free(GPIO_LED1);
+
+       gpio_request(GPIO_SWITCH1, "SWITCH1");
+       gpio_direction_input(GPIO_SWITCH1);
+       gpio_free(GPIO_SWITCH1);
+
+       i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+                               ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
index 69816ba82930edcab94de16580d9d62c30610b33..395d83be8c98ed9b90590051f0744789d7a74778 100644 (file)
@@ -53,8 +53,6 @@ struct sys_timer zn5_timer = {
 };
 
 MACHINE_START(MAGX_ZN5, "Motorola Zn5")
-       .phys_io        = MXC91231_AIPS1_BASE_ADDR,
-       .io_pg_offst    = ((MXC91231_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
        .boot_params    = MXC91231_PHYS_OFFSET + 0x100,
        .map_io         = mxc91231_map_io,
        .init_irq       = mxc91231_init_irq,
index e96339e71d88fec6cbf56e72f08ba9d0dd4d9008..56a9152281801fd7f0e32ccbd2c61895f69db4be 100644 (file)
 
 #include "hardware.h"
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x00100000                @ physical
-               movne   \rx, #io_p2v(0x00100000)        @ virtual
-               orr     \rx, \rx, #0x00000a00
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00000a00
+               orr     \rv, \rp, #io_p2v(0x00100000)   @ virtual
+               orr     \rp, \rp, #0x00100000           @ physical
                .endm
 
                .macro  senduart,rd,rx
index 25d5cc676e0fbfa9bbe701f34f925d39ddfe43a2..7cca3574308f0403a07c93edf6e427e6d29f0299 100644 (file)
@@ -16,4 +16,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
index c9b174bc8ccfa12b6146eb6a522dc0e7f5b74484..ca8b203a3c99d3f9ffab9e686c5c0c9958154c74 100644 (file)
@@ -200,8 +200,6 @@ static void __init nxdb500_init(void)
 }
 
 MACHINE_START(NXDB500, "Hilscher nxdb500")
-       .phys_io        = 0x00100000,
-       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
index 15b54c62d60f88e6b1348d1be80b2c0365932ed8..d775cbe072780bef9d12f4dc01bc3b1c1eb63bc5 100644 (file)
@@ -93,8 +93,6 @@ static void __init nxdkn_init(void)
 }
 
 MACHINE_START(NXDKN, "Hilscher nxdkn")
-       .phys_io        = 0x00100000,
-       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
index 1061c01ff679d4d660fff96f2f43670465b7ab54..de369cd1dcbed9ec667adfec8edd700081fc753f 100644 (file)
@@ -177,8 +177,6 @@ static void __init nxeb500hmi_init(void)
 }
 
 MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-       .phys_io        = 0x00100000,
-       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
index 841d459ad59db6480f18ef4cffba44fee640a8db..139930350d939289c729fdde62339873aa2989bd 100644 (file)
@@ -276,8 +276,6 @@ static void __init nhk8815_platform_init(void)
 
 MACHINE_START(NOMADIK, "NHK8815")
        /* Maintainer: ST MicroElectronics */
-       .phys_io        = NOMADIK_UART0_BASE,
-       .io_pg_offst    = (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = cpu8815_map_io,
        .init_irq       = cpu8815_init_irq,
index 4f92acfba9545aaf5f9043925b51d8fcd1334ac0..e7151b4b88896f8a8426d6c7c7eb8db4ae79860f 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x10000000        @ physical base address
-               movne   \rx, #0xf0000000        @ virtual base
-               add     \rx, \rx, #0x00100000
-               add     \rx, \rx, #0x000fb000
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00100000
+               add     \rp, \rp, #0x000fb000
+               add     \rv, \rp, #0xf0000000   @ virtual base
+               add     \rp, \rp, #0x10000000   @ physical base address
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index 5c934bdb71583e037c59fdadc3490e43838ff425..5a2acbdc3d679f2563aab0a8a24b4988b26431aa 100644 (file)
 
 #include <mach/regs-board-a9m9750dev.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, =NS9XXX_CSxSTAT_PHYS(0)
-               ldrne   \rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+               .macro  addruart, rp, rv
+               ldr     \rp, =NS9XXX_CSxSTAT_PHYS(0)
+               ldr     \rv, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
                .endm
 
 #define UART_SHIFT     2
index 9f79266f08e247dd7c4051773253e9cf7c68e11d..d702570424809fce752734e4f503881c818d5ba8 100644 (file)
@@ -35,8 +35,6 @@ static void __init nuc932evb_init(void)
 
 MACHINE_START(NUC932EVB, "NUC932EVB")
        /* Maintainer: Wan ZongShun */
-       .phys_io        = NUC93X_PA_UART,
-       .io_pg_offst    = (((u32)NUC93X_VA_UART) >> 18) & 0xfffc,
        .boot_params    = 0,
        .map_io         = nuc932evb_map_io,
        .init_irq       = nuc93x_init_irq,
index 41992ab71961ce6b1448ac0df659ced75ed94684..73c86392fcd3ac1e147bcc7e25d64eb5f91daedf 100644 (file)
@@ -297,8 +297,6 @@ static void __init ams_delta_map_io(void)
 
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
        /* Maintainer: Jonathan McDowell <noodles@earth.li> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = ams_delta_map_io,
        .reserve        = omap_reserve,
index 180ce79e5eacf9cae09583e568b2bc232d155a00..149fdd32e127338caf6d6ab6898a3b78289ec712 100644 (file)
@@ -386,8 +386,6 @@ static void __init omap_fsample_map_io(void)
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_fsample_map_io,
        .reserve        = omap_reserve,
index 93b9ab8fc3be092d82d00ec8ef5cc934a0ac3cd0..23f4ab9e265128bcc9ee0846b56789e2beadade4 100644 (file)
@@ -94,8 +94,6 @@ static void __init omap_generic_map_io(void)
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
        /* Maintainer: Tony Lindgren <tony@atomide.com> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_generic_map_io,
        .reserve        = omap_reserve,
index d2cda58bcc480873c9befbd9806366f358283779..197adb49dc5a49b2c706cb35369ac1bd997a5aac 100644 (file)
@@ -458,8 +458,6 @@ static void __init h2_map_io(void)
 
 MACHINE_START(OMAP_H2, "TI-H2")
        /* Maintainer: Imre Deak <imre.deak@nokia.com> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = h2_map_io,
        .reserve        = omap_reserve,
index c2ef4ff846c74608adbc3f5041d1ab53aa8e6eb4..9126e3e37b4a7d90b9f7fd75e4a2746ba6f29e0f 100644 (file)
@@ -446,8 +446,6 @@ static void __init h3_map_io(void)
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
        /* Maintainer: Texas Instruments, Inc. */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = h3_map_io,
        .reserve        = omap_reserve,
index 311899ff5ffcdfee5425f2f949cd1828863eea2b..86afb29522259e63efecc5d1758ee4ce007d55c9 100644 (file)
@@ -300,8 +300,6 @@ static void __init htcherald_init_irq(void)
 MACHINE_START(HERALD, "HTC Herald")
        /* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
        /* Maintainer: wing-linux.sourceforge.net */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = htcherald_map_io,
        .reserve        = omap_reserve,
index 3daf87ad25765813f2aabe95090954df565bc132..dc2b86fd66c12312119ab3d9770667030886fe30 100644 (file)
@@ -459,8 +459,6 @@ static void __init innovator_map_io(void)
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
        /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = innovator_map_io,
        .reserve        = omap_reserve,
index 51a4539aecf54ba1a7046227a695d2014610ce30..aa8375b2a0a3df0778f8ba9680f32d80d61482dd 100644 (file)
@@ -262,8 +262,6 @@ static void __init omap_nokia770_map_io(void)
 }
 
 MACHINE_START(NOKIA770, "Nokia 770")
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_nokia770_map_io,
        .reserve        = omap_reserve,
index 679740cc1e9020e8ea0200524215c31f92827178..e9dd79149a8e5744c4d2f1a79f30762e4f657196 100644 (file)
@@ -580,8 +580,6 @@ static void __init osk_map_io(void)
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
        /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = osk_map_io,
        .reserve        = omap_reserve,
index 782bb257a85d9a901b4478eaf4923abe877e849d..f32738b1eb6bcce83a8e20fcb9d9121270a876a9 100644 (file)
@@ -285,8 +285,6 @@ static void __init omap_palmte_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_palmte_map_io,
        .reserve        = omap_reserve,
index 0b35ef54a64fa47f47bc4d369e450034b03543b9..ed1400a67f7572ba90605a222f15ccaa565f14c9 100644 (file)
@@ -317,8 +317,6 @@ static void __init omap_palmtt_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_palmtt_map_io,
        .reserve        = omap_reserve,
index 66362903b6e238ec1646e336e74377488a4ccea7..d7a245cef9a426ba180708b222c16efbcfce1cdd 100644 (file)
@@ -338,8 +338,6 @@ omap_palmz71_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_palmz71_map_io,
        .reserve        = omap_reserve,
index 34ab354758b0b5f835d1b97607f5286884d13eda..a8d16a255c1866daedf2af778aad68b4fc0e6ff0 100644 (file)
@@ -347,8 +347,6 @@ static void __init omap_perseus2_map_io(void)
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
        /* Maintainer: Kevin Hilman <kjh@hilman.org> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_perseus2_map_io,
        .reserve        = omap_reserve,
index 2eb148b8de937aa5f8e839ea7ba07d85806c0869..d25f59e5a7733ca79c23b18662bf701aa49f936b 100644 (file)
@@ -419,8 +419,6 @@ static void __init omap_sx1_map_io(void)
 }
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = omap_sx1_map_io,
        .reserve        = omap_reserve,
index 6b3cf14bc7572e8884366db6ffa8cc4e4c0ef6ed..f5992c239bcd18b3a773b732fc6787b804acd7e3 100644 (file)
@@ -283,8 +283,6 @@ EXPORT_SYMBOL(voiceblue_wdt_ping);
 
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
        /* Maintainer: Ladislav Michl <michl@2n.cz> */
-       .phys_io        = 0xfff00000,
-       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .map_io         = voiceblue_map_io,
        .reserve        = omap_reserve,
index 671408eb4ab42f8d0128f125c546a8b2405bc9d0..6a0fa04623650237d7f496a045eb8e498ded221e 100644 (file)
@@ -28,56 +28,58 @@ omap_uart_virt:     .word   0x0
                 * the desired UART phys and virt addresses temporarily into
                 * the omap_uart_phys and omap_uart_virt above.
                 */
-               .macro  addruart, rx, tmp
+               .macro  addruart, rp, rv
 
                /* Use omap_uart_phys/virt if already configured */
-9:             mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =__virt_to_phys(omap_uart_phys)    @ physical base address
-               ldrne   \rx, =omap_uart_virt    @ virtual base
-               ldr     \rx, [\rx, #0]
-               cmp     \rx, #0                 @ is port configured?
+9:             mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               ldreq   \rp, =__virt_to_phys(omap_uart_phys)    @ MMU not enabled
+               ldrne   \rp, =omap_uart_phys    @ MMU enabled
+               add     \rv, \rp, #4            @ omap_uart_virt
+               ldr     \rp, [\rp, #0]
+               ldr     \rv, [\rv, #0]
+               cmp     \rp, #0                 @ is port configured?
+               cmpne   \rv, #0
                bne     99f                     @ already configured
 
                /* Check the debug UART configuration set in uncompress.h */
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =OMAP_UART_INFO
-               ldrne   \rx, =__phys_to_virt(OMAP_UART_INFO)
-               ldr     \rx, [\rx, #0]
+               mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               ldreq   \rp, =OMAP_UART_INFO    @ MMU not enabled
+               ldrne   \rp, =__phys_to_virt(OMAP_UART_INFO)    @ MMU enabled
+               ldr     \rp, [\rp, #0]
 
                /* Select the UART to use based on the UART1 scratchpad value */
-10:            cmp     \rx, #0                 @ no port configured?
+10:            cmp     \rp, #0                 @ no port configured?
                beq     11f                     @ if none, try to use UART1
-               cmp     \rx, #OMAP1UART1
+               cmp     \rp, #OMAP1UART1
                beq     11f                     @ configure OMAP1UART1
-               cmp     \rx, #OMAP1UART2
+               cmp     \rp, #OMAP1UART2
                beq     12f                     @ configure OMAP1UART2
-               cmp     \rx, #OMAP1UART3
+               cmp     \rp, #OMAP1UART3
                beq     13f                     @ configure OMAP2UART3
 
                /* Configure the UART offset from the phys/virt base */
-11:            mov     \rx, #0x00fb0000        @ OMAP1UART1
+11:            mov     \rp, #0x00fb0000        @ OMAP1UART1
                b       98f
-12:            mov     \rx, #0x00fb0000        @ OMAP1UART1
-               orr     \rx, \rx, #0x00000800   @ OMAP1UART2
+12:            mov     \rp, #0x00fb0000        @ OMAP1UART1
+               orr     \rp, \rp, #0x00000800   @ OMAP1UART2
                b       98f
-13:            mov     \rx, #0x00fb0000        @ OMAP1UART1
-               orr     \rx, \rx, #0x00000800   @ OMAP1UART2
-               orr     \rx, \rx, #0x00009000   @ OMAP1UART3
+13:            mov     \rp, #0x00fb0000        @ OMAP1UART1
+               orr     \rp, \rp, #0x00000800   @ OMAP1UART2
+               orr     \rp, \rp, #0x00009000   @ OMAP1UART3
 
                /* Store both phys and virt address for the uart */
-98:            add     \rx, \rx, #0xff000000   @ phys base
-               mrc     p15, 0, \tmp, c1, c0
-               tst     \tmp, #1                @ MMU enabled?
-               ldreq   \tmp, =__virt_to_phys(omap_uart_phys)
-               ldrne   \tmp, =omap_uart_phys
-               str     \rx, [\tmp, #0]
-               sub     \rx, \rx, #0xff000000   @ phys base
-               add     \rx, \rx, #0xfe000000   @ virt base
-               ldreq   \tmp, =__virt_to_phys(omap_uart_virt)
-               ldrne   \tmp, =omap_uart_virt
-               str     \rx, [\tmp, #0]
+98:            add     \rp, \rp, #0xff000000   @ phys base
+               mrc     p15, 0, \rv, c1, c0
+               tst     \rv, #1                 @ MMU enabled?
+               ldreq   \rv, =__virt_to_phys(omap_uart_phys)    @ MMU not enabled
+               ldrne   \rv, =omap_uart_phys    @ MMU enabled
+               str     \rp, [\rv, #0]
+               sub     \rp, \rp, #0xff000000   @ phys base
+               add     \rp, \rp, #0xfe000000   @ virt base
+               add     \rv, \rv, #4            @ omap_uart_lsr
+               str     \rp, [\rv, #0]
                b       9b
 99:
                .endm
index 1b2af14df151627b06c2459af6ddb603b7f95094..b001f67d695b28e3ff6f10f16fd1842d7f3742fc 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VMALLOC_END    (PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END    0xd8000000
index 63b2d8859c3c291af8e8af729f63d8302ad4915e..88d3a1e920f583110a88aa8c90bbe7903b098f8f 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_LOCAL_TIMERS)            += timer-mpu.o
 obj-$(CONFIG_HOTPLUG_CPU)              += omap-hotplug.o
 obj-$(CONFIG_ARCH_OMAP4)               += omap44xx-smc.o omap4-common.o
 
+AFLAGS_omap-headsmp.o                  :=-Wa,-march=armv7-a
 AFLAGS_omap44xx-smc.o                  :=-Wa,-march=armv7-a
 
 # Functions loaded to SRAM
index 8538e4131d27670de9b7f0c4a2a32c075f6cf27b..b857ce48451068cd24e4e5ae8125d7680ec73621 100644 (file)
@@ -253,8 +253,6 @@ static void __init omap_2430sdp_map_io(void)
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
        /* Maintainer: Syed Khasim - Texas Instruments Inc */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap_2430sdp_map_io,
        .reserve        = omap_reserve,
index 67b95b5f1a2f62d8270a92a5a5cf1d7bcee57b0e..a5b095cf2adcdd67a14690e7eb0c8d99244f6167 100644 (file)
@@ -817,8 +817,6 @@ static void __init omap_3430sdp_init(void)
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
        /* Maintainer: Syed Khasim - Texas Instruments Inc */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index b359c3f7bb399b9608ddc315226f263ae76d8ec0..fd27ac0860b0c6b6d217f0d46b61c65a4574c36b 100644 (file)
@@ -217,8 +217,6 @@ static void __init omap_sdp_init(void)
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index 9447644774c234435667a548e409bb0b4df76163..0b6a65f3a10a2adf508d209c7daeccfc51fea68c 100644 (file)
@@ -458,8 +458,6 @@ static void __init omap_4430sdp_map_io(void)
 
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
        /* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap_4430sdp_map_io,
        .reserve        = omap_reserve,
index 4d0f58592864972429c0a19fb3d5e2ff9ecc0d27..f85c8da17e8bb8bcf69bbf208b2030277c3879be 100644 (file)
@@ -462,8 +462,6 @@ static void __init am3517_evm_init(void)
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index c6421a72514a2a4e776aab63a2e1107434c3ffc2..68f07f5f441a65887e9d7783173b30916ccb0461 100644 (file)
@@ -356,8 +356,6 @@ static void __init omap_apollon_map_io(void)
 
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
        /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap_apollon_map_io,
        .reserve        = omap_reserve,
index e10bc109415c4d3793b89b3e6e6ac1580311645a..934d9380c372e5ec31710fb47f6f4aa58714c60e 100644 (file)
@@ -809,8 +809,6 @@ static void __init cm_t35_init(void)
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index a07086d6a0b26b6cb7d7fbe7d810ea330bcdae28..2205c20a4cdb61cf17ea11dd199b752baacafc65 100644 (file)
@@ -800,8 +800,6 @@ static void __init devkit8000_init(void)
 }
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index 3482b99e8c8653c4e72240d263692a436674afdc..69064b1c6a75da991e7a229296be750eb68c4649 100644 (file)
@@ -54,8 +54,6 @@ static void __init omap_generic_map_io(void)
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap_generic_map_io,
        .reserve        = omap_reserve,
index e09bd686389f32dc385da26db744efbecc7fe5a7..cc39fc866524bfa1def1a0e7ec727a346f592196 100644 (file)
@@ -376,8 +376,6 @@ static void __init omap_h4_map_io(void)
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap_h4_map_io,
        .reserve        = omap_reserve,
index 175f043397612df6bc764a668338789d301e69c2..b62a68ba069bae2e198af22e76b7cf1500ae9ec9 100644 (file)
@@ -533,8 +533,6 @@ static void __init igep2_init(void)
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index 00d9b13b01c5938e0118ced2a8801595dede232f..f28fd77bceb322f476b142f5cb5496b6a9dcf2db 100644 (file)
@@ -442,8 +442,6 @@ static void __init omap_ldp_init(void)
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index a3e2b49aa39f001046c0994b09c64aa14cd10581..3f796687350771fe4334fc8ee0646f0405079e98 100644 (file)
@@ -674,8 +674,6 @@ static void __init n8x0_init_machine(void)
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = n8x0_map_io,
        .reserve        = omap_reserve,
@@ -685,8 +683,6 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = n8x0_map_io,
        .reserve        = omap_reserve,
@@ -696,8 +692,6 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = n8x0_map_io,
        .reserve        = omap_reserve,
index 87969c7df652885ff6210519f3043cb7bb4f055e..9d9f5b881ee872137407901b3e5300921bc0cf0c 100644 (file)
@@ -487,8 +487,6 @@ static void __init omap3_beagle_init(void)
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
        /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index f76d9c0a47a1e83c8220977d75908c181899d53c..8936e4fba334796c2de6a68a96efe1330a0e2b15 100644 (file)
@@ -714,8 +714,6 @@ static void __init omap3_evm_init(void)
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
        /* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index dd3af2be13be2a79e14a52360088c8cbb9db575b..b7d6df4e3cf95aa3f553a126087ba59353c1c5b3 100644 (file)
@@ -717,8 +717,6 @@ static void __init omap3pandora_init(void)
 }
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index bcd01d278c656f0b09a742a31370e5e278b1fb9e..bc5ac83bd4cf19824a432b8135357999577a6431 100644 (file)
@@ -654,8 +654,6 @@ static void __init omap3_stalker_init(void)
 
 MACHINE_START(SBC3530, "OMAP3 STALKER")
        /* Maintainer: Jason Lam -lzg@ema-tech.com */
-       .phys_io                = 0x48000000,
-       .io_pg_offst            = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params            = 0x80000100,
        .map_io                 = omap3_map_io,
        .init_irq               = omap3_stalker_init_irq,
index 663c62d271e8bfa0fcdec35bd9f03333ac0af87c..0e99ce584dbfc518f68ec87c75af1a5e9e3562e1 100644 (file)
@@ -538,8 +538,6 @@ static void __init omap3_touchbook_init(void)
 
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
        /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index c03d1d56db562b1d4ef9f6fb86ce3da44d7d360e..db69bcadf4c7400e60cba20659d73ddfaf893e49 100644 (file)
@@ -294,8 +294,6 @@ static void __init omap4_panda_map_io(void)
 
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
        /* Maintainer: David Anders - Texas Instruments Inc */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap4_panda_map_io,
        .init_irq       = omap4_panda_init_irq,
index 4c484361835063d17de2df8fe27c7fb28be7984f..5e528ca015a1a38b69a7b4cf89661c173e868497 100644 (file)
@@ -501,8 +501,6 @@ static void __init overo_init(void)
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index a58e8cb1a7fc9abf639225bed3fa5de8cc3187c9..36f2cf4efd57630b593bf42ca28965891c14f906 100644 (file)
@@ -150,8 +150,6 @@ static void __init rx51_map_io(void)
 
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
        /* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
-       .phys_io        = 0x48000000,
-       .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = rx51_map_io,
        .reserve        = omap_reserve,
index 3ad9ecf7f5e2b32d2361ae1df84aaa54b63013f8..24bbd0def64ff4b3e6617dc01910c491a7b557c8 100644 (file)
@@ -141,8 +141,6 @@ static void __init omap_zoom2_init(void)
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-       .phys_io        = ZOOM_UART_BASE,
-       .io_pg_offst    = (ZOOM_UART_VIRT >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index 6ca0b8341615efcbe628648bfe478bf9c1e91b35..b2bb3ff971ac9c940a73d6f093350c45126cc6f8 100644 (file)
@@ -123,8 +123,6 @@ static void __init omap_zoom_init(void)
 }
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-       .phys_io        = ZOOM_UART_BASE,
-       .io_pg_offst    = (ZOOM_UART_VIRT >> 18) & 0xfffc,
        .boot_params    = 0x80000100,
        .map_io         = omap3_map_io,
        .reserve        = omap_reserve,
index 138646deac8932210cc6168ab647444908c92b85..dfdce2d8277992b3e6ccb9fcfbc247e3b8df3708 100644 (file)
@@ -3417,7 +3417,13 @@ int __init omap3xxx_clk_init(void)
        struct omap_clk *c;
        u32 cpu_clkflg = CK_3XXX;
 
-       if (cpu_is_omap34xx()) {
+       if (cpu_is_omap3517()) {
+               cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
+               cpu_clkflg |= CK_3517;
+       } else if (cpu_is_omap3505()) {
+               cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
+               cpu_clkflg |= CK_3505;
+       } else if (cpu_is_omap34xx()) {
                cpu_mask = RATE_IN_3XXX;
                cpu_clkflg |= CK_343X;
 
@@ -3432,12 +3438,6 @@ int __init omap3xxx_clk_init(void)
                        cpu_mask |= RATE_IN_3430ES2PLUS;
                        cpu_clkflg |= CK_3430ES2;
                }
-       } else if (cpu_is_omap3517()) {
-               cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
-               cpu_clkflg |= CK_3517;
-       } else if (cpu_is_omap3505()) {
-               cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
-               cpu_clkflg |= CK_3505;
        }
 
        if (omap3_has_192mhz_clk())
index e8256a2ed8e782dd56a7bfa674b98886a9f63e71..9a879f9595098dd5e3fcb303b8d205af744d3a28 100644 (file)
@@ -284,8 +284,8 @@ static void __init omap3_check_revision(void)
                default:
                        omap_revision =  OMAP3630_REV_ES1_2;
                        omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
-                       break;
                }
+               break;
        default:
                /* Unknown default to latest silicon rev as default*/
                omap_revision =  OMAP3630_REV_ES1_2;
index 09331bbbda52b66e267756b58cf8294472a010bb..6a4d4136002ed9999fa401e61c3776b74abe7581 100644 (file)
@@ -31,95 +31,94 @@ omap_uart_lsr:      .word   0
                 * the desired UART phys and virt addresses temporarily into
                 * the omap_uart_phys and omap_uart_virt above.
                 */
-               .macro  addruart, rx, tmp
+               .macro  addruart, rp, rv
 
                /* Use omap_uart_phys/virt if already configured */
-10:            mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =__virt_to_phys(omap_uart_phys)    @ physical base address
-               ldrne   \rx, =omap_uart_virt    @ virtual base address
-               ldr     \rx, [\rx, #0]
-               cmp     \rx, #0                 @ is port configured?
+10:            mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               ldreq   \rp, =__virt_to_phys(omap_uart_phys)    @ MMU not enabled
+               ldrne   \rp, =omap_uart_phys    @ MMU enabled
+               add     \rv, \rp, #4            @ omap_uart_virt
+               ldr     \rp, [\rp, #0]
+               ldr     \rv, [\rv, #0]
+               cmp     \rp, #0                 @ is port configured?
+               cmpne   \rv, #0
                bne     99f                     @ already configured
 
                /* Check the debug UART configuration set in uncompress.h */
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =OMAP_UART_INFO
-               ldrne   \rx, =__phys_to_virt(OMAP_UART_INFO)
-               ldr     \rx, [\rx, #0]
+               mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               ldreq   \rp, =OMAP_UART_INFO    @ MMU not enabled
+               ldrne   \rp, =__phys_to_virt(OMAP_UART_INFO)    @ MMU enabled
+               ldr     \rp, [\rp, #0]
 
                /* Select the UART to use based on the UART1 scratchpad value */
-               cmp     \rx, #0                 @ no port configured?
+               cmp     \rp, #0                 @ no port configured?
                beq     21f                     @ if none, try to use UART1
-               cmp     \rx, #OMAP2UART1        @ OMAP2/3/4UART1
+               cmp     \rp, #OMAP2UART1        @ OMAP2/3/4UART1
                beq     21f                     @ configure OMAP2/3/4UART1
-               cmp     \rx, #OMAP2UART2        @ OMAP2/3/4UART2
+               cmp     \rp, #OMAP2UART2        @ OMAP2/3/4UART2
                beq     22f                     @ configure OMAP2/3/4UART2
-               cmp     \rx, #OMAP2UART3        @ only on 24xx
+               cmp     \rp, #OMAP2UART3        @ only on 24xx
                beq     23f                     @ configure OMAP2UART3
-               cmp     \rx, #OMAP3UART3        @ only on 34xx
+               cmp     \rp, #OMAP3UART3        @ only on 34xx
                beq     33f                     @ configure OMAP3UART3
-               cmp     \rx, #OMAP4UART3        @ only on 44xx
+               cmp     \rp, #OMAP4UART3        @ only on 44xx
                beq     43f                     @ configure OMAP4UART3
-               cmp     \rx, #OMAP3UART4        @ only on 36xx
+               cmp     \rp, #OMAP3UART4        @ only on 36xx
                beq     34f                     @ configure OMAP3UART4
-               cmp     \rx, #OMAP4UART4        @ only on 44xx
+               cmp     \rp, #OMAP4UART4        @ only on 44xx
                beq     44f                     @ configure OMAP4UART4
-               cmp     \rx, #ZOOM_UART         @ only on zoom2/3
+               cmp     \rp, #ZOOM_UART         @ only on zoom2/3
                beq     95f                     @ configure ZOOM_UART
 
                /* Configure the UART offset from the phys/virt base */
-21:            mov     \rx, #UART_OFFSET(OMAP2_UART1_BASE)     @ omap2/3/4
+21:            mov     \rp, #UART_OFFSET(OMAP2_UART1_BASE)     @ omap2/3/4
                b       98f
-22:            mov     \rx, #UART_OFFSET(OMAP2_UART2_BASE)     @ omap2/3/4
+22:            mov     \rp, #UART_OFFSET(OMAP2_UART2_BASE)     @ omap2/3/4
                b       98f
-23:            mov     \rx, #UART_OFFSET(OMAP2_UART3_BASE)
+23:            mov     \rp, #UART_OFFSET(OMAP2_UART3_BASE)
                b       98f
-33:            mov     \rx, #UART_OFFSET(OMAP3_UART1_BASE)
-               add     \rx, \rx, #0x00fb0000
-               add     \rx, \rx, #0x00006000           @ OMAP3_UART3_BASE
+33:            mov     \rp, #UART_OFFSET(OMAP3_UART1_BASE)
+               add     \rp, \rp, #0x00fb0000
+               add     \rp, \rp, #0x00006000           @ OMAP3_UART3_BASE
                b       98f
-34:            mov     \rx, #UART_OFFSET(OMAP3_UART1_BASE)
-               add     \rx, \rx, #0x00fb0000
-               add     \rx, \rx, #0x00028000           @ OMAP3_UART4_BASE
+34:            mov     \rp, #UART_OFFSET(OMAP3_UART1_BASE)
+               add     \rp, \rp, #0x00fb0000
+               add     \rp, \rp, #0x00028000           @ OMAP3_UART4_BASE
                b       98f
-43:            mov     \rx, #UART_OFFSET(OMAP4_UART3_BASE)
+43:            mov     \rp, #UART_OFFSET(OMAP4_UART3_BASE)
                b       98f
-44:            mov     \rx, #UART_OFFSET(OMAP4_UART4_BASE)
+44:            mov     \rp, #UART_OFFSET(OMAP4_UART4_BASE)
                b       98f
-95:            ldr     \rx, =ZOOM_UART_BASE
-               mrc     p15, 0, \tmp, c1, c0
-               tst     \tmp, #1                @ MMU enabled?
-               ldreq   \tmp, =__virt_to_phys(omap_uart_phys)
-               ldrne   \tmp, =omap_uart_phys
-               str     \rx, [\tmp, #0]
-               ldr     \rx, =ZOOM_UART_VIRT
-               ldreq   \tmp, =__virt_to_phys(omap_uart_virt)
-               ldrne   \tmp, =omap_uart_virt
-               str     \rx, [\tmp, #0]
-               mov     \rx, #(UART_LSR << ZOOM_PORT_SHIFT)
-               ldreq   \tmp, =__virt_to_phys(omap_uart_lsr)
-               ldrne   \tmp, =omap_uart_lsr
-               str     \rx, [\tmp, #0]
+95:            ldr     \rp, =ZOOM_UART_BASE
+               mrc     p15, 0, \rv, c1, c0
+               tst     \rv, #1                 @ MMU enabled?
+               ldreq   \rv, =__virt_to_phys(omap_uart_phys)    @ MMU not enabled
+               ldrne   \rv, =omap_uart_phys    @ MMU enabled
+               str     \rp, [\rv, #0]
+               ldr     \rp, =ZOOM_UART_VIRT
+               add     \rv, \rv, #4            @ omap_uart_virt
+               str     \rp, [\rv, #0]
+               mov     \rp, #(UART_LSR << ZOOM_PORT_SHIFT)
+               add     \rv, \rv, #4            @ omap_uart_lsr
+               str     \rp, [\rv, #0]
                b       10b
 
                /* Store both phys and virt address for the uart */
-98:            add     \rx, \rx, #0x48000000   @ phys base
-               mrc     p15, 0, \tmp, c1, c0
-               tst     \tmp, #1                @ MMU enabled?
-               ldreq   \tmp, =__virt_to_phys(omap_uart_phys)
-               ldrne   \tmp, =omap_uart_phys
-               str     \rx, [\tmp, #0]
-               sub     \rx, \rx, #0x48000000   @ phys base
-               add     \rx, \rx, #0xfa000000   @ virt base
-               ldreq   \tmp, =__virt_to_phys(omap_uart_virt)
-               ldrne   \tmp, =omap_uart_virt
-               str     \rx, [\tmp, #0]
-               mov     \rx, #(UART_LSR << OMAP_PORT_SHIFT)
-               ldreq   \tmp, =__virt_to_phys(omap_uart_lsr)
-               ldrne   \tmp, =omap_uart_lsr
-               str     \rx, [\tmp, #0]
+98:            add     \rp, \rp, #0x48000000   @ phys base
+               mrc     p15, 0, \rv, c1, c0
+               tst     \rv, #1                 @ MMU enabled?
+               ldreq   \rv, =__virt_to_phys(omap_uart_phys)    @ MMU not enabled
+               ldrne   \rv, =omap_uart_phys    @ MMU enabled
+               str     \rp, [\rv, #0]
+               sub     \rp, \rp, #0x48000000   @ phys base
+               add     \rp, \rp, #0xfa000000   @ virt base
+               add     \rv, \rv, #4            @ omap_uart_virt
+               str     \rp, [\rv, #0]
+               mov     \rp, #(UART_LSR << OMAP_PORT_SHIFT)
+               add     \rv, \rv, #4            @ omap_uart_lsr
+               str     \rp, [\rv, #0]
 
                b       10b
 99:
@@ -131,9 +130,9 @@ omap_uart_lsr:      .word   0
 
                .macro  busyuart,rd,rx
 1001:          mrc     p15, 0, \rd, c1, c0
-               tst     \rd, #1         @ MMU enabled?
-               ldreq   \rd, =__virt_to_phys(omap_uart_lsr)
-               ldrne   \rd, =omap_uart_lsr
+               tst     \rd, #1                 @ MMU enabled?
+               ldreq   \rd, =__virt_to_phys(omap_uart_lsr)     @ MMU not enabled
+               ldrne   \rd, =omap_uart_lsr     @ MMU enabled
                ldr     \rd, [\rd, #0]
                ldrb    \rd, [\rx, \rd]
                and     \rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
index 50fd749166433f7ebadfa492a4ea136718660e7e..06e64e1fc28a7e18957ff0bb9fe620e7487f7284 100644 (file)
@@ -177,7 +177,10 @@ omap_irq_base:     .word   0
                cmpne   \irqnr, \tmp
                cmpcs   \irqnr, \irqnr
                .endm
+#endif
+#endif /* MULTI_OMAP2 */
 
+#ifdef CONFIG_SMP
                /* We assume that irqstat (the raw value of the IRQ acknowledge
                 * register) is preserved from the macro above.
                 * If there is an IPI, we immediately signal end of interrupt
@@ -205,8 +208,7 @@ omap_irq_base:      .word   0
                streq   \irqstat, [\base, #GIC_CPU_EOI]
                cmp     \tmp, #0
                .endm
-#endif
-#endif /* MULTI_OMAP2 */
+#endif /* CONFIG_SMP */
 
                .macro  irq_prio_table
                .endm
index 9ce9b6e8ad23c6df97167845a85b51e95bf0d23c..4da31e997efead8da47b602699a210f9127231b7 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VMALLOC_END      (PAGE_OFFSET + 0x38000000)
+#define VMALLOC_END      0xf8000000
index af3c20c8d3f9202e742068f8ba1e57c911e3c265..9e9f70e18e3c95436cf6b957e2791175a3cdc90a 100644 (file)
@@ -102,8 +102,7 @@ static void __init wakeup_secondary(void)
         * Send a 'sev' to wake the secondary core from WFE.
         * Drain the outstanding writes to memory
         */
-       dsb();
-       set_event();
+       dsb_sev();
        mb();
 }
 
index fb4994ad622ec469aaec34665a98af6250d29dc8..7b03426c72a317307db1df3931a5018443117b33 100644 (file)
@@ -480,7 +480,9 @@ void omap_sram_idle(void)
        }
 
        /* Disable IO-PAD and IO-CHAIN wakeup */
-       if (omap3_has_io_wakeup() && core_next_state < PWRDM_POWER_ON) {
+       if (omap3_has_io_wakeup() &&
+           (per_next_state < PWRDM_POWER_ON ||
+            core_next_state < PWRDM_POWER_ON)) {
                prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
                omap3_disable_io_chain();
        }
index 7130904ad9998e28c8a0bd5eb884f7bc5649f329..b1c451f5ee27e56b23f46969bb4917010a1b2f31 100644 (file)
@@ -336,8 +336,6 @@ static void __init d2net_init(void)
 
 #ifdef CONFIG_MACH_D2NET
 MACHINE_START(D2NET, "LaCie d2 Network")
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = d2net_init,
        .map_io         = orion5x_map_io,
@@ -349,8 +347,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_BIGDISK
 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = d2net_init,
        .map_io         = orion5x_map_io,
index d318bea2af91bbb5e9ec46a57813d6ef5add40e7..df1083f5b6eba92e32c044bebde773551bfd67f0 100644 (file)
@@ -358,8 +358,6 @@ static void __init db88f5281_init(void)
 
 MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
        /* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .init_machine   = db88f5281_init,
        .map_io         = orion5x_map_io,
index a47100d46a4e88a9f3f41b4d1705ddc397cfe622..3a7bc0e36982bff6e9e73863960277ac01249cdb 100644 (file)
@@ -730,8 +730,6 @@ 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> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = dns323_init,
        .map_io         = orion5x_map_io,
index b24ee0c2cd618ab35f5e0b21cf06ab50b11d148d..ba98459f44b08d9084208d732f1e7f27fa6b80ad 100644 (file)
@@ -251,8 +251,6 @@ 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> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = edmini_v2_init,
        .map_io         = orion5x_map_io,
index 91e0e39bb23f1602a98068234c28268f262e455c..5e3bf5b68aecae6da23e23fdd4f204a3602e991d 100644 (file)
 
 #include <mach/orion5x.h>
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =ORION5X_REGS_PHYS_BASE
-       ldrne   \rx, =ORION5X_REGS_VIRT_BASE
-       orr     \rx, \rx, #0x00012000
+       .macro  addruart, rp, rv
+       ldr     \rp, =ORION5X_REGS_PHYS_BASE
+       ldr     \rv, =ORION5X_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
        .endm
 
 #define UART_SHIFT     2
index dfbb68df7b0986de42918ef5a6222eb0e337e940..4be9aa08de6996372391516c857e17802f0bf5f4 100644 (file)
@@ -379,8 +379,6 @@ 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> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = kurobox_pro_init,
        .map_io         = orion5x_map_io,
@@ -393,8 +391,6 @@ MACHINE_END
 #ifdef CONFIG_MACH_LINKSTATION_PRO
 MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
        /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = kurobox_pro_init,
        .map_io         = orion5x_map_io,
index 8e569be6e2c7f4bc75f275660a83360cd1ccb20f..437364b7168ec9f4060725904df90b23772f10e5 100644 (file)
@@ -265,8 +265,6 @@ static void __init ls_hgl_init(void)
 
 MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
        /* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = ls_hgl_init,
        .map_io         = orion5x_map_io,
index c704f056de1e165bfad370c32b6f4bc2659592fa..ab9b0cf0a90b116ab3f607a0e05014a46a161136 100644 (file)
@@ -267,8 +267,6 @@ static void __init lsmini_init(void)
 #ifdef CONFIG_MACH_LINKSTATION_MINI
 MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
        /* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = lsmini_init,
        .map_io         = orion5x_map_io,
index 61c086b66723d96296a51d38363f8d3584523cea..2f0e16cd7e8164d79bb3814fed13ccbab8a8bfd6 100644 (file)
@@ -261,8 +261,6 @@ static void __init mss2_init(void)
 
 MACHINE_START(MSS2, "Maxtor Shared Storage II")
        /* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = mss2_init,
        .map_io         = orion5x_map_io,
index 97c9ccb2ac60f7713bc076e38b3b23b8dff94c04..b3d90f25de9f1119235e4f5e46d9e58fa0846313 100644 (file)
@@ -229,8 +229,6 @@ 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> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = mv2120_init,
        .map_io         = orion5x_map_io,
index 7bd6283476f9e46017ca0be56ad06d16ae670ce8..d6665b31665fc4f41eac9fd612af5b3d6c6688a7 100644 (file)
@@ -419,8 +419,6 @@ static void __init net2big_init(void)
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(NET2BIG, "LaCie 2Big Network")
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = net2big_init,
        .map_io         = orion5x_map_io,
index 9c1ca41730ba4fc00d248029dedfb0d7bc8d8417..f4c26fd731f4f4f923a3c2a71c2442d3043a2b6c 100644 (file)
@@ -169,8 +169,6 @@ subsys_initcall(rd88f5181l_fxo_pci_init);
 
 MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
        /* Maintainer: Nicolas Pitre <nico@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f5181l_fxo_init,
        .map_io         = orion5x_map_io,
index ee1399ff0cedbe38aab1f8a4ff82dbdb921158be..b5942909bab07b72405cf73df452d4a01e7365e0 100644 (file)
@@ -181,8 +181,6 @@ subsys_initcall(rd88f5181l_ge_pci_init);
 
 MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f5181l_ge_init,
        .map_io         = orion5x_map_io,
index a04f9e4b633a409a10a80cfb5c63da32f4ce3793..165ed87029b2c77705e68443ef84e427fa3e1e3c 100644 (file)
@@ -305,8 +305,6 @@ static void __init rd88f5182_init(void)
 
 MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
        /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f5182_init,
        .map_io         = orion5x_map_io,
index 7737cf9a8f5046a80911cd80b70a3f506d6fc057..02ff45f3e2e3f20420ee2922f527302e3d2b90f4 100644 (file)
@@ -123,8 +123,6 @@ subsys_initcall(rd88f6183ap_ge_pci_init);
 
 MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = rd88f6183ap_ge_init,
        .map_io         = orion5x_map_io,
index 0b101d7d41c2caa089fd8f4234a1e3b184f5432b..4403fae5ab0e8a0c843718a1b28ad30da073428f 100644 (file)
@@ -358,8 +358,6 @@ static void __init tsp2_init(void)
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
        /* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = tsp2_init,
        .map_io         = orion5x_map_io,
index 9d6890514199759919b211859e8a864f4a6db7e8..1e196129d763785e0ec8047b2d462fde1826e651 100644 (file)
@@ -322,8 +322,6 @@ static void __init qnap_ts209_init(void)
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
        /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = qnap_ts209_init,
        .map_io         = orion5x_map_io,
index d85588ac7ef8f53ac141c695bee18ed37f7700b9..428af2046e36ded13192b5009fa05aa94061c933 100644 (file)
@@ -311,8 +311,6 @@ static void __init qnap_ts409_init(void)
 
 MACHINE_START(TS409, "QNAP TS-409")
        /* Maintainer:  Sylver Bruneau <sylver.bruneau@gmail.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = qnap_ts409_init,
        .map_io         = orion5x_map_io,
index 696b1a97f9e2eaf5b7c88735a2f41fa17262ba97..16f1bd5324bebb94b01ec5af9db5eb82d4e3509f 100644 (file)
@@ -550,8 +550,6 @@ static void __init ts78xx_init(void)
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
        /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = ts78xx_init,
        .map_io         = ts78xx_map_io,
index 69208217b22037096e4c467c2cc4508fb75dd9e5..7994d6ec08a87b7ad058a41e35e0111e1df906da 100644 (file)
@@ -172,8 +172,6 @@ subsys_initcall(wnr854t_pci_init);
 
 MACHINE_START(WNR854T, "Netgear WNR854T")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = wnr854t_init,
        .map_io         = orion5x_map_io,
index f9f222ebb7ed0c5b12064cebddfe63c9399b3846..a5989b7eb53ee36526d0bef1f26f680deb044e13 100644 (file)
@@ -260,8 +260,6 @@ subsys_initcall(wrt350n_v2_pci_init);
 
 MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .phys_io        = ORION5X_REGS_PHYS_BASE,
-       .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
        .boot_params    = 0x00000100,
        .init_machine   = wrt350n_v2_init,
        .map_io         = orion5x_map_io,
index 45734bb880a88477d7221760291f4c6f399883f8..63399755f199dd91202f89917fbb04a1b0c44adc 100644 (file)
@@ -264,8 +264,6 @@ extern struct sys_timer pnx4008_timer;
 
 MACHINE_START(PNX4008, "Philips PNX4008")
        /* Maintainer: MontaVista Software Inc. */
-       .phys_io                = 0x40090000,
-       .io_pg_offst            = (0xf4090000 >> 18) & 0xfffc,
        .boot_params            = 0x80000100,
        .map_io                 = pnx4008_map_io,
        .init_irq               = pnx4008_init_irq,
index 6ca8bd30bf46f32dd0e55c9284b0962242596dff..931afebaf06439fc78dc4192ce8f58f416d0a2b1 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               mov     \rx, #0x00090000
-               addeq   \rx, \rx, #0x40000000
-               addne   \rx, \rx, #0xf4000000
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00090000
+               add     \rv, \rp, #0xf4000000   @ virtual
+               add     \rp, \rp, #0x40000000   @ physical
                .endm
 
 #define UART_SHIFT     2
index 2ad398378aed3241e47bf9dc14237f9acf63bd95..31b65ee07b0b17f498e9796c2704ff6f427f5662 100644 (file)
@@ -17,4 +17,4 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
index 7aefb90748527ae5b68550b7e311d1244b55639d..dd235ecc9d6c5946d6610bb7adef42cb57476210 100644 (file)
@@ -8,19 +8,16 @@ config ARCH_LUBBOCK
        bool "Intel DBPXA250 Development Platform (aka Lubbock)"
        select PXA25x
        select SA1111
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_MAINSTONE
        bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
        select PXA27x
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_ZYLONITE
        bool
        select PXA3xx
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_ZYLONITE300
        bool "PXA3xx Development Platform (aka Zylonite) PXA300/310"
@@ -44,6 +41,10 @@ config MACH_TAVOREVB
        select PXA3xx
        select CPU_PXA930
 
+config MACH_TAVOREVB3
+       bool "PXA95x Development Platform (aka TavorEVB III)"
+       select CPU_PXA950
+
 config MACH_SAAR
        bool "PXA930 Handheld Platform (aka SAAR)"
        select PXA3xx
@@ -61,7 +62,6 @@ config ARCH_VIPER
        select ISA
        select I2C_GPIO
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
        select PXA_HAVE_ISA_IRQS
        select ARCOM_PCMCIA
 
@@ -69,7 +69,6 @@ config MACH_ARCOM_ZEUS
        bool "Arcom/Eurotech ZEUS SBC"
        select PXA27x
        select ISA
-       select PXA_HAVE_BOARD_IRQS
        select PXA_HAVE_ISA_IRQS
        select ARCOM_PCMCIA
 
@@ -77,7 +76,6 @@ config MACH_BALLOON3
        bool "Balloon 3 board"
        select PXA27x
        select IWMMXT
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_CSB726
        bool "Enable Cogent CSB726 System On a Module"
@@ -140,13 +138,11 @@ config MACH_INTELMOTE2
        bool "Intel Mote 2 Platform"
        select PXA27x
        select IWMMXT
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_STARGATE2
        bool "Intel Stargate 2 Platform"
        select PXA27x
        select IWMMXT
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_XCEP
        bool "Iskratel Electronics XCEP"
@@ -206,13 +202,11 @@ config MACH_LOGICPD_PXA270
        bool "LogicPD PXA270 Card Engine Development Platform"
        select PXA27x
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_PCM027
        bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
        select PXA27x
        select IWMMXT
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_PCM990_BASEBOARD
        bool "PHYTEC PCM-990 development board"
@@ -247,7 +241,6 @@ config MACH_COLIBRI_PXA270_INCOME
        depends on MACH_COLIBRI
        select PXA27x
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_COLIBRI300
        bool "Toradex Colibri PXA300/310"
@@ -274,7 +267,6 @@ config MACH_H4700
        select PXA27x
        select IWMMXT
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_H5000
        bool "HP iPAQ h5000"
@@ -289,7 +281,6 @@ config MACH_MAGICIAN
        select PXA27x
        select IWMMXT
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_MIOA701
        bool "Mitac Mio A701 Support"
@@ -307,7 +298,6 @@ config PXA_EZX
        select PXA27x
        select IWMMXT
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_EZX_A780
        bool "Motorola EZX A780"
@@ -478,7 +468,6 @@ config MACH_POODLE
        depends on PXA_SHARPSL
        select PXA25x
        select SHARP_LOCOMO
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_CORGI
        bool "Enable Sharp SL-C700 (Corgi) Support"
@@ -523,7 +512,6 @@ config MACH_TOSA
        bool "Enable Sharp SL-6000x (Tosa) Support"
        depends on PXA_SHARPSL
        select PXA25x
-       select PXA_HAVE_BOARD_IRQS
 
 config TOSA_BT
        tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
@@ -552,7 +540,6 @@ config MACH_ICONTROL
 config ARCH_PXA_ESERIES
        bool "PXA based Toshiba e-series PDAs"
        select PXA25x
-       select PXA_HAVE_BOARD_IRQS
 
 config MACH_E330
        bool "Toshiba e330"
@@ -606,7 +593,6 @@ config MACH_ZIPIT2
        bool "Zipit Z2 Handheld"
        select PXA27x
        select HAVE_PWM
-       select PXA_HAVE_BOARD_IRQS
 
 endmenu
 
@@ -643,6 +629,7 @@ config CPU_PXA300
 config CPU_PXA310
        bool
        select CPU_PXA300
+       select PXA310_ULPI if USB_ULPI
        help
          PXA310 (codename Monahans-LV)
 
@@ -692,10 +679,10 @@ config SHARPSL_PM_MAX1111
        select HWMON
        select SENSORS_MAX1111
 
-config PXA_HAVE_BOARD_IRQS
+config PXA_HAVE_ISA_IRQS
        bool
 
-config PXA_HAVE_ISA_IRQS
+config PXA310_ULPI
        bool
 
 endif
index 85c7fb324dbb88ee68ce1d0da0cf0f9c0e92035c..e2f89c2c6f4962ea38a98ea9adb6e3dca8e63ed9 100644 (file)
@@ -18,7 +18,7 @@ endif
 # SoC-specific code
 obj-$(CONFIG_PXA25x)           += mfp-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)           += mfp-pxa2xx.o pxa2xx.o pxa27x.o
-obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o pxa3xx.o smemc.o
+obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
 obj-$(CONFIG_CPU_PXA300)       += pxa300.o
 obj-$(CONFIG_CPU_PXA320)       += pxa320.o
 obj-$(CONFIG_CPU_PXA930)       += pxa930.o
@@ -32,6 +32,7 @@ obj-$(CONFIG_MACH_ZYLONITE300)        += zylonite.o zylonite_pxa300.o
 obj-$(CONFIG_MACH_ZYLONITE320) += zylonite.o zylonite_pxa320.o
 obj-$(CONFIG_MACH_LITTLETON)   += littleton.o
 obj-$(CONFIG_MACH_TAVOREVB)    += tavorevb.o
+obj-$(CONFIG_MACH_TAVOREVB3)   += tavorevb3.o
 obj-$(CONFIG_MACH_SAAR)                += saar.o
 
 # 3rd Party Dev Platforms
index 9041340fee1db17cdb6aa670ba43a2457a8193bf..21e188901935fc4f5e4c6b56b58161ed40ac5ab9 100644 (file)
@@ -68,42 +68,6 @@ static unsigned long balloon3_pin_config[] __initdata = {
 
        /* Reset, configured as GPIO wakeup source */
        GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
-
-       /* LEDs */
-       GPIO9_GPIO,     /* NAND activity LED */
-       GPIO10_GPIO,    /* Heartbeat LED */
-
-       /* AC97 */
-       GPIO28_AC97_BITCLK,
-       GPIO29_AC97_SDATA_IN_0,
-       GPIO30_AC97_SDATA_OUT,
-       GPIO31_AC97_SYNC,
-       GPIO113_AC97_nRESET,
-       GPIO95_GPIO,
-
-       /* MMC */
-       GPIO32_MMC_CLK,
-       GPIO92_MMC_DAT_0,
-       GPIO109_MMC_DAT_1,
-       GPIO110_MMC_DAT_2,
-       GPIO111_MMC_DAT_3,
-       GPIO112_MMC_CMD,
-
-       /* USB Host */
-       GPIO88_USBH1_PWR,
-       GPIO89_USBH1_PEN,
-
-       /* PC Card */
-       GPIO48_nPOE,
-       GPIO49_nPWE,
-       GPIO50_nPIOR,
-       GPIO51_nPIOW,
-       GPIO85_nPCE_1,
-       GPIO54_nPCE_2,
-       GPIO79_PSKTSEL,
-       GPIO55_nPREG,
-       GPIO56_nPWAIT,
-       GPIO57_nIOIS16,
 };
 
 /******************************************************************************
@@ -131,6 +95,34 @@ int __init parse_balloon3_features(char *arg)
 }
 early_param("balloon3_features", parse_balloon3_features);
 
+/******************************************************************************
+ * Compact Flash slot
+ ******************************************************************************/
+#if    defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE)
+static unsigned long balloon3_cf_pin_config[] __initdata = {
+       GPIO48_nPOE,
+       GPIO49_nPWE,
+       GPIO50_nPIOR,
+       GPIO51_nPIOW,
+       GPIO85_nPCE_1,
+       GPIO54_nPCE_2,
+       GPIO79_PSKTSEL,
+       GPIO55_nPREG,
+       GPIO56_nPWAIT,
+       GPIO57_nIOIS16,
+};
+
+static void __init balloon3_cf_init(void)
+{
+       if (!balloon3_has(BALLOON3_FEATURE_CF))
+               return;
+
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config));
+}
+#else
+static inline void balloon3_cf_init(void) {}
+#endif
+
 /******************************************************************************
  * NOR Flash
  ******************************************************************************/
@@ -179,6 +171,15 @@ static inline void balloon3_nor_init(void) {}
  ******************************************************************************/
 #if    defined(CONFIG_TOUCHSCREEN_UCB1400) || \
        defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
+static unsigned long balloon3_ac97_pin_config[] __initdata = {
+       GPIO28_AC97_BITCLK,
+       GPIO29_AC97_SDATA_IN_0,
+       GPIO30_AC97_SDATA_OUT,
+       GPIO31_AC97_SYNC,
+       GPIO113_AC97_nRESET,
+       GPIO95_GPIO,
+};
+
 static struct ucb1400_pdata vpac270_ucb1400_pdata = {
        .irq            = IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ),
 };
@@ -197,6 +198,7 @@ static void __init balloon3_ts_init(void)
        if (!balloon3_has(BALLOON3_FEATURE_AUDIO))
                return;
 
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config));
        pxa_set_ac97_info(NULL);
        platform_device_register(&balloon3_ucb1400_device);
 }
@@ -208,6 +210,11 @@ static inline void balloon3_ts_init(void) {}
  * Framebuffer
  ******************************************************************************/
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static unsigned long balloon3_lcd_pin_config[] __initdata = {
+       GPIOxx_LCD_TFT_16BPP,
+       GPIO99_GPIO,
+};
+
 static struct pxafb_mode_info balloon3_lcd_modes[] = {
        {
                .pixclock               = 38000,
@@ -242,6 +249,8 @@ static void __init balloon3_lcd_init(void)
        if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY))
                return;
 
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config));
+
        ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON");
        if (ret) {
                pr_err("Requesting BKL-ON GPIO failed!\n");
@@ -271,6 +280,15 @@ static inline void balloon3_lcd_init(void) {}
  * SD/MMC card controller
  ******************************************************************************/
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static unsigned long balloon3_mmc_pin_config[] __initdata = {
+       GPIO32_MMC_CLK,
+       GPIO92_MMC_DAT_0,
+       GPIO109_MMC_DAT_1,
+       GPIO110_MMC_DAT_2,
+       GPIO111_MMC_DAT_3,
+       GPIO112_MMC_CMD,
+};
+
 static struct pxamci_platform_data balloon3_mci_platform_data = {
        .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
        .gpio_card_detect       = -1,
@@ -281,6 +299,7 @@ static struct pxamci_platform_data balloon3_mci_platform_data = {
 
 static void __init balloon3_mmc_init(void)
 {
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config));
        pxa_set_mci_info(&balloon3_mci_platform_data);
 }
 #else
@@ -339,6 +358,11 @@ static inline void balloon3_irda_init(void) {}
  * USB Host
  ******************************************************************************/
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static unsigned long balloon3_uhc_pin_config[] __initdata = {
+       GPIO88_USBH1_PWR,
+       GPIO89_USBH1_PEN,
+};
+
 static struct pxaohci_platform_data balloon3_ohci_info = {
        .port_mode      = PMM_PERPORT_MODE,
        .flags          = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
@@ -348,6 +372,7 @@ static void __init balloon3_uhc_init(void)
 {
        if (!balloon3_has(BALLOON3_FEATURE_OHCI))
                return;
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config));
        pxa_set_ohci_info(&balloon3_ohci_info);
 }
 #else
@@ -358,6 +383,11 @@ static inline void balloon3_uhc_init(void) {}
  * LEDs
  ******************************************************************************/
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static unsigned long balloon3_led_pin_config[] __initdata = {
+       GPIO9_GPIO,     /* NAND activity LED */
+       GPIO10_GPIO,    /* Heartbeat LED */
+};
+
 struct gpio_led balloon3_gpio_leds[] = {
        {
                .name                   = "balloon3:green:idle",
@@ -436,6 +466,7 @@ static struct platform_device balloon3_pcf_leds = {
 
 static void __init balloon3_leds_init(void)
 {
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config));
        platform_device_register(&balloon3_leds);
        platform_device_register(&balloon3_pcf_leds);
 }
@@ -757,6 +788,7 @@ static void __init balloon3_init(void)
        balloon3_ts_init();
        balloon3_udc_init();
        balloon3_uhc_init();
+       balloon3_cf_init();
 }
 
 static struct map_desc balloon3_io_desc[] __initdata = {
@@ -776,9 +808,8 @@ static void __init balloon3_map_io(void)
 
 MACHINE_START(BALLOON3, "Balloon3")
        /* Maintainer: Nick Bane. */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = balloon3_map_io,
+       .nr_irqs        = BALLOON3_NR_IRQS,
        .init_irq       = balloon3_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = balloon3_init,
index aae544631a8bf223522b1d645637a1a391828ac7..4bd7a3cda48c12b07932a36ffcaa473919f56224 100644 (file)
@@ -148,9 +148,7 @@ static void __init capc7117_init(void)
 
 MACHINE_START(CAPC7117,
              "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
-       .phys_io = 0x40000000,
        .boot_params = 0xa0000100,
-       .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io = pxa_map_io,
        .init_irq = pxa3xx_init_irq,
        .timer = &pxa_timer,
index bff6e78f033d250d803c9a9bc82474ac3804b317..ac5598ce97241f7d29947ee434d539c5c2109fe6 100644 (file)
@@ -33,6 +33,9 @@
 extern void cmx255_init(void);
 extern void cmx270_init(void);
 
+/* reserve IRQs for IT8152 */
+#define CMX2XX_NR_IRQS         (IRQ_BOARD_START + 40)
+
 /* virtual addresses for statically mapped regions */
 #define CMX2XX_VIRT_BASE       (0xe8000000)
 #define CMX2XX_IT8152_VIRT     (CMX2XX_VIRT_BASE)
@@ -511,9 +514,8 @@ static void __init cmx2xx_map_io(void)
 
 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
        .boot_params    = 0xa0000100,
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = cmx2xx_map_io,
+       .nr_irqs        = CMX2XX_NR_IRQS,
        .init_irq       = cmx2xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = cmx2xx_init,
index c70e6c2f4e7c47daf9c8a595bf6fafd11f2971d7..922b1075b9de75ea38d2070cbedaf4f0a16a5d2b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 
 #include <linux/gpio.h>
 #include <linux/dm9000.h>
@@ -50,6 +51,7 @@
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <mach/audio.h>
+#include <mach/pxa3xx-u2d.h>
 
 #include <asm/mach/map.h>
 
@@ -68,6 +70,8 @@
 #define GPIO97_RTC_RD          (97)
 #define GPIO98_RTC_IO          (98)
 
+#define GPIO_ULPI_PHY_RST      (127)
+
 static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
        /* LCD */
        GPIO54_LCD_LDD_0,
@@ -472,6 +476,78 @@ static void __init cm_x300_init_mmc(void)
 static inline void cm_x300_init_mmc(void) {}
 #endif
 
+#if defined(CONFIG_PXA310_ULPI)
+static struct clk *pout_clk;
+
+static int cm_x300_ulpi_phy_reset(void)
+{
+       int err;
+
+       /* reset the PHY */
+       err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset");
+       if (err) {
+               pr_err("%s: failed to request ULPI reset GPIO: %d\n",
+                      __func__, err);
+               return err;
+       }
+
+       gpio_direction_output(GPIO_ULPI_PHY_RST, 0);
+       msleep(10);
+       gpio_set_value(GPIO_ULPI_PHY_RST, 1);
+       msleep(10);
+
+       gpio_free(GPIO_ULPI_PHY_RST);
+
+       return 0;
+}
+
+static inline int cm_x300_u2d_init(struct device *dev)
+{
+       int err = 0;
+
+       if (cpu_is_pxa310()) {
+               /* CLK_POUT is connected to the ULPI PHY */
+               pout_clk = clk_get(NULL, "CLK_POUT");
+               if (IS_ERR(pout_clk)) {
+                       err = PTR_ERR(pout_clk);
+                       pr_err("%s: failed to get CLK_POUT: %d\n",
+                              __func__, err);
+                       return err;
+               }
+               clk_enable(pout_clk);
+
+               err = cm_x300_ulpi_phy_reset();
+               if (err) {
+                       clk_disable(pout_clk);
+                       clk_put(pout_clk);
+               }
+       }
+
+       return err;
+}
+
+static void cm_x300_u2d_exit(struct device *dev)
+{
+       if (cpu_is_pxa310()) {
+               clk_disable(pout_clk);
+               clk_put(pout_clk);
+       }
+}
+
+static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
+       .ulpi_mode      = ULPI_SER_6PIN,
+       .init           = cm_x300_u2d_init,
+       .exit           = cm_x300_u2d_exit,
+};
+
+static void cm_x300_init_u2d(void)
+{
+       pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
+}
+#else
+static inline void cm_x300_init_u2d(void) {}
+#endif
+
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int cm_x300_ohci_init(struct device *dev)
 {
@@ -754,6 +830,7 @@ static void __init cm_x300_init(void)
        cm_x300_init_da9030();
        cm_x300_init_dm9000();
        cm_x300_init_lcd();
+       cm_x300_init_u2d();
        cm_x300_init_ohci();
        cm_x300_init_mmc();
        cm_x300_init_nand();
@@ -779,9 +856,7 @@ static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index 98673ac6efd0d74f66dc270a67e97e7c874ecf97..bc045100ec159927cdcd1afe84b954c103537742 100644 (file)
@@ -207,8 +207,6 @@ static void __init colibri_pxa270_income_init(void)
 }
 
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa270_init,
        .map_io         = pxa_map_io,
@@ -217,8 +215,6 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
 MACHINE_END
 
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .init_machine   = colibri_pxa270_income_init,
        .map_io         = pxa_map_io,
index 40b6ac2de876cf8dcc4c0328b72b086e15253eb8..a70b256591e673414f0499c3bbe6a0b9e64b923e 100644 (file)
@@ -186,8 +186,6 @@ void __init colibri_pxa300_init(void)
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa300_init,
        .map_io         = pxa_map_io,
index 99e850d847103eab977badf1d7a2491df942f687..ca5f29e2e9cd412fcb3ca010603ffd3019898190 100644 (file)
@@ -255,8 +255,6 @@ void __init colibri_pxa320_init(void)
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa320_init,
        .map_io         = pxa_map_io,
index 3fb0fc09908076b24ed5f7b0200da4afcda12788..821229acabe6333ff3787b14ac9e8892c1c6811c 100644 (file)
@@ -720,8 +720,6 @@ static void __init fixup_corgi(struct machine_desc *desc,
 
 #ifdef CONFIG_MACH_CORGI
 MACHINE_START(CORGI, "SHARP Corgi")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
@@ -732,8 +730,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_SHEPHERD
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
@@ -744,8 +740,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_HUSKY
 MACHINE_START(HUSKY, "SHARP Husky")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
index 268a9bc6be8a22a4ca0ac4fed742d035753581a3..58093d9e07be44ea482df319c88acb78c0db3975 100644 (file)
@@ -312,8 +312,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
        freqs.cpu = policy->cpu;
 
        if (freq_debug)
-               pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, "
-                        "(SDRAM %d Mhz)\n",
+               pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
                         freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
                         (new_freq_mem / 2000) : (new_freq_mem / 1000));
 
@@ -398,7 +397,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
        return 0;
 }
 
-static __init int pxa_cpufreq_init(struct cpufreq_policy *policy)
+static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 {
        int i;
        unsigned int freq;
index 27fa329d9a8b7a5677c2cf75e25900797130eb46..88fbec05ec50f09e1724e431e761b1b9b4f1a261 100644 (file)
@@ -159,7 +159,7 @@ static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
 
 static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
 {
-       return get_clk_frequency_khz(0);
+       return pxa3xx_get_clk_frequency_khz(0);
 }
 
 static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
@@ -204,7 +204,7 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
        return 0;
 }
 
-static __init int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
+static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
 {
        int ret = -EINVAL;
 
@@ -212,7 +212,8 @@ static __init int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
        policy->cpuinfo.min_freq = 104000;
        policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-       policy->cur = policy->min = policy->max = get_clk_frequency_khz(0);
+       policy->max = pxa3xx_get_clk_frequency_khz(0);
+       policy->cur = policy->min = policy->max;
 
        if (cpu_is_pxa300() || cpu_is_pxa310())
                ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
index 91fd4fea6a5417fc515ff1beecdfc7a6b545823b..57cacaff194db96ea3f83590517e9339efd6002e 100644 (file)
@@ -272,9 +272,7 @@ static void __init csb726_init(void)
 }
 
 MACHINE_START(CSB726, "Cogent CSB726")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .init_machine   = csb726_init,
index 65447dc736c2fd5b3f0fd4e3ce4c46c3c9711dc3..08b410343870ae2518afb4303110d5807dfc12d1 100644 (file)
@@ -6,11 +6,12 @@
 
 #include <asm/pmu.h>
 #include <mach/udc.h>
+#include <mach/pxa3xx-u2d.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
@@ -134,6 +135,33 @@ struct platform_device pxa27x_device_udc = {
        }
 };
 
+#ifdef CONFIG_PXA3xx
+static struct resource pxa3xx_u2d_resources[] = {
+       [0] = {
+               .start  = 0x54100000,
+               .end    = 0x54100fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_USB2,
+               .end    = IRQ_USB2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device pxa3xx_device_u2d = {
+       .name           = "pxa3xx-u2d",
+       .id             = -1,
+       .resource       = pxa3xx_u2d_resources,
+       .num_resources  = ARRAY_SIZE(pxa3xx_u2d_resources),
+};
+
+void __init pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info)
+{
+       pxa_register_device(&pxa3xx_device_u2d, info);
+}
+#endif /* CONFIG_PXA3xx */
+
 static struct resource pxafb_resources[] = {
        [0] = {
                .start  = 0x44000000,
index 50353ea49ba455bc856d371f1e6170861337f8c4..715e8bd02e248930e449c4e6c2c169054c837c6e 100644 (file)
@@ -4,6 +4,7 @@ extern struct platform_device pxa3xx_device_mci2;
 extern struct platform_device pxa3xx_device_mci3;
 extern struct platform_device pxa25x_device_udc;
 extern struct platform_device pxa27x_device_udc;
+extern struct platform_device pxa3xx_device_u2d;
 extern struct platform_device pxa_device_fb;
 extern struct platform_device pxa_device_ffuart;
 extern struct platform_device pxa_device_btuart;
index 0517c17978f3103d96e51954237801fbf34088a0..ab48bb81b570d518f8a84f419ed2e85a857e3c13 100644 (file)
@@ -43,7 +43,7 @@
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/pxa2xx_spi.h>
@@ -1301,8 +1301,6 @@ static void __init em_x270_init(void)
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
        .boot_params    = 0xa0000100,
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -1311,8 +1309,6 @@ MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
        .boot_params    = 0xa0000100,
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
index 349212a1cbd3ab741a60412c431ab43fd1b17330..b25690ccadc4baeebb7da03985bcbf69d66ae3e4 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
+#include <mach/eseries-irq.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/udc.h>
@@ -179,10 +180,9 @@ static void __init e330_init(void)
 
 MACHINE_START(E330, "Toshiba e330")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e330_init,
@@ -229,10 +229,9 @@ static void __init e350_init(void)
 
 MACHINE_START(E350, "Toshiba e350")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e350_init,
@@ -352,10 +351,9 @@ static void __init e400_init(void)
 
 MACHINE_START(E400, "Toshiba e400")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e400_init,
@@ -541,10 +539,9 @@ static void __init e740_init(void)
 
 MACHINE_START(E740, "Toshiba e740")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e740_init,
@@ -733,10 +730,9 @@ static void __init e750_init(void)
 
 MACHINE_START(E750, "Toshiba e750")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e750_init,
@@ -929,10 +925,9 @@ static void __init e800_init(void)
 
 MACHINE_START(E800, "Toshiba e800")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e800_init,
index 626c82b1397031bef376ddf1acbfd5feb8a9fe41..80a9352d43f31017c26a079d29849bb0840beff7 100644 (file)
 #include <mach/ohci.h>
 #include <plat/i2c.h>
 #include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
 
 #include "devices.h"
 #include "generic.h"
 
+#define EZX_NR_IRQS                    (IRQ_BOARD_START + 24)
+
 #define GPIO12_A780_FLIP_LID           12
 #define GPIO15_A1200_FLIP_LID          15
 #define GPIO15_A910_FLIP_LID           15
@@ -796,10 +798,9 @@ static void __init a780_init(void)
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a780_init,
@@ -862,10 +863,9 @@ static void __init e680_init(void)
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e680_init,
@@ -928,10 +928,9 @@ static void __init a1200_init(void)
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a1200_init,
@@ -1120,10 +1119,9 @@ static void __init a910_init(void)
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a910_init,
@@ -1186,10 +1184,9 @@ static void __init e6_init(void)
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e6_init,
@@ -1226,10 +1223,9 @@ static void __init e2_init(void)
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
+       .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e2_init,
index baabb3ce088e842669bfd70e3a60e56489fcbe00..6451e9c3a93fba45a7a1b1d39693dc98f94a40d2 100644 (file)
@@ -66,8 +66,7 @@ unsigned int get_clk_frequency_khz(int info)
                return pxa25x_get_clk_frequency_khz(info);
        else if (cpu_is_pxa27x())
                return pxa27x_get_clk_frequency_khz(info);
-       else
-               return pxa3xx_get_clk_frequency_khz(info);
+       return 0;
 }
 EXPORT_SYMBOL(get_clk_frequency_khz);
 
@@ -80,8 +79,7 @@ unsigned int get_memclk_frequency_10khz(void)
                return pxa25x_get_memclk_frequency_10khz();
        else if (cpu_is_pxa27x())
                return pxa27x_get_memclk_frequency_10khz();
-       else
-               return pxa3xx_get_memclk_frequency_10khz();
+       return 0;
 }
 EXPORT_SYMBOL(get_memclk_frequency_10khz);
 
index c6305c5b8a72c1497ee05aee42d7795b07513c94..4b1ad2769ed70387fad13ba9e9a775f6e1ce2466 100644 (file)
@@ -54,11 +54,9 @@ static inline void pxa2xx_clear_reset_status(unsigned int mask) {}
 
 #ifdef CONFIG_PXA3xx
 extern unsigned pxa3xx_get_clk_frequency_khz(int);
-extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
 extern void pxa3xx_clear_reset_status(unsigned int);
 #else
 #define pxa3xx_get_clk_frequency_khz(x)                (0)
-#define pxa3xx_get_memclk_frequency_10khz()    (0)
 static inline void pxa3xx_clear_reset_status(unsigned int mask) {}
 #endif
 
index 96c3451291358f74ef6fcf288dc9d489a397ef0a..1e2a9a13aec143bbb34cdf783bbc8a1a82a5571a 100644 (file)
@@ -224,9 +224,7 @@ static void __init gumstix_init(void)
 }
 
 MACHINE_START(GUMSTIX, "Gumstix")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100, /* match u-boot bi_boot_params */
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
index c1cab0871c996de961920257a3f5140f2af98a0e..7057a1f46db4ed9a35094563216137c80708ade4 100644 (file)
@@ -201,8 +201,6 @@ static void __init h5000_init(void)
 }
 
 MACHINE_START(H5400, "HP iPAQ H5000")
-       .phys_io = 0x40000000,
-       .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params = 0xa0000100,
        .map_io = pxa_map_io,
        .init_irq = pxa25x_init_irq,
index f9a2e4b0f090aa3661b701bb70ef1f93e176ff04..01b7f07ebad291d96ceb12cbbf4a5b8cdd9ac77b 100644 (file)
@@ -159,8 +159,6 @@ static void __init himalaya_init(void)
 
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
-       .phys_io = 0x40000000,
-       .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params = 0xa0000100,
        .map_io = pxa_map_io,
        .init_irq = pxa25x_init_irq,
index 848c861dd23f20acbbd121d32a9e0721acbee45c..76d93a25bab62fa33d09cb48965ba1f6267e59a4 100644 (file)
@@ -870,10 +870,9 @@ static void __init hx4700_init(void)
 }
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
-       .phys_io      = 0x40000000,
-       .io_pg_offst  = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params  = 0xa0000100,
        .map_io       = pxa_map_io,
+       .nr_irqs      = HX4700_NR_IRQS,
        .init_irq     = pxa27x_init_irq,
        .init_machine = hx4700_init,
        .timer        = &pxa_timer,
index 5ccb0ceff6c4160f153d795b1bbcfcf4e035facb..d51ee3d25e7027c8386635940f93a56f89fc7cbf 100644 (file)
@@ -191,9 +191,7 @@ static void __init icontrol_init(void)
 }
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index bc78c4dc0c66d601d79e796bd1c998544677b5b6..e773dceeabc6c8fdc3f5f627147f236118d8a6fd 100644 (file)
@@ -194,8 +194,6 @@ static void __init idp_map_io(void)
 
 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        /* Maintainer: Vibren Technologies */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = idp_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
index eec92e6fd7cf804f3ba611325cdbc491da3dcf96..561562b4360b7b22477373c8d7fab7a6eb715478 100644 (file)
@@ -174,6 +174,8 @@ enum balloon3_features {
 #define BALLOON3_CODEC_IRQ     IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
 #define BALLOON3_S0_CD_IRQ     IRQ_GPIO(BALLOON3_GPIO_S0_CD)
 
+#define BALLOON3_NR_IRQS       (IRQ_BOARD_START + 4)
+
 extern int balloon3_has(enum balloon3_features feature);
 
 #endif
index 01cf81393fe2d5e25787ea87b375aa510e754f2c..7d5c75125d658cd6dcb26e11ed6640254ee13382 100644 (file)
 
 #include "hardware.h"
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x40000000                @ physical
-               movne   \rx, #io_p2v(0x40000000)        @ virtual
-               orr     \rx, \rx, #0x00100000
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00100000
+               orr     \rv, \rp, #io_p2v(0x40000000)   @ virtual
+               orr     \rp, \rp, #0x40000000           @ physical
                .endm
 
 #define UART_SHIFT     2
index f2a93d5e31d303034074425b2735e71f37227bf1..de292b269c63ead3a54c29acc920d5cab1786582 100644 (file)
@@ -25,3 +25,4 @@
 #define TMIO_SD_IRQ     IRQ_TMIO(1)
 #define TMIO_USB_IRQ    IRQ_TMIO(2)
 
+#define ESERIES_NR_IRQS        (IRQ_BOARD_START + 16)
index 7f64d24cd5648df0790c6ec570322195d92359e5..814f1458a06a52ec5af6b37643ca4b6db602dd55 100644 (file)
  * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
  * == 0x3 for pxa300/pxa310/pxa320
  */
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
 #define __cpu_is_pxa2xx(id)                            \
        ({                                              \
                unsigned int _id = (id) >> 13 & 0x7;    \
                _id <= 0x2;                             \
         })
+#else
+#define __cpu_is_pxa2xx(id)    (0)
+#endif
 
+#ifdef CONFIG_PXA3xx
 #define __cpu_is_pxa3xx(id)                            \
        ({                                              \
                unsigned int _id = (id) >> 13 & 0x7;    \
                _id == 0x3;                             \
         })
+#else
+#define __cpu_is_pxa3xx(id)    (0)
+#endif
 
+#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935)
 #define __cpu_is_pxa93x(id)                            \
        ({                                              \
                unsigned int _id = (id) >> 4 & 0xfff;   \
                _id == 0x683 || _id == 0x693;           \
         })
+#else
+#define __cpu_is_pxa93x(id)    (0)
+#endif
 
 #define cpu_is_pxa2xx()                                        \
        ({                                              \
@@ -309,7 +321,7 @@ extern unsigned long get_clock_tick_rate(void);
 #define PCIBIOS_MIN_IO         0
 #define PCIBIOS_MIN_MEM                0
 #define pcibios_assign_all_busses()    1
+#define ARCH_HAS_DMA_SET_COHERENT_MASK
 #endif
 
-
 #endif  /* _ASM_ARCH_HARDWARE_H */
index 9eaeed1f87f1fad6f8754dfa736473ecf113f33a..37408449ec25e023264ae8852fc3bec9feb381a6 100644 (file)
@@ -17,6 +17,7 @@
 
 #define HX4700_ASIC3_GPIO_BASE NR_BUILTIN_GPIO
 #define HX4700_EGPIO_BASE      (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
+#define HX4700_NR_IRQS         (IRQ_BOARD_START + 70)
 
 /*
  * PXA GPIOs
index 262691fb97d86c2ce36de96d7e180a35b4906298..fdca3be47d9bb1fdaa70d8b7b9c112c34b32c495 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <mach/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
index ffc8314520f2e109b5db96bfebdfb97096f90d90..d372caa75dc737d4ca51f4ddcc34c64ac530bd43 100644 (file)
 /*
  * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
- * these.  There will be 16 IRQs by default.  If it is not enough,
- * IRQ_BOARD_END is allowed be customized for each board, but keep
- * the numbers within sensible limits and in descending order, so
- * when multiple config options are selected, the maximum will be
- * used.
+ * these.
+ * By default, no board IRQ is reserved. It should be finished in
+ * custom board since sparse IRQ is already enabled.
  */
 #define IRQ_BOARD_START                (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 
-#if defined(CONFIG_MACH_H4700)
-#define IRQ_BOARD_END          (IRQ_BOARD_START + 70)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define IRQ_BOARD_END          (IRQ_BOARD_START + 32)
-#elif defined(CONFIG_PXA_EZX)
-#define IRQ_BOARD_END          (IRQ_BOARD_START + 23)
-#else
-#define IRQ_BOARD_END          (IRQ_BOARD_START + 16)
-#endif
-
-/*
- * Figure out the MAX IRQ number.
- *
- * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
- * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
- * Otherwise, we have the standard IRQs only.
- */
-#ifdef CONFIG_SA1111
-#define NR_IRQS                        (IRQ_BOARD_END + 55)
-#elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
-#define NR_IRQS                        (IRQ_BOARD_END)
-#else
 #define NR_IRQS                        (IRQ_BOARD_START)
-#endif
-
-/* add IT8152 IRQs beyond BOARD_END */
-#ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_LAST_IRQ         (IRQ_BOARD_END + 40)
-
-#if NR_IRQS < (IT8152_LAST_IRQ+1)
-#undef NR_IRQS
-#define NR_IRQS (IT8152_LAST_IRQ+1)
-#endif
-
-#endif /* CONFIG_PCI_HOST_ITE8152 */
 
 #endif /* __ASM_MACH_IRQS_H */
index 6c9b21c5132254dad261aa1dba4097293248684d..2a5726c15e0e446f855f857d4e773a6785ba8486 100644 (file)
@@ -10,4 +10,6 @@
 #define EXT0_GPIO_BASE (NR_BUILTIN_GPIO)
 #define EXT0_GPIO(x)   (EXT0_GPIO_BASE + (x))
 
+#define LITTLETON_NR_IRQS      (IRQ_BOARD_START + 8)
+
 #endif /* __ASM_ARCH_LITTLETON_H */
index 0e6440c81683d0c18548bdd863016fa9444fe64e..cd070092b6eb708b1397fa82ba3e2e05b6104bf0 100644 (file)
@@ -38,5 +38,6 @@
 #define LPD270_USBC_IRQ                LPD270_IRQ(2)
 #define LPD270_ETHERNET_IRQ    LPD270_IRQ(3)
 #define LPD270_AC97_IRQ                LPD270_IRQ(4)
+#define LPD270_NR_IRQS         (IRQ_BOARD_START + 5)
 
 #endif
index a0d4247f08fc56aedcb845bb1c8403d64f64d11b..2a086e8373eb7bf1104892784aba7a5236a3bd5b 100644 (file)
@@ -45,6 +45,9 @@
 #define LUBBOCK_USB_DISC_IRQ   LUBBOCK_IRQ(6)  /* usb disconnect */
 #define LUBBOCK_LAST_IRQ       LUBBOCK_IRQ(6)
 
+#define LUBBOCK_SA1111_IRQ_BASE        (IRQ_BOARD_START + 16)
+#define LUBBOCK_NR_IRQS                (IRQ_BOARD_START + 16 + 55)
+
 #ifndef __ASSEMBLY__
 extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set);
 #endif
index 20ef37d4a9a75b2567e73791d1ba8ee5056ae563..0a2efcf7947c5c4da26e7140f4256387f3387769 100644 (file)
@@ -71,6 +71,8 @@
 #define IRQ_MAGICIAN_BT                (IRQ_BOARD_START + 2)
 #define IRQ_MAGICIAN_VBUS      (IRQ_BOARD_START + 3)
 
+#define MAGICIAN_NR_IRQS       (IRQ_BOARD_START + 8)
+
 /*
  * CPLD EGPIOs
  */
index 86e623abd64d6404e3d39848d5fee8b1a50682d4..4c2d11cd824dda4415d1ad74af1a368ffdd9b439 100644 (file)
 #define MAINSTONE_S1_STSCHG_IRQ        MAINSTONE_IRQ(14)
 #define MAINSTONE_S1_IRQ       MAINSTONE_IRQ(15)
 
+#define MAINSTONE_NR_IRQS      (IRQ_BOARD_START + 16)
+
 #endif
index 7139e0dc26d16062304bd72beca1f339e61899e7..4e1287070d219c32235aebadfbf2d97df3d059fb 100644 (file)
 #define GPIO46_CI_DD_7         MFP_CFG_DRV(GPIO46, AF0, DS04X)
 #define GPIO47_CI_DD_8         MFP_CFG_DRV(GPIO47, AF1, DS04X)
 #define GPIO48_CI_DD_9         MFP_CFG_DRV(GPIO48, AF1, DS04X)
-#define GPIO52_CI_HSYNC                MFP_CFG_DRV(GPIO52, AF0, DS04X)
-#define GPIO51_CI_VSYNC                MFP_CFG_DRV(GPIO51, AF0, DS04X)
 #define GPIO49_CI_MCLK         MFP_CFG_DRV(GPIO49, AF0, DS04X)
 #define GPIO50_CI_PCLK         MFP_CFG_DRV(GPIO50, AF0, DS04X)
+#define GPIO51_CI_HSYNC                MFP_CFG_DRV(GPIO51, AF0, DS04X)
+#define GPIO52_CI_VSYNC                MFP_CFG_DRV(GPIO52, AF0, DS04X)
 
 /* KEYPAD */
 #define GPIO3_KP_DKIN_6                MFP_CFG_LPM(GPIO3,   AF2, FLOAT)
index 0d119d3b922143211b12350244c3087209ba3cbd..04f7c97044f3bf4c1a8798b87bf4e86b31086975 100644 (file)
@@ -69,6 +69,7 @@
 #define nBE0_GPIO_60           MFP_CFG(nBE0, AF0)
 #define nBE1_GPIO_61           MFP_CFG(nBE1, AF0)
 #define RDY_GPIO_62            MFP_CFG(RDY, AF0)
+#define PMIC_INT_GPIO83                MFP_CFG_LPM(PMIC_INT, AF0, PULL_HIGH)
 
 /* Chip Select */
 #define DF_nCS0_nCS2           MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH)
@@ -92,6 +93,9 @@
 #define GPIO63_CI2C_SCL                MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH)
 #define GPIO64_CI2C_SDA                MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH)
 
+#define GPIO73_CI2C_SCL                MFP_CFG_LPM(GPIO73, AF1, PULL_HIGH)
+#define GPIO74_CI2C_SDA                MFP_CFG_LPM(GPIO74, AF1, PULL_HIGH)
+
 #define GPIO77_CI2C_SCL                MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH)
 #define GPIO78_CI2C_SDA                MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH)
 
 #define GPIO69_UART1_CTS       MFP_CFG(GPIO69, AF2)
 #define GPIO70_UART1_RTS       MFP_CFG(GPIO70, AF2)
 
+#define GPIO53_UART1_TXD       MFP_CFG(GPIO53, AF2)
+#define GPIO54_UART1_RXD       MFP_CFG(GPIO54, AF2)
+
 /* UART2 - BTUART */
 #define GPIO91_UART2_RXD       MFP_CFG(GPIO91, AF1)
 #define GPIO92_UART2_TXD       MFP_CFG(GPIO92, AF1)
index 04083263167ed5ad0ab84a014cc14420c4175ffd..4bac588478a898ee6dae6107a9cd44fc7d365c69 100644 (file)
@@ -30,6 +30,8 @@
 #define PCM027_MMCDET_IRQ      PCM027_IRQ(2)
 #define PCM027_PM_5V_IRQ       PCM027_IRQ(3)
 
+#define PCM027_NR_IRQS         (IRQ_BOARD_START + 32)
+
 /* I2C RTC */
 #define PCM027_RTC_IRQ_GPIO    0
 #define PCM027_RTC_IRQ         IRQ_GPIO(PCM027_RTC_IRQ_GPIO)
index 0b3e6d051c6425d86238473ab31f25702cd29c92..83d1cfd00fc9f7d05e75c4a0c94383c479407179 100644 (file)
@@ -85,6 +85,8 @@
 #define POODLE_LOCOMO_GPIO_232VCC_ON   LOCOMO_GPIO(12)
 #define POODLE_LOCOMO_GPIO_JK_B        LOCOMO_GPIO(13)
 
+#define POODLE_NR_IRQS         (IRQ_BOARD_START + 4)   /* 4 for LoCoMo */
+
 extern struct platform_device poodle_locomo_device;
 
 #endif /* __ASM_ARCH_POODLE_H  */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
new file mode 100644 (file)
index 0000000..9d82cb6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * PXA3xx U2D header
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * 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.
+ */
+#ifndef __PXA310_U2D__
+#define __PXA310_U2D__
+
+#include <linux/usb/ulpi.h>
+
+struct pxa3xx_u2d_platform_data {
+
+#define ULPI_SER_6PIN  (1 << 0)
+#define ULPI_SER_3PIN  (1 << 1)
+       unsigned int ulpi_mode;
+
+       int (*init)(struct device *);
+       void (*exit)(struct device *);
+};
+
+
+/* Start PXA3xx U2D host */
+int pxa3xx_u2d_start_hc(struct usb_bus *host);
+/* Stop PXA3xx U2D host */
+void pxa3xx_u2d_stop_hc(struct usb_bus *host);
+
+extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
+
+#endif /* __PXA310_U2D__ */
index 1bbd1f2e4beb3065ff75d4204d375ac88dc10847..1272c4b56ceb8de05875e75310df11b86b377982 100644 (file)
@@ -20,6 +20,7 @@
 /* Jacket Scoop */
 #define TOSA_SCOOP_PHYS        (PXA_CS5_PHYS + 0x00800000)
 
+#define TOSA_NR_IRQS           (IRQ_BOARD_START + TC6393XB_NR_IRQS)
 /*
  * SCOOP2 internal GPIOs
  */
index 6e119976003e72979af443fb07e2b82c9441f74f..faa408ab7ad72f38c6951849008c86397b866c99 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _MACH_ZEUS_H
 #define _MACH_ZEUS_H
 
+#define ZEUS_NR_IRQS           (IRQ_BOARD_START + 48)
+
 /* Physical addresses */
 #define ZEUS_FLASH_PHYS                PXA_CS0_PHYS
 #define ZEUS_ETH0_PHYS         PXA_CS1_PHYS
index 9edf645368d65989376ca144a2d49a1fbc2d0f74..ea24998b923c27aed8b13d7aa091368b2f47a7ef 100644 (file)
@@ -5,6 +5,8 @@
 
 #define EXT_GPIO(x)            (128 + (x))
 
+#define ZYLONITE_NR_IRQS       (IRQ_BOARD_START + 32)
+
 /* the following variables are processor specific and initialized
  * by the corresponding zylonite_pxa3xx_init()
  */
index 9b9046185b00e3e8c2c7e47b13fd37c478f74640..41aa89e3577255ecfbec44bfb2cfe4a70540eeab 100644 (file)
@@ -43,7 +43,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
@@ -437,10 +437,9 @@ static void __init littleton_init(void)
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
+       .nr_irqs        = LITTLETON_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = littleton_init,
index d279507fc748275dfff6670544699cf6464eee7f..623af0232a5405d8eb29ab5e3d85df5c028fa42a 100644 (file)
@@ -505,10 +505,9 @@ static void __init lpd270_map_io(void)
 
 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
        /* Maintainer: Peter Barada */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = lpd270_map_io,
+       .nr_irqs        = LPD270_NR_IRQS,
        .init_irq       = lpd270_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = lpd270_init,
index 330c3282856e620ec879563e16655c6d56d6d2a9..1499493cd070b4636f5eb7bb7abc971cd35f385c 100644 (file)
@@ -229,7 +229,7 @@ static struct resource sa1111_resources[] = {
 };
 
 static struct sa1111_platform_data sa1111_info = {
-       .irq_base       = IRQ_BOARD_END,
+       .irq_base       = LUBBOCK_SA1111_IRQ_BASE,
 };
 
 static struct platform_device sa1111_device = {
@@ -557,9 +557,8 @@ static void __init lubbock_map_io(void)
 
 MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
        /* Maintainer: MontaVista Software Inc. */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = lubbock_map_io,
+       .nr_irqs        = LUBBOCK_NR_IRQS,
        .init_irq       = lubbock_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = lubbock_init,
index e81dd0c8e40dcced02770cb7dc57c4ca4634102b..90663760307aac11f4a1e5956ba3d7a1212ad41f 100644 (file)
@@ -764,10 +764,9 @@ static void __init magician_init(void)
 
 
 MACHINE_START(MAGICIAN, "HTC Magician")
-       .phys_io = 0x40000000,
-       .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params = 0xa0000100,
        .map_io = pxa_map_io,
+       .nr_irqs = MAGICIAN_NR_IRQS,
        .init_irq = pxa27x_init_irq,
        .init_machine = magician_init,
        .timer = &pxa_timer,
index 5543c64da9efbaedf903d8eaff3904616f90bd7e..a980a5c93e49c71e88ff256eefe6715f96d9e965 100644 (file)
@@ -50,7 +50,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -624,10 +624,9 @@ static void __init mainstone_map_io(void)
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
        /* Maintainer: MontaVista Software Inc. */
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,   /* BLOB boot parameter setting */
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = mainstone_map_io,
+       .nr_irqs        = MAINSTONE_NR_IRQS,
        .init_irq       = mainstone_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = mainstone_init,
index dc66942ef9ab47d6b911bfde28b70c1c43fb5feb..0c31fabfc7fdd46ee793252bf62fe9be2541cc47 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <mach/pxa27x.h>
 #include <mach/regs-rtc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
@@ -819,8 +819,6 @@ static void mioa701_machine_exit(void)
 }
 
 MACHINE_START(MIOA701, "MIO A701")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = &pxa_map_io,
        .init_irq       = &pxa27x_init_irq,
index 6d4503927a760dded47a892847310a03dd6fd058..116167aaba685f0848410917531eab8690fae1ae 100644 (file)
@@ -92,9 +92,7 @@ static void __init mp900c_init(void)
 
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0220100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .timer          = &pxa_timer,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
index 77ad6d34ab5bc9cd0eb5ce2917a461ce8904c55c..405b92a29793d80fa771546418d78b4bec7094cd 100644 (file)
@@ -469,9 +469,13 @@ static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = {
        },
 };
 
+static struct i2c_pxa_platform_data palm27x_i2c_power_info = {
+       .use_pio        = 1,
+};
+
 void __init palm27x_pmic_init(void)
 {
        i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info));
-       pxa27x_set_i2c_power_info(NULL);
+       pxa27x_set_i2c_power_info(&palm27x_i2c_power_info);
 }
 #endif
index 91038eeafe44c10680741f1266ed770d61755274..ce092c521e6df248c470bfe984e08ddac10a0f03 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
 
@@ -343,8 +343,6 @@ static void __init palmld_init(void)
 }
 
 MACHINE_START(PALMLD, "Palm LifeDrive")
-       .phys_io        = PALMLD_PHYS_IO_START,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = palmld_map_io,
        .init_irq       = pxa27x_init_irq,
index 1c281995f6583faf34faa0e5daa1a5d294a7c3de..862da812cd10a61f5d80bef7290626f06bc88491 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -202,8 +202,6 @@ static void __init palmt5_init(void)
 }
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
-       .phys_io        = PALMT5_PHYS_IO_START,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .reserve        = palmt5_reserve,
index ce1104d1bc17862834f92473cbe304070e996457..2131d5860919f6df9baa74e9765008936ed0ad69 100644 (file)
@@ -412,9 +412,7 @@ static void __init palmtc_init(void)
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
index 93c11a0438d5ac5b04705e67a1a0d5919854c0b4..a9dae7bc35d9ae585299ad4af92904c41ba9f013 100644 (file)
@@ -373,8 +373,6 @@ static void __init palmte2_init(void)
 }
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .init_irq       = pxa25x_init_irq,
index 52defd5e42e520edb4912dbbaf676d6beb15d6d6..00e2d7ba84ed47c5d93c16bd699c62cdff400269 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
@@ -441,8 +441,6 @@ static void __init centro_init(void)
 }
 
 MACHINE_START(TREO680, "Palm Treo 680")
-       .phys_io        = TREO_PHYS_IO_START,
-       .io_pg_offst    = io_p2v(0x40000000),
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .reserve        = treo_reserve,
@@ -452,8 +450,6 @@ MACHINE_START(TREO680, "Palm Treo 680")
 MACHINE_END
 
 MACHINE_START(CENTRO, "Palm Centro 685")
-       .phys_io        = TREO_PHYS_IO_START,
-       .io_pg_offst    = io_p2v(0x40000000),
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .reserve        = treo_reserve,
index 144dc2b6911f784f6630c8966f60d57befc7a330..d2060a1d1d6820bcaf796e1a256a92989ce45365 100644 (file)
@@ -43,7 +43,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -363,8 +363,6 @@ static void __init palmtx_init(void)
 }
 
 MACHINE_START(PALMTX, "Palm T|X")
-       .phys_io        = PALMTX_PHYS_IO_START,
-       .io_pg_offst    = io_p2v(0x40000000),
        .boot_params    = 0xa0000100,
        .map_io         = palmtx_map_io,
        .init_irq       = pxa27x_init_irq,
index 87e4b1044e0b68564c12f27646453123c8eea16c..af6203fbca9caa1a06299490e7aded1e9789e327 100644 (file)
@@ -41,7 +41,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -279,8 +279,6 @@ static void __init palmz72_init(void)
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = io_p2v(0x40000000),
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
index 2190af066470e546a151293801f75b2311ed474c..c77e8f30a439835c2acd1ea809f9130749ac4c02 100644 (file)
@@ -259,9 +259,8 @@ static void __init pcm027_map_io(void)
 MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
        /* Maintainer: Pengutronix */
        .boot_params    = 0xa0000100,
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pcm027_map_io,
+       .nr_irqs        = PCM027_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = pcm027_init,
index 55e8fcde0141df75dccd32b49c6a452e4f2daaea..93a191c889df5fa3d440ee269e28894a4e61dbac 100644 (file)
@@ -465,10 +465,9 @@ static void __init fixup_poodle(struct machine_desc *desc,
 }
 
 MACHINE_START(POODLE, "SHARP Poodle")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_poodle,
        .map_io         = pxa_map_io,
+       .nr_irqs        = POODLE_NR_IRQS,       /* 4 for LoCoMo */
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = poodle_init,
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
new file mode 100644 (file)
index 0000000..ce7168b
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c
+ *
+ * code specific to pxa3xx aka Monahans
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il>
+ *             initial version: pxa310 USB Host mode support
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-u2d.h>
+#include <mach/pxa3xx-u2d.h>
+
+struct pxa3xx_u2d_ulpi {
+       struct clk              *clk;
+       void __iomem            *mmio_base;
+
+       struct otg_transceiver  *otg;
+       unsigned int            ulpi_mode;
+};
+
+static struct pxa3xx_u2d_ulpi *u2d;
+
+static inline u32 u2d_readl(u32 reg)
+{
+       return __raw_readl(u2d->mmio_base + reg);
+}
+
+static inline void u2d_writel(u32 reg, u32 val)
+{
+       __raw_writel(val, u2d->mmio_base + reg);
+}
+
+#if defined(CONFIG_PXA310_ULPI)
+enum u2d_ulpi_phy_mode {
+       SYNCH           = 0,
+       CARKIT          = (1 << 0),
+       SER_3PIN        = (1 << 1),
+       SER_6PIN        = (1 << 2),
+       LOWPOWER        = (1 << 3),
+};
+
+static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void)
+{
+       return (u2d_readl(U2DOTGUSR) >> 28) & 0xF;
+}
+
+static int pxa310_ulpi_poll(void)
+{
+       int timeout = 50000;
+
+       while (timeout--) {
+               if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       pr_warning("%s: ULPI access timed out!\n", __func__);
+
+       return -ETIMEDOUT;
+}
+
+static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+       int err;
+
+       if (pxa310_ulpi_get_phymode() != SYNCH) {
+               pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+               return -EBUSY;
+       }
+
+       u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16));
+       msleep(5);
+
+       err = pxa310_ulpi_poll();
+       if (err)
+               return err;
+
+       return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA;
+}
+
+static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+{
+       if (pxa310_ulpi_get_phymode() != SYNCH) {
+               pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+               return -EBUSY;
+       }
+
+       u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8));
+       msleep(5);
+
+       return pxa310_ulpi_poll();
+}
+
+struct otg_io_access_ops pxa310_ulpi_access_ops = {
+       .read   = pxa310_ulpi_read,
+       .write  = pxa310_ulpi_write,
+};
+
+static void pxa310_otg_transceiver_rtsm(void)
+{
+       u32 u2dotgcr;
+
+       /* put PHY to sync mode */
+       u2dotgcr = u2d_readl(U2DOTGCR);
+       u2dotgcr |=  U2DOTGCR_RTSM | U2DOTGCR_UTMID;
+       u2d_writel(U2DOTGCR, u2dotgcr);
+       msleep(10);
+
+       /* setup OTG sync mode */
+       u2dotgcr = u2d_readl(U2DOTGCR);
+       u2dotgcr |= U2DOTGCR_ULAF;
+       u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+       u2d_writel(U2DOTGCR, u2dotgcr);
+}
+
+static int pxa310_start_otg_host_transcvr(struct usb_bus *host)
+{
+       int err;
+
+       pxa310_otg_transceiver_rtsm();
+
+       err = otg_init(u2d->otg);
+       if (err) {
+               pr_err("OTG transceiver init failed");
+               return err;
+       }
+
+       err = otg_set_vbus(u2d->otg, 1);
+       if (err) {
+               pr_err("OTG transceiver VBUS set failed");
+               return err;
+       }
+
+       err = otg_set_host(u2d->otg, host);
+       if (err)
+               pr_err("OTG transceiver Host mode set failed");
+
+       return err;
+}
+
+static int pxa310_start_otg_hc(struct usb_bus *host)
+{
+       u32 u2dotgcr;
+       int err;
+
+       /* disable USB device controller */
+       u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE);
+       u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID);
+       u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+
+       err = pxa310_start_otg_host_transcvr(host);
+       if (err)
+               return err;
+
+       /* set xceiver mode */
+       if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL)
+               u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS);
+       else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL)
+               u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS);
+
+       /* start OTG host controller */
+       u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF;
+       u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF));
+
+       return 0;
+}
+
+static void pxa310_stop_otg_hc(void)
+{
+       pxa310_otg_transceiver_rtsm();
+
+       otg_set_host(u2d->otg, NULL);
+       otg_set_vbus(u2d->otg, 0);
+       otg_shutdown(u2d->otg);
+}
+
+static void pxa310_u2d_setup_otg_hc(void)
+{
+       u32 u2dotgcr;
+
+       u2dotgcr = u2d_readl(U2DOTGCR);
+       u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID;
+       u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+       u2d_writel(U2DOTGCR, u2dotgcr);
+       msleep(5);
+       u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE);
+       msleep(5);
+       u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+}
+
+static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+       unsigned int ulpi_mode = ULPI_OTG_DRVVBUS;
+
+       if (pdata) {
+               if (pdata->ulpi_mode & ULPI_SER_6PIN)
+                       ulpi_mode |= ULPI_IC_6PIN_SERIAL;
+               else if (pdata->ulpi_mode & ULPI_SER_3PIN)
+                       ulpi_mode |= ULPI_IC_3PIN_SERIAL;
+       }
+
+       u2d->ulpi_mode = ulpi_mode;
+
+       u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode);
+       if (!u2d->otg)
+               return -ENOMEM;
+
+       u2d->otg->io_priv = u2d->mmio_base;
+
+       return 0;
+}
+
+static void pxa310_otg_exit(void)
+{
+       kfree(u2d->otg);
+}
+#else
+static inline void pxa310_u2d_setup_otg_hc(void) {}
+static inline int pxa310_start_otg_hc(struct usb_bus *host)
+{
+       return 0;
+}
+static inline void pxa310_stop_otg_hc(void) {}
+static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+       return 0;
+}
+static inline void pxa310_otg_exit(void) {}
+#endif /* CONFIG_PXA310_ULPI */
+
+int pxa3xx_u2d_start_hc(struct usb_bus *host)
+{
+       int err = 0;
+
+       /* In case the PXA3xx ULPI isn't used, do nothing. */
+       if (!u2d)
+               return 0;
+
+       clk_enable(u2d->clk);
+
+       if (cpu_is_pxa310()) {
+               pxa310_u2d_setup_otg_hc();
+               err = pxa310_start_otg_hc(host);
+       }
+
+       return err;
+}
+
+void pxa3xx_u2d_stop_hc(struct usb_bus *host)
+{
+       /* In case the PXA3xx ULPI isn't used, do nothing. */
+       if (!u2d)
+               return;
+
+       if (cpu_is_pxa310())
+               pxa310_stop_otg_hc();
+
+       clk_disable(u2d->clk);
+}
+
+static int pxa3xx_u2d_probe(struct platform_device *pdev)
+{
+       struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+       struct resource *r;
+       int err;
+
+       u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL);
+       if (!u2d) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       u2d->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(u2d->clk)) {
+               dev_err(&pdev->dev, "failed to get u2d clock\n");
+               err = PTR_ERR(u2d->clk);
+               goto err_free_mem;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "no IO memory resource defined\n");
+               err = -ENODEV;
+               goto err_put_clk;
+       }
+
+        r = request_mem_region(r->start, resource_size(r), pdev->name);
+        if (!r) {
+                dev_err(&pdev->dev, "failed to request memory resource\n");
+                err = -EBUSY;
+                goto err_put_clk;
+        }
+
+       u2d->mmio_base = ioremap(r->start, resource_size(r));
+       if (!u2d->mmio_base) {
+               dev_err(&pdev->dev, "ioremap() failed\n");
+               err = -ENODEV;
+               goto err_free_res;
+       }
+
+       if (pdata->init) {
+               err = pdata->init(&pdev->dev);
+               if (err)
+                       goto err_free_io;
+       }
+
+       /* Only PXA310 U2D has OTG functionality */
+       if (cpu_is_pxa310()) {
+               err = pxa310_otg_init(pdata);
+               if (err)
+                       goto err_free_plat;
+       }
+
+       platform_set_drvdata(pdev, &u2d);
+
+       return 0;
+
+err_free_plat:
+       if (pdata->exit)
+               pdata->exit(&pdev->dev);
+err_free_io:
+       iounmap(u2d->mmio_base);
+err_free_res:
+       release_mem_region(r->start, resource_size(r));
+err_put_clk:
+       clk_put(u2d->clk);
+err_free_mem:
+       kfree(u2d);
+       return err;
+}
+
+static int pxa3xx_u2d_remove(struct platform_device *pdev)
+{
+       struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+       struct resource *r;
+
+       if (cpu_is_pxa310()) {
+               pxa310_stop_otg_hc();
+               pxa310_otg_exit();
+       }
+
+       if (pdata->exit)
+               pdata->exit(&pdev->dev);
+
+       platform_set_drvdata(pdev, NULL);
+       iounmap(u2d->mmio_base);
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(r->start, resource_size(r));
+
+       clk_put(u2d->clk);
+
+       kfree(u2d);
+
+       return 0;
+}
+
+static struct platform_driver pxa3xx_u2d_ulpi_driver = {
+        .driver                = {
+                .name   = "pxa3xx-u2d",
+               .owner  = THIS_MODULE,
+        },
+        .probe          = pxa3xx_u2d_probe,
+        .remove         = pxa3xx_u2d_remove,
+};
+
+static int pxa3xx_u2d_ulpi_init(void)
+{
+       return platform_driver_register(&pxa3xx_u2d_ulpi_driver);
+}
+module_init(pxa3xx_u2d_ulpi_init);
+
+static void __exit pxa3xx_u2d_ulpi_exit(void)
+{
+       platform_driver_unregister(&pxa3xx_u2d_ulpi_driver);
+}
+module_exit(pxa3xx_u2d_ulpi_exit);
+
+MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
+MODULE_AUTHOR("Igor Grinberg");
+MODULE_LICENSE("GPL v2");
index fa0014847c71503f4f929870cce2622deb0abd9d..c85c3a7abd314f84cce570a79d4f38ecce21ecce 100644 (file)
@@ -98,23 +98,6 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
        return CLK / 1000;
 }
 
-/*
- * Return the current static memory controller clock frequency
- * in units of 10kHz
- */
-unsigned int pxa3xx_get_memclk_frequency_10khz(void)
-{
-       unsigned long acsr;
-       unsigned int smcfs, clk = 0;
-
-       acsr = ACSR;
-
-       smcfs = (acsr >> 23) & 0x7;
-       clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
-
-       return (clk / 10000);
-}
-
 void pxa3xx_clear_reset_status(unsigned int mask)
 {
        /* RESET_STATUS_* has a 1:1 mapping with ARSR */
@@ -265,7 +248,7 @@ static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL),
        INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL),
        INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL),
-       INIT_CLKREG(&clk_pxa3xx_u2d, NULL, "U2DCLK"),
+       INIT_CLKREG(&clk_pxa3xx_u2d, "pxa3xx-u2d", NULL),
        INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL),
        INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa27x-ssp.0", NULL),
        INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa27x-ssp.1", NULL),
index 064292008288c86f3b4b3bb9a9e7132092cf5067..7d29dd3af79d20cb55c1e20296c7f80adcd171f8 100644 (file)
@@ -192,7 +192,7 @@ static struct mfp_addr_map pxa935_mfp_addr_map[] __initdata = {
 
 static int __init pxa930_init(void)
 {
-       if (cpu_is_pxa930() || cpu_is_pxa935()) {
+       if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) {
                mfp_init_base(io_p2v(MFPR_BASE));
                mfp_init_addr(pxa930_mfp_addr_map);
        }
index 67e04f4e07c122781e42ca184c30f1e7b4329e7e..4121d03ea2c3eecaa39c7c340ac0a92455adf3de 100644 (file)
@@ -1083,8 +1083,6 @@ static void __init raumfeld_speaker_init(void)
 
 #ifdef CONFIG_MACH_RAUMFELD_RC
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_controller_init,
        .map_io         = pxa_map_io,
@@ -1095,8 +1093,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_connector_init,
        .map_io         = pxa_map_io,
@@ -1107,8 +1103,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_SPEAKER
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_speaker_init,
        .map_io         = pxa_map_io,
index 115b6f234bdd0e5ae0cc1fd4e3195177605d844d..4b521e045d754471df4cf4a66daff5d7434992b5 100644 (file)
@@ -596,9 +596,7 @@ static void __init saar_init(void)
 
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index 1cd99cb87bb1ff19cd9bc02e72706db89e0318a8..f736119f1ebfd46c59b7904e13685fc159b245dd 100644 (file)
@@ -979,8 +979,6 @@ static void __init spitz_fixup(struct machine_desc *desc,
 
 #ifdef CONFIG_MACH_SPITZ
 MACHINE_START(SPITZ, "SHARP Spitz")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = spitz_fixup,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
@@ -991,8 +989,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_BORZOI
 MACHINE_START(BORZOI, "SHARP Borzoi")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = spitz_fixup,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
@@ -1003,8 +999,6 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_AKITA
 MACHINE_START(AKITA, "SHARP Akita")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = spitz_fixup,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
index a654d1e6b38ad11eb6420667028c8395ab10c1ae..738adc1773fdf643cfc4a81c662fd10da0b2bc8e 100644 (file)
@@ -56,6 +56,8 @@
 #include "devices.h"
 #include "generic.h"
 
+#define STARGATE_NR_IRQS       (IRQ_BOARD_START + 8)
+
 /* Bluetooth */
 #define SG2_BT_RESET           81
 
@@ -996,8 +998,6 @@ static void __init stargate2_init(void)
 
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -1008,9 +1008,8 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_STARGATE2
 MACHINE_START(STARGATE2, "Stargate 2")
-       .phys_io = 0x40000000,
-       .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io = pxa_map_io,
+       .nr_irqs = STARGATE_NR_IRQS,
        .init_irq = pxa27x_init_irq,
        .timer = &pxa_timer,
        .init_machine = stargate2_init,
index f02dcb5b4e97e53e14212e0b61892abc8f3f3046..2ea7545273ad949e2b07fd2f107ef2e40a114eaf 100644 (file)
@@ -25,7 +25,7 @@
 
 #include <mach/pxa930.h>
 #include <mach/pxafb.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -489,9 +489,7 @@ static void __init tavorevb_init(void)
 
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
new file mode 100644 (file)
index 0000000..dc30116
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  linux/arch/arm/mach-pxa/tavorevb3.c
+ *
+ *  Support for the Marvell EVB3 Development Platform.
+ *
+ *  Copyright:  (C) Copyright 2008-2010 Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/mfd/88pm860x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa930.h>
+
+#include <plat/i2c.h>
+
+#include "devices.h"
+#include "generic.h"
+
+#define TAVOREVB3_NR_IRQS      (IRQ_BOARD_START + 24)
+
+static mfp_cfg_t evb3_mfp_cfg[] __initdata = {
+       /* UART */
+       GPIO53_UART1_TXD,
+       GPIO54_UART1_RXD,
+
+       /* PMIC */
+       PMIC_INT_GPIO83,
+};
+
+#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
+static struct pm860x_touch_pdata evb3_touch = {
+       .gpadc_prebias  = 1,
+       .slot_cycle     = 1,
+       .tsi_prebias    = 6,
+       .pen_prebias    = 16,
+       .pen_prechg     = 2,
+       .res_x          = 300,
+};
+
+static struct pm860x_backlight_pdata evb3_backlight[] = {
+       {
+               .id     = PM8606_ID_BACKLIGHT,
+               .iset   = PM8606_WLED_CURRENT(24),
+               .flags  = PM8606_BACKLIGHT1,
+       },
+       {},
+};
+
+static struct pm860x_led_pdata evb3_led[] = {
+       {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_RED,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_GREEN,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_BLUE,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_RED,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_GREEN,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_BLUE,
+       },
+};
+
+static struct pm860x_platform_data evb3_pm8607_info = {
+       .touch                          = &evb3_touch,
+       .backlight                      = &evb3_backlight[0],
+       .led                            = &evb3_led[0],
+       .companion_addr                 = 0x10,
+       .irq_mode                       = 0,
+       .irq_base                       = IRQ_BOARD_START,
+
+       .i2c_port                       = GI2C_PORT,
+};
+
+static struct i2c_board_info evb3_i2c_info[] = {
+       {
+               .type           = "88PM860x",
+               .addr           = 0x34,
+               .platform_data  = &evb3_pm8607_info,
+               .irq            = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)),
+       },
+};
+
+static void __init evb3_init_i2c(void)
+{
+       pxa_set_i2c_info(NULL);
+       i2c_register_board_info(0, ARRAY_AND_SIZE(evb3_i2c_info));
+}
+#else
+static inline void evb3_init_i2c(void) {}
+#endif
+
+static void __init evb3_init(void)
+{
+       /* initialize MFP configurations */
+       pxa3xx_mfp_config(ARRAY_AND_SIZE(evb3_mfp_cfg));
+
+       pxa_set_ffuart_info(NULL);
+
+       evb3_init_i2c();
+}
+
+MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
+       .boot_params    = 0xa0000100,
+       .map_io         = pxa_map_io,
+       .nr_irqs        = TAVOREVB3_NR_IRQS,
+       .init_irq       = pxa3xx_init_irq,
+       .timer          = &pxa_timer,
+       .init_machine   = evb3_init,
+MACHINE_END
index 83cc3a18c2e9a0ded180a0b223f29167b3a290f7..0ee1df49606db3e33a03c76e0889dc7cc50907d0 100644 (file)
@@ -952,10 +952,9 @@ static void __init fixup_tosa(struct machine_desc *desc,
 }
 
 MACHINE_START(TOSA, "SHARP Tosa")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_tosa,
        .map_io         = pxa_map_io,
+       .nr_irqs        = TOSA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = tosa_init,
        .timer          = &pxa_timer,
index 0acff172ef228eae96dfdc7e9dec36a2188c2430..565d062f51d58fe740ace0ec28108990a910e1d7 100644 (file)
@@ -555,8 +555,6 @@ static void __init trizeps4_map_io(void)
 
 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        /* MAINTAINER("Jürgen Schindele") */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
@@ -566,8 +564,6 @@ MACHINE_END
 
 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        /* MAINTAINER("Jürgen Schindele") */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
index e90114a7e246ad4627db5ece88d0b2d159b677fa..438fc9a5ed59f625c21a4c6940f96c1020ad71cf 100644 (file)
@@ -992,8 +992,6 @@ static void __init viper_map_io(void)
 
 MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = viper_map_io,
        .init_irq       = viper_init_irq,
index c9b747cedea8fb48a4a9615d52394fa5d2e77fcc..f45ac0961778776e1e9cc34ea540ab1825a4a013 100644 (file)
@@ -240,6 +240,7 @@ static void __init vpac270_onenand_init(void) {}
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data vpac270_mci_platform_data = {
        .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
+       .gpio_power             = -1,
        .gpio_card_detect       = GPIO53_VPAC270_SD_DETECT_N,
        .gpio_card_ro           = GPIO52_VPAC270_SD_READONLY,
        .detect_delay_ms        = 200,
@@ -717,8 +718,6 @@ static void __init vpac270_init(void)
 }
 
 MACHINE_START(VPAC270, "Voipac PXA270")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
index d3b4e3f2e033bdea1f0cd726cd73314be23a7e5d..3260ce73d327202b5e83b7de7789ae7bab0a9b65 100644 (file)
@@ -181,8 +181,6 @@ static void __init xcep_init(void)
 }
 
 MACHINE_START(XCEP, "Iskratel XCEP")
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .init_machine   = xcep_init,
        .map_io         = pxa_map_io,
index f0d02288b4ca3089e754dce9396ff28f23ceb3d4..fefde9848d82349e08554dd74b3fea9d7f9cbd1e 100644 (file)
@@ -37,7 +37,7 @@
 #include <mach/z2.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
 
 #include <plat/i2c.h>
@@ -703,9 +703,7 @@ static void __init z2_init(void)
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
index 03b9cb910e085b1911465e77d57a12ac11a71c9f..dea46a2d089b8a6f6d42040f8fd2debcf1b2d1c6 100644 (file)
@@ -900,10 +900,9 @@ static void __init zeus_map_io(void)
 
 MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = ((io_p2v(0x40000000) >> 18) & 0xfffc),
        .boot_params    = 0xa0000100,
        .map_io         = zeus_map_io,
+       .nr_irqs        = ZEUS_NR_IRQS,
        .init_irq       = zeus_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = zeus_init,
index c479cbecf784ac3c53f634d2b4fad3e1fefd4daa..f25fb6245bd787bc93636163b241f8fefe9f0210 100644 (file)
@@ -30,7 +30,7 @@
 #include <mach/zylonite.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "devices.h"
@@ -411,10 +411,9 @@ static void __init zylonite_init(void)
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
-       .phys_io        = 0x40000000,
        .boot_params    = 0xa0000100,
-       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
+       .nr_irqs        = ZYLONITE_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = zylonite_init,
index 2fa38df284140e08099739d55305a93e7899ebe3..07c08151dfe6434be39b510e215acd79e86ea297 100644 (file)
@@ -259,6 +259,7 @@ struct mmci_platform_data realview_mmc0_plat_data = {
        .status         = realview_mmc_status,
        .gpio_wp        = 17,
        .gpio_cd        = 16,
+       .cd_invert      = true,
 };
 
 struct mmci_platform_data realview_mmc1_plat_data = {
@@ -266,6 +267,7 @@ struct mmci_platform_data realview_mmc1_plat_data = {
        .status         = realview_mmc_status,
        .gpio_wp        = 19,
        .gpio_cd        = 18,
+       .cd_invert      = true,
 };
 
 /*
index 86622289b74e97950cabe4817bfaa5fc1f378e12..90b687cbe04ef2cad3fcdf023963062233cb67f7 100644 (file)
 #error "Unknown RealView platform"
 #endif
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx,      #0x10000000
-               movne   \rx,      #0xfb000000   @ virtual base
-               orr     \rx, \rx, #DEBUG_LL_UART_OFFSET
+               .macro  addruart, rp, rv
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rv, \rp, #0xfb000000   @ virtual base
+               orr     \rp, \rp, #0x10000000   @ physical base
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index dd53892d44a7adbaa7758cbb2293e43ee2af1433..d3cd265cb058c4acf0d29c4a14a16e097aa1ee55 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()                        \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x0F;                         \
-       })
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
index 991c1f8390e2a8eccfbbfae39ccab3768a7badbe..f2697106f809fd44a5ad35903496412602dfa1ba 100644 (file)
@@ -486,8 +486,6 @@ static void __init realview_eb_init(void)
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_EB_UART0_BASE & SECTION_MASK,
-       .io_pg_offst    = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
        .map_io         = realview_eb_map_io,
index d2be12eb829eb3b759be8a37bc8020df9f01d253..a4125619d71b2ed54bcaad9431524803c7fe79f1 100644 (file)
@@ -378,8 +378,6 @@ static void __init realview_pb1176_init(void)
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PB1176_UART0_BASE & SECTION_MASK,
-       .io_pg_offst    = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_pb1176_fixup,
        .map_io         = realview_pb1176_map_io,
index d591bc00b86ec74147b0ff0b8c7bb85e99d52041..117b95b2ca15c7b4bba1f398934f799fbdec570b 100644 (file)
@@ -381,8 +381,6 @@ static void __init realview_pb11mp_init(void)
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PB11MP_UART0_BASE & SECTION_MASK,
-       .io_pg_offst    = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
        .map_io         = realview_pb11mp_map_io,
index 6c37621217bc916fba02af26a8d3163c4b1d4aec..929b8dc12e81754bfb0fdf88f25fa6e4d2664aa6 100644 (file)
@@ -331,8 +331,6 @@ static void __init realview_pba8_init(void)
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PBA8_UART0_BASE & SECTION_MASK,
-       .io_pg_offst    = (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
        .map_io         = realview_pba8_map_io,
index 9428eff0b116addda238d99d492cbe9d80c6b8a5..b9f9e20031a75e1ef9442c252849689fa50d486e 100644 (file)
@@ -417,8 +417,6 @@ static void __init realview_pbx_init(void)
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PBX_UART0_BASE & SECTION_MASK,
-       .io_pg_offst    = (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_pbx_fixup,
        .map_io         = realview_pbx_map_io,
index 6fc8d66395dc373d48935ec26c7364da1561ca90..85effffdc2b2a08f372f3a578e0c9e065d0ff3f8 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x03000000
-               movne   \rx, #0xe0000000
-               orr     \rx, \rx, #0x00010000
-               orr     \rx, \rx, #0x00000fe0
+               .macro  addruart, rp, rv
+               mov     \rp, #0x00010000
+               orr     \rp, \rp, #0x00000fe0
+               orr     \rv, \rp, #0xe0000000   @ virtual
+               orr     \rp, \rp, #0x03000000   @ physical
                .endm
 
 #define UART_SHIFT     2
index 9a96fd69e7051e88f9d031bb91155cc56e4a8844..3bcd86fadb81ad994e771c27441eeb851c0b3d70 100644 (file)
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
+#define VMALLOC_END       0xdc000000
index c7fc01e9d1f64bd9c5be760475f7d9537e497312..580b3c73d2c71ffd1b5d1a257615e4fe61bfdf61 100644 (file)
@@ -218,8 +218,6 @@ extern struct sys_timer ioc_timer;
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
        /* Maintainer: Russell King */
-       .phys_io        = 0x03000000,
-       .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
        .boot_params    = 0x10000100,
        .reserve_lp0    = 1,
        .reserve_lp1    = 1,
index 0eef78b4a6ed6fa24cddf346dfe55afeaf28a2e8..5882deaa56bebcf36a0b9bc073fddd964d36f2a0 100644 (file)
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
 
-       .macro addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C24XX_PA_UART
-               ldrne   \rx, = S3C24XX_VA_UART
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C24XX_PA_UART
+               ldr     \rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index 315b0078a34d68e9f020157721cf26b836817993..54297eb0bf5ea437103cd104106a8b6340a895f9 100644 (file)
@@ -15,6 +15,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END      (0xE0000000)
+#define VMALLOC_END    0xE0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 34fc05a4244b6424230d3f7d0f386ab516fed3ac..44440cbd76204f7212d97f87228ae4d8394ae4b0 100644 (file)
@@ -241,8 +241,6 @@ static void __init amlm5900_init(void)
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = amlm5900_map_io,
        .init_irq       = s3c24xx_init_irq,
index c1f90f6fab42c0d867ccfe25ffe7fbdee835fda8..2970ea9f7c2bfced373562f3d0c8e157a23f8bf3 100644 (file)
@@ -664,8 +664,6 @@ static void __init bast_init(void)
 
 MACHINE_START(BAST, "Simtec-BAST")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = bast_map_io,
        .init_irq       = s3c24xx_init_irq,
index 3ba3bab139d0917ce45feaeb079573428f8a2af2..98c5c9e81ee9d8e20af0c27ee98d7f2e4001a8b5 100644 (file)
@@ -350,8 +350,6 @@ static void __init h1940_init(void)
 
 MACHINE_START(H1940, "IPAQ-H1940")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = h1940_map_io,
        .reserve        = h1940_reserve,
index 41f299d983eb0a06a8c9e6b64e660963b871431b..271b9aa6d40a35ecf971543790f5c44182d11f9d 100644 (file)
@@ -605,8 +605,6 @@ MACHINE_START(N30, "Acer-N30")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>,
                                Ben Dooks <ben-linux@fluff.org>
        */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .timer          = &s3c24xx_timer,
        .init_machine   = n30_init,
@@ -617,8 +615,6 @@ MACHINE_END
 MACHINE_START(N35, "Acer-N35")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>
        */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .timer          = &s3c24xx_timer,
        .init_machine   = n30_init,
index d8c7f2efc1a7bbf050cbcbe710fc0441eb0ae816..0aa16cd5acbcf6c9837126672e44c132befb7db5 100644 (file)
@@ -116,8 +116,6 @@ static void __init otom11_init(void)
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = otom11_map_io,
        .init_machine   = otom11_init,
index d0e87b6e2e0fce574a843862a77666ba03a5f4df..e8f49feef28cc55736d530f186851f15a02d67ef 100644 (file)
@@ -362,8 +362,6 @@ static void __init qt2410_machine_init(void)
 }
 
 MACHINE_START(QT2410, "QT2410")
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = qt2410_map_io,
        .init_irq       = s3c24xx_init_irq,
index 452223042201afc2c60654bb0aac9a3d11c47a8a..e17f03387aba98447c00d582381d3af64bb9454b 100644 (file)
@@ -111,8 +111,6 @@ static void __init smdk2410_init(void)
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                                    * to SMDK2410 */
        /* Maintainer: Jonas Dietsche */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = smdk2410_map_io,
        .init_irq       = s3c24xx_init_irq,
index 929164a8e9b148dc747d3d36e66a318128ec479b..a15d0621c22f2e4bbb4f7786d0435b575d3217ba 100644 (file)
@@ -152,8 +152,6 @@ static void __init tct_hammer_init(void)
 }
 
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = tct_hammer_map_io,
        .init_irq       = s3c24xx_init_irq,
index d540d79dd264ce04b31f3eddbb6a96380a8ce19e..6ccce5a761b4009b28f0905e6ea398596fb40b86 100644 (file)
@@ -400,8 +400,6 @@ static void __init vr1000_init(void)
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = vr1000_map_io,
        .init_machine   = vr1000_init,
index 478f4b4606c2bd024c4209a4f59cc8c301542b46..923e01bdf0170c370c683f5f268d87067863da3f 100644 (file)
@@ -675,8 +675,6 @@ static void __init jive_machine_init(void)
 
 MACHINE_START(JIVE, "JIVE")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .init_irq       = s3c24xx_init_irq,
index 054c9f92232aa676dad11c0b86359ad21ef47fa6..8e5758bdd666ee18bc12a419a0240e738d296e13 100644 (file)
@@ -150,8 +150,6 @@ static void __init smdk2413_machine_init(void)
 
 MACHINE_START(S3C2413, "S3C2413")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .fixup          = smdk2413_fixup,
@@ -163,8 +161,6 @@ MACHINE_END
 
 MACHINE_START(SMDK2412, "SMDK2412")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .fixup          = smdk2413_fixup,
@@ -176,8 +172,6 @@ MACHINE_END
 
 MACHINE_START(SMDK2413, "SMDK2413")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .fixup          = smdk2413_fixup,
index f291ac25d31252a8882bc632434a2c03f71e0361..83544ebe20ac9282f17498998ef5b03df8215bb8 100644 (file)
@@ -156,8 +156,6 @@ static void __init vstms_init(void)
 }
 
 MACHINE_START(VSTMS, "VSTMS")
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .fixup          = vstms_fixup,
index 5fc3f67ef265006d271d9a185d5fd6a9b5c09fbd..7fc366476d7e0e68522f8b47f8065d264840b9ed 100644 (file)
@@ -195,8 +195,6 @@ static void __init smdk2416_machine_init(void)
 
 MACHINE_START(SMDK2416, "SMDK2416")
        /* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .init_irq       = s3c24xx_init_irq,
index b73f78a9da5cfdeb40086664be5344e8b8a7756d..d7086788b1ff40c2a7a458faab5ac9c9ee4c42b0 100644 (file)
@@ -498,8 +498,6 @@ static void __init anubis_init(void)
 
 MACHINE_START(ANUBIS, "Simtec-Anubis")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = anubis_map_io,
        .init_machine   = anubis_init,
index 84725791e6bfe7298d85ff0bf06a49a911812975..e3810c86a5e6fd3754f67deaa0b069dac7aec908 100644 (file)
@@ -233,8 +233,6 @@ static void __init at2440evb_init(void)
 
 
 MACHINE_START(AT2440EVB, "AT2440EVB")
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = at2440evb_map_io,
        .init_machine   = at2440evb_init,
index deaabe86741d2336acb2886e4db2ff99baece745..9f2c14ec71819f89b7f327f5c97bf70370211b92 100644 (file)
@@ -572,8 +572,6 @@ static void __init gta02_machine_init(void)
 
 MACHINE_START(NEO1973_GTA02, "GTA02")
        /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = gta02_map_io,
        .init_irq       = s3c24xx_init_irq,
index a76bcda210ad78c9aeb0a090d9c2903ca28eb5cb..f62bb4c793bdd6e226d6651d1e704b3b1459b94f 100644 (file)
@@ -691,8 +691,6 @@ static void __init mini2440_init(void)
 
 MACHINE_START(MINI2440, "MINI2440")
        /* Maintainer: Michel Pollet <buserror@gmail.com> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = mini2440_map_io,
        .init_machine   = mini2440_init,
index 3ff62de45fde3644ae2827feec9f517ec216fa7f..37dd306fb7dcab1da53f81f721e802811ae67897 100644 (file)
@@ -151,8 +151,6 @@ static void __init nexcoder_init(void)
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = nexcoder_map_io,
        .init_machine   = nexcoder_init,
index 319458da71a0761dd4bfaa9838144ae8a991474f..14dc67897757ea4d27dcde40fab8de7af74341a5 100644 (file)
@@ -455,8 +455,6 @@ static void __init osiris_init(void)
 
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = osiris_map_io,
        .init_irq       = s3c24xx_init_irq,
index 142d1f92117651e60fdad7e55fcc52997e430962..32019bd9db3bb8506f2562ff31fc00741b0bdd26 100644 (file)
@@ -580,8 +580,6 @@ static void __init rx1950_reserve(void)
 
 MACHINE_START(RX1950, "HP iPAQ RX1950")
     /* Maintainers: Vasily Khoruzhick */
-    .phys_io = S3C2410_PA_UART,
-       .io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params = S3C2410_SDRAM_PA + 0x100,
        .map_io = rx1950_map_io,
        .reserve        = rx1950_reserve,
index 6bb44f75a9ce65094a35c1bdad78775c1c655eee..1472b1a5b2fbc4f1348de2bf6fc74c9882b7d139 100644 (file)
@@ -218,8 +218,6 @@ static void __init rx3715_init_machine(void)
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = rx3715_map_io,
        .reserve        = rx3715_reserve,
index df83276d85aeba60bd582c7e5106c1380a36d890..eedfe0f11643ddb9ac48bc487505ef8d0257d679 100644 (file)
@@ -175,8 +175,6 @@ static void __init smdk2440_machine_init(void)
 
 MACHINE_START(S3C2440, "SMDK2440")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .init_irq       = s3c24xx_init_irq,
index 4c863d3a52f4689bd50212ea6550f33ffcda8dec..4337f0a9960d17eef0c6fbe413a95ea10f2c626b 100644 (file)
@@ -132,8 +132,6 @@ static void __init smdk2443_machine_init(void)
 
 MACHINE_START(SMDK2443, "SMDK2443")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C2410_PA_UART,
-       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 
        .init_irq       = s3c24xx_init_irq,
index 239476b81f3b4fd643410401fad18c1b646739ef..0c5a73805560f664684a3692d23f8cf44749ea82 100644 (file)
 #include <mach/map.h>
 #include <plat/regs-serial.h>
 
-       .macro addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C24XX_PA_UART
-               ldrne   \rx, = S3C24XX_VA_UART
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C24XX_PA_UART
+               ldr     \rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index a492b982aa062705a0c24d03dd696b020719b262..405e621289172512bbf01527d9061717a95d55d6 100644 (file)
 #include <mach/map.h>
 #include <mach/gpio-bank-c.h>
 #include <mach/spi-clocks.h>
+#include <mach/irqs.h>
 
 #include <plat/s3c64xx-spi.h>
 #include <plat/gpio-cfg.h>
-#include <plat/irqs.h>
+#include <plat/devs.h>
 
 static char *spi_src_clks[] = {
        [S3C64XX_SPI_SRCCLK_PCLK] = "pclk",
index f9ab5d26052a38762c1559b51dbe1d46ab7786cc..a29e70550c70849ec7a8c271cb50d6684eee52da 100644 (file)
         * aligned and add in the offset when we load the value here.
         */
 
-       .macro addruart, rx, rtmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C_PA_UART
+               ldr     \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index 7411ef3711a6e047ad37ba8a2fe617f8381de646..bc0e913898642ef3f374188f4d928cc56a83f0a5 100644 (file)
@@ -15,6 +15,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END      (0xE0000000)
+#define VMALLOC_END    0xE0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 742dc87bd9c1f1f374a17ff2ca3b8ced7e7208a7..a53cf149476e882b7c96e5d776b39eb6486e9957 100644 (file)
@@ -233,8 +233,6 @@ static void __init anw6410_machine_init(void)
 
 MACHINE_START(ANW6410, "A&W6410")
        /* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
 
        .init_irq       = s3c6410_init_irq,
index fba90229f0dfb1627135f3a2c4f09517890d04c2..b2639582cacaa32013804a385e3a5b0079ae6108 100644 (file)
@@ -265,8 +265,6 @@ static void __init hmt_machine_init(void)
 
 MACHINE_START(HMT, "Airgoo-HMT")
        /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = hmt_map_io,
index bf65747ea68ec2e5700464f007870d611139999b..c4986498cd1203f93bd15783d801216f3d2f8fc8 100644 (file)
@@ -97,8 +97,6 @@ static void __init ncp_machine_init(void)
 
 MACHINE_START(NCP, "NCP")
        /* Maintainer: Samsung Electronics */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = ncp_map_io,
index 5c07d013b23da47dc387a436a2cedbeea2c826b7..4b4475da8ec6f129c478b6c0ade9c2116738372e 100644 (file)
 #include <plat/devs.h>
 #include <plat/regs-serial.h>
 
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
 
 static struct s3c2410_uartcfg real6410_uartcfgs[] __initdata = {
        [0] = {
-               .hwport      = 0,
-               .flags       = 0,
-               .ucon        = UCON,
-               .ulcon       = ULCON,
-               .ufcon       = UFCON,
+               .hwport = 0,
+               .flags  = 0,
+               .ucon   = UCON,
+               .ulcon  = ULCON,
+               .ufcon  = UFCON,
        },
        [1] = {
-               .hwport      = 1,
-               .flags       = 0,
-               .ucon        = UCON,
-               .ulcon       = ULCON,
-               .ufcon       = UFCON,
+               .hwport = 1,
+               .flags  = 0,
+               .ucon   = UCON,
+               .ulcon  = ULCON,
+               .ufcon  = UFCON,
        },
        [2] = {
-               .hwport      = 2,
-               .flags       = 0,
-               .ucon        = UCON,
-               .ulcon       = ULCON,
-               .ufcon       = UFCON,
+               .hwport = 2,
+               .flags  = 0,
+               .ucon   = UCON,
+               .ulcon  = ULCON,
+               .ufcon  = UFCON,
        },
        [3] = {
-               .hwport      = 3,
-               .flags       = 0,
-               .ucon        = UCON,
-               .ulcon       = ULCON,
-               .ufcon       = UFCON,
+               .hwport = 3,
+               .flags  = 0,
+               .ucon   = UCON,
+               .ulcon  = ULCON,
+               .ufcon  = UFCON,
        },
 };
 
 /* DM9000AEP 10/100 ethernet controller */
 
 static struct resource real6410_dm9k_resource[] = {
-        [0] = {
-                .start = S3C64XX_PA_XM0CSN1,
-                .end   = S3C64XX_PA_XM0CSN1 + 1,
-                .flags = IORESOURCE_MEM
-        },
-        [1] = {
-                .start = S3C64XX_PA_XM0CSN1 + 4,
-                .end   = S3C64XX_PA_XM0CSN1 + 5,
-                .flags = IORESOURCE_MEM
-        },
-        [2] = {
-                .start = S3C_EINT(7),
-                .end   = S3C_EINT(7),
-                .flags = IORESOURCE_IRQ,
-        }
+       [0] = {
+               .start  = S3C64XX_PA_XM0CSN1,
+               .end    = S3C64XX_PA_XM0CSN1 + 1,
+               .flags  = IORESOURCE_MEM
+       },
+       [1] = {
+               .start  = S3C64XX_PA_XM0CSN1 + 4,
+               .end    = S3C64XX_PA_XM0CSN1 + 5,
+               .flags  = IORESOURCE_MEM
+       },
+       [2] = {
+               .start  = S3C_EINT(7),
+               .end    = S3C_EINT(7),
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
+       }
 };
 
 static struct dm9000_plat_data real6410_dm9k_pdata = {
-        .flags          = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+       .flags          = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
 };
 
 static struct platform_device real6410_device_eth = {
-        .name           = "dm9000",
-        .id             = -1,
-        .num_resources  = ARRAY_SIZE(real6410_dm9k_resource),
-        .resource       = real6410_dm9k_resource,
-        .dev            = {
-                .platform_data  = &real6410_dm9k_pdata,
-        },
+       .name           = "dm9000",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(real6410_dm9k_resource),
+       .resource       = real6410_dm9k_resource,
+       .dev            = {
+               .platform_data  = &real6410_dm9k_pdata,
+       },
 };
 
 static struct platform_device *real6410_devices[] __initdata = {
@@ -129,20 +129,18 @@ static void __init real6410_machine_init(void)
        /* set timing for nCS1 suitable for ethernet chip */
 
        __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
-                       (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
-                       (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
-                       (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
-                       (13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
-                       (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
-                       (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
+               (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
+               (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
+               (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
+               (13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
+               (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
+               (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
 
        platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices));
 }
 
 MACHINE_START(REAL6410, "REAL6410")
        /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
 
        .init_irq       = s3c6410_init_irq,
index 3a9639bc3d9b24df59de162b428a6965d2bba093..cb1ebeb087631a8f39cac7a85ebf597eb4a4f19e 100644 (file)
@@ -136,7 +136,7 @@ static struct platform_device smartq_usb_otg_vbus_dev = {
        .dev.platform_data      = &smartq_usb_otg_vbus_pdata,
 };
 
-static int __init smartq_bl_init(struct device *dev)
+static int smartq_bl_init(struct device *dev)
 {
     s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
 
index a4d59b076e3d9d31b518160b28d87d65c93d1300..3a3e5acde523c8fde3a12d254d476a9ac9d03fd2 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mach-smartq.h"
 
-static struct gpio_led smartq5_leds[] __initdata = {
+static struct gpio_led smartq5_leds[] = {
        {
                .name                   = "smartq5:green",
                .active_low             = 1,
@@ -146,8 +146,6 @@ static void __init smartq5_machine_init(void)
 
 MACHINE_START(SMARTQ5, "SmartQ 5")
        /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = smartq_map_io,
index e50a7d781732fd2e7d072f647439421e7489c8f3..e65375877d53437b7ee51a508025a4afc56d1414 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mach-smartq.h"
 
-static struct gpio_led smartq7_leds[] __initdata = {
+static struct gpio_led smartq7_leds[] = {
        {
                .name                   = "smartq7:red",
                .active_low             = 1,
@@ -162,8 +162,6 @@ static void __init smartq7_machine_init(void)
 
 MACHINE_START(SMARTQ7, "SmartQ 7")
        /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = smartq_map_io,
index 59916676d8d26c2b9def21828a9386daf45e877e..3cca642f1e6da9655c4192aab673ffe8d116ab65 100644 (file)
@@ -85,8 +85,6 @@ static void __init smdk6400_machine_init(void)
 
 MACHINE_START(SMDK6400, "SMDK6400")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
 
        .init_irq       = s3c6400_init_irq,
index d498219fff1bd34ed1c8b180a67c1ce24fe1835c..ec8865c03a1965d0ae51c7f64251fd8e0a08beae 100644 (file)
@@ -704,8 +704,6 @@ static void __init smdk6410_machine_init(void)
 
 MACHINE_START(SMDK6410, "SMDK6410")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C64XX_PA_SDRAM + 0x100,
 
        .init_irq       = s3c6410_init_irq,
diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig
deleted file mode 100644 (file)
index 6a4af7f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# arch/arm/mach-s5p6440/Kconfig
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-#              http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-if ARCH_S5P6440
-
-config CPU_S5P6440
-       bool
-       select S3C_PL330_DMA
-       help
-         Enable S5P6440 CPU support
-
-config S5P6440_SETUP_I2C1
-       bool
-       help
-         Common setup code for i2c bus 1.
-
-config MACH_SMDK6440
-       bool "SMDK6440"
-       select CPU_S5P6440
-       select S3C_DEV_I2C1
-       select S3C_DEV_RTC
-       select S3C_DEV_WDT
-       select SAMSUNG_DEV_ADC
-       select SAMSUNG_DEV_TS
-       select S5P6440_SETUP_I2C1
-       help
-         Machine support for the Samsung SMDK6440
-
-endif
diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile
deleted file mode 100644 (file)
index c3fe4d3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# arch/arm/mach-s5p6440/Makefile
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-#              http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y                          :=
-obj-m                          :=
-obj-n                          :=
-obj-                           :=
-
-# Core support for S5P6440 system
-
-obj-$(CONFIG_CPU_S5P6440)      += cpu.o init.o clock.o gpio.o dma.o
-obj-$(CONFIG_CPU_S5P6440)      += setup-i2c0.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDK6440)    += mach-smdk6440.o
-
-# device support
-obj-y                          += dev-audio.o
-obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
-obj-$(CONFIG_S5P6440_SETUP_I2C1)       += setup-i2c1.o
diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c
deleted file mode 100644 (file)
index ca6e48d..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/clock.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/clock-clksrc.h>
-#include <plat/s5p-clock.h>
-#include <plat/pll.h>
-#include <plat/s5p6440.h>
-
-/* APLL Mux output clock */
-static struct clksrc_clk clk_mout_apll = {
-       .clk    = {
-               .name           = "mout_apll",
-               .id             = -1,
-       },
-       .sources        = &clk_src_apll,
-       .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static int s5p6440_epll_enable(struct clk *clk, int enable)
-{
-       unsigned int ctrlbit = clk->ctrlbit;
-       unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
-
-       if (enable)
-               __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
-       else
-               __raw_writel(epll_con, S5P_EPLL_CON);
-
-       return 0;
-}
-
-static unsigned long s5p6440_epll_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-
-static u32 epll_div[][5] = {
-       { 36000000,     0,      48, 1, 4 },
-       { 48000000,     0,      32, 1, 3 },
-       { 60000000,     0,      40, 1, 3 },
-       { 72000000,     0,      48, 1, 3 },
-       { 84000000,     0,      28, 1, 2 },
-       { 96000000,     0,      32, 1, 2 },
-       { 32768000,     45264,  43, 1, 4 },
-       { 45158000,     6903,   30, 1, 3 },
-       { 49152000,     50332,  32, 1, 3 },
-       { 67738000,     10398,  45, 1, 3 },
-       { 73728000,     9961,   49, 1, 3 }
-};
-
-static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned int epll_con, epll_con_k;
-       unsigned int i;
-
-       if (clk->rate == rate)  /* Return if nothing changed */
-               return 0;
-
-       epll_con = __raw_readl(S5P_EPLL_CON);
-       epll_con_k = __raw_readl(S5P_EPLL_CON_K);
-
-       epll_con_k &= ~(PLL90XX_KDIV_MASK);
-       epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
-       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-                if (epll_div[i][0] == rate) {
-                       epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
-                       epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
-                                   (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
-                                   (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
-                       break;
-               }
-       }
-
-       if (i == ARRAY_SIZE(epll_div)) {
-               printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
-               return -EINVAL;
-       }
-
-       __raw_writel(epll_con, S5P_EPLL_CON);
-       __raw_writel(epll_con_k, S5P_EPLL_CON_K);
-
-       clk->rate = rate;
-
-       return 0;
-}
-
-static struct clk_ops s5p6440_epll_ops = {
-       .get_rate = s5p6440_epll_get_rate,
-       .set_rate = s5p6440_epll_set_rate,
-};
-
-static struct clksrc_clk clk_mout_epll = {
-       .clk    = {
-               .name           = "mout_epll",
-               .id             = -1,
-       },
-       .sources        = &clk_src_epll,
-       .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-       .clk = {
-               .name           = "mout_mpll",
-               .id             = -1,
-       },
-       .sources        = &clk_src_mpll,
-       .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
-};
-
-enum perf_level {
-       L0 = 532*1000,
-       L1 = 266*1000,
-       L2 = 133*1000,
-};
-
-static const u32 clock_table[][3] = {
-       /*{ARM_CLK, DIVarm, DIVhclk}*/
-       {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
-       {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
-       {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
-};
-
-static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
-{
-       unsigned long rate = clk_get_rate(clk->parent);
-       u32 clkdiv;
-
-       /* divisor mask starts at bit0, so no need to shift */
-       clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
-
-       return rate / (clkdiv + 1);
-}
-
-static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
-                                               unsigned long rate)
-{
-       u32 iter;
-
-       for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-               if (rate > clock_table[iter][0])
-                       return clock_table[iter-1][0];
-       }
-
-       return clock_table[ARRAY_SIZE(clock_table) - 1][0];
-}
-
-static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 round_tmp;
-       u32 iter;
-       u32 clk_div0_tmp;
-       u32 cur_rate = clk->ops->get_rate(clk);
-       unsigned long flags;
-
-       round_tmp = clk->ops->round_rate(clk, rate);
-       if (round_tmp == cur_rate)
-               return 0;
-
-
-       for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-               if (round_tmp == clock_table[iter][0])
-                       break;
-       }
-
-       if (iter >= ARRAY_SIZE(clock_table))
-               iter = ARRAY_SIZE(clock_table) - 1;
-
-       local_irq_save(flags);
-       if (cur_rate > round_tmp) {
-               /* Frequency Down */
-               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-               clk_div0_tmp |= clock_table[iter][1];
-               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-                               ~(S5P_CLKDIV0_HCLK_MASK);
-               clk_div0_tmp |= clock_table[iter][2];
-               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-
-       } else {
-               /* Frequency Up */
-               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-                               ~(S5P_CLKDIV0_HCLK_MASK);
-               clk_div0_tmp |= clock_table[iter][2];
-               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-               clk_div0_tmp |= clock_table[iter][1];
-               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-               }
-       local_irq_restore(flags);
-
-       clk->rate = clock_table[iter][0];
-
-       return 0;
-}
-
-static struct clk_ops s5p6440_clkarm_ops = {
-       .get_rate       = s5p6440_armclk_get_rate,
-       .set_rate       = s5p6440_armclk_set_rate,
-       .round_rate     = s5p6440_armclk_round_rate,
-};
-
-static struct clksrc_clk clk_armclk = {
-       .clk    = {
-               .name   = "armclk",
-               .id     = 1,
-               .parent = &clk_mout_apll.clk,
-               .ops    = &s5p6440_clkarm_ops,
-       },
-       .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mpll = {
-       .clk    = {
-               .name   = "dout_mpll",
-               .id     = -1,
-               .parent = &clk_mout_mpll.clk,
-       },
-       .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_hclk = {
-       .clk    = {
-               .name   = "clk_hclk",
-               .id     = -1,
-               .parent = &clk_armclk.clk,
-       },
-       .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
-       .clk    = {
-               .name   = "clk_pclk",
-               .id     = -1,
-               .parent = &clk_hclk.clk,
-       },
-       .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
-};
-
-static struct clk *clkset_hclklow_list[] = {
-       &clk_mout_apll.clk,
-       &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_hclklow = {
-       .sources        = clkset_hclklow_list,
-       .nr_sources     = ARRAY_SIZE(clkset_hclklow_list),
-};
-
-static struct clksrc_clk clk_hclk_low = {
-       .clk = {
-               .name   = "hclk_low",
-               .id     = -1,
-       },
-       .sources        = &clkset_hclklow,
-       .reg_src        = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
-       .reg_div        = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
-       .clk    = {
-               .name   = "pclk_low",
-               .id     = -1,
-               .parent = &clk_hclk_low.clk,
-       },
-       .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
-{
-       unsigned long flags;
-       u32 val;
-
-       /* can't rely on clock lock, this register has other usages */
-       local_irq_save(flags);
-
-       val = __raw_readl(S5P_OTHERS);
-       if (enable)
-               val |= S5P_OTHERS_USB_SIG_MASK;
-       else
-               val &= ~S5P_OTHERS_USB_SIG_MASK;
-
-       __raw_writel(val, S5P_OTHERS);
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
-}
-
-static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
-}
-
-static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
-}
-
-static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
-}
-
-static int s5p6440_sclk1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable);
-}
-
-static int s5p6440_mem_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
-}
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_disable[] = {
-       {
-               .name           = "nand",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_mem_ctrl,
-               .ctrlbit        = S5P_CLKCON_MEM0_HCLK_NFCON,
-       }, {
-               .name           = "adc",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_TSADC,
-       }, {
-               .name           = "i2c",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_IIC0,
-       }, {
-               .name           = "i2s_v40",
-               .id             = 0,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_IIS2,
-       }, {
-               .name           = "spi",
-               .id             = 0,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_SPI0,
-       }, {
-               .name           = "spi",
-               .id             = 1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_SPI1,
-       }, {
-               .name           = "sclk_spi_48",
-               .id             = 0,
-               .parent         = &clk_48m,
-               .enable         = s5p6440_sclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_SCLK0_SPI0_48,
-       }, {
-               .name           = "sclk_spi_48",
-               .id             = 1,
-               .parent         = &clk_48m,
-               .enable         = s5p6440_sclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_SCLK0_SPI1_48,
-       }, {
-               .name           = "mmc_48m",
-               .id             = 0,
-               .parent         = &clk_48m,
-               .enable         = s5p6440_sclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_SCLK0_MMC0_48,
-       }, {
-               .name           = "mmc_48m",
-               .id             = 1,
-               .parent         = &clk_48m,
-               .enable         = s5p6440_sclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_SCLK0_MMC1_48,
-       }, {
-               .name           = "mmc_48m",
-               .id             = 2,
-               .parent         = &clk_48m,
-               .enable         = s5p6440_sclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_SCLK0_MMC2_48,
-       }, {
-               .name           = "otg",
-               .id             = -1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK0_USB
-       }, {
-               .name           = "post",
-               .id             = -1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK0_POST0
-       }, {
-               .name           = "lcd",
-               .id             = -1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk1_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK1_DISPCON,
-       }, {
-               .name           = "hsmmc",
-               .id             = 0,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC0,
-       }, {
-               .name           = "hsmmc",
-               .id             = 1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC1,
-       }, {
-               .name           = "hsmmc",
-               .id             = 2,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC2,
-       }, {
-               .name           = "rtc",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_RTC,
-       }, {
-               .name           = "watchdog",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_WDT,
-       }, {
-               .name           = "timers",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_PWM,
-       }, {
-               .name           = "hclk_fimgvg",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_hclk1_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "tsi",
-               .id             = -1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk1_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "pclk_fimgvg",
-               .id             = -1,
-               .parent         = &clk_pclk.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 31),
-       }, {
-               .name           = "dmc0",
-               .id             = -1,
-               .parent         = &clk_pclk.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 30),
-       }, {
-               .name           = "etm",
-               .id             = -1,
-               .parent         = &clk_pclk.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 29),
-       }, {
-               .name           = "dsim",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 28),
-       }, {
-               .name           = "gps",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 25),
-       }, {
-               .name           = "pcm",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "irom",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = (1 << 25),
-       }, {
-               .name           = "dma",
-               .id             = -1,
-               .parent         = &clk_hclk_low.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "2d",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
-       {
-               .name           = "gpio",
-               .id             = -1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_GPIO,
-       }, {
-               .name           = "uart",
-               .id             = 0,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_UART0,
-       }, {
-               .name           = "uart",
-               .id             = 1,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_UART1,
-       }, {
-               .name           = "uart",
-               .id             = 2,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_UART2,
-       }, {
-               .name           = "uart",
-               .id             = 3,
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p6440_pclk_ctrl,
-               .ctrlbit        = S5P_CLKCON_PCLK_UART3,
-       }, {
-               .name           = "mem",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = (1 << 21),
-       }, {
-               .name           = "intc",
-               .id             = -1,
-               .parent         = &clk_hclk.clk,
-               .enable         = s5p6440_hclk0_ctrl,
-               .ctrlbit        = (1 << 1),
-       },
-};
-
-static struct clk clk_iis_cd_v40 = {
-       .name           = "iis_cdclk_v40",
-       .id             = -1,
-};
-
-static struct clk clk_pcm_cd = {
-       .name           = "pcm_cdclk",
-       .id             = -1,
-};
-
-static struct clk *clkset_group1_list[] = {
-       &clk_mout_epll.clk,
-       &clk_dout_mpll.clk,
-       &clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_group1 = {
-       .sources        = clkset_group1_list,
-       .nr_sources     = ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_uart_list[] = {
-       &clk_mout_epll.clk,
-       &clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
-       .sources        = clkset_uart_list,
-       .nr_sources     = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_audio_list[] = {
-       &clk_mout_epll.clk,
-       &clk_dout_mpll.clk,
-       &clk_fin_epll,
-       &clk_iis_cd_v40,
-       &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio = {
-       .sources        = clkset_audio_list,
-       .nr_sources     = ARRAY_SIZE(clkset_audio_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
-       {
-               .clk    = {
-                       .name           = "mmc_bus",
-                       .id             = 0,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "mmc_bus",
-                       .id             = 1,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "mmc_bus",
-                       .id             = 2,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "uclk1",
-                       .id             = -1,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_UART,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_uart,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
-               .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "spi_epll",
-                       .id             = 0,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "spi_epll",
-                       .id             = 1,
-                       .ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_post",
-                       .id             = -1,
-                       .ctrlbit        = (1 << 10),
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_dispcon",
-                       .id             = -1,
-                       .ctrlbit        = (1 << 1),
-                       .enable         = s5p6440_sclk1_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimgvg",
-                       .id             = -1,
-                       .ctrlbit        = (1 << 2),
-                       .enable         = s5p6440_sclk1_ctrl,
-               },
-               .sources = &clkset_group1,
-               .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
-               .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_audio2",
-                       .id             = -1,
-                       .ctrlbit        = (1 << 11),
-                       .enable         = s5p6440_sclk_ctrl,
-               },
-               .sources = &clkset_audio,
-               .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 },
-               .reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 },
-       },
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
-       &clk_mout_apll,
-       &clk_mout_epll,
-       &clk_mout_mpll,
-       &clk_dout_mpll,
-       &clk_armclk,
-       &clk_hclk,
-       &clk_pclk,
-       &clk_hclk_low,
-       &clk_pclk_low,
-};
-
-void __init_or_cpufreq s5p6440_setup_clocks(void)
-{
-       struct clk *xtal_clk;
-       unsigned long xtal;
-       unsigned long fclk;
-       unsigned long hclk;
-       unsigned long hclk_low;
-       unsigned long pclk;
-       unsigned long pclk_low;
-       unsigned long epll;
-       unsigned long apll;
-       unsigned long mpll;
-       unsigned int ptr;
-
-       /* Set S5P6440 functions for clk_fout_epll */
-       clk_fout_epll.enable = s5p6440_epll_enable;
-       clk_fout_epll.ops = &s5p6440_epll_ops;
-
-       clk_48m.enable = s5p6440_clk48m_ctrl;
-
-       xtal_clk = clk_get(NULL, "ext_xtal");
-       BUG_ON(IS_ERR(xtal_clk));
-
-       xtal = clk_get_rate(xtal_clk);
-       clk_put(xtal_clk);
-
-       epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
-                               __raw_readl(S5P_EPLL_CON_K));
-       mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
-       apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
-
-       clk_fout_mpll.rate = mpll;
-       clk_fout_epll.rate = epll;
-       clk_fout_apll.rate = apll;
-
-       printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
-                       " E=%ld.%ldMHz\n",
-                       print_mhz(apll), print_mhz(mpll), print_mhz(epll));
-
-       fclk = clk_get_rate(&clk_armclk.clk);
-       hclk = clk_get_rate(&clk_hclk.clk);
-       pclk = clk_get_rate(&clk_pclk.clk);
-       hclk_low = clk_get_rate(&clk_hclk_low.clk);
-       pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
-       printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
-                       " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
-                       print_mhz(hclk), print_mhz(hclk_low),
-                       print_mhz(pclk), print_mhz(pclk_low));
-
-       clk_f.rate = fclk;
-       clk_h.rate = hclk;
-       clk_p.rate = pclk;
-
-       for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-               s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-       &clk_ext,
-       &clk_iis_cd_v40,
-       &clk_pcm_cd,
-};
-
-void __init s5p6440_register_clocks(void)
-{
-       struct clk *clkp;
-       int ret;
-       int ptr;
-
-       ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-       if (ret > 0)
-               printk(KERN_ERR "Failed to register %u clocks\n", ret);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-               s3c_register_clksrc(sysclks[ptr], 1);
-
-       s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-       s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-       clkp = init_clocks_disable;
-       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-               ret = s3c24xx_register_clock(clkp);
-               if (ret < 0) {
-                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
-                              clkp->name, ret);
-               }
-               (clkp->enable)(clkp, 0);
-       }
-
-       s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c
deleted file mode 100644 (file)
index 526f33a..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/cpu.c
- *
- * Copyright (c) 2009 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 version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/s5p6440.h>
-#include <plat/adc-core.h>
-
-static void s5p6440_idle(void)
-{
-       unsigned long val;
-
-       if (!need_resched()) {
-               val = __raw_readl(S5P_PWR_CFG);
-               val &= ~(0x3<<5);
-               val |= (0x1<<5);
-               __raw_writel(val, S5P_PWR_CFG);
-
-               cpu_do_idle();
-       }
-       local_irq_enable();
-}
-
-/* s5p6440_map_io
- *
- * register the standard cpu IO areas
-*/
-
-void __init s5p6440_map_io(void)
-{
-       /* initialize any device information early */
-       s3c_adc_setname("s3c64xx-adc");
-}
-
-void __init s5p6440_init_clocks(int xtal)
-{
-       printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-       s3c24xx_register_baseclocks(xtal);
-       s5p_register_clocks(xtal);
-       s5p6440_register_clocks();
-       s5p6440_setup_clocks();
-}
-
-void __init s5p6440_init_irq(void)
-{
-       /* S5P6440 supports only 2 VIC */
-       u32 vic[2];
-
-       /*
-        * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
-        * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
-        */
-       vic[0] = 0xff800ae7;
-       vic[1] = 0xffbf23e5;
-
-       s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-struct sysdev_class s5p6440_sysclass = {
-       .name   = "s5p6440-core",
-};
-
-static struct sys_device s5p6440_sysdev = {
-       .cls    = &s5p6440_sysclass,
-};
-
-static int __init s5p6440_core_init(void)
-{
-       return sysdev_class_register(&s5p6440_sysclass);
-}
-
-core_initcall(s5p6440_core_init);
-
-int __init s5p6440_init(void)
-{
-       printk(KERN_INFO "S5P6440: Initializing architecture\n");
-
-       /* set idle function */
-       pm_idle = s5p6440_idle;
-
-       return sysdev_register(&s5p6440_sysdev);
-}
diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c
deleted file mode 100644 (file)
index 3ca0d2b..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5p6440_cfg_i2s(struct platform_device *pdev)
-{
-       /* configure GPIO for i2s port */
-       switch (pdev->id) {
-       case -1:
-               s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
-               s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
-               break;
-
-       default:
-               printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static struct s3c_audio_pdata s3c_i2s_pdata = {
-       .cfg_gpio = s5p6440_cfg_i2s,
-};
-
-static struct resource s5p6440_iis0_resource[] = {
-       [0] = {
-               .start = S5P6440_PA_I2S,
-               .end   = S5P6440_PA_I2S + 0x100 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = DMACH_I2S0_TX,
-               .end   = DMACH_I2S0_TX,
-               .flags = IORESOURCE_DMA,
-       },
-       [2] = {
-               .start = DMACH_I2S0_RX,
-               .end   = DMACH_I2S0_RX,
-               .flags = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device s5p6440_device_iis = {
-       .name             = "s3c64xx-iis-v4",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s5p6440_iis0_resource),
-       .resource         = s5p6440_iis0_resource,
-       .dev = {
-               .platform_data = &s3c_i2s_pdata,
-       },
-};
-
-/* PCM Controller platform_devices */
-
-static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
-{
-       switch (pdev->id) {
-       case 0:
-               s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
-               break;
-
-       default:
-               printk(KERN_DEBUG "Invalid PCM Controller number!");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-       .cfg_gpio = s5p6440_pcm_cfg_gpio,
-};
-
-static struct resource s5p6440_pcm0_resource[] = {
-       [0] = {
-               .start = S5P6440_PA_PCM,
-               .end   = S5P6440_PA_PCM + 0x100 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = DMACH_PCM0_TX,
-               .end   = DMACH_PCM0_TX,
-               .flags = IORESOURCE_DMA,
-       },
-       [2] = {
-               .start = DMACH_PCM0_RX,
-               .end   = DMACH_PCM0_RX,
-               .flags = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device s5p6440_device_pcm = {
-       .name             = "samsung-pcm",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s5p6440_pcm0_resource),
-       .resource         = s5p6440_pcm0_resource,
-       .dev = {
-               .platform_data = &s3c_pcm_pdata,
-       },
-};
diff --git a/arch/arm/mach-s5p6440/dev-spi.c b/arch/arm/mach-s5p6440/dev-spi.c
deleted file mode 100644 (file)
index 510af44..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/dev-spi.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <mach/dma.h>
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/spi-clocks.h>
-
-#include <plat/s3c64xx-spi.h>
-#include <plat/gpio-cfg.h>
-
-static char *spi_src_clks[] = {
-       [S5P6440_SPI_SRCCLK_PCLK] = "pclk",
-       [S5P6440_SPI_SRCCLK_SCLK] = "spi_epll",
-};
-
-/* SPI Controller platform_devices */
-
-/* Since we emulate multi-cs capability, we do not touch the CS.
- * The emulated CS is toggled by board specific mechanism, as it can
- * be either some immediate GPIO or some signal out of some other
- * chip in between ... or some yet another way.
- * We simply do not assume anything about CS.
- */
-static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
-{
-       switch (pdev->id) {
-       case 0:
-               s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
-               s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
-               s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
-               s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
-               break;
-
-       case 1:
-               s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
-               s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
-               s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
-               s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
-               s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
-               break;
-
-       default:
-               dev_err(&pdev->dev, "Invalid SPI Controller number!");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static struct resource s5p6440_spi0_resource[] = {
-       [0] = {
-               .start = S5P6440_PA_SPI0,
-               .end   = S5P6440_PA_SPI0 + 0x100 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = DMACH_SPI0_TX,
-               .end   = DMACH_SPI0_TX,
-               .flags = IORESOURCE_DMA,
-       },
-       [2] = {
-               .start = DMACH_SPI0_RX,
-               .end   = DMACH_SPI0_RX,
-               .flags = IORESOURCE_DMA,
-       },
-       [3] = {
-               .start = IRQ_SPI0,
-               .end   = IRQ_SPI0,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
-       .cfg_gpio = s5p6440_spi_cfg_gpio,
-       .fifo_lvl_mask = 0x1ff,
-       .rx_lvl_offset = 15,
-};
-
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5p6440_device_spi0 = {
-       .name             = "s3c64xx-spi",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s5p6440_spi0_resource),
-       .resource         = s5p6440_spi0_resource,
-       .dev = {
-               .dma_mask               = &spi_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data = &s5p6440_spi0_pdata,
-       },
-};
-
-static struct resource s5p6440_spi1_resource[] = {
-       [0] = {
-               .start = S5P6440_PA_SPI1,
-               .end   = S5P6440_PA_SPI1 + 0x100 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = DMACH_SPI1_TX,
-               .end   = DMACH_SPI1_TX,
-               .flags = IORESOURCE_DMA,
-       },
-       [2] = {
-               .start = DMACH_SPI1_RX,
-               .end   = DMACH_SPI1_RX,
-               .flags = IORESOURCE_DMA,
-       },
-       [3] = {
-               .start = IRQ_SPI1,
-               .end   = IRQ_SPI1,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
-       .cfg_gpio = s5p6440_spi_cfg_gpio,
-       .fifo_lvl_mask = 0x7f,
-       .rx_lvl_offset = 15,
-};
-
-struct platform_device s5p6440_device_spi1 = {
-       .name             = "s3c64xx-spi",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s5p6440_spi1_resource),
-       .resource         = s5p6440_spi1_resource,
-       .dev = {
-               .dma_mask               = &spi_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data = &s5p6440_spi1_pdata,
-       },
-};
-
-void __init s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
-{
-       struct s3c64xx_spi_info *pd;
-
-       /* Reject invalid configuration */
-       if (!num_cs || src_clk_nr < 0
-                       || src_clk_nr > S5P6440_SPI_SRCCLK_SCLK) {
-               printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
-               return;
-       }
-
-       switch (cntrlr) {
-       case 0:
-               pd = &s5p6440_spi0_pdata;
-               break;
-       case 1:
-               pd = &s5p6440_spi1_pdata;
-               break;
-       default:
-               printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
-                                                       __func__, cntrlr);
-               return;
-       }
-
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       pd->src_clk_name = spi_src_clks[src_clk_nr];
-}
diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S
deleted file mode 100644 (file)
index 1347d7f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S
- *
- * Copyright (c) 2009 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 version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-
-       /* note, for the boot process to work we have to keep the UART
-        * virtual address aligned to an 1MiB boundary for the L1
-        * mapping the head code makes. We keep the UART virtual address
-        * aligned and add in the offset when we load the value here.
-        */
-
-       .macro addruart, rx, rtmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-       .endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h
deleted file mode 100644 (file)
index 2178383..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - GPIO lib support
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep  __gpio_cansleep
-#define gpio_to_irq    __gpio_to_irq
-
-/* GPIO bank sizes */
-#define S5P6440_GPIO_A_NR      (6)
-#define S5P6440_GPIO_B_NR      (7)
-#define S5P6440_GPIO_C_NR      (8)
-#define S5P6440_GPIO_F_NR      (2)
-#define S5P6440_GPIO_G_NR      (7)
-#define S5P6440_GPIO_H_NR      (10)
-#define S5P6440_GPIO_I_NR      (16)
-#define S5P6440_GPIO_J_NR      (12)
-#define S5P6440_GPIO_N_NR      (16)
-#define S5P6440_GPIO_P_NR      (8)
-#define S5P6440_GPIO_R_NR      (15)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-#define S5P6440_GPIO_NEXT(__gpio) \
-       ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-       S5P6440_GPIO_A_START = 0,
-       S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A),
-       S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B),
-       S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C),
-       S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F),
-       S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G),
-       S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H),
-       S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I),
-       S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J),
-       S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N),
-       S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P),
-};
-
-/* S5P6440 GPIO number definitions. */
-#define S5P6440_GPA(_nr)       (S5P6440_GPIO_A_START + (_nr))
-#define S5P6440_GPB(_nr)       (S5P6440_GPIO_B_START + (_nr))
-#define S5P6440_GPC(_nr)       (S5P6440_GPIO_C_START + (_nr))
-#define S5P6440_GPF(_nr)       (S5P6440_GPIO_F_START + (_nr))
-#define S5P6440_GPG(_nr)       (S5P6440_GPIO_G_START + (_nr))
-#define S5P6440_GPH(_nr)       (S5P6440_GPIO_H_START + (_nr))
-#define S5P6440_GPI(_nr)       (S5P6440_GPIO_I_START + (_nr))
-#define S5P6440_GPJ(_nr)       (S5P6440_GPIO_J_START + (_nr))
-#define S5P6440_GPN(_nr)       (S5P6440_GPIO_N_START + (_nr))
-#define S5P6440_GPP(_nr)       (S5P6440_GPIO_P_START + (_nr))
-#define S5P6440_GPR(_nr)       (S5P6440_GPIO_R_START + (_nr))
-
-/* the end of the S5P6440 specific gpios */
-#define S5P6440_GPIO_END       (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
-#define S3C_GPIO_END           S5P6440_GPIO_END
-
-/* define the number of gpios we need to the one after the GPR() range */
-#define ARCH_NR_GPIOS          (S5P6440_GPR(S5P6440_GPIO_R_NR) +       \
-                                CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h
deleted file mode 100644 (file)
index fa2d69c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5p6440/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C64XX based
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h
deleted file mode 100644 (file)
index 6cc5cbc..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/map.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - Memory map definitions
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5P6440_PA_CHIPID      (0xE0000000)
-#define S5P_PA_CHIPID          S5P6440_PA_CHIPID
-
-#define S5P6440_PA_SYSCON      (0xE0100000)
-#define S5P6440_PA_CLK         (S5P6440_PA_SYSCON + 0x0)
-#define S5P_PA_SYSCON          S5P6440_PA_SYSCON
-
-#define S5P6440_PA_GPIO                (0xE0308000)
-#define S5P_PA_GPIO            S5P6440_PA_GPIO
-
-#define S5P6440_PA_VIC0                (0xE4000000)
-#define S5P_PA_VIC0            S5P6440_PA_VIC0
-
-#define S5P6440_PA_PDMA                0xE9000000
-
-#define S5P6440_PA_VIC1                (0xE4100000)
-#define S5P_PA_VIC1            S5P6440_PA_VIC1
-
-#define S5P6440_PA_TIMER       (0xEA000000)
-#define S5P_PA_TIMER           S5P6440_PA_TIMER
-
-#define S5P6440_PA_RTC         (0xEA100000)
-
-#define S5P6440_PA_WDT         (0xEA200000)
-#define S5P_PA_WDT             S5P6440_PA_WDT
-
-#define S5P6440_PA_UART                (0xEC000000)
-
-#define S5P_PA_UART0           (S5P6440_PA_UART + 0x0)
-#define S5P_PA_UART1           (S5P6440_PA_UART + 0x400)
-#define S5P_PA_UART2           (S5P6440_PA_UART + 0x800)
-#define S5P_PA_UART3           (S5P6440_PA_UART + 0xC00)
-
-#define S5P_SZ_UART            SZ_256
-
-#define S5P6440_PA_IIC0                (0xEC104000)
-#define S5P6440_PA_IIC1                (0xEC20F000)
-
-#define S5P6440_PA_SPI0                0xEC400000
-#define S5P6440_PA_SPI1                0xEC500000
-
-#define S5P6440_PA_HSOTG       (0xED100000)
-
-#define S5P6440_PA_HSMMC0      (0xED800000)
-#define S5P6440_PA_HSMMC1      (0xED900000)
-#define S5P6440_PA_HSMMC2      (0xEDA00000)
-
-#define S5P6440_PA_SDRAM       (0x20000000)
-#define S5P_PA_SDRAM           S5P6440_PA_SDRAM
-
-/* I2S */
-#define S5P6440_PA_I2S         0xF2000000
-
-/* PCM */
-#define S5P6440_PA_PCM         0xF2100000
-
-#define S5P6440_PA_ADC         (0xF3000000)
-
-/* compatibiltiy defines. */
-#define S3C_PA_UART            S5P6440_PA_UART
-#define S3C_PA_IIC             S5P6440_PA_IIC0
-#define S3C_PA_RTC             S5P6440_PA_RTC
-#define S3C_PA_IIC1            S5P6440_PA_IIC1
-#define S3C_PA_WDT             S5P6440_PA_WDT
-
-#define SAMSUNG_PA_ADC         S5P6440_PA_ADC
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h
deleted file mode 100644 (file)
index c783ecc..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - Clock register definitions
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)          (S3C_VA_SYS + (x))
-
-#define S5P_APLL_LOCK          S5P_CLKREG(0x00)
-#define S5P_MPLL_LOCK          S5P_CLKREG(0x04)
-#define S5P_EPLL_LOCK          S5P_CLKREG(0x08)
-#define S5P_APLL_CON           S5P_CLKREG(0x0C)
-#define S5P_MPLL_CON           S5P_CLKREG(0x10)
-#define S5P_EPLL_CON           S5P_CLKREG(0x14)
-#define S5P_EPLL_CON_K         S5P_CLKREG(0x18)
-#define S5P_CLK_SRC0           S5P_CLKREG(0x1C)
-#define S5P_CLK_DIV0           S5P_CLKREG(0x20)
-#define S5P_CLK_DIV1           S5P_CLKREG(0x24)
-#define S5P_CLK_DIV2           S5P_CLKREG(0x28)
-#define S5P_CLK_OUT            S5P_CLKREG(0x2C)
-#define S5P_CLK_GATE_HCLK0     S5P_CLKREG(0x30)
-#define S5P_CLK_GATE_PCLK      S5P_CLKREG(0x34)
-#define S5P_CLK_GATE_SCLK0     S5P_CLKREG(0x38)
-#define S5P_CLK_GATE_MEM0      S5P_CLKREG(0x3C)
-#define S5P_CLK_DIV3           S5P_CLKREG(0x40)
-#define S5P_CLK_GATE_HCLK1     S5P_CLKREG(0x44)
-#define S5P_CLK_GATE_SCLK1     S5P_CLKREG(0x48)
-#define S5P_AHB_CON0                   S5P_CLKREG(0x100)
-#define S5P_CLK_SRC1                   S5P_CLKREG(0x10C)
-#define S5P_SWRESET            S5P_CLKREG(0x114)
-#define S5P_SYS_ID             S5P_CLKREG(0x118)
-#define S5P_SYS_OTHERS         S5P_CLKREG(0x11C)
-#define S5P_MEM_CFG_STAT       S5P_CLKREG(0x12C)
-#define S5P_PWR_CFG            S5P_CLKREG(0x804)
-#define S5P_EINT_WAKEUP_MASK   S5P_CLKREG(0x808)
-#define S5P_NORMAL_CFG         S5P_CLKREG(0x810)
-#define S5P_STOP_CFG           S5P_CLKREG(0x814)
-#define S5P_SLEEP_CFG          S5P_CLKREG(0x818)
-#define S5P_OSC_FREQ           S5P_CLKREG(0x820)
-#define S5P_OSC_STABLE         S5P_CLKREG(0x824)
-#define S5P_PWR_STABLE         S5P_CLKREG(0x828)
-#define S5P_MTC_STABLE         S5P_CLKREG(0x830)
-#define S5P_OTHERS             S5P_CLKREG(0x900)
-#define S5P_RST_STAT           S5P_CLKREG(0x904)
-#define S5P_WAKEUP_STAT                S5P_CLKREG(0x908)
-#define S5P_SLPEN              S5P_CLKREG(0x930)
-#define S5P_INFORM0            S5P_CLKREG(0xA00)
-#define S5P_INFORM1            S5P_CLKREG(0xA04)
-#define S5P_INFORM2            S5P_CLKREG(0xA08)
-#define S5P_INFORM3            S5P_CLKREG(0xA0C)
-
-/* CLKDIV0 */
-#define S5P_CLKDIV0_PCLK_MASK          (0xf << 12)
-#define S5P_CLKDIV0_PCLK_SHIFT         (12)
-#define S5P_CLKDIV0_HCLK_MASK          (0xf << 8)
-#define S5P_CLKDIV0_HCLK_SHIFT         (8)
-#define S5P_CLKDIV0_MPLL_MASK          (0x1 << 4)
-#define S5P_CLKDIV0_ARM_MASK           (0xf << 0)
-#define S5P_CLKDIV0_ARM_SHIFT          (0)
-
-/* CLKDIV3 */
-#define S5P_CLKDIV3_PCLK_LOW_MASK      (0xf << 12)
-#define S5P_CLKDIV3_PCLK_LOW_SHIFT     (12)
-#define S5P_CLKDIV3_HCLK_LOW_MASK      (0xf << 8)
-#define S5P_CLKDIV3_HCLK_LOW_SHIFT     (8)
-
-/* HCLK0 GATE Registers */
-#define S5P_CLKCON_HCLK0_USB           (1<<20)
-#define S5P_CLKCON_HCLK0_HSMMC2                (1<<19)
-#define S5P_CLKCON_HCLK0_HSMMC1                (1<<18)
-#define S5P_CLKCON_HCLK0_HSMMC0                (1<<17)
-#define S5P_CLKCON_HCLK0_POST0         (1<<5)
-
-/* HCLK1 GATE Registers */
-#define S5P_CLKCON_HCLK1_DISPCON       (1<<1)
-
-/* PCLK GATE Registers */
-#define S5P_CLKCON_PCLK_IIS2           (1<<26)
-#define S5P_CLKCON_PCLK_SPI1           (1<<22)
-#define S5P_CLKCON_PCLK_SPI0           (1<<21)
-#define S5P_CLKCON_PCLK_GPIO           (1<<18)
-#define S5P_CLKCON_PCLK_IIC0           (1<<17)
-#define S5P_CLKCON_PCLK_TSADC          (1<<12)
-#define S5P_CLKCON_PCLK_PWM            (1<<7)
-#define S5P_CLKCON_PCLK_RTC            (1<<6)
-#define S5P_CLKCON_PCLK_WDT            (1<<5)
-#define S5P_CLKCON_PCLK_UART3          (1<<4)
-#define S5P_CLKCON_PCLK_UART2          (1<<3)
-#define S5P_CLKCON_PCLK_UART1          (1<<2)
-#define S5P_CLKCON_PCLK_UART0          (1<<1)
-
-/* SCLK0 GATE Registers */
-#define S5P_CLKCON_SCLK0_MMC2_48       (1<<29)
-#define S5P_CLKCON_SCLK0_MMC1_48       (1<<28)
-#define S5P_CLKCON_SCLK0_MMC0_48       (1<<27)
-#define S5P_CLKCON_SCLK0_MMC2          (1<<26)
-#define S5P_CLKCON_SCLK0_MMC1          (1<<25)
-#define S5P_CLKCON_SCLK0_MMC0          (1<<24)
-#define S5P_CLKCON_SCLK0_SPI1_48       (1<<23)
-#define S5P_CLKCON_SCLK0_SPI0_48       (1<<22)
-#define S5P_CLKCON_SCLK0_SPI1          (1<<21)
-#define S5P_CLKCON_SCLK0_SPI0          (1<<20)
-#define S5P_CLKCON_SCLK0_UART          (1<<5)
-
-/* SCLK1 GATE Registers */
-
-/* MEM0 GATE Registers */
-#define S5P_CLKCON_MEM0_HCLK_NFCON     (1<<2)
-
-/*OTHERS Resgister */
-#define S5P_OTHERS_USB_SIG_MASK                (1<<16)
-#define S5P_OTHERS_HCLK_LOW_SEL_MPLL   (1<<6)
-
-/* Compatibility defines */
-#define ARM_CLK_DIV                    S5P_CLK_DIV0
-#define ARM_DIV_RATIO_SHIFT            0
-#define ARM_DIV_MASK                   (0xf << ARM_DIV_RATIO_SHIFT)
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h b/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 5fbca50..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5P6440_PLAT_SPI_CLKS_H
-#define __S5P6440_PLAT_SPI_CLKS_H __FILE__
-
-#define S5P6440_SPI_SRCCLK_PCLK                0
-#define S5P6440_SPI_SRCCLK_SCLK                1
-
-#endif /* __S5P6440_PLAT_SPI_CLKS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h
deleted file mode 100644 (file)
index 7c1f600..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - uncompress code
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static void arch_detect_cpu(void)
-{
-       /* we do not need to do any cpu detection here at the moment. */
-}
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c
deleted file mode 100644 (file)
index a1f3727..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/init.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P6440 - Init support
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/s5p6440.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc s5p6440_serial_clocks[] = {
-       [0] = {
-               .name           = "pclk_low",
-               .divisor        = 1,
-               .min_baud       = 0,
-               .max_baud       = 0,
-       },
-       [1] = {
-               .name           = "uclk1",
-               .divisor        = 1,
-               .min_baud       = 0,
-               .max_baud       = 0,
-       },
-};
-
-/* uart registration process */
-void __init s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-       struct s3c2410_uartcfg *tcfg = cfg;
-       u32 ucnt;
-
-       for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
-               if (!tcfg->clocks) {
-                       tcfg->clocks = s5p6440_serial_clocks;
-                       tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks);
-               }
-       }
-
-       s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
index a48fb553fd01cf5d42e1ab590146d7cad1e7680f..842af86bda6def3db35fcab32bd36127f5e14aad 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s5p6442/cpu.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ *             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 version 2 as
@@ -19,6 +19,7 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -46,11 +47,31 @@ static struct map_desc s5p6442_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(S5P6442_PA_SYSTIMER),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GPIO,
+               .pfn            = __phys_to_pfn(S5P6442_PA_GPIO),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC0,
+               .pfn            = __phys_to_pfn(S5P6442_PA_VIC0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC1,
+               .pfn            = __phys_to_pfn(S5P6442_PA_VIC1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)VA_VIC2,
                .pfn            = __phys_to_pfn(S5P6442_PA_VIC2),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S3C_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
        }
 };
 
@@ -62,10 +83,11 @@ static void s5p6442_idle(void)
        local_irq_enable();
 }
 
-/* s5p6442_map_io
+/*
+ * s5p6442_map_io
  *
  * register the standard cpu IO areas
-*/
+ */
 
 void __init s5p6442_map_io(void)
 {
index bb6536147ffb0bd7c55c95d8eb796401824ceeb7..e2213205d780bbdfdb0083d49747b632ebbf445b 100644 (file)
 #include <mach/map.h>
 #include <plat/regs-serial.h>
 
-       .macro addruart, rx, rtmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = S3C_VA_UART
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C_PA_UART
+               ldr     \rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index 281d256faafb0d6e4e817261ac78e5b091a4078d..31fb2e68d527915080df5f9ff498c835218f972c 100644 (file)
 #define S5P_PA_SYSCON          S5P6442_PA_SYSCON
 
 #define S5P6442_PA_GPIO                (0xE0200000)
-#define S5P_PA_GPIO            S5P6442_PA_GPIO
 
 #define S5P6442_PA_VIC0                (0xE4000000)
-#define S5P_PA_VIC0            S5P6442_PA_VIC0
-
 #define S5P6442_PA_VIC1                (0xE4100000)
-#define S5P_PA_VIC1            S5P6442_PA_VIC1
-
 #define S5P6442_PA_VIC2                (0xE4200000)
-#define S5P_PA_VIC2            S5P6442_PA_VIC2
 
 #define S5P6442_PA_MDMA                0xE8000000
 #define S5P6442_PA_PDMA                0xE9000000
index be3333688c20d98015eba94704c1ad84502d7b6c..f5c83f02c18efe57aed0b021779d160469dcc86f 100644 (file)
@@ -12,6 +12,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END      (0xE0000000)
+#define VMALLOC_END    0xE0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 8d8d04272f852eec0bf843d94a2f14a80a5a3b79..819fd80d00afc74a34c2741409de363bd14ecde7 100644 (file)
@@ -83,8 +83,6 @@ static void __init smdk6442_machine_init(void)
 
 MACHINE_START(SMDK6442, "SMDK6442")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5p6442_init_irq,
        .map_io         = smdk6442_map_io,
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
new file mode 100644 (file)
index 0000000..fbcae93
--- /dev/null
@@ -0,0 +1,57 @@
+# arch/arm/mach-s5p64x0/Kconfig
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+#              http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+if ARCH_S5P64X0
+
+config CPU_S5P6440
+       bool
+       select PLAT_S5P
+       select S3C_PL330_DMA
+       help
+         Enable S5P6440 CPU support
+
+config CPU_S5P6450
+       bool
+       select PLAT_S5P
+       select S3C_PL330_DMA
+       help
+         Enable S5P6450 CPU support
+
+config S5P64X0_SETUP_I2C1
+       bool
+       help
+         Common setup code for i2c bus 1.
+
+# machine support
+
+config MACH_SMDK6440
+       bool "SMDK6440"
+       select CPU_S5P6440
+       select S3C_DEV_I2C1
+       select S3C_DEV_RTC
+       select S3C_DEV_WDT
+       select S3C64XX_DEV_SPI
+       select SAMSUNG_DEV_ADC
+       select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_I2C1
+       help
+         Machine support for the Samsung SMDK6440
+
+config MACH_SMDK6450
+       bool "SMDK6450"
+       select CPU_S5P6450
+       select S3C_DEV_I2C1
+       select S3C_DEV_RTC
+       select S3C_DEV_WDT
+       select S3C64XX_DEV_SPI
+       select SAMSUNG_DEV_ADC
+       select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_I2C1
+       help
+         Machine support for the Samsung SMDK6450
+
+endif
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
new file mode 100644 (file)
index 0000000..2655829
--- /dev/null
@@ -0,0 +1,30 @@
+# arch/arm/mach-s5p64x0/Makefile
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+#              http://www.samsung.com
+#
+# Licensed under GPLv2
+
+obj-y                          :=
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+# Core support for S5P64X0 system
+
+obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.o
+obj-$(CONFIG_ARCH_S5P64X0)     += setup-i2c0.o
+obj-$(CONFIG_CPU_S5P6440)      += clock-s5p6440.o gpio.o
+obj-$(CONFIG_CPU_S5P6450)      += clock-s5p6450.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDK6440)    += mach-smdk6440.o
+obj-$(CONFIG_MACH_SMDK6450)    += mach-smdk6450.o
+
+# device support
+
+obj-y                          += dev-audio.o
+obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
+
+obj-$(CONFIG_S5P64X0_SETUP_I2C1)       += setup-i2c1.o
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
new file mode 100644 (file)
index 0000000..f93dcd8
--- /dev/null
@@ -0,0 +1,626 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P6440 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+
+static u32 epll_div[][5] = {
+       { 36000000,     0,      48, 1, 4 },
+       { 48000000,     0,      32, 1, 3 },
+       { 60000000,     0,      40, 1, 3 },
+       { 72000000,     0,      48, 1, 3 },
+       { 84000000,     0,      28, 1, 2 },
+       { 96000000,     0,      32, 1, 2 },
+       { 32768000,     45264,  43, 1, 4 },
+       { 45158000,     6903,   30, 1, 3 },
+       { 49152000,     50332,  32, 1, 3 },
+       { 67738000,     10398,  45, 1, 3 },
+       { 73728000,     9961,   49, 1, 3 }
+};
+
+static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int epll_con, epll_con_k;
+       unsigned int i;
+
+       if (clk->rate == rate)  /* Return if nothing changed */
+               return 0;
+
+       epll_con = __raw_readl(S5P64X0_EPLL_CON);
+       epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+       epll_con_k &= ~(PLL90XX_KDIV_MASK);
+       epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+                if (epll_div[i][0] == rate) {
+                       epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+                       epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+                                   (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+                                   (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(epll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(epll_con, S5P64X0_EPLL_CON);
+       __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+       clk->rate = rate;
+
+       return 0;
+}
+
+static struct clk_ops s5p6440_epll_ops = {
+       .get_rate = s5p64x0_epll_get_rate,
+       .set_rate = s5p6440_epll_set_rate,
+};
+
+static struct clksrc_clk clk_hclk = {
+       .clk    = {
+               .name           = "clk_hclk",
+               .id             = -1,
+               .parent         = &clk_armclk.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+       .clk    = {
+               .name           = "clk_pclk",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_hclk_low = {
+       .clk    = {
+               .name           = "clk_hclk_low",
+               .id             = -1,
+       },
+       .sources        = &clkset_hclk_low,
+       .reg_src        = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+       .clk    = {
+               .name           = "clk_pclk_low",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_mem_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "post",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 5)
+       }, {
+               .name           = "2d",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "hsmmc",
+               .id             = 0,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 17),
+       }, {
+               .name           = "hsmmc",
+               .id             = 1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 18),
+       }, {
+               .name           = "hsmmc",
+               .id             = 2,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 19),
+       }, {
+               .name           = "otg",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 20)
+       }, {
+               .name           = "irom",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 25),
+       }, {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk1_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "hclk_fimgvg",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk1_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "tsi",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk1_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 6),
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = "pcm",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 17),
+       }, {
+               .name           = "spi",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 21),
+       }, {
+               .name           = "spi",
+               .id             = 1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 22),
+       }, {
+               .name           = "gps",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 25),
+       }, {
+               .name           = "i2s_v40",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 26),
+       }, {
+               .name           = "dsim",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 28),
+       }, {
+               .name           = "etm",
+               .id             = -1,
+               .parent         = &clk_pclk.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 29),
+       }, {
+               .name           = "dmc0",
+               .id             = -1,
+               .parent         = &clk_pclk.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 30),
+       }, {
+               .name           = "pclk_fimgvg",
+               .id             = -1,
+               .parent         = &clk_pclk.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 31),
+       }, {
+               .name           = "sclk_spi_48",
+               .id             = 0,
+               .parent         = &clk_48m,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 22),
+       }, {
+               .name           = "sclk_spi_48",
+               .id             = 1,
+               .parent         = &clk_48m,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 23),
+       }, {
+               .name           = "mmc_48m",
+               .id             = 0,
+               .parent         = &clk_48m,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 27),
+       }, {
+               .name           = "mmc_48m",
+               .id             = 1,
+               .parent         = &clk_48m,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 28),
+       }, {
+               .name           = "mmc_48m",
+               .id             = 2,
+               .parent         = &clk_48m,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 29),
+       },
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+       {
+               .name           = "intc",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "mem",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 21),
+       }, {
+               .name           = "dma",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "uart",
+               .id             = 3,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 18),
+       },
+};
+
+static struct clk clk_iis_cd_v40 = {
+       .name           = "iis_cdclk_v40",
+       .id             = -1,
+};
+
+static struct clk clk_pcm_cd = {
+       .name           = "pcm_cdclk",
+       .id             = -1,
+};
+
+static struct clk *clkset_group1_list[] = {
+       &clk_mout_epll.clk,
+       &clk_dout_mpll.clk,
+       &clk_fin_epll,
+};
+
+static struct clksrc_sources clkset_group1 = {
+       .sources        = clkset_group1_list,
+       .nr_sources     = ARRAY_SIZE(clkset_group1_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+       &clk_mout_epll.clk,
+       &clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+       .sources        = clkset_uart_list,
+       .nr_sources     = ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_audio_list[] = {
+       &clk_mout_epll.clk,
+       &clk_dout_mpll.clk,
+       &clk_fin_epll,
+       &clk_iis_cd_v40,
+       &clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio = {
+       .sources        = clkset_audio_list,
+       .nr_sources     = ARRAY_SIZE(clkset_audio_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+       {
+               .clk    = {
+                       .name           = "mmc_bus",
+                       .id             = 0,
+                       .ctrlbit        = (1 << 24),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "mmc_bus",
+                       .id             = 1,
+                       .ctrlbit        = (1 << 25),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "mmc_bus",
+                       .id             = 2,
+                       .ctrlbit        = (1 << 26),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "uclk1",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 5),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_uart,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_spi",
+                       .id             = 0,
+                       .ctrlbit        = (1 << 20),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_spi",
+                       .id             = 1,
+                       .ctrlbit        = (1 << 21),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_post",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 10),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_dispcon",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 1),
+                       .enable         = s5p64x0_sclk1_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_fimgvg",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 2),
+                       .enable         = s5p64x0_sclk1_ctrl,
+               },
+               .sources = &clkset_group1,
+               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_audio2",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 11),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_audio,
+               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
+       },
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+       &clk_mout_apll,
+       &clk_mout_epll,
+       &clk_mout_mpll,
+       &clk_dout_mpll,
+       &clk_armclk,
+       &clk_hclk,
+       &clk_pclk,
+       &clk_hclk_low,
+       &clk_pclk_low,
+};
+
+void __init_or_cpufreq s5p6440_setup_clocks(void)
+{
+       struct clk *xtal_clk;
+
+       unsigned long xtal;
+       unsigned long fclk;
+       unsigned long hclk;
+       unsigned long hclk_low;
+       unsigned long pclk;
+       unsigned long pclk_low;
+
+       unsigned long apll;
+       unsigned long mpll;
+       unsigned long epll;
+       unsigned int ptr;
+
+       /* Set S5P6440 functions for clk_fout_epll */
+
+       clk_fout_epll.enable = s5p64x0_epll_enable;
+       clk_fout_epll.ops = &s5p6440_epll_ops;
+
+       clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+       xtal_clk = clk_get(NULL, "ext_xtal");
+       BUG_ON(IS_ERR(xtal_clk));
+
+       xtal = clk_get_rate(xtal_clk);
+       clk_put(xtal_clk);
+
+       apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+       mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+       epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+                               __raw_readl(S5P64X0_EPLL_CON_K));
+
+       clk_fout_apll.rate = apll;
+       clk_fout_mpll.rate = mpll;
+       clk_fout_epll.rate = epll;
+
+       printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+                       " E=%ld.%ldMHz\n",
+                       print_mhz(apll), print_mhz(mpll), print_mhz(epll));
+
+       fclk = clk_get_rate(&clk_armclk.clk);
+       hclk = clk_get_rate(&clk_hclk.clk);
+       pclk = clk_get_rate(&clk_pclk.clk);
+       hclk_low = clk_get_rate(&clk_hclk_low.clk);
+       pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+       printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+                       " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+                       print_mhz(hclk), print_mhz(hclk_low),
+                       print_mhz(pclk), print_mhz(pclk_low));
+
+       clk_f.rate = fclk;
+       clk_h.rate = hclk;
+       clk_p.rate = pclk;
+
+       for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+               s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+       &clk_ext,
+       &clk_iis_cd_v40,
+       &clk_pcm_cd,
+};
+
+void __init s5p6440_register_clocks(void)
+{
+       struct clk *clkp;
+       int ret;
+       int ptr;
+
+       s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+       for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+               s3c_register_clksrc(sysclks[ptr], 1);
+
+       s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+       s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+               (clkp->enable)(clkp, 0);
+       }
+
+       s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
new file mode 100644 (file)
index 0000000..f9afb05
--- /dev/null
@@ -0,0 +1,655 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P6450 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6450.h>
+
+static struct clksrc_clk clk_mout_dpll = {
+       .clk    = {
+               .name           = "mout_dpll",
+               .id             = -1,
+       },
+       .sources        = &clk_src_dpll,
+       .reg_src        = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
+};
+
+static u32 epll_div[][5] = {
+       { 133000000,    27307,  55, 2, 2 },
+       { 100000000,    43691,  41, 2, 2 },
+       { 480000000,    0,      80, 2, 0 },
+};
+
+static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int epll_con, epll_con_k;
+       unsigned int i;
+
+       if (clk->rate == rate)  /* Return if nothing changed */
+               return 0;
+
+       epll_con = __raw_readl(S5P64X0_EPLL_CON);
+       epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+       epll_con_k &= ~(PLL90XX_KDIV_MASK);
+       epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+                if (epll_div[i][0] == rate) {
+                       epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+                       epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+                                   (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+                                   (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(epll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(epll_con, S5P64X0_EPLL_CON);
+       __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+       clk->rate = rate;
+
+       return 0;
+}
+
+static struct clk_ops s5p6450_epll_ops = {
+       .get_rate = s5p64x0_epll_get_rate,
+       .set_rate = s5p6450_epll_set_rate,
+};
+
+static struct clksrc_clk clk_dout_epll = {
+       .clk    = {
+               .name           = "dout_epll",
+               .id             = -1,
+               .parent         = &clk_mout_epll.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
+};
+
+static struct clksrc_clk clk_mout_hclk_sel = {
+       .clk    = {
+               .name           = "mout_hclk_sel",
+               .id             = -1,
+       },
+       .sources        = &clkset_hclk_low,
+       .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
+};
+
+static struct clk *clkset_hclk_list[] = {
+       &clk_mout_hclk_sel.clk,
+       &clk_armclk.clk,
+};
+
+static struct clksrc_sources clkset_hclk = {
+       .sources        = clkset_hclk_list,
+       .nr_sources     = ARRAY_SIZE(clkset_hclk_list),
+};
+
+static struct clksrc_clk clk_hclk = {
+       .clk    = {
+               .name           = "clk_hclk",
+               .id             = -1,
+       },
+       .sources        = &clkset_hclk,
+       .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+       .clk    = {
+               .name           = "clk_pclk",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+       },
+       .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_dout_pwm_ratio0 = {
+       .clk    = {
+               .name           = "clk_dout_pwm_ratio0",
+               .id             = -1,
+               .parent         = &clk_mout_hclk_sel.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_to_wdt_pwm = {
+       .clk    = {
+               .name           = "clk_pclk_to_wdt_pwm",
+               .id             = -1,
+               .parent         = &clk_dout_pwm_ratio0.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
+};
+
+static struct clksrc_clk clk_hclk_low = {
+       .clk    = {
+               .name           = "clk_hclk_low",
+               .id             = -1,
+       },
+       .sources        = &clkset_hclk_low,
+       .reg_src        = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+       .clk    = {
+               .name           = "clk_pclk_low",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "usbhost",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "hsmmc",
+               .id             = 0,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 17),
+       }, {
+               .name           = "hsmmc",
+               .id             = 1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 18),
+       }, {
+               .name           = "hsmmc",
+               .id             = 2,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 19),
+       }, {
+               .name           = "usbotg",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 20),
+       }, {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s5p64x0_hclk1_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "i2c",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 17),
+       }, {
+               .name           = "spi",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 21),
+       }, {
+               .name           = "spi",
+               .id             = 1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 22),
+       }, {
+               .name           = "iis",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 26),
+       }, {
+               .name           = "i2c",
+               .id             = 1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 27),
+       }, {
+               .name           = "dmc0",
+               .id             = -1,
+               .parent         = &clk_pclk.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 30),
+       }
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+       {
+               .name           = "intc",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "mem",
+               .id             = -1,
+               .parent         = &clk_hclk.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 21),
+       }, {
+               .name           = "dma",
+               .id             = -1,
+               .parent         = &clk_hclk_low.clk,
+               .enable         = s5p64x0_hclk0_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "uart",
+               .id             = 3,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_pclk_to_wdt_pwm.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_pclk_low.clk,
+               .enable         = s5p64x0_pclk_ctrl,
+               .ctrlbit        = (1 << 18),
+       },
+};
+
+static struct clk *clkset_uart_list[] = {
+       &clk_dout_epll.clk,
+       &clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+       .sources        = clkset_uart_list,
+       .nr_sources     = ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_mali_list[] = {
+       &clk_mout_epll.clk,
+       &clk_mout_apll.clk,
+       &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_mali = {
+       .sources        = clkset_mali_list,
+       .nr_sources     = ARRAY_SIZE(clkset_mali_list),
+};
+
+static struct clk *clkset_group2_list[] = {
+       &clk_dout_epll.clk,
+       &clk_dout_mpll.clk,
+       &clk_ext_xtal_mux,
+};
+
+static struct clksrc_sources clkset_group2 = {
+       .sources        = clkset_group2_list,
+       .nr_sources     = ARRAY_SIZE(clkset_group2_list),
+};
+
+static struct clk *clkset_dispcon_list[] = {
+       &clk_dout_epll.clk,
+       &clk_dout_mpll.clk,
+       &clk_ext_xtal_mux,
+       &clk_mout_dpll.clk,
+};
+
+static struct clksrc_sources clkset_dispcon = {
+       .sources        = clkset_dispcon_list,
+       .nr_sources     = ARRAY_SIZE(clkset_dispcon_list),
+};
+
+static struct clk *clkset_hsmmc44_list[] = {
+       &clk_dout_epll.clk,
+       &clk_dout_mpll.clk,
+       &clk_ext_xtal_mux,
+       &s5p_clk_27m,
+       &clk_48m,
+};
+
+static struct clksrc_sources clkset_hsmmc44 = {
+       .sources        = clkset_hsmmc44_list,
+       .nr_sources     = ARRAY_SIZE(clkset_hsmmc44_list),
+};
+
+static struct clk *clkset_sclk_audio0_list[] = {
+       [0] = &clk_dout_epll.clk,
+       [1] = &clk_dout_mpll.clk,
+       [2] = &clk_ext_xtal_mux,
+       [3] = NULL,
+       [4] = NULL,
+};
+
+static struct clksrc_sources clkset_sclk_audio0 = {
+       .sources        = clkset_sclk_audio0_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_audio0_list),
+};
+
+static struct clksrc_clk clk_sclk_audio0 = {
+       .clk            = {
+               .name           = "audio-bus",
+               .id             = -1,
+               .enable         = s5p64x0_sclk_ctrl,
+               .ctrlbit        = (1 << 8),
+               .parent         = &clk_dout_epll.clk,
+       },
+       .sources        = &clkset_sclk_audio0,
+       .reg_src        = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+       {
+               .clk    = {
+                       .name           = "sclk_mmc",
+                       .id             = 0,
+                       .ctrlbit        = (1 << 24),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_mmc",
+                       .id             = 1,
+                       .ctrlbit        = (1 << 25),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_mmc",
+                       .id             = 2,
+                       .ctrlbit        = (1 << 26),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "uclk1",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 5),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_uart,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_spi",
+                       .id             = 0,
+                       .ctrlbit        = (1 << 20),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_spi",
+                       .id             = 1,
+                       .ctrlbit        = (1 << 21),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_fimc",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 10),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "aclk_mali",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 2),
+                       .enable         = s5p64x0_sclk1_ctrl,
+               },
+               .sources = &clkset_mali,
+               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_2d",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 12),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_mali,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_usi",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 7),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_camif",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 6),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_group2,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_dispcon",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 1),
+                       .enable         = s5p64x0_sclk1_ctrl,
+               },
+               .sources = &clkset_dispcon,
+               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_hsmmc44",
+                       .id             = -1,
+                       .ctrlbit        = (1 << 30),
+                       .enable         = s5p64x0_sclk_ctrl,
+               },
+               .sources = &clkset_hsmmc44,
+               .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
+               .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
+       },
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+       &clk_mout_apll,
+       &clk_mout_epll,
+       &clk_dout_epll,
+       &clk_mout_mpll,
+       &clk_dout_mpll,
+       &clk_armclk,
+       &clk_mout_hclk_sel,
+       &clk_dout_pwm_ratio0,
+       &clk_pclk_to_wdt_pwm,
+       &clk_hclk,
+       &clk_pclk,
+       &clk_hclk_low,
+       &clk_pclk_low,
+       &clk_sclk_audio0,
+};
+
+void __init_or_cpufreq s5p6450_setup_clocks(void)
+{
+       struct clk *xtal_clk;
+
+       unsigned long xtal;
+       unsigned long fclk;
+       unsigned long hclk;
+       unsigned long hclk_low;
+       unsigned long pclk;
+       unsigned long pclk_low;
+
+       unsigned long apll;
+       unsigned long mpll;
+       unsigned long epll;
+       unsigned long dpll;
+       unsigned int ptr;
+
+       /* Set S5P6450 functions for clk_fout_epll */
+
+       clk_fout_epll.enable = s5p64x0_epll_enable;
+       clk_fout_epll.ops = &s5p6450_epll_ops;
+
+       clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+       xtal_clk = clk_get(NULL, "ext_xtal");
+       BUG_ON(IS_ERR(xtal_clk));
+
+       xtal = clk_get_rate(xtal_clk);
+       clk_put(xtal_clk);
+
+       apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+       mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+       epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+                               __raw_readl(S5P64X0_EPLL_CON_K));
+       dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
+                               __raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
+
+       clk_fout_apll.rate = apll;
+       clk_fout_mpll.rate = mpll;
+       clk_fout_epll.rate = epll;
+       clk_fout_dpll.rate = dpll;
+
+       printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+                       " E=%ld.%ldMHz, D=%ld.%ldMHz\n",
+                       print_mhz(apll), print_mhz(mpll), print_mhz(epll),
+                       print_mhz(dpll));
+
+       fclk = clk_get_rate(&clk_armclk.clk);
+       hclk = clk_get_rate(&clk_hclk.clk);
+       pclk = clk_get_rate(&clk_pclk.clk);
+       hclk_low = clk_get_rate(&clk_hclk_low.clk);
+       pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+       printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+                       " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+                       print_mhz(hclk), print_mhz(hclk_low),
+                       print_mhz(pclk), print_mhz(pclk_low));
+
+       clk_f.rate = fclk;
+       clk_h.rate = hclk;
+       clk_p.rate = pclk;
+
+       for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+               s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+void __init s5p6450_register_clocks(void)
+{
+       struct clk *clkp;
+       int ret;
+       int ptr;
+
+       for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+               s3c_register_clksrc(sysclks[ptr], 1);
+
+       s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+       s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+               (clkp->enable)(clkp, 0);
+       }
+
+       s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c
new file mode 100644 (file)
index 0000000..523ba80
--- /dev/null
@@ -0,0 +1,253 @@
+/* linux/arch/arm/mach-s5p64x0/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+
+struct clksrc_clk clk_mout_apll = {
+       .clk    = {
+               .name           = "mout_apll",
+               .id             = -1,
+       },
+       .sources        = &clk_src_apll,
+       .reg_src        = { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+       .clk    = {
+               .name           = "mout_mpll",
+               .id             = -1,
+       },
+       .sources        = &clk_src_mpll,
+       .reg_src        = { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+       .clk    = {
+               .name           = "mout_epll",
+               .id             = -1,
+       },
+       .sources        = &clk_src_epll,
+       .reg_src        = { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 },
+};
+
+enum perf_level {
+       L0 = 532*1000,
+       L1 = 266*1000,
+       L2 = 133*1000,
+};
+
+static const u32 clock_table[][3] = {
+       /*{ARM_CLK, DIVarm, DIVhclk}*/
+       {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+       {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+       {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+};
+
+int s5p64x0_epll_enable(struct clk *clk, int enable)
+{
+       unsigned int ctrlbit = clk->ctrlbit;
+       unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit;
+
+       if (enable)
+               __raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON);
+       else
+               __raw_writel(epll_con, S5P64X0_EPLL_CON);
+
+       return 0;
+}
+
+unsigned long s5p64x0_epll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
+{
+       unsigned long rate = clk_get_rate(clk->parent);
+       u32 clkdiv;
+
+       /* divisor mask starts at bit0, so no need to shift */
+       clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
+
+       return rate / (clkdiv + 1);
+}
+
+unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 iter;
+
+       for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+               if (rate > clock_table[iter][0])
+                       return clock_table[iter-1][0];
+       }
+
+       return clock_table[ARRAY_SIZE(clock_table) - 1][0];
+}
+
+int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 round_tmp;
+       u32 iter;
+       u32 clk_div0_tmp;
+       u32 cur_rate = clk->ops->get_rate(clk);
+       unsigned long flags;
+
+       round_tmp = clk->ops->round_rate(clk, rate);
+       if (round_tmp == cur_rate)
+               return 0;
+
+
+       for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+               if (round_tmp == clock_table[iter][0])
+                       break;
+       }
+
+       if (iter >= ARRAY_SIZE(clock_table))
+               iter = ARRAY_SIZE(clock_table) - 1;
+
+       local_irq_save(flags);
+       if (cur_rate > round_tmp) {
+               /* Frequency Down */
+               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+               clk_div0_tmp |= clock_table[iter][1];
+               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+                               ~(S5P64X0_CLKDIV0_HCLK_MASK);
+               clk_div0_tmp |= clock_table[iter][2];
+               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+
+       } else {
+               /* Frequency Up */
+               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+                               ~(S5P64X0_CLKDIV0_HCLK_MASK);
+               clk_div0_tmp |= clock_table[iter][2];
+               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+               clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+               clk_div0_tmp |= clock_table[iter][1];
+               __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+       }
+       local_irq_restore(flags);
+
+       clk->rate = clock_table[iter][0];
+
+       return 0;
+}
+
+struct clk_ops s5p64x0_clkarm_ops = {
+       .get_rate       = s5p64x0_armclk_get_rate,
+       .set_rate       = s5p64x0_armclk_set_rate,
+       .round_rate     = s5p64x0_armclk_round_rate,
+};
+
+struct clksrc_clk clk_armclk = {
+       .clk    = {
+               .name           = "armclk",
+               .id             = 1,
+               .parent         = &clk_mout_apll.clk,
+               .ops            = &s5p64x0_clkarm_ops,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 },
+};
+
+struct clksrc_clk clk_dout_mpll = {
+       .clk    = {
+               .name           = "dout_mpll",
+               .id             = -1,
+               .parent         = &clk_mout_mpll.clk,
+       },
+       .reg_div        = { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 },
+};
+
+struct clk *clkset_hclk_low_list[] = {
+       &clk_mout_apll.clk,
+       &clk_mout_mpll.clk,
+};
+
+struct clksrc_sources clkset_hclk_low = {
+       .sources        = clkset_hclk_low_list,
+       .nr_sources     = ARRAY_SIZE(clkset_hclk_low_list),
+};
+
+int s5p64x0_pclk_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable);
+}
+
+int s5p64x0_hclk0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable);
+}
+
+int s5p64x0_hclk1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable);
+}
+
+int s5p64x0_sclk_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable);
+}
+
+int s5p64x0_sclk1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable);
+}
+
+int s5p64x0_mem_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable);
+}
+
+int s5p64x0_clk48m_ctrl(struct clk *clk, int enable)
+{
+       unsigned long flags;
+       u32 val;
+
+       /* can't rely on clock lock, this register has other usages */
+       local_irq_save(flags);
+
+       val = __raw_readl(S5P64X0_OTHERS);
+       if (enable)
+               val |= S5P64X0_OTHERS_USB_SIG_MASK;
+       else
+               val &= ~S5P64X0_OTHERS_USB_SIG_MASK;
+
+       __raw_writel(val, S5P64X0_OTHERS);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c
new file mode 100644 (file)
index 0000000..b8d02eb
--- /dev/null
@@ -0,0 +1,209 @@
+/* linux/arch/arm/mach-s5p64x0/cpu.c
+ *
+ * Copyright (c) 2009-2010 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/proc-fns.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/adc-core.h>
+
+/* Initial IO mappings */
+
+static struct map_desc s5p64x0_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)S5P_VA_GPIO,
+               .pfn            = __phys_to_pfn(S5P64X0_PA_GPIO),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC0,
+               .pfn            = __phys_to_pfn(S5P64X0_PA_VIC0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC1,
+               .pfn            = __phys_to_pfn(S5P64X0_PA_VIC1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       },
+};
+
+static struct map_desc s5p6440_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S5P6440_PA_UART(0)),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       },
+};
+
+static struct map_desc s5p6450_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S5P6450_PA_UART(0)),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART + SZ_512K,
+               .pfn            = __phys_to_pfn(S5P6450_PA_UART(5)),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       },
+};
+
+static void s5p64x0_idle(void)
+{
+       unsigned long val;
+
+       if (!need_resched()) {
+               val = __raw_readl(S5P64X0_PWR_CFG);
+               val &= ~(0x3 << 5);
+               val |= (0x1 << 5);
+               __raw_writel(val, S5P64X0_PWR_CFG);
+
+               cpu_do_idle();
+       }
+       local_irq_enable();
+}
+
+/*
+ * s5p64x0_map_io
+ *
+ * register the standard CPU IO areas
+ */
+
+void __init s5p6440_map_io(void)
+{
+       /* initialize any device information early */
+       s3c_adc_setname("s3c64xx-adc");
+
+       iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+       iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+void __init s5p6450_map_io(void)
+{
+       /* initialize any device information early */
+       s3c_adc_setname("s3c64xx-adc");
+
+       iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+       iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+/*
+ * s5p64x0_init_clocks
+ *
+ * register and setup the CPU clocks
+ */
+
+void __init s5p6440_init_clocks(int xtal)
+{
+       printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+       s3c24xx_register_baseclocks(xtal);
+       s5p_register_clocks(xtal);
+       s5p6440_register_clocks();
+       s5p6440_setup_clocks();
+}
+
+void __init s5p6450_init_clocks(int xtal)
+{
+       printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+       s3c24xx_register_baseclocks(xtal);
+       s5p_register_clocks(xtal);
+       s5p6450_register_clocks();
+       s5p6450_setup_clocks();
+}
+
+/*
+ * s5p64x0_init_irq
+ *
+ * register the CPU interrupts
+ */
+
+void __init s5p6440_init_irq(void)
+{
+       /* S5P6440 supports 2 VIC */
+       u32 vic[2];
+
+       /*
+        * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
+        * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
+        */
+       vic[0] = 0xff800ae7;
+       vic[1] = 0xffbf23e5;
+
+       s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+void __init s5p6450_init_irq(void)
+{
+       /* S5P6450 supports only 2 VIC */
+       u32 vic[2];
+
+       /*
+        * VIC0 is missing IRQ_VIC0[(13-15), (21-22)]
+        * VIC1 is missing IRQ VIC1[12, 14, 23]
+        */
+       vic[0] = 0xff9f1fff;
+       vic[1] = 0xff7fafff;
+
+       s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+struct sysdev_class s5p64x0_sysclass = {
+       .name   = "s5p64x0-core",
+};
+
+static struct sys_device s5p64x0_sysdev = {
+       .cls    = &s5p64x0_sysclass,
+};
+
+static int __init s5p64x0_core_init(void)
+{
+       return sysdev_class_register(&s5p64x0_sysclass);
+}
+core_initcall(s5p64x0_core_init);
+
+int __init s5p64x0_init(void)
+{
+       printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n");
+
+       /* set idle function */
+       pm_idle = s5p64x0_idle;
+
+       return sysdev_register(&s5p64x0_sysdev);
+}
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
new file mode 100644 (file)
index 0000000..fa097bd
--- /dev/null
@@ -0,0 +1,164 @@
+/* linux/arch/arm/mach-s5p64x0/dev-audio.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+static int s5p6440_cfg_i2s(struct platform_device *pdev)
+{
+       /* configure GPIO for i2s port */
+       switch (pdev->id) {
+       case -1:
+               s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
+               break;
+
+       default:
+               printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int s5p6450_cfg_i2s(struct platform_device *pdev)
+{
+       /* configure GPIO for i2s port */
+       switch (pdev->id) {
+       case -1:
+               s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5));
+               s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5));
+               break;
+
+       default:
+               printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_i2s_pdata = {
+       .cfg_gpio = s5p6440_cfg_i2s,
+};
+
+static struct s3c_audio_pdata s5p6450_i2s_pdata = {
+       .cfg_gpio = s5p6450_cfg_i2s,
+};
+
+static struct resource s5p64x0_iis0_resource[] = {
+       [0] = {
+               .start  = S5P64X0_PA_I2S,
+               .end    = S5P64X0_PA_I2S + 0x100 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = DMACH_I2S0_TX,
+               .end    = DMACH_I2S0_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [2] = {
+               .start  = DMACH_I2S0_RX,
+               .end    = DMACH_I2S0_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+struct platform_device s5p6440_device_iis = {
+       .name           = "s3c64xx-iis-v4",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p64x0_iis0_resource),
+       .resource       = s5p64x0_iis0_resource,
+       .dev = {
+               .platform_data = &s5p6440_i2s_pdata,
+       },
+};
+
+struct platform_device s5p6450_device_iis0 = {
+       .name           = "s3c64xx-iis-v4",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p64x0_iis0_resource),
+       .resource       = s5p64x0_iis0_resource,
+       .dev = {
+               .platform_data = &s5p6450_i2s_pdata,
+       },
+};
+
+/* PCM Controller platform_devices */
+
+static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
+{
+       switch (pdev->id) {
+       case 0:
+               s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
+               break;
+
+       default:
+               printk(KERN_DEBUG "Invalid PCM Controller number!");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_pcm_pdata = {
+       .cfg_gpio = s5p6440_pcm_cfg_gpio,
+};
+
+static struct resource s5p6440_pcm0_resource[] = {
+       [0] = {
+               .start  = S5P64X0_PA_PCM,
+               .end    = S5P64X0_PA_PCM + 0x100 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = DMACH_PCM0_TX,
+               .end    = DMACH_PCM0_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [2] = {
+               .start  = DMACH_PCM0_RX,
+               .end    = DMACH_PCM0_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+struct platform_device s5p6440_device_pcm = {
+       .name           = "samsung-pcm",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p6440_pcm0_resource),
+       .resource       = s5p6440_pcm0_resource,
+       .dev = {
+               .platform_data = &s5p6440_pcm_pdata,
+       },
+};
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
new file mode 100644 (file)
index 0000000..5b69ec4
--- /dev/null
@@ -0,0 +1,232 @@
+/* linux/arch/arm/mach-s5p64x0/dev-spi.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-clock.h>
+#include <mach/spi-clocks.h>
+
+#include <plat/s3c64xx-spi.h>
+#include <plat/gpio-cfg.h>
+
+static char *s5p64x0_spi_src_clks[] = {
+       [S5P64X0_SPI_SRCCLK_PCLK] = "pclk",
+       [S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi",
+};
+
+/* SPI Controller platform_devices */
+
+/* Since we emulate multi-cs capability, we do not touch the CS.
+ * The emulated CS is toggled by board specific mechanism, as it can
+ * be either some immediate GPIO or some signal out of some other
+ * chip in between ... or some yet another way.
+ * We simply do not assume anything about CS.
+ */
+static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
+{
+       switch (pdev->id) {
+       case 0:
+               s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
+               break;
+
+       case 1:
+               s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
+               break;
+
+       default:
+               dev_err(&pdev->dev, "Invalid SPI Controller number!");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
+{
+       switch (pdev->id) {
+       case 0:
+               s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP);
+               break;
+
+       case 1:
+               s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2));
+               s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP);
+               s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP);
+               break;
+
+       default:
+               dev_err(&pdev->dev, "Invalid SPI Controller number!");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct resource s5p64x0_spi0_resource[] = {
+       [0] = {
+               .start  = S5P64X0_PA_SPI0,
+               .end    = S5P64X0_PA_SPI0 + 0x100 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = DMACH_SPI0_TX,
+               .end    = DMACH_SPI0_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [2] = {
+               .start  = DMACH_SPI0_RX,
+               .end    = DMACH_SPI0_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [3] = {
+               .start  = IRQ_SPI0,
+               .end    = IRQ_SPI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
+       .cfg_gpio       = s5p6440_spi_cfg_gpio,
+       .fifo_lvl_mask  = 0x1ff,
+       .rx_lvl_offset  = 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi0_pdata = {
+       .cfg_gpio       = s5p6450_spi_cfg_gpio,
+       .fifo_lvl_mask  = 0x1ff,
+       .rx_lvl_offset  = 15,
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p64x0_device_spi0 = {
+       .name           = "s3c64xx-spi",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p64x0_spi0_resource),
+       .resource       = s5p64x0_spi0_resource,
+       .dev = {
+               .dma_mask               = &spi_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+static struct resource s5p64x0_spi1_resource[] = {
+       [0] = {
+               .start  = S5P64X0_PA_SPI1,
+               .end    = S5P64X0_PA_SPI1 + 0x100 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = DMACH_SPI1_TX,
+               .end    = DMACH_SPI1_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [2] = {
+               .start  = DMACH_SPI1_RX,
+               .end    = DMACH_SPI1_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [3] = {
+               .start  = IRQ_SPI1,
+               .end    = IRQ_SPI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
+       .cfg_gpio       = s5p6440_spi_cfg_gpio,
+       .fifo_lvl_mask  = 0x7f,
+       .rx_lvl_offset  = 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi1_pdata = {
+       .cfg_gpio       = s5p6450_spi_cfg_gpio,
+       .fifo_lvl_mask  = 0x7f,
+       .rx_lvl_offset  = 15,
+};
+
+struct platform_device s5p64x0_device_spi1 = {
+       .name           = "s3c64xx-spi",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s5p64x0_spi1_resource),
+       .resource       = s5p64x0_spi1_resource,
+       .dev = {
+               .dma_mask               = &spi_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
+{
+       unsigned int id;
+       struct s3c64xx_spi_info *pd;
+
+       id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+       /* Reject invalid configuration */
+       if (!num_cs || src_clk_nr < 0
+                       || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
+               printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
+               return;
+       }
+
+       switch (cntrlr) {
+       case 0:
+               if (id == 0x50000)
+                       pd = &s5p6450_spi0_pdata;
+               else
+                       pd = &s5p6440_spi0_pdata;
+
+               s5p64x0_device_spi0.dev.platform_data = pd;
+               break;
+       case 1:
+               if (id == 0x50000)
+                       pd = &s5p6450_spi1_pdata;
+               else
+                       pd = &s5p6440_spi1_pdata;
+
+               s5p64x0_device_spi1.dev.platform_data = pd;
+               break;
+       default:
+               printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
+                                                       __func__, cntrlr);
+               return;
+       }
+
+       pd->num_cs = num_cs;
+       pd->src_clk_nr = src_clk_nr;
+       pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr];
+}
similarity index 55%
rename from arch/arm/mach-s5p6440/dma.c
rename to arch/arm/mach-s5p64x0/dma.c
index 07606ad57519a21656b6dcac2af45eea419f6013..29a8c2410049f7fa6b41c51a71f938abcdec9eb7 100644 (file)
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5p64x0/dma.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
  * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+*/
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
 #include <mach/map.h>
 #include <mach/irqs.h>
+#include <mach/regs-clock.h>
 
+#include <plat/devs.h>
 #include <plat/s3c-pl330-pdata.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p6440_pdma_resource[] = {
+static struct resource s5p64x0_pdma_resource[] = {
        [0] = {
-               .start  = S5P6440_PA_PDMA,
-               .end    = S5P6440_PA_PDMA + SZ_4K,
-               .flags = IORESOURCE_MEM,
+               .start  = S5P64X0_PA_PDMA,
+               .end    = S5P64X0_PA_PDMA + SZ_4K,
+               .flags  = IORESOURCE_MEM,
        },
        [1] = {
                .start  = IRQ_DMA0,
@@ -80,26 +83,67 @@ static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
        },
 };
 
-static struct platform_device s5p6440_device_pdma = {
+static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
+       .peri = {
+               [0] = DMACH_UART0_RX,
+               [1] = DMACH_UART0_TX,
+               [2] = DMACH_UART1_RX,
+               [3] = DMACH_UART1_TX,
+               [4] = DMACH_UART2_RX,
+               [5] = DMACH_UART2_TX,
+               [6] = DMACH_UART3_RX,
+               [7] = DMACH_UART3_TX,
+               [8] = DMACH_UART4_RX,
+               [9] = DMACH_UART4_TX,
+               [10] = DMACH_PCM0_TX,
+               [11] = DMACH_PCM0_RX,
+               [12] = DMACH_I2S0_TX,
+               [13] = DMACH_I2S0_RX,
+               [14] = DMACH_SPI0_TX,
+               [15] = DMACH_SPI0_RX,
+               [16] = DMACH_PCM1_TX,
+               [17] = DMACH_PCM1_RX,
+               [18] = DMACH_PCM2_TX,
+               [19] = DMACH_PCM2_RX,
+               [20] = DMACH_SPI1_TX,
+               [21] = DMACH_SPI1_RX,
+               [22] = DMACH_USI_TX,
+               [23] = DMACH_USI_RX,
+               [24] = DMACH_MAX,
+               [25] = DMACH_I2S1_TX,
+               [26] = DMACH_I2S1_RX,
+               [27] = DMACH_I2S2_TX,
+               [28] = DMACH_I2S2_RX,
+               [29] = DMACH_PWM,
+               [30] = DMACH_UART5_RX,
+               [31] = DMACH_UART5_TX,
+       },
+};
+
+static struct platform_device s5p64x0_device_pdma = {
        .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5p6440_pdma_resource),
-       .resource       = s5p6440_pdma_resource,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p64x0_pdma_resource),
+       .resource       = s5p64x0_pdma_resource,
        .dev            = {
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
-               .platform_data = &s5p6440_pdma_pdata,
        },
 };
 
-static struct platform_device *s5p6440_dmacs[] __initdata = {
-       &s5p6440_device_pdma,
-};
-
-static int __init s5p6440_dma_init(void)
+static int __init s5p64x0_dma_init(void)
 {
-       platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs));
+       unsigned int id;
+
+       id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+       if (id == 0x50000)
+               s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
+       else
+               s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
+
+       platform_device_register(&s5p64x0_device_pdma);
 
        return 0;
 }
-arch_initcall(s5p6440_dma_init);
+arch_initcall(s5p64x0_dma_init);
similarity index 74%
rename from arch/arm/mach-s5p6440/gpio.c
rename to arch/arm/mach-s5p64x0/gpio.c
index 8bf6e0ce51c9cd9b95830770e6e62edf8710d83f..39159dd5a29ac7bf091e457a03d6eed14ef6573d 100644 (file)
@@ -1,14 +1,14 @@
-/* arch/arm/mach-s5p6440/gpio.c
+/* linux/arch/arm/mach-s5p64x0/gpio.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - GPIOlib support
+ * S5P64X0 - GPIOlib support
  *
  * 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/irq.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
 
-/* GPIO bank summary:
-*
-* Bank GPIOs   Style   SlpCon  ExtInt Group
-* A    6       4Bit    Yes     1
-* B    7       4Bit    Yes     1
-* C    8       4Bit    Yes     2
-* F    2       2Bit    Yes     4 [1]
-* G    7       4Bit    Yes     5
-* H    10      4Bit[2] Yes     6
-* I    16      2Bit    Yes     None
-* J    12      2Bit    Yes     None
-* N    16      2Bit    No      IRQ_EINT
-* P    8       2Bit    Yes     8
-* R    15      4Bit[2] Yes     8
-*
-* [1] BANKF pins 14,15 do not form part of the external interrupt sources
-* [2] BANK has two control registers, GPxCON0 and GPxCON1
-*/
+/* To be implemented S5P6450 GPIO */
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   6       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * F   2       2Bit    Yes     4 [1]
+ * G   7       4Bit    Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * N   16      2Bit    No      IRQ_EINT
+ * P   8       2Bit    Yes     8
+ * R   15      4Bit[2] Yes     8
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
 
-static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
+static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
                                             unsigned int offset)
 {
        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
@@ -77,7 +80,7 @@ static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
        return 0;
 }
 
-static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
+static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
                                              unsigned int offset, int value)
 {
        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
@@ -124,12 +127,11 @@ static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
        return 0;
 }
 
-int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
+int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
                                   unsigned int off, unsigned int cfg)
 {
        void __iomem *reg = chip->base;
        unsigned int shift;
-       unsigned long flags;
        u32 con;
 
        switch (off) {
@@ -155,26 +157,22 @@ int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
                cfg <<= shift;
        }
 
-       s3c_gpio_lock(chip, flags);
-
        con = __raw_readl(reg);
        con &= ~(0xf << shift);
        con |= cfg;
        __raw_writel(con, reg);
 
-       s3c_gpio_unlock(chip, flags);
-
        return 0;
 }
 
-static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
+static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
        {
                .cfg_eint       = 0,
        }, {
                .cfg_eint       = 7,
        }, {
                .cfg_eint       = 3,
-               .set_config     = s5p6440_gpio_setcfg_4bit_rbank,
+               .set_config     = s5p64x0_gpio_setcfg_4bit_rbank,
        }, {
                .cfg_eint       = 0,
                .set_config     = s3c_gpio_setcfg_s3c24xx,
@@ -193,7 +191,7 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
 static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
        {
                .base   = S5P6440_GPA_BASE,
-               .config = &s5p6440_gpio_cfgs[1],
+               .config = &s5p64x0_gpio_cfgs[1],
                .chip   = {
                        .base   = S5P6440_GPA(0),
                        .ngpio  = S5P6440_GPIO_A_NR,
@@ -201,7 +199,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
                },
        }, {
                .base   = S5P6440_GPB_BASE,
-               .config = &s5p6440_gpio_cfgs[1],
+               .config = &s5p64x0_gpio_cfgs[1],
                .chip   = {
                        .base   = S5P6440_GPB(0),
                        .ngpio  = S5P6440_GPIO_B_NR,
@@ -209,7 +207,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
                },
        }, {
                .base   = S5P6440_GPC_BASE,
-               .config = &s5p6440_gpio_cfgs[1],
+               .config = &s5p64x0_gpio_cfgs[1],
                .chip   = {
                        .base   = S5P6440_GPC(0),
                        .ngpio  = S5P6440_GPIO_C_NR,
@@ -217,7 +215,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
                },
        }, {
                .base   = S5P6440_GPG_BASE,
-               .config = &s5p6440_gpio_cfgs[1],
+               .config = &s5p64x0_gpio_cfgs[1],
                .chip   = {
                        .base   = S5P6440_GPG(0),
                        .ngpio  = S5P6440_GPIO_G_NR,
@@ -229,7 +227,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
 static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
        {
                .base   = S5P6440_GPH_BASE + 0x4,
-               .config = &s5p6440_gpio_cfgs[1],
+               .config = &s5p64x0_gpio_cfgs[1],
                .chip   = {
                        .base   = S5P6440_GPH(0),
                        .ngpio  = S5P6440_GPIO_H_NR,
@@ -238,10 +236,10 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
        },
 };
 
-static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
+static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
        {
                .base   = S5P6440_GPR_BASE + 0x4,
-               .config = &s5p6440_gpio_cfgs[2],
+               .config = &s5p64x0_gpio_cfgs[2],
                .chip   = {
                        .base   = S5P6440_GPR(0),
                        .ngpio  = S5P6440_GPIO_R_NR,
@@ -253,7 +251,7 @@ static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
 static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
        {
                .base   = S5P6440_GPF_BASE,
-               .config = &s5p6440_gpio_cfgs[5],
+               .config = &s5p64x0_gpio_cfgs[5],
                .chip   = {
                        .base   = S5P6440_GPF(0),
                        .ngpio  = S5P6440_GPIO_F_NR,
@@ -261,7 +259,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
                },
        }, {
                .base   = S5P6440_GPI_BASE,
-               .config = &s5p6440_gpio_cfgs[3],
+               .config = &s5p64x0_gpio_cfgs[3],
                .chip   = {
                        .base   = S5P6440_GPI(0),
                        .ngpio  = S5P6440_GPIO_I_NR,
@@ -269,7 +267,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
                },
        }, {
                .base   = S5P6440_GPJ_BASE,
-               .config = &s5p6440_gpio_cfgs[3],
+               .config = &s5p64x0_gpio_cfgs[3],
                .chip   = {
                        .base   = S5P6440_GPJ(0),
                        .ngpio  = S5P6440_GPIO_J_NR,
@@ -277,7 +275,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
                },
        }, {
                .base   = S5P6440_GPN_BASE,
-               .config = &s5p6440_gpio_cfgs[4],
+               .config = &s5p64x0_gpio_cfgs[4],
                .chip   = {
                        .base   = S5P6440_GPN(0),
                        .ngpio  = S5P6440_GPIO_N_NR,
@@ -285,7 +283,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
                },
        }, {
                .base   = S5P6440_GPP_BASE,
-               .config = &s5p6440_gpio_cfgs[5],
+               .config = &s5p64x0_gpio_cfgs[5],
                .chip   = {
                        .base   = S5P6440_GPP(0),
                        .ngpio  = S5P6440_GPIO_P_NR,
@@ -294,7 +292,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
        },
 };
 
-void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
+void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
 {
        for (; nr_chips > 0; nr_chips--, chipcfg++) {
                if (!chipcfg->set_config)
@@ -308,13 +306,13 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
        }
 }
 
-static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
+static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
                                                int nr_chips)
 {
        for (; nr_chips > 0; nr_chips--, chip++) {
-               chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input;
+               chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
                chip->chip.direction_output =
-                                       s5p6440_gpiolib_rbank_4bit2_output;
+                                       s5p64x0_gpiolib_rbank_4bit2_output;
                s3c_gpiolib_add(chip);
        }
 }
@@ -324,8 +322,8 @@ static int __init s5p6440_gpiolib_init(void)
        struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
        int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
 
-       s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs,
-                               ARRAY_SIZE(s5p6440_gpio_cfgs));
+       s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
+                               ARRAY_SIZE(s5p64x0_gpio_cfgs));
 
        for (; nr_chips > 0; nr_chips--, chips++)
                s3c_gpiolib_add(chips);
@@ -336,8 +334,8 @@ static int __init s5p6440_gpiolib_init(void)
        samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
                                ARRAY_SIZE(s5p6440_gpio_4bit2));
 
-       s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2,
-                               ARRAY_SIZE(gpio_rbank_4bit2));
+       s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
+                               ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
 
        return 0;
 }
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..79b04e6
--- /dev/null
@@ -0,0 +1,33 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2009-2010 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#include <plat/regs-serial.h>
+
+       .macro addruart, rp, rv
+               mov     \rp, #0xE0000000
+               orr     \rp, \rp, #0x00100000
+               ldr     \rp, [\rp, #0x118 ]
+               and     \rp, \rp, #0xff000
+               teq     \rp, #0x50000           @@ S5P6450
+               ldreq   \rp, =0xEC800000
+               movne   \rp, #0xEC000000        @@ S5P6440
+               ldrne   \rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+               add     \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+       .endm
+
+#include <plat/debug-macro.S>
similarity index 58%
rename from arch/arm/mach-s5p6440/include/mach/entry-macro.S
rename to arch/arm/mach-s5p64x0/include/mach/entry-macro.S
index e65f1b9672626d512d95e004aa8f740e30b4ae43..10b62b4f821177aa2c45fd2d7c91748411973d44 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S
+/* linux/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * Low-level IRQ helper macros for the Samsung S5P6440
+ * Low-level IRQ helper macros for the Samsung S5P64X0
  *
  * 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
diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..5486c8f
--- /dev/null
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - GPIO lib support
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep  __gpio_cansleep
+#define gpio_to_irq    __gpio_to_irq
+
+/* GPIO bank sizes */
+
+#define S5P6440_GPIO_A_NR      (6)
+#define S5P6440_GPIO_B_NR      (7)
+#define S5P6440_GPIO_C_NR      (8)
+#define S5P6440_GPIO_F_NR      (2)
+#define S5P6440_GPIO_G_NR      (7)
+#define S5P6440_GPIO_H_NR      (10)
+#define S5P6440_GPIO_I_NR      (16)
+#define S5P6440_GPIO_J_NR      (12)
+#define S5P6440_GPIO_N_NR      (16)
+#define S5P6440_GPIO_P_NR      (8)
+#define S5P6440_GPIO_R_NR      (15)
+
+#define S5P6450_GPIO_A_NR      (6)
+#define S5P6450_GPIO_B_NR      (7)
+#define S5P6450_GPIO_C_NR      (8)
+#define S5P6450_GPIO_D_NR      (8)
+#define S5P6450_GPIO_F_NR      (2)
+#define S5P6450_GPIO_G_NR      (14)
+#define S5P6450_GPIO_H_NR      (10)
+#define S5P6450_GPIO_I_NR      (16)
+#define S5P6450_GPIO_J_NR      (12)
+#define S5P6450_GPIO_K_NR      (5)
+#define S5P6450_GPIO_N_NR      (16)
+#define S5P6450_GPIO_P_NR      (11)
+#define S5P6450_GPIO_Q_NR      (14)
+#define S5P6450_GPIO_R_NR      (15)
+#define S5P6450_GPIO_S_NR      (8)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S5P64X0_GPIO_NEXT(__gpio) \
+       ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p6440_gpio_number {
+       S5P6440_GPIO_A_START    = 0,
+       S5P6440_GPIO_B_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_A),
+       S5P6440_GPIO_C_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_B),
+       S5P6440_GPIO_F_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_C),
+       S5P6440_GPIO_G_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_F),
+       S5P6440_GPIO_H_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_G),
+       S5P6440_GPIO_I_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_H),
+       S5P6440_GPIO_J_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_I),
+       S5P6440_GPIO_N_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_J),
+       S5P6440_GPIO_P_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_N),
+       S5P6440_GPIO_R_START    = S5P64X0_GPIO_NEXT(S5P6440_GPIO_P),
+};
+
+enum s5p6450_gpio_number {
+       S5P6450_GPIO_A_START    = 0,
+       S5P6450_GPIO_B_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_A),
+       S5P6450_GPIO_C_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_B),
+       S5P6450_GPIO_D_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_C),
+       S5P6450_GPIO_F_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_D),
+       S5P6450_GPIO_G_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_F),
+       S5P6450_GPIO_H_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_G),
+       S5P6450_GPIO_I_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_H),
+       S5P6450_GPIO_J_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_I),
+       S5P6450_GPIO_K_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_J),
+       S5P6450_GPIO_N_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_K),
+       S5P6450_GPIO_P_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_N),
+       S5P6450_GPIO_Q_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_P),
+       S5P6450_GPIO_R_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q),
+       S5P6450_GPIO_S_START    = S5P64X0_GPIO_NEXT(S5P6450_GPIO_R),
+};
+
+/* GPIO number definitions */
+
+#define S5P6440_GPA(_nr)       (S5P6440_GPIO_A_START + (_nr))
+#define S5P6440_GPB(_nr)       (S5P6440_GPIO_B_START + (_nr))
+#define S5P6440_GPC(_nr)       (S5P6440_GPIO_C_START + (_nr))
+#define S5P6440_GPF(_nr)       (S5P6440_GPIO_F_START + (_nr))
+#define S5P6440_GPG(_nr)       (S5P6440_GPIO_G_START + (_nr))
+#define S5P6440_GPH(_nr)       (S5P6440_GPIO_H_START + (_nr))
+#define S5P6440_GPI(_nr)       (S5P6440_GPIO_I_START + (_nr))
+#define S5P6440_GPJ(_nr)       (S5P6440_GPIO_J_START + (_nr))
+#define S5P6440_GPN(_nr)       (S5P6440_GPIO_N_START + (_nr))
+#define S5P6440_GPP(_nr)       (S5P6440_GPIO_P_START + (_nr))
+#define S5P6440_GPR(_nr)       (S5P6440_GPIO_R_START + (_nr))
+
+#define S5P6450_GPA(_nr)       (S5P6450_GPIO_A_START + (_nr))
+#define S5P6450_GPB(_nr)       (S5P6450_GPIO_B_START + (_nr))
+#define S5P6450_GPC(_nr)       (S5P6450_GPIO_C_START + (_nr))
+#define S5P6450_GPD(_nr)       (S5P6450_GPIO_D_START + (_nr))
+#define S5P6450_GPF(_nr)       (S5P6450_GPIO_F_START + (_nr))
+#define S5P6450_GPG(_nr)       (S5P6450_GPIO_G_START + (_nr))
+#define S5P6450_GPH(_nr)       (S5P6450_GPIO_H_START + (_nr))
+#define S5P6450_GPI(_nr)       (S5P6450_GPIO_I_START + (_nr))
+#define S5P6450_GPJ(_nr)       (S5P6450_GPIO_J_START + (_nr))
+#define S5P6450_GPK(_nr)       (S5P6450_GPIO_K_START + (_nr))
+#define S5P6450_GPN(_nr)       (S5P6450_GPIO_N_START + (_nr))
+#define S5P6450_GPP(_nr)       (S5P6450_GPIO_P_START + (_nr))
+#define S5P6450_GPQ(_nr)       (S5P6450_GPIO_Q_START + (_nr))
+#define S5P6450_GPR(_nr)       (S5P6450_GPIO_R_START + (_nr))
+#define S5P6450_GPS(_nr)       (S5P6450_GPIO_S_START + (_nr))
+
+/* the end of the S5P64X0 specific gpios */
+
+#define S5P6440_GPIO_END       (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
+#define S5P6450_GPIO_END       (S5P6450_GPS(S5P6450_GPIO_S_NR) + 1)
+
+#define S5P64X0_GPIO_END       (S5P6440_GPIO_END > S5P6450_GPIO_END ?  \
+                                S5P6440_GPIO_END : S5P6450_GPIO_END)
+
+#define S3C_GPIO_END           S5P64X0_GPIO_END
+
+/* define the number of gpios we need to the one after the last GPIO range */
+
+#define ARCH_NR_GPIOS          (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
similarity index 67%
rename from arch/arm/mach-s5p6440/include/mach/hardware.h
rename to arch/arm/mach-s5p64x0/include/mach/hardware.h
index be8b26e875db5fb51211b676a34e4cb1448f2cbc..d3e87996dd9a752db134b0f790fe9fda94673933 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - Hardware support
+ * S5P64X0 - Hardware support
  *
  * 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
diff --git a/arch/arm/mach-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/include/mach/i2c.h
new file mode 100644 (file)
index 0000000..887d252
--- /dev/null
@@ -0,0 +1,17 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 I2C configuration
+ *
+ * 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.
+*/
+
+extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev);
+
+extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev);
diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h
new file mode 100644 (file)
index 0000000..a3e095c
--- /dev/null
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/io.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S5P64X0 based
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)                __typesafe_io(a)
+#define __mem_pci(a)   (a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
similarity index 71%
rename from arch/arm/mach-s5p6440/include/mach/irqs.h
rename to arch/arm/mach-s5p64x0/include/mach/irqs.h
index 16a761270de108fd76dc9159da3f2af9dbae4600..513abffc760495a1ac1cdf69fce010682d707478 100644 (file)
@@ -1,17 +1,17 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h
  *
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - IRQ definitions
+ * S5P64X0 - IRQ definitions
  *
  * 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.
 */
 
-#ifndef __ASM_ARCH_S5P_IRQS_H
-#define __ASM_ARCH_S5P_IRQS_H __FILE__
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
 
 #include <plat/irqs.h>
 
 #define IRQ_EINT0_3            S5P_IRQ_VIC0(0)
 #define IRQ_EINT4_11           S5P_IRQ_VIC0(1)
 #define IRQ_RTC_TIC            S5P_IRQ_VIC0(2)
+#define IRQ_IIS1               S5P_IRQ_VIC0(3) /* for only S5P6450 */
+#define IRQ_IIS2               S5P_IRQ_VIC0(4) /* for only S5P6450 */
 #define IRQ_IIC1               S5P_IRQ_VIC0(5)
 #define IRQ_I2SV40             S5P_IRQ_VIC0(6)
-#define IRQ_GPS                        S5P_IRQ_VIC0(7)
-#define IRQ_POST0              S5P_IRQ_VIC0(9)
+#define IRQ_GPS                        S5P_IRQ_VIC0(7) /* for only S5P6450 */
+
 #define IRQ_2D                 S5P_IRQ_VIC0(11)
 #define IRQ_TIMER0_VIC         S5P_IRQ_VIC0(23)
 #define IRQ_TIMER1_VIC         S5P_IRQ_VIC0(24)
 
 #define IRQ_EINT12_15          S5P_IRQ_VIC1(0)
 #define IRQ_PCM0               S5P_IRQ_VIC1(2)
+#define IRQ_PCM1               S5P_IRQ_VIC1(3) /* for only S5P6450 */
+#define IRQ_PCM2               S5P_IRQ_VIC1(4) /* for only S5P6450 */
 #define IRQ_UART0              S5P_IRQ_VIC1(5)
 #define IRQ_UART1              S5P_IRQ_VIC1(6)
 #define IRQ_UART2              S5P_IRQ_VIC1(7)
 #define IRQ_UART3              S5P_IRQ_VIC1(8)
 #define IRQ_DMA0               S5P_IRQ_VIC1(9)
+#define IRQ_UART4              S5P_IRQ_VIC1(10)        /* S5P6450 */
+#define IRQ_UART5              S5P_IRQ_VIC1(11)        /* S5P6450 */
 #define IRQ_NFC                        S5P_IRQ_VIC1(13)
+#define IRQ_USI                        S5P_IRQ_VIC1(15)        /* S5P6450 */
 #define IRQ_SPI0               S5P_IRQ_VIC1(16)
 #define IRQ_SPI1               S5P_IRQ_VIC1(17)
+#define IRQ_HSMMC2             S5P_IRQ_VIC1(17)        /* Shared */
 #define IRQ_IIC                        S5P_IRQ_VIC1(18)
 #define IRQ_DISPCON3           S5P_IRQ_VIC1(19)
-#define IRQ_FIMGVG             S5P_IRQ_VIC1(20)
 #define IRQ_EINT_GROUPS                S5P_IRQ_VIC1(21)
-#define IRQ_PMU                        S5P_IRQ_VIC1(23)
+#define IRQ_PMU                        S5P_IRQ_VIC1(23)        /* S5P6440 */
 #define IRQ_HSMMC0             S5P_IRQ_VIC1(24)
 #define IRQ_HSMMC1             S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC2             IRQ_SPI1        /* shared with SPI1 */
 #define IRQ_OTG                        S5P_IRQ_VIC1(26)
 #define IRQ_DSI                        S5P_IRQ_VIC1(27)
 #define IRQ_RTC_ALARM          S5P_IRQ_VIC1(28)
 #define IRQ_TC                 IRQ_PENDN
 #define IRQ_ADC                        S5P_IRQ_VIC1(31)
 
+/* UART interrupts, S5P6450 has 5 UARTs */
+#define IRQ_S5P_UART_BASE4     (96)
+#define IRQ_S5P_UART_BASE5     (100)
+
+#define IRQ_S5P_UART_RX4       (IRQ_S5P_UART_BASE4 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX4       (IRQ_S5P_UART_BASE4 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR4      (IRQ_S5P_UART_BASE4 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX5       (IRQ_S5P_UART_BASE5 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX5       (IRQ_S5P_UART_BASE5 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR5      (IRQ_S5P_UART_BASE5 + UART_IRQ_ERR)
+
+/* S3C compatibilty defines */
+#define IRQ_S3CUART_RX4                IRQ_S5P_UART_RX4
+#define IRQ_S3CUART_RX5                IRQ_S5P_UART_RX5
+
+/* S5P6450 EINT feature will be added */
+
 /*
  * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
  * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
 
 #define NR_IRQS                        (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
 
-#endif /* __ASM_ARCH_S5P_IRQS_H */
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
new file mode 100644 (file)
index 0000000..31e5341
--- /dev/null
@@ -0,0 +1,83 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/map.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - Memory map definitions
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#define S5P64X0_PA_SDRAM       (0x20000000)
+
+#define S5P64X0_PA_CHIPID      (0xE0000000)
+#define S5P_PA_CHIPID          S5P64X0_PA_CHIPID
+
+#define S5P64X0_PA_SYSCON      (0xE0100000)
+#define S5P_PA_SYSCON          S5P64X0_PA_SYSCON
+
+#define S5P64X0_PA_GPIO                (0xE0308000)
+
+#define S5P64X0_PA_VIC0                (0xE4000000)
+#define S5P64X0_PA_VIC1                (0xE4100000)
+
+#define S5P64X0_PA_PDMA                (0xE9000000)
+
+#define S5P64X0_PA_TIMER       (0xEA000000)
+#define S5P_PA_TIMER           S5P64X0_PA_TIMER
+
+#define S5P64X0_PA_RTC         (0xEA100000)
+
+#define S5P64X0_PA_WDT         (0xEA200000)
+
+#define S5P6440_PA_UART(x)     (0xEC000000 + ((x) * S3C_UART_OFFSET))
+#define S5P6450_PA_UART(x)     ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
+
+#define S5P_PA_UART0           S5P6450_PA_UART(0)
+#define S5P_PA_UART1           S5P6450_PA_UART(1)
+#define S5P_PA_UART2           S5P6450_PA_UART(2)
+#define S5P_PA_UART3           S5P6450_PA_UART(3)
+#define S5P_PA_UART4           S5P6450_PA_UART(4)
+#define S5P_PA_UART5           S5P6450_PA_UART(5)
+
+#define S5P_SZ_UART            SZ_256
+
+#define S5P6440_PA_IIC0                (0xEC104000)
+#define S5P6440_PA_IIC1                (0xEC20F000)
+#define S5P6450_PA_IIC0                (0xEC100000)
+#define S5P6450_PA_IIC1                (0xEC200000)
+
+#define S5P64X0_PA_SPI0                (0xEC400000)
+#define S5P64X0_PA_SPI1                (0xEC500000)
+
+#define S5P64X0_PA_HSOTG       (0xED100000)
+
+#define S5P64X0_PA_HSMMC(x)    (0xED800000 + ((x) * 0x100000))
+
+#define S5P64X0_PA_I2S         (0xF2000000)
+
+#define S5P64X0_PA_PCM         (0xF2100000)
+
+#define S5P64X0_PA_ADC         (0xF3000000)
+
+/* compatibiltiy defines. */
+
+#define S3C_PA_HSMMC0          S5P64X0_PA_HSMMC(0)
+#define S3C_PA_HSMMC1          S5P64X0_PA_HSMMC(1)
+#define S3C_PA_HSMMC2          S5P64X0_PA_HSMMC(2)
+#define S3C_PA_IIC             S5P6440_PA_IIC0
+#define S3C_PA_IIC1            S5P6440_PA_IIC1
+#define S3C_PA_RTC             S5P64X0_PA_RTC
+#define S3C_PA_WDT             S5P64X0_PA_WDT
+
+#define SAMSUNG_PA_ADC         S5P64X0_PA_ADC
+
+#endif /* __ASM_ARCH_MAP_H */
similarity index 55%
rename from arch/arm/mach-s5p6440/include/mach/memory.h
rename to arch/arm/mach-s5p64x0/include/mach/memory.h
index d62910c71b566af0b5214a9eb426b55572eb541f..1b036b0a24cee858c35676e0609e744c56e3381b 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/memory.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - Memory definitions
+ * S5P64X0 - Memory definitions
  *
  * 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
@@ -11,9 +11,9 @@
 */
 
 #ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
 
-#define PHYS_OFFSET            UL(0x20000000)
+#define PHYS_OFFSET            UL(0x20000000)
 #define CONSISTENT_DMA_SIZE    SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
similarity index 86%
rename from arch/arm/mach-s5p6440/include/mach/pwm-clock.h
rename to arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
index 6a2a02fdf12a23df33ce6783c7a7181923348ddb..19fff8b701c0bf73126c93d9f1c33d6676a0b5ae 100644 (file)
@@ -1,16 +1,14 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
  *      http://armlinux.simtec.co.uk/
  *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5P6440 - pwm clock and timer support
+ * S5P64X0 - pwm clock and timer support
  *
  * 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
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
new file mode 100644 (file)
index 0000000..58e1bc8
--- /dev/null
@@ -0,0 +1,63 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - Clock register definitions
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)                  (S3C_VA_SYS + (x))
+
+#define S5P64X0_APLL_CON               S5P_CLKREG(0x0C)
+#define S5P64X0_MPLL_CON               S5P_CLKREG(0x10)
+#define S5P64X0_EPLL_CON               S5P_CLKREG(0x14)
+#define S5P64X0_EPLL_CON_K             S5P_CLKREG(0x18)
+
+#define S5P64X0_CLK_SRC0               S5P_CLKREG(0x1C)
+
+#define S5P64X0_CLK_DIV0               S5P_CLKREG(0x20)
+#define S5P64X0_CLK_DIV1               S5P_CLKREG(0x24)
+#define S5P64X0_CLK_DIV2               S5P_CLKREG(0x28)
+
+#define S5P64X0_CLK_GATE_HCLK0         S5P_CLKREG(0x30)
+#define S5P64X0_CLK_GATE_PCLK          S5P_CLKREG(0x34)
+#define S5P64X0_CLK_GATE_SCLK0         S5P_CLKREG(0x38)
+#define S5P64X0_CLK_GATE_MEM0          S5P_CLKREG(0x3C)
+
+#define S5P64X0_CLK_DIV3               S5P_CLKREG(0x40)
+
+#define S5P64X0_CLK_GATE_HCLK1         S5P_CLKREG(0x44)
+#define S5P64X0_CLK_GATE_SCLK1         S5P_CLKREG(0x48)
+
+#define S5P6450_DPLL_CON               S5P_CLKREG(0x50)
+#define S5P6450_DPLL_CON_K             S5P_CLKREG(0x54)
+
+#define S5P64X0_CLK_SRC1               S5P_CLKREG(0x10C)
+
+#define S5P64X0_SYS_ID                 S5P_CLKREG(0x118)
+#define S5P64X0_SYS_OTHERS             S5P_CLKREG(0x11C)
+
+#define S5P64X0_PWR_CFG                        S5P_CLKREG(0x804)
+#define S5P64X0_OTHERS                 S5P_CLKREG(0x900)
+
+#define S5P64X0_CLKDIV0_HCLK_SHIFT     (8)
+#define S5P64X0_CLKDIV0_HCLK_MASK      (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
+
+#define S5P64X0_OTHERS_USB_SIG_MASK    (1 << 16)
+
+/* Compatibility defines */
+
+#define ARM_CLK_DIV                    S5P64X0_CLK_DIV0
+#define ARM_DIV_RATIO_SHIFT            0
+#define ARM_DIV_MASK                   (0xF << ARM_DIV_RATIO_SHIFT)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
similarity index 79%
rename from arch/arm/mach-s5p6440/include/mach/regs-gpio.h
rename to arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
index 82ff753913da73ccdc77f5dd2c6ebd4f560ffc3f..85f448e20a8b22cc537f3c844ac16e0612418f4f 100644 (file)
@@ -1,21 +1,24 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - GPIO register definitions
+ * S5P64X0 - GPIO register definitions
  *
  * 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.
- */
+*/
 
 #ifndef __ASM_ARCH_REGS_GPIO_H
 #define __ASM_ARCH_REGS_GPIO_H __FILE__
 
 #include <mach/map.h>
 
+/* Will be implemented S5P6442 GPIOlib */
+
 /* Base addresses for each of the banks */
+
 #define S5P6440_GPA_BASE               (S5P_VA_GPIO + 0x0000)
 #define S5P6440_GPB_BASE               (S5P_VA_GPIO + 0x0020)
 #define S5P6440_GPC_BASE               (S5P_VA_GPIO + 0x0040)
@@ -27,6 +30,7 @@
 #define S5P6440_GPN_BASE               (S5P_VA_GPIO + 0x0830)
 #define S5P6440_GPP_BASE               (S5P_VA_GPIO + 0x0160)
 #define S5P6440_GPR_BASE               (S5P_VA_GPIO + 0x0290)
+
 #define S5P6440_EINT0CON0              (S5P_VA_GPIO + 0x900)
 #define S5P6440_EINT0FLTCON0           (S5P_VA_GPIO + 0x910)
 #define S5P6440_EINT0FLTCON1           (S5P_VA_GPIO + 0x914)
 #define S5P6440_EINT0PEND              (S5P_VA_GPIO + 0x924)
 
 /* for LCD */
+
 #define S5P6440_SPCON_LCD_SEL_RGB      (1 << 0)
 #define S5P6440_SPCON_LCD_SEL_MASK     (3 << 0)
 
-/* These set of macros are not really useful for the
- * GPF/GPI/GPJ/GPN/GPP,
- * useful for others set of GPIO's (4 bit)
+/*
+ * These set of macros are not really useful for the
+ * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit)
  */
+
 #define S5P6440_GPIO_CONMASK(__gpio)   (0xf << ((__gpio) * 4))
 #define S5P6440_GPIO_INPUT(__gpio)     (0x0 << ((__gpio) * 4))
 #define S5P6440_GPIO_OUTPUT(__gpio)    (0x1 << ((__gpio) * 4))
 
-/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
- * */
+/*
+ * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
+ */
+
 #define S5P6440_GPIO2_CONMASK(__gpio)  (0x3 << ((__gpio) * 2))
 #define S5P6440_GPIO2_INPUT(__gpio)    (0x0 << ((__gpio) * 2))
 #define S5P6440_GPIO2_OUTPUT(__gpio)   (0x1 << ((__gpio) * 2))
similarity index 66%
rename from arch/arm/mach-s5p6440/include/mach/regs-irq.h
rename to arch/arm/mach-s5p64x0/include/mach/regs-irq.h
index a961f4beeb0c2b3c0785c6cbdf4135e6803cd10d..4aaebdace55f9fe5b3cb86cd3bbf2e441f08391d 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - IRQ register definitions
+ * S5P64X0 - IRQ register definitions
  *
  * 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
diff --git a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
new file mode 100644 (file)
index 0000000..ff85b4b
--- /dev/null
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Header file for s5p64x0 clock support
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clksrc_clk clk_mout_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_mout_epll;
+
+extern int s5p64x0_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p64x0_epll_get_rate(struct clk *clk);
+
+extern unsigned long s5p64x0_armclk_get_rate(struct clk *clk);
+extern unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate);
+extern int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate);
+
+extern struct clk_ops s5p64x0_clkarm_ops;
+
+extern struct clksrc_clk clk_armclk;
+extern struct clksrc_clk clk_dout_mpll;
+
+extern struct clk *clkset_hclk_low_list[];
+extern struct clksrc_sources clkset_hclk_low;
+
+extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_mem_ctrl(struct clk *clk, int enable);
+
+extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
new file mode 100644 (file)
index 0000000..170a20a
--- /dev/null
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SPI_CLKS_H
+#define __ASM_ARCH_SPI_CLKS_H __FILE__
+
+#define S5P64X0_SPI_SRCCLK_PCLK                0
+#define S5P64X0_SPI_SRCCLK_SCLK                1
+
+#endif /* __ASM_ARCH_SPI_CLKS_H */
similarity index 69%
rename from arch/arm/mach-s5p6440/include/mach/system.h
rename to arch/arm/mach-s5p64x0/include/mach/system.h
index a359ee3fa51083b6b0314e67b16506e522ec2398..60f57532c970eca7f1c140156bcbbc2de069bb5a 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/system.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/system.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - system support header
+ * S5P64X0 - system support header
  *
  * 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
similarity index 60%
rename from arch/arm/mach-s5p6440/include/mach/tick.h
rename to arch/arm/mach-s5p64x0/include/mach/tick.h
index 2f25c7f079700bbe8c268ac65533cfbfe7388d35..00aa7f1d8e51c803e16a970df1f8b1d6b5322d6b 100644 (file)
@@ -1,9 +1,14 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/tick.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
- * S5P6440 - Timer tick support definitions
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S5P64X0 - Timer tick support definitions
  *
  * 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
similarity index 80%
rename from arch/arm/mach-s5p6440/include/mach/timex.h
rename to arch/arm/mach-s5p64x0/include/mach/timex.h
index fb2e8cd4082931255fa4df5dad45a23d4939b002..4b91faa195a85546d03f68e3c97d1dfdc7f7903f 100644 (file)
@@ -1,9 +1,12 @@
-/* arch/arm/mach-s3c64xx/include/mach/timex.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Copyright (c) 2003-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C6400 - time parameters
+ * S5P64X0 - time parameters
  *
  * 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
diff --git a/arch/arm/mach-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..c65b229
--- /dev/null
@@ -0,0 +1,212 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/uncompress.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - uncompress code
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <mach/map.h>
+
+/*
+ * cannot use commonly <plat/uncompress.h>
+ * because uart base of S5P6440 and S5P6450 is different
+ */
+
+typedef unsigned int upf_t;    /* cannot include linux/serial_core.h */
+
+/* uart setup */
+
+static unsigned int fifo_mask;
+static unsigned int fifo_max;
+
+/* forward declerations */
+
+static void arch_detect_cpu(void);
+
+/* defines for UART registers */
+
+#include <plat/regs-serial.h>
+#include <plat/regs-watchdog.h>
+
+/* working in physical space... */
+#undef S3C2410_WDOGREG
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
+
+/* how many bytes we allow into the FIFO at a time in FIFO mode */
+#define FIFO_MAX        (14)
+
+static unsigned long uart_base;
+
+static __inline__ void get_uart_base(void)
+{
+       unsigned int chipid;
+
+       chipid = *(const volatile unsigned int __force *) 0xE0100118;
+
+       uart_base = S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT;
+
+       if ((chipid & 0xff000) == 0x50000)
+               uart_base += 0xEC800000;
+       else
+               uart_base += 0xEC000000;
+}
+
+static __inline__ void uart_wr(unsigned int reg, unsigned int val)
+{
+       volatile unsigned int *ptr;
+
+       get_uart_base();
+       ptr = (volatile unsigned int *)(reg + uart_base);
+       *ptr = val;
+}
+
+static __inline__ unsigned int uart_rd(unsigned int reg)
+{
+       volatile unsigned int *ptr;
+
+       get_uart_base();
+       ptr = (volatile unsigned int *)(reg + uart_base);
+       return *ptr;
+}
+
+/*
+ * we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+ */
+
+static void putc(int ch)
+{
+       if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+               int level;
+
+               while (1) {
+                       level = uart_rd(S3C2410_UFSTAT);
+                       level &= fifo_mask;
+
+                       if (level < fifo_max)
+                               break;
+               }
+
+       } else {
+               /* not using fifos */
+
+               while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+                       barrier();
+       }
+
+       /* write byte to transmission register */
+       uart_wr(S3C2410_UTXH, ch);
+}
+
+static inline void flush(void)
+{
+}
+
+#define __raw_writel(d, ad)                    \
+       do {                                                    \
+               *((volatile unsigned int __force *)(ad)) = (d); \
+       } while (0)
+
+/*
+ * CONFIG_S3C_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+ */
+
+#ifdef CONFIG_S3C_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+static inline void arch_decomp_wdog(void)
+{
+       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+       __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+#ifdef CONFIG_S3C_BOOT_ERROR_RESET
+
+static void arch_decomp_error(const char *x)
+{
+       putstr("\n\n");
+       putstr(x);
+       putstr("\n\n -- System resetting\n");
+
+       __raw_writel(0x4000, S3C2410_WTDAT);
+       __raw_writel(0x4000, S3C2410_WTCNT);
+       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+
+       while(1);
+}
+
+#define arch_error arch_decomp_error
+#endif
+
+#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
+static inline void arch_enable_uart_fifo(void)
+{
+       u32 fifocon = uart_rd(S3C2410_UFCON);
+
+       if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
+               fifocon |= S3C2410_UFCON_RESETBOTH;
+               uart_wr(S3C2410_UFCON, fifocon);
+
+               /* wait for fifo reset to complete */
+               while (1) {
+                       fifocon = uart_rd(S3C2410_UFCON);
+                       if (!(fifocon & S3C2410_UFCON_RESETBOTH))
+                               break;
+               }
+       }
+}
+#else
+#define arch_enable_uart_fifo() do { } while(0)
+#endif
+
+static void arch_decomp_setup(void)
+{
+       /*
+        * we may need to setup the uart(s) here if we are not running
+        * on an BAST... the BAST will have left the uarts configured
+        * after calling linux.
+        */
+
+       arch_detect_cpu();
+       arch_decomp_wdog_start();
+
+       /*
+        * Enable the UART FIFOs if they where not enabled and our
+        * configuration says we should turn them on.
+        */
+
+       arch_enable_uart_fifo();
+}
+
+
+
+static void arch_detect_cpu(void)
+{
+       /* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
similarity index 68%
rename from arch/arm/mach-s5p6440/include/mach/vmalloc.h
rename to arch/arm/mach-s5p64x0/include/mach/vmalloc.h
index 16df257b1dce7a21610afe84b8be1f4b9011dc0c..97a9df38f1cf5ef2438cce77a77f95c5cfad88c7 100644 (file)
@@ -1,4 +1,7 @@
-/* arch/arm/mach-s5p6440/include/mach/vmalloc.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
  *
@@ -12,6 +15,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END      (0xE0000000)
+#define VMALLOC_END    0xE0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c
new file mode 100644 (file)
index 0000000..79833ca
--- /dev/null
@@ -0,0 +1,73 @@
+/* linux/arch/arm/mach-s5p64x0/init.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - Init support
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = {
+       [0] = {
+               .name           = "pclk_low",
+               .divisor        = 1,
+               .min_baud       = 0,
+               .max_baud       = 0,
+       },
+       [1] = {
+               .name           = "uclk1",
+               .divisor        = 1,
+               .min_baud       = 0,
+               .max_baud       = 0,
+       },
+};
+
+/* uart registration process */
+
+void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       struct s3c2410_uartcfg *tcfg = cfg;
+       u32 ucnt;
+
+       for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+               if (!tcfg->clocks) {
+                       tcfg->clocks = s5p64x0_serial_clocks;
+                       tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks);
+               }
+       }
+}
+
+void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       int uart;
+
+       for (uart = 0; uart < no; uart++) {
+               s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart);
+               s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
+       }
+
+       s5p64x0_common_init_uarts(cfg, no);
+       s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
+
+void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       s5p64x0_common_init_uarts(cfg, no);
+       s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
similarity index 67%
rename from arch/arm/mach-s5p6440/mach-smdk6440.c
rename to arch/arm/mach-s5p64x0/mach-smdk6440.c
index 9202aaac3b566d5f41f39fcc27ebcda01c007285..87c3f03c618c4c7057e052b89909df24711e91ad 100644 (file)
@@ -1,7 +1,7 @@
-/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 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 version 2 as
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
 
 #include <mach/hardware.h>
 #include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
 
 #include <plat/regs-serial.h>
-
+#include <plat/gpio-cfg.h>
 #include <plat/s5p6440.h>
 #include <plat/clock.h>
-#include <mach/regs-clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/iic.h>
 
 static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
        [0] = {
-               .hwport      = 0,
-               .flags       = 0,
-               .ucon        = SMDK6440_UCON_DEFAULT,
-               .ulcon       = SMDK6440_ULCON_DEFAULT,
-               .ufcon       = SMDK6440_UFCON_DEFAULT,
+               .hwport         = 0,
+               .flags          = 0,
+               .ucon           = SMDK6440_UCON_DEFAULT,
+               .ulcon          = SMDK6440_ULCON_DEFAULT,
+               .ufcon          = SMDK6440_UFCON_DEFAULT,
        },
        [1] = {
-               .hwport      = 1,
-               .flags       = 0,
-               .ucon        = SMDK6440_UCON_DEFAULT,
-               .ulcon       = SMDK6440_ULCON_DEFAULT,
-               .ufcon       = SMDK6440_UFCON_DEFAULT,
+               .hwport         = 1,
+               .flags          = 0,
+               .ucon           = SMDK6440_UCON_DEFAULT,
+               .ulcon          = SMDK6440_ULCON_DEFAULT,
+               .ufcon          = SMDK6440_UFCON_DEFAULT,
        },
        [2] = {
-               .hwport      = 2,
-               .flags       = 0,
-               .ucon        = SMDK6440_UCON_DEFAULT,
-               .ulcon       = SMDK6440_ULCON_DEFAULT,
-               .ufcon       = SMDK6440_UFCON_DEFAULT,
+               .hwport         = 2,
+               .flags          = 0,
+               .ucon           = SMDK6440_UCON_DEFAULT,
+               .ulcon          = SMDK6440_ULCON_DEFAULT,
+               .ufcon          = SMDK6440_UFCON_DEFAULT,
        },
        [3] = {
-               .hwport      = 3,
-               .flags       = 0,
-               .ucon        = SMDK6440_UCON_DEFAULT,
-               .ulcon       = SMDK6440_ULCON_DEFAULT,
-               .ufcon       = SMDK6440_UFCON_DEFAULT,
+               .hwport         = 3,
+               .flags          = 0,
+               .ucon           = SMDK6440_UCON_DEFAULT,
+               .ulcon          = SMDK6440_ULCON_DEFAULT,
+               .ufcon          = SMDK6440_UFCON_DEFAULT,
        },
 };
 
 static struct platform_device *smdk6440_devices[] __initdata = {
-       &s5p6440_device_iis,
        &s3c_device_adc,
        &s3c_device_rtc,
        &s3c_device_i2c0,
        &s3c_device_i2c1,
        &s3c_device_ts,
        &s3c_device_wdt,
+       &s5p6440_device_iis,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
+       .flags          = 0,
+       .slave_addr     = 0x10,
+       .frequency      = 100*1000,
+       .sda_delay      = 100,
+       .cfg_gpio       = s5p6440_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = {
+       .flags          = 0,
+       .bus_num        = 1,
+       .slave_addr     = 0x10,
+       .frequency      = 100*1000,
+       .sda_delay      = 100,
+       .cfg_gpio       = s5p6440_i2c1_cfg_gpio,
 };
 
 static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
@@ -113,7 +131,7 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 
 static void __init smdk6440_map_io(void)
 {
-       s5p_init_io(NULL, 0, S5P_SYS_ID);
+       s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
 }
@@ -122,9 +140,8 @@ static void __init smdk6440_machine_init(void)
 {
        s3c24xx_ts_set_platdata(&s3c_ts_platform);
 
-       /* I2C */
-       s3c_i2c0_set_platdata(NULL);
-       s3c_i2c1_set_platdata(NULL);
+       s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
+       s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
        i2c_register_board_info(0, smdk6440_i2c_devs0,
                        ARRAY_SIZE(smdk6440_i2c_devs0));
        i2c_register_board_info(1, smdk6440_i2c_devs1,
@@ -135,9 +152,7 @@ static void __init smdk6440_machine_init(void)
 
 MACHINE_START(SMDK6440, "SMDK6440")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .boot_params    = S5P64X0_PA_SDRAM + 0x100,
 
        .init_irq       = s5p6440_init_irq,
        .map_io         = smdk6440_map_io,
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
new file mode 100644 (file)
index 0000000..d609f5a
--- /dev/null
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c
+ *
+ * Copyright (c) 2010 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
+
+#include <plat/regs-serial.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s5p6450.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+#include <plat/pll.h>
+#include <plat/adc.h>
+#include <plat/ts.h>
+
+#define SMDK6450_UCON_DEFAULT  (S3C2410_UCON_TXILEVEL |        \
+                               S3C2410_UCON_RXILEVEL |         \
+                               S3C2410_UCON_TXIRQMODE |        \
+                               S3C2410_UCON_RXIRQMODE |        \
+                               S3C2410_UCON_RXFIFO_TOI |       \
+                               S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK6450_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define SMDK6450_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE |       \
+                               S3C2440_UFCON_TXTRIG16 |        \
+                               S3C2410_UFCON_RXTRIG8)
+
+static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport         = 0,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+       [1] = {
+               .hwport         = 1,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+       [2] = {
+               .hwport         = 2,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+       [3] = {
+               .hwport         = 3,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+       [4] = {
+               .hwport         = 4,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+#endif
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+       [5] = {
+               .hwport         = 5,
+               .flags          = 0,
+               .ucon           = SMDK6450_UCON_DEFAULT,
+               .ulcon          = SMDK6450_ULCON_DEFAULT,
+               .ufcon          = SMDK6450_UFCON_DEFAULT,
+       },
+#endif
+};
+
+static struct platform_device *smdk6450_devices[] __initdata = {
+       &s3c_device_adc,
+       &s3c_device_rtc,
+       &s3c_device_i2c0,
+       &s3c_device_i2c1,
+       &s3c_device_ts,
+       &s3c_device_wdt,
+       &s5p6450_device_iis0,
+       /* s5p6450_device_spi0 will be added */
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = {
+       .flags          = 0,
+       .slave_addr     = 0x10,
+       .frequency      = 100*1000,
+       .sda_delay      = 100,
+       .cfg_gpio       = s5p6450_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = {
+       .flags          = 0,
+       .bus_num        = 1,
+       .slave_addr     = 0x10,
+       .frequency      = 100*1000,
+       .sda_delay      = 100,
+       .cfg_gpio       = s5p6450_i2c1_cfg_gpio,
+};
+
+static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
+       { I2C_BOARD_INFO("24c08", 0x50), },     /* Samsung KS24C080C EEPROM */
+};
+
+static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
+       { I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
+};
+
+static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
+       .delay                  = 10000,
+       .presc                  = 49,
+       .oversampling_shift     = 2,
+};
+
+static void __init smdk6450_map_io(void)
+{
+       s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
+       s3c24xx_init_clocks(19200000);
+       s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
+}
+
+static void __init smdk6450_machine_init(void)
+{
+       s3c24xx_ts_set_platdata(&s3c_ts_platform);
+
+       s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
+       s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
+       i2c_register_board_info(0, smdk6450_i2c_devs0,
+                       ARRAY_SIZE(smdk6450_i2c_devs0));
+       i2c_register_board_info(1, smdk6450_i2c_devs1,
+                       ARRAY_SIZE(smdk6450_i2c_devs1));
+
+       platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
+}
+
+MACHINE_START(SMDK6450, "SMDK6450")
+       /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+       .boot_params    = S5P64X0_PA_SDRAM + 0x100,
+
+       .init_irq       = s5p6450_init_irq,
+       .map_io         = smdk6450_map_io,
+       .init_machine   = smdk6450_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
similarity index 52%
rename from arch/arm/mach-s5p6440/setup-i2c0.c
rename to arch/arm/mach-s5p64x0/setup-i2c0.c
index 2c99d14f7ac7bd55cccd8adc42eccfffdde600d8..dc4cc65a5019c3ba74321dc3fd78247003df6cae 100644 (file)
@@ -1,11 +1,11 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c0.c
+/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * I2C0 GPIO configuration.
  *
- * Based on plat-s3c64xx/setup-i2c0.c
+ * Based on plat-s3c64x0/setup-i2c0.c
  *
  * 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
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/gpio.h>
 
 struct platform_device; /* don't need the contents */
 
-#include <linux/gpio.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+#include <mach/i2c.h>
+
+void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
 {
        s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP);
        s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP);
 }
+
+void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
+{
+       s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2));
+       s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP);
+       s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2));
+       s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
similarity index 55%
rename from arch/arm/mach-s5p6440/setup-i2c1.c
rename to arch/arm/mach-s5p64x0/setup-i2c1.c
index 9a1537f786e0e793f2dfbaf4fa60286cf9cbb364..2edd7912f8e405afa674b17d02e0f6a93d1ea04d 100644 (file)
@@ -1,7 +1,7 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c1.c
+/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * I2C1 GPIO configuration.
  *
@@ -21,10 +21,22 @@ struct platform_device; /* don't need the contents */
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+#include <mach/i2c.h>
+
+void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
 {
        s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6));
        s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP);
        s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6));
        s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP);
 }
+
+void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
+{
+       s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6));
+       s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP);
+       s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6));
+       s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
index 251c92ac5b227e05a28251ed7b890ff1f84eccfb..fd2708e7d8a9f4aa61bf645abad7f644149720e7 100644 (file)
@@ -1,4 +1,7 @@
 /* linux/arch/arm/mach-s5pc100/cpu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Copyright 2009 Samsung Electronics Co.
  *     Byungho Min <bhmin@samsung.com>
@@ -21,6 +24,7 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -55,11 +59,31 @@ static struct map_desc s5pc100_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(S5PC100_PA_SYSTIMER),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GPIO,
+               .pfn            = __phys_to_pfn(S5PC100_PA_GPIO),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC0,
+               .pfn            = __phys_to_pfn(S5PC100_PA_VIC0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC1,
+               .pfn            = __phys_to_pfn(S5PC100_PA_VIC1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)VA_VIC2,
-               .pfn            = __phys_to_pfn(S5P_PA_VIC2),
+               .pfn            = __phys_to_pfn(S5PC100_PA_VIC2),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S3C_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5PC100_VA_OTHERS,
                .pfn            = __phys_to_pfn(S5PC100_PA_OTHERS),
index 70e02e91ee3c99602b2864f5a07cd8da820f8d32..b2ba95ddf8e06a0259288804160cc255bd18f8e6 100644 (file)
         * aligned and add in the offset when we load the value here.
         */
 
-       .macro addruart, rx, rtmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = S3C_VA_UART
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C_PA_UART
+               ldr     \rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index 01b9134feff0d055fd33418f7b07bc68c000b885..8751ef4a6804d481d3f1d4ae2c5842dd88f4635a 100644 (file)
 #define S5PC100_PA_OTHERS      (0xE0200000)
 #define S5PC100_VA_OTHERS      (S3C_VA_SYS + 0x10000)
 
-#define S5P_PA_GPIO            (0xE0300000)
+#define S5PC100_PA_GPIO                (0xE0300000)
 #define S5PC1XX_VA_GPIO                S3C_ADDR(0x00500000)
 
 /* Interrupt */
-#define S5PC100_PA_VIC         (0xE4000000)
+#define S5PC100_PA_VIC0                (0xE4000000)
+#define S5PC100_PA_VIC1                (0xE4100000)
+#define S5PC100_PA_VIC2                (0xE4200000)
 #define S5PC100_VA_VIC         S3C_VA_IRQ
-#define S5PC100_PA_VIC_OFFSET  0x100000
 #define S5PC100_VA_VIC_OFFSET  0x10000
-#define S5PC1XX_PA_VIC(x)      (S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET))
 #define S5PC1XX_VA_VIC(x)      (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET))
-#define S5P_PA_VIC0            S5PC1XX_PA_VIC(0)
-#define S5P_PA_VIC1            S5PC1XX_PA_VIC(1)
-#define S5P_PA_VIC2            S5PC1XX_PA_VIC(2)
 
 
 #define S5PC100_PA_ONENAND     (0xE7100000)
index 020c3f98f81fa0237f2c82b9694dc6a358c1c4fb..880fb075092cf3d65ed3fb7236652cb7a737caf0 100644 (file)
@@ -235,8 +235,6 @@ static void __init smdkc100_machine_init(void)
 
 MACHINE_START(SMDKC100, "SMDKC100")
        /* Maintainer: Byungho Min <bhmin@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pc100_init_irq,
        .map_io         = smdkc100_map_io,
index d3a38955c7418cc626e6bfea534613b090bb0262..5315fec3db86ae31df32ff0629a91e913b66a502 100644 (file)
@@ -53,11 +53,6 @@ config S5PV210_SETUP_SDHCI_GPIO
        help
          Common setup code for SDHCI gpio.
 
-config S5PC110_DEV_ONENAND
-       bool
-       help
-         Compile in platform device definition for OneNAND1 controller
-
 menu "S5PC110 Machines"
 
 config MACH_AQUILA
@@ -71,7 +66,7 @@ config MACH_AQUILA
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
-       select S5PC110_DEV_ONENAND
+       select S5P_DEV_ONENAND
        select S5PV210_SETUP_FB_24BPP
        select S5PV210_SETUP_SDHCI
        help
@@ -88,7 +83,7 @@ config MACH_GONI
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
-       select S5PC110_DEV_ONENAND
+       select S5P_DEV_ONENAND
        select S5PV210_SETUP_FB_24BPP
        select S5PV210_SETUP_SDHCI
        help
index 05048c5aa4c6e7e7e8eb94d435b9cb8c2243ddbd..7045489124082d69715df5c9f4ec62061738763b 100644 (file)
@@ -26,7 +26,6 @@ obj-$(CONFIG_MACH_GONI)               += mach-goni.o
 
 obj-y                          += dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
-obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o
 
 obj-$(CONFIG_S5PV210_SETUP_FB_24BPP)   += setup-fb-24bpp.o
 obj-$(CONFIG_S5PV210_SETUP_I2C1)       += setup-i2c1.o
index af91fefef2c6c77899c4f96ffc9bed03cacee633..d562670e1b0b44005ade9644f69338de44b459bb 100644 (file)
@@ -173,11 +173,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
 }
 
-static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
-}
-
 static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
@@ -280,6 +275,24 @@ static struct clk init_clocks_disable[] = {
                .parent         = &clk_hclk_dsys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1<<29),
+       }, {
+               .name           = "fimc",
+               .id             = 0,
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip0_ctrl,
+               .ctrlbit        = (1 << 24),
+       }, {
+               .name           = "fimc",
+               .id             = 1,
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip0_ctrl,
+               .ctrlbit        = (1 << 25),
+       }, {
+               .name           = "fimc",
+               .id             = 2,
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip0_ctrl,
+               .ctrlbit        = (1 << 26),
        }, {
                .name           = "otg",
                .id             = -1,
@@ -357,7 +370,7 @@ static struct clk init_clocks_disable[] = {
                .id             = 1,
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
-               .ctrlbit        = (1<<8),
+               .ctrlbit        = (1 << 10),
        }, {
                .name           = "i2c",
                .id             = 2,
index b9f4d677cf5541460747a5086fb25f5fbcea744e..2f16bfc0a116cd4bde8298b8c83ed4f076145080 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s5pv210/cpu.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ *             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 version 2 as
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,7 +48,22 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S5P_VA_SYSTIMER,
                .pfn            = __phys_to_pfn(S5PV210_PA_SYSTIMER),
-               .length         = SZ_1M,
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GPIO,
+               .pfn            = __phys_to_pfn(S5PV210_PA_GPIO),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC0,
+               .pfn            = __phys_to_pfn(S5PV210_PA_VIC0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)VA_VIC1,
+               .pfn            = __phys_to_pfn(S5PV210_PA_VIC1),
+               .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)VA_VIC2,
@@ -59,6 +75,11 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(S5PV210_PA_VIC3),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S3C_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_SROMC,
                .pfn            = __phys_to_pfn(S5PV210_PA_SROMC),
index 7872f5c3dfc24271fb1853d8a6e86a7ad79ff051..169fe654a59eac3c2dfd91cf33c0d29d1fc8e50c 100644 (file)
         * aligned and add in the offset when we load the value here.
         */
 
-       .macro addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = S3C_VA_UART
+       .macro addruart, rp, rv
+               ldr     \rp, = S3C_PA_UART
+               ldr     \rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index dd4fb6bf14b506a463fb77de68d78baa85c41106..bd9afd52466ad2cb787ed90ba394cc1f73870cb0 100644 (file)
 #include <plat/map-s5p.h>
 
 #define S5PC110_PA_ONENAND     (0xB0000000)
+#define S5P_PA_ONENAND         S5PC110_PA_ONENAND
+
 #define S5PC110_PA_ONENAND_DMA (0xB0600000)
+#define S5P_PA_ONENAND_DMA     S5PC110_PA_ONENAND_DMA
 
 #define S5PV210_PA_CHIPID      (0xE0000000)
 #define S5P_PA_CHIPID          S5PV210_PA_CHIPID
@@ -26,7 +29,6 @@
 #define S5P_PA_SYSCON          S5PV210_PA_SYSCON
 
 #define S5PV210_PA_GPIO                (0xE0200000)
-#define S5P_PA_GPIO            S5PV210_PA_GPIO
 
 /* SPI */
 #define S5PV210_PA_SPI0                0xE1300000
 #define S5PV210_PA_HSMMC(x)    (0xEB000000 + ((x) * 0x100000))
 
 #define S5PV210_PA_VIC0                (0xF2000000)
-#define S5P_PA_VIC0            S5PV210_PA_VIC0
-
 #define S5PV210_PA_VIC1                (0xF2100000)
-#define S5P_PA_VIC1            S5PV210_PA_VIC1
-
 #define S5PV210_PA_VIC2                (0xF2200000)
-#define S5P_PA_VIC2            S5PV210_PA_VIC2
-
 #define S5PV210_PA_VIC3                (0xF2300000)
-#define S5P_PA_VIC3            S5PV210_PA_VIC3
 
 #define S5PV210_PA_SDRAM       (0x20000000)
 #define S5P_PA_SDRAM           S5PV210_PA_SDRAM
index 58f515e0747ef8069eeca119707b30fe0efa18c1..df9a28808323e44efed82fe7d67b880180dfa6b6 100644 (file)
@@ -17,6 +17,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H __FILE__
 
-#define VMALLOC_END      (0xE0000000)
+#define VMALLOC_END    (0xE0000000UL)
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 0dda8012d6b22c029a6da035a19a934c6092e5e3..00883087363c9229acde4d81e96e7d43668c412d 100644 (file)
@@ -477,7 +477,7 @@ static struct platform_device *aquila_devices[] __initdata = {
        &aquila_i2c_gpio_pmic,
        &aquila_device_gpiokeys,
        &s3c_device_fb,
-       &s5pc110_device_onenand,
+       &s5p_device_onenand,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
@@ -516,8 +516,6 @@ MACHINE_START(AQUILA, "Aquila")
        /* Maintainers:
           Marek Szyprowski <m.szyprowski@samsung.com>
           Kyungmin Park <kyungmin.park@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = aquila_map_io,
index 53754d7d364ef513c233c5e77fcdee038e734635..d9ecf57fc2a5698ce0ff4067b243b052a9661efc 100644 (file)
@@ -456,7 +456,7 @@ static void goni_setup_sdhci(void)
 
 static struct platform_device *goni_devices[] __initdata = {
        &s3c_device_fb,
-       &s5pc110_device_onenand,
+       &s5p_device_onenand,
        &goni_i2c_gpio_pmic,
        &goni_device_gpiokeys,
        &s5p_device_fimc0,
@@ -491,8 +491,6 @@ static void __init goni_machine_init(void)
 
 MACHINE_START(GONI, "GONI")
        /* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = goni_map_io,
index 8211bb87c54bbd5a03127689a5ffc9a76f06b82d..cea9bca79d880c20bc0cb46df7dd8b77883976d8 100644 (file)
@@ -127,8 +127,6 @@ static void __init smdkc110_machine_init(void)
 
 MACHINE_START(SMDKC110, "SMDKC110")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkc110_map_io,
index fbbc0a3c3738aaf2f99bab6556a139b708ee4985..83189ae9da9ad9dad00f16f6fc9ca459aaa89808 100644 (file)
@@ -165,8 +165,6 @@ static void __init smdkv210_machine_init(void)
 
 MACHINE_START(SMDKV210, "SMDKV210")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkv210_map_io,
index 77f2b4d85e6bb09a91bcdcb0ef32e16afda16f84..26a0f03df8eaf2ae85323cda81e3b1044ec66d97 100644 (file)
@@ -30,6 +30,16 @@ static struct clk clk_sclk_hdmi27m = {
        .rate           = 27000000,
 };
 
+static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
+}
+
+static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk clk_mout_apll = {
@@ -39,6 +49,14 @@ static struct clksrc_clk clk_mout_apll = {
        },
        .sources        = &clk_src_apll,
        .reg_src        = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_apll = {
+       .clk    = {
+               .name           = "sclk_apll",
+               .id             = -1,
+               .parent         = &clk_mout_apll.clk,
+       },
        .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
 };
 
@@ -61,7 +79,7 @@ static struct clksrc_clk clk_mout_mpll = {
 };
 
 static struct clk *clkset_moutcore_list[] = {
-       [0] = &clk_mout_apll.clk,
+       [0] = &clk_sclk_apll.clk,
        [1] = &clk_mout_mpll.clk,
 };
 
@@ -154,7 +172,7 @@ static struct clksrc_clk clk_pclk_dbg = {
 
 static struct clk *clkset_corebus_list[] = {
        [0] = &clk_mout_mpll.clk,
-       [1] = &clk_mout_apll.clk,
+       [1] = &clk_sclk_apll.clk,
 };
 
 static struct clksrc_sources clkset_mout_corebus = {
@@ -220,7 +238,7 @@ static struct clksrc_clk clk_pclk_acp = {
 
 static struct clk *clkset_aclk_top_list[] = {
        [0] = &clk_mout_mpll.clk,
-       [1] = &clk_mout_apll.clk,
+       [1] = &clk_sclk_apll.clk,
 };
 
 static struct clksrc_sources clkset_aclk_200 = {
@@ -321,11 +339,6 @@ static struct clksrc_clk clk_sclk_vpll = {
        .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
 };
 
-static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
-}
-
 static struct clk init_clocks_disable[] = {
        {
                .name           = "timers",
@@ -337,7 +350,37 @@ static struct clk init_clocks_disable[] = {
 };
 
 static struct clk init_clocks[] = {
-       /* Nothing here yet */
+       {
+               .name           = "uart",
+               .id             = 0,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "uart",
+               .id             = 3,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "uart",
+               .id             = 4,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "uart",
+               .id             = 5,
+               .enable         = s5pv310_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 5),
+       }
 };
 
 static struct clk *clkset_group_list[] = {
@@ -359,8 +402,8 @@ static struct clksrc_clk clksrcs[] = {
                .clk    = {
                        .name           = "uclk1",
                        .id             = 0,
+                       .enable         = s5pv310_clksrc_mask_peril0_ctrl,
                        .ctrlbit        = (1 << 0),
-                       .enable         = s5pv310_clk_ip_peril_ctrl,
                },
                .sources = &clkset_group,
                .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
@@ -369,8 +412,8 @@ static struct clksrc_clk clksrcs[] = {
                .clk            = {
                        .name           = "uclk1",
                        .id             = 1,
-                       .enable         = s5pv310_clk_ip_peril_ctrl,
-                       .ctrlbit        = (1 << 1),
+                       .enable         = s5pv310_clksrc_mask_peril0_ctrl,
+                       .ctrlbit        = (1 << 4),
                },
                .sources = &clkset_group,
                .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
@@ -379,8 +422,8 @@ static struct clksrc_clk clksrcs[] = {
                .clk            = {
                        .name           = "uclk1",
                        .id             = 2,
-                       .enable         = s5pv310_clk_ip_peril_ctrl,
-                       .ctrlbit        = (1 << 2),
+                       .enable         = s5pv310_clksrc_mask_peril0_ctrl,
+                       .ctrlbit        = (1 << 8),
                },
                .sources = &clkset_group,
                .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
@@ -389,8 +432,8 @@ static struct clksrc_clk clksrcs[] = {
                .clk            = {
                        .name           = "uclk1",
                        .id             = 3,
-                       .enable         = s5pv310_clk_ip_peril_ctrl,
-                       .ctrlbit        = (1 << 3),
+                       .enable         = s5pv310_clksrc_mask_peril0_ctrl,
+                       .ctrlbit        = (1 << 12),
                },
                .sources = &clkset_group,
                .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
@@ -399,7 +442,7 @@ static struct clksrc_clk clksrcs[] = {
                .clk            = {
                        .name           = "sclk_pwm",
                        .id             = -1,
-                       .enable         = s5pv310_clk_ip_peril_ctrl,
+                       .enable         = s5pv310_clksrc_mask_peril0_ctrl,
                        .ctrlbit        = (1 << 24),
                },
                .sources = &clkset_group,
@@ -411,6 +454,7 @@ static struct clksrc_clk clksrcs[] = {
 /* Clock initialization code */
 static struct clksrc_clk *sysclks[] = {
        &clk_mout_apll,
+       &clk_sclk_apll,
        &clk_mout_epll,
        &clk_mout_mpll,
        &clk_moutcore,
@@ -470,11 +514,11 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
        apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
        mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
        epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
-                               __raw_readl(S5P_EPLL_CON1), pll_4500);
+                               __raw_readl(S5P_EPLL_CON1), pll_4600);
 
        vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
        vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
-                               __raw_readl(S5P_VPLL_CON1), pll_4502);
+                               __raw_readl(S5P_VPLL_CON1), pll_4650);
 
        clk_fout_apll.rate = apll;
        clk_fout_mpll.rate = mpll;
index 196c9f12ed85719be8bf757bc19b2ac6b092f68a..4add39853ff9dcf34f3e3c4aeeb25ea8e194da80 100644 (file)
@@ -31,20 +31,40 @@ extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
 /* Initial IO mappings */
 static struct map_desc s5pv310_iodesc[] __initdata = {
        {
-               .virtual        = (unsigned long)S5P_VA_COREPERI_BASE,
-               .pfn            = __phys_to_pfn(S5PV310_PA_COREPERI),
-               .length         = SZ_8K,
+               .virtual        = (unsigned long)S5P_VA_SYSRAM,
+               .pfn            = __phys_to_pfn(S5PV310_PA_SYSRAM),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_CMU,
+               .pfn            = __phys_to_pfn(S5PV310_PA_CMU),
+               .length         = SZ_128K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
                .pfn            = __phys_to_pfn(S5PV310_PA_COMBINER),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_COREPERI_BASE,
+               .pfn            = __phys_to_pfn(S5PV310_PA_COREPERI),
+               .length         = SZ_8K,
+               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_L2CC,
                .pfn            = __phys_to_pfn(S5PV310_PA_L2CC),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GPIO,
+               .pfn            = __phys_to_pfn(S5PV310_PA_GPIO1),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S3C_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
        },
 };
 
index 6fb3893486bec83100c03c0cc9df3c969d3bf9fe..b0d920c474d3f4b501004ec8ef058c49bc66b002 100644 (file)
         * aligned and add in the offset when we load the value here.
         */
 
-       .macro addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1
-               ldreq   \rx, = S3C_PA_UART
-               ldrne   \rx, = S3C_VA_UART
+       .macro addruart, rp, rv
+               ldreq   \rp, = S3C_PA_UART
+               ldrne   \rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-               add     \rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+               add     \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+               add     \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
 #endif
        .endm
 
index 56885ca3773cb2c85d275ecb11e6bce284de2888..471fc3bb199a7a10becae92cd99fae46871ad997 100644 (file)
 
 #include <plat/irqs.h>
 
-/* Private Peripheral Interrupt */
+/* PPI: Private Peripheral Interrupt */
+
 #define IRQ_PPI(x)             S5P_IRQ(x+16)
 
 #define IRQ_LOCALTIMER         IRQ_PPI(13)
 
-/* Shared Peripheral Interrupt */
+/* SPI: Shared Peripheral Interrupt */
+
 #define IRQ_SPI(x)             S5P_IRQ(x+32)
 
 #define IRQ_EINT0              IRQ_SPI(40)
@@ -36,7 +38,7 @@
 #define IRQ_PCIE               IRQ_SPI(50)
 #define IRQ_SYSTEM_TIMER       IRQ_SPI(51)
 #define IRQ_MFC                        IRQ_SPI(52)
-#define IRQ_WTD                        IRQ_SPI(53)
+#define IRQ_WDT                        IRQ_SPI(53)
 #define IRQ_AUDIO_SS           IRQ_SPI(54)
 #define IRQ_AC97               IRQ_SPI(55)
 #define IRQ_SPDIF              IRQ_SPI(56)
 
 #define IRQ_IIC                        COMBINER_IRQ(27, 0)
 
+#define IRQ_ONENAND_AUDI       COMBINER_IRQ(34, 0)
+
 /* Set the default NR_IRQS */
+
 #define NR_IRQS                        COMBINER_IRQ(MAX_COMBINER_NR, 0)
 
 #define MAX_COMBINER_NR                39
 
-#endif /* ASM_ARCH_IRQS_H */
+#endif /* __ASM_ARCH_IRQS_H */
index 87697c9fca5b47757ddcd24c1510f2783c5ca8f1..aff6d23624bb6d457e118ee7381a004a79968ceb 100644 (file)
 
 #include <plat/map-s5p.h>
 
+#define S5PV310_PA_SYSRAM              (0x02025000)
+
+#define S5PC210_PA_ONENAND             (0x0C000000)
+#define S5P_PA_ONENAND                 S5PC210_PA_ONENAND
+
+#define S5PC210_PA_ONENAND_DMA         (0x0C600000)
+#define S5P_PA_ONENAND_DMA             S5PC210_PA_ONENAND_DMA
+
 #define S5PV310_PA_CHIPID              (0x10000000)
 #define S5P_PA_CHIPID                  S5PV310_PA_CHIPID
 
 #define S5PV310_PA_SYSCON              (0x10020000)
 #define S5P_PA_SYSCON                  S5PV310_PA_SYSCON
 
+#define S5PV310_PA_CMU                 (0x10030000)
+
 #define S5PV310_PA_WATCHDOG            (0x10060000)
 
 #define S5PV310_PA_COMBINER            (0x10448000)
 #define S5PV310_PA_GIC_DIST            (0x10501000)
 #define S5PV310_PA_L2CC                        (0x10502000)
 
-#define S5PV310_PA_GPIO                        (0x11000000)
-#define S5P_PA_GPIO                    S5PV310_PA_GPIO
+#define S5PV310_PA_GPIO1               (0x11400000)
+#define S5PV310_PA_GPIO2               (0x11000000)
+#define S5PV310_PA_GPIO3               (0x03860000)
+
+#define S5PV310_PA_HSMMC(x)            (0x12510000 + ((x) * 0x10000))
 
 #define S5PV310_PA_UART                        (0x13800000)
 
 
 /* compatibiltiy defines. */
 #define S3C_PA_UART                    S5PV310_PA_UART
+#define S3C_PA_HSMMC0                  S5PV310_PA_HSMMC(0)
+#define S3C_PA_HSMMC1                  S5PV310_PA_HSMMC(1)
+#define S3C_PA_HSMMC2                  S5PV310_PA_HSMMC(2)
+#define S3C_PA_HSMMC3                  S5PV310_PA_HSMMC(3)
 #define S3C_PA_IIC                     S5PV310_PA_IIC0
 #define S3C_PA_WDT                     S5PV310_PA_WATCHDOG
 
index 59e3a7e94d801c86e99dc6683466876d5b948567..4013553cd9be8de219ffb3cfbd51905b35f517c7 100644 (file)
 
 #include <mach/map.h>
 
-#define S5P_CLKREG(x)                  (S3C_VA_SYS + (x))
+#define S5P_CLKREG(x)                  (S5P_VA_CMU + (x))
 
 #define S5P_INFORM0                    S5P_CLKREG(0x800)
 
-#define S5P_EPLL_CON0                  S5P_CLKREG(0x1C110)
-#define S5P_EPLL_CON1                  S5P_CLKREG(0x1C114)
-#define S5P_VPLL_CON0                  S5P_CLKREG(0x1C120)
-#define S5P_VPLL_CON1                  S5P_CLKREG(0x1C124)
+#define S5P_EPLL_CON0                  S5P_CLKREG(0x0C110)
+#define S5P_EPLL_CON1                  S5P_CLKREG(0x0C114)
+#define S5P_VPLL_CON0                  S5P_CLKREG(0x0C120)
+#define S5P_VPLL_CON1                  S5P_CLKREG(0x0C124)
 
-#define S5P_CLKSRC_TOP0                        S5P_CLKREG(0x1C210)
-#define S5P_CLKSRC_TOP1                        S5P_CLKREG(0x1C214)
+#define S5P_CLKSRC_TOP0                        S5P_CLKREG(0x0C210)
+#define S5P_CLKSRC_TOP1                        S5P_CLKREG(0x0C214)
 
-#define S5P_CLKSRC_PERIL0              S5P_CLKREG(0x1C250)
+#define S5P_CLKSRC_PERIL0              S5P_CLKREG(0x0C250)
 
-#define S5P_CLKDIV_TOP                 S5P_CLKREG(0x1C510)
+#define S5P_CLKDIV_TOP                 S5P_CLKREG(0x0C510)
 
-#define S5P_CLKDIV_PERIL0              S5P_CLKREG(0x1C550)
-#define S5P_CLKDIV_PERIL1              S5P_CLKREG(0x1C554)
-#define S5P_CLKDIV_PERIL2              S5P_CLKREG(0x1C558)
-#define S5P_CLKDIV_PERIL3              S5P_CLKREG(0x1C55C)
-#define S5P_CLKDIV_PERIL4              S5P_CLKREG(0x1C560)
-#define S5P_CLKDIV_PERIL5              S5P_CLKREG(0x1C564)
+#define S5P_CLKDIV_PERIL0              S5P_CLKREG(0x0C550)
+#define S5P_CLKDIV_PERIL1              S5P_CLKREG(0x0C554)
+#define S5P_CLKDIV_PERIL2              S5P_CLKREG(0x0C558)
+#define S5P_CLKDIV_PERIL3              S5P_CLKREG(0x0C55C)
+#define S5P_CLKDIV_PERIL4              S5P_CLKREG(0x0C560)
+#define S5P_CLKDIV_PERIL5              S5P_CLKREG(0x0C564)
 
-#define S5P_CLKGATE_IP_PERIL           S5P_CLKREG(0x1C950)
+#define S5P_CLKSRC_MASK_PERIL0         S5P_CLKREG(0x0C350)
 
-#define S5P_CLKSRC_CORE                        S5P_CLKREG(0x20200)
+#define S5P_CLKGATE_IP_PERIL           S5P_CLKREG(0x0C950)
 
-#define S5P_CLKDIV_CORE0               S5P_CLKREG(0x20500)
+#define S5P_CLKSRC_CORE                        S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_CORE0               S5P_CLKREG(0x10500)
 
-#define S5P_APLL_LOCK                  S5P_CLKREG(0x24000)
-#define S5P_MPLL_LOCK                  S5P_CLKREG(0x24004)
-#define S5P_APLL_CON0                  S5P_CLKREG(0x24100)
-#define S5P_APLL_CON1                  S5P_CLKREG(0x24104)
-#define S5P_MPLL_CON0                  S5P_CLKREG(0x24108)
-#define S5P_MPLL_CON1                  S5P_CLKREG(0x2410C)
+#define S5P_APLL_LOCK                  S5P_CLKREG(0x14000)
+#define S5P_MPLL_LOCK                  S5P_CLKREG(0x14004)
+#define S5P_APLL_CON0                  S5P_CLKREG(0x14100)
+#define S5P_APLL_CON1                  S5P_CLKREG(0x14104)
+#define S5P_MPLL_CON0                  S5P_CLKREG(0x14108)
+#define S5P_MPLL_CON1                  S5P_CLKREG(0x1410C)
 
-#define S5P_CLKSRC_CPU                 S5P_CLKREG(0x24200)
-#define S5P_CLKMUX_STATCPU             S5P_CLKREG(0x24400)
+#define S5P_CLKSRC_CPU                 S5P_CLKREG(0x14200)
+#define S5P_CLKMUX_STATCPU             S5P_CLKREG(0x14400)
 
-#define S5P_CLKDIV_CPU                 S5P_CLKREG(0x24500)
-#define S5P_CLKDIV_STATCPU             S5P_CLKREG(0x24600)
+#define S5P_CLKDIV_CPU                 S5P_CLKREG(0x14500)
+#define S5P_CLKDIV_STATCPU             S5P_CLKREG(0x14600)
 
-#define S5P_CLKGATE_SCLKCPU            S5P_CLKREG(0x24800)
+#define S5P_CLKGATE_SCLKCPU            S5P_CLKREG(0x14800)
 
 #endif /* __ASM_ARCH_REGS_CLOCK_H */
index 990f3ba88a1fb59cee621cacd21e2ff72b263f0e..b7ec252384f47059f681ddad95c1d183ad8b39dc 100644 (file)
@@ -7,17 +7,10 @@
 #define ASM_ARCH_SMP_H __FILE__
 
 #include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
 
 extern void __iomem *gic_cpu_base_addr;
 
-#define hard_smp_processor_id()                        \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x03;                         \
-       })
-
 /*
  * We use IRQ1 as the IPI
  */
index 3f565ebb7daa940dea8d199e51d7d1eda43d7fb2..256f221edf3aca654d59000d3016cdbabe1f80c1 100644 (file)
@@ -17,6 +17,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H __FILE__
 
-#define VMALLOC_END      (0xF0000000)
+#define VMALLOC_END    (0xF0000000UL)
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 0d6ab77709d263e28bd79790dd4601a4716b1eb8..46215a14b3bb49ec24ba11f9592565733a08b266 100644 (file)
@@ -82,8 +82,6 @@ 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> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv310_init_irq,
        .map_io         = smdkv310_map_io,
index 2388cb947936b0bcd2494ed3a9859656aee1d226..d7c2ec770f88bf1e80cc74e2749262726e10c598 100644 (file)
@@ -76,8 +76,6 @@ static void __init universal_machine_init(void)
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-       .phys_io        = S3C_PA_UART & 0xfff00000,
-       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S5P_PA_SDRAM + 0x100,
        .init_irq       = s5pv310_init_irq,
        .map_io         = universal_map_io,
index fe9469abd0066190286d1e6dd382bb18073e24a7..d357c198edee308112bc3633256376ca69720abb 100644 (file)
@@ -187,6 +187,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                 * until it receives a soft interrupt, and then the
                 * secondary CPU branches to this address.
                 */
-       __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0);
+       __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
        }
 }
index 169e5b87dbffa5ac001dda528e282bada4c7b673..5778274a8260c8229987dac0be15cfb8d50d19fe 100644 (file)
@@ -447,8 +447,6 @@ static void __init assabet_map_io(void)
 
 
 MACHINE_START(ASSABET, "Intel-Assabet")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .fixup          = fixup_assabet,
        .map_io         = assabet_map_io,
index 259cb2c15fffee94f679c424c9d2146bd8d36b5f..4f19ff868b00dca86d800ad7602b776a5a4b6ad2 100644 (file)
@@ -302,8 +302,6 @@ static void __init badge4_map_io(void)
 }
 
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = badge4_map_io,
        .init_irq       = sa1100_init_irq,
index bc950ef418af35a534bf01900482d68b8232ddf1..98d780608c7e98ffb3a64fb285301cc88731a6b5 100644 (file)
@@ -135,8 +135,6 @@ static void __init cerf_init(void)
 
 MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
        /* Maintainer: support@intrinsyc.com */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .map_io         = cerf_map_io,
        .init_irq       = cerf_init_irq,
        .timer          = &sa1100_timer,
index 16e682d5dbb7986fd1f0f038a65f87b8c2907910..d43c5ef58eb698f088820a0d0b9cc5c629dd8cc1 100644 (file)
@@ -379,8 +379,6 @@ static void __init collie_map_io(void)
 }
 
 MACHINE_START(COLLIE, "Sharp-Collie")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .map_io         = collie_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 0c7cea0dc01314381137ed85070c5e678371bba2..03d7376cf8a0a57e50dca58bc56d68d7868713e8 100644 (file)
@@ -84,8 +84,6 @@ static void __init h3100_mach_init(void)
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = h3100_map_io,
        .init_irq       = sa1100_init_irq,
index af3b71459f8d2adf794d91ac0da199d2e9eadfd5..965f64a836f8b13f22d1f26680403d26f2a9db40 100644 (file)
@@ -125,8 +125,6 @@ static void __init h3600_mach_init(void)
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = h3600_map_io,
        .init_irq       = sa1100_init_irq,
index 51568dfc8e97187c2892b699bc5ac493d1b16008..db5e434a17dbf5de939030112149e199eb4523ff 100644 (file)
@@ -195,8 +195,6 @@ static void __init hackkit_init(void)
  */
 
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = hackkit_map_io,
        .init_irq       = sa1100_init_irq,
index 336adccea54232ef50f7b43367f824c26bc20163..0cd0fc9635b6b3e2afb8668a43bb9a8389b9bbb1 100644 (file)
 */
 #include <mach/hardware.h>
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x80000000        @ physical base address
-               movne   \rx, #0xf8000000        @ virtual address
+               .macro  addruart, rp, rv
+               mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               moveq   \rp, #0x80000000        @ physical base address
+               movne   \rp, #0xf8000000        @ virtual address
 
                @ We probe for the active serial port here, coherently with
                @ the comment in arch/arm/mach-sa1100/include/mach/uncompress.h.
                @ We assume r1 can be clobbered.
 
                @ see if Ser3 is active
-               add     \rx, \rx, #0x00050000
-               ldr     r1, [\rx, #UTCR3]
-               tst     r1, #UTCR3_TXE
+               add     \rp, \rp, #0x00050000
+               ldr     \rv, [\rp, #UTCR3]
+               tst     \rv, #UTCR3_TXE
 
                @ if Ser3 is inactive, then try Ser1
-               addeq   \rx, \rx, #(0x00010000 - 0x00050000)
-               ldreq   r1, [\rx, #UTCR3]
-               tsteq   r1, #UTCR3_TXE
+               addeq   \rp, \rp, #(0x00010000 - 0x00050000)
+               ldreq   \rv, [\rp, #UTCR3]
+               tsteq   \rv, #UTCR3_TXE
 
                @ if Ser1 is inactive, then try Ser2
-               addeq   \rx, \rx, #(0x00030000 - 0x00010000)
-               ldreq   r1, [\rx, #UTCR3]
-               tsteq   r1, #UTCR3_TXE
+               addeq   \rp, \rp, #(0x00030000 - 0x00010000)
+               ldreq   \rv, [\rp, #UTCR3]
+               tsteq   \rv, #UTCR3_TXE
+
+               @ clear top bits, and generate both phys and virt addresses
+               lsl     \rp, \rp, #8
+               lsr     \rp, \rp, #8
+               orr     \rv, \rp, #0xf8000000   @ virtual
+               orr     \rp, \rp, #0x80000000   @ physical
 
-               @ if all ports are inactive, then there is nothing we can do
-               moveq   pc, lr
                .endm
 
                .macro  senduart,rd,rx
index d3ec620618f1866edf026abecc2739865dd2ad24..491ac9f20fb48c27045ecfc87be3971cdf4a54e1 100644 (file)
@@ -364,8 +364,6 @@ static void __init jornada720_mach_init(void)
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
        /* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = jornada720_map_io,
        .init_irq       = sa1100_init_irq,
index 68069d6dc07a8b26d29787f0632a4895d66021ea..7b9556b59057b9c575d72a24129b60129b4be93a 100644 (file)
@@ -61,8 +61,6 @@ static void __init lart_map_io(void)
 }
 
 MACHINE_START(LART, "LART")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = lart_map_io,
        .init_irq       = sa1100_init_irq,
index 1ccd6018d3a3a1dcec774ae0aad88108f75c9be0..42b80400c1006b8927f8c71046ab090ae536447c 100644 (file)
@@ -146,8 +146,6 @@ static void __init pleb_map_io(void)
 }
 
 MACHINE_START(PLEB, "PLEB")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .map_io         = pleb_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 85e82bb73d7ef7b3244428954949716906ebdd8e..7917b2405579961f3e6968d241d8740b9eb4e189 100644 (file)
@@ -82,8 +82,6 @@ static void __init shannon_map_io(void)
 }
 
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = shannon_map_io,
        .init_irq       = sa1100_init_irq,
index 49cfd64663ac5753cec35a0db395d809baf4fc15..27692d0ffbe81c9d2a5e6931bc323f107973c7c6 100644 (file)
@@ -228,8 +228,6 @@ arch_initcall(simpad_init);
 
 MACHINE_START(SIMPAD, "Simpad")
        /* Maintainer: Holger Freyther */
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
        .boot_params    = 0xc0000100,
        .map_io         = simpad_map_io,
        .init_irq       = sa1100_init_irq,
index 358d875ace1478e67f8e32b03713917946650139..5cf7f94c1f3116837eeed4e15e7e03b7e8d1bb96 100644 (file)
@@ -152,8 +152,6 @@ static struct sys_timer shark_timer = {
 
 MACHINE_START(SHARK, "Shark")
        /* Maintainer: Alexander Schulz */
-       .phys_io        = 0x40000000,
-       .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
        .boot_params    = 0x08003000,
        .map_io         = shark_map_io,
        .init_irq       = shark_init_irq,
index 5ea24d4d1ba6e176985b16076b48412952de9aec..a473f55dc71fef28a2cbdafb5291d7ccf488ef24 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mov     \rx, #0xe0000000
-               orr     \rx, \rx, #0x000003f8
+               .macro  addruart, rp, rv
+               mov     \rp, #0xe0000000
+               orr     \rp, \rp, #0x000003f8
+               mov     \rv, \rp
                .endm
 
                .macro  senduart,rd,rx
index f6c6837c5451888257a86601ae8031a9d0a598d5..8e845b6a7cb57a3f74b9f00c16ba12b2bc0dd6f9 100644 (file)
@@ -1,4 +1,4 @@
 /*
  * arch/arm/mach-shark/include/mach/vmalloc.h
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
index 5e16b4c692222a4a45d5728cec5b4970cae495e0..ae416fe7daf2e61b09f683c9be36ebc57c105c62 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y                          := timer.o console.o clock.o
+obj-y                          := timer.o console.o clock.o pm_runtime.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)      += setup-sh7367.o clock-sh7367.o intc-sh7367.o
index 23d472f9525e6a160c97cbf8adc21c505819fb05..14923989ea0563831f0c176377c0400f603a6416 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -39,6 +40,7 @@
 #include <linux/sh_clk.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
+#include <linux/leds.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
 
@@ -307,6 +309,7 @@ static struct sh_mobile_sdhi_info sdhi1_info = {
        .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
        .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
        .tmio_ocr_mask  = MMC_VDD_165_195,
+       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE,
 };
 
 static struct resource sdhi1_resources[] = {
@@ -558,7 +561,7 @@ static struct resource fsi_resources[] = {
 
 static struct platform_device fsi_device = {
        .name           = "sh_fsi2",
-       .id             = 0,
+       .id             = -1,
        .num_resources  = ARRAY_SIZE(fsi_resources),
        .resource       = fsi_resources,
        .dev    = {
@@ -650,7 +653,44 @@ static struct platform_device hdmi_device = {
        },
 };
 
+static struct gpio_led ap4evb_leds[] = {
+       {
+               .name                   = "led4",
+               .gpio                   = GPIO_PORT185,
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       },
+       {
+               .name                   = "led2",
+               .gpio                   = GPIO_PORT186,
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       },
+       {
+               .name                   = "led3",
+               .gpio                   = GPIO_PORT187,
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       },
+       {
+               .name                   = "led1",
+               .gpio                   = GPIO_PORT188,
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       }
+};
+
+static struct gpio_led_platform_data ap4evb_leds_pdata = {
+       .num_leds = ARRAY_SIZE(ap4evb_leds),
+       .leds = ap4evb_leds,
+};
+
+static struct platform_device leds_device = {
+       .name = "leds-gpio",
+       .id = 0,
+       .dev = {
+               .platform_data  = &ap4evb_leds_pdata,
+       },
+};
+
 static struct platform_device *ap4evb_devices[] __initdata = {
+       &leds_device,
        &nor_flash_device,
        &smc911x_device,
        &sdhi0_device,
@@ -840,20 +880,6 @@ static void __init ap4evb_init(void)
        gpio_request(GPIO_FN_CS5A,      NULL);
        gpio_request(GPIO_FN_IRQ6_39,   NULL);
 
-       /* enable LED 1 - 4 */
-       gpio_request(GPIO_PORT185, NULL);
-       gpio_request(GPIO_PORT186, NULL);
-       gpio_request(GPIO_PORT187, NULL);
-       gpio_request(GPIO_PORT188, NULL);
-       gpio_direction_output(GPIO_PORT185, 1);
-       gpio_direction_output(GPIO_PORT186, 1);
-       gpio_direction_output(GPIO_PORT187, 1);
-       gpio_direction_output(GPIO_PORT188, 1);
-       gpio_export(GPIO_PORT185, 0);
-       gpio_export(GPIO_PORT186, 0);
-       gpio_export(GPIO_PORT187, 0);
-       gpio_export(GPIO_PORT188, 0);
-
        /* enable Debug switch (S6) */
        gpio_request(GPIO_PORT32, NULL);
        gpio_request(GPIO_PORT33, NULL);
@@ -1079,8 +1105,6 @@ static struct sys_timer ap4evb_timer = {
 };
 
 MACHINE_START(AP4EVB, "ap4evb")
-       .phys_io        = 0xe6000000,
-       .io_pg_offst    = ((0xe6000000) >> 18) & 0xfffc,
        .map_io         = ap4evb_map_io,
        .init_irq       = sh7372_init_irq,
        .init_machine   = ap4evb_init,
index a5525901e91f43e849811688d2066c6909f65ca8..3b83d6320bec808d5f4259fc4308c307f7e62f2e 100644 (file)
@@ -365,8 +365,6 @@ static struct sys_timer g3evm_timer = {
 };
 
 MACHINE_START(G3EVM, "g3evm")
-       .phys_io        = 0xe6000000,
-       .io_pg_offst    = ((0xe6000000) >> 18) & 0xfffc,
        .map_io         = g3evm_map_io,
        .init_irq       = sh7367_init_irq,
        .init_machine   = g3evm_init,
index 2c3ff6f7f34cec4909897fd13422c6ef04a65f54..5b3b582ef3f25fefd4430c071e89f42355832fb1 100644 (file)
@@ -392,8 +392,6 @@ static struct sys_timer g4evm_timer = {
 };
 
 MACHINE_START(G4EVM, "g4evm")
-       .phys_io        = 0xe6000000,
-       .io_pg_offst    = ((0xe6000000) >> 18) & 0xfffc,
        .map_io         = g4evm_map_io,
        .init_irq       = sh7377_init_irq,
        .init_machine   = g4evm_init,
index fb4e9b1d788e464922ba2345d60fb43b8e1173d2..759468992ad287ff3f40b2f2e92e19d99734c94a 100644 (file)
@@ -286,7 +286,6 @@ static struct clk_ops pllc2_clk_ops = {
 
 struct clk pllc2_clk = {
        .ops            = &pllc2_clk_ops,
-       .flags          = CLK_ENABLE_ON_INIT,
        .parent         = &extal1_div2_clk,
        .freq_table     = pllc2_freq_table,
        .parent_table   = pllc2_parent,
@@ -395,7 +394,7 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
 
 enum { MSTP001,
        MSTP131, MSTP130,
-       MSTP129, MSTP128,
+       MSTP129, MSTP128, MSTP127, MSTP126,
        MSTP118, MSTP117, MSTP116,
        MSTP106, MSTP101, MSTP100,
        MSTP223,
@@ -413,6 +412,8 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
        [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
        [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
+       [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */
+       [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */
        [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
        [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
        [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
@@ -428,7 +429,7 @@ static struct clk mstp_clks[MSTP_NR] = {
        [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, CLK_ENABLE_ON_INIT), /* FSIA */
+       [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSIA */
        [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
        [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
        [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
@@ -498,6 +499,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
        CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
        CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
+       CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */
+       CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */
        CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
        CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
        CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
index b7c705a213a2a1400e180df83d9e5a6f67649db4..6b7c7c42bc8fc529678fe7e77d01878299d049c4 100644 (file)
@@ -1,8 +1,10 @@
 /*
- * SH-Mobile Timer
+ * SH-Mobile Clock Framework
  *
  * Copyright (C) 2010  Magnus Damm
  *
+ * Used together with arch/arm/common/clkdev.c and drivers/sh/clk.c.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; version 2 of the License.
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
new file mode 100644 (file)
index 0000000..94912d3
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * arch/arm/mach-shmobile/pm_runtime.c
+ *
+ * Runtime PM support code for SuperH Mobile ARM
+ *
+ *  Copyright (C) 2009-2010 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
+#include <linux/bitmap.h>
+
+#ifdef CONFIG_PM_RUNTIME
+#define BIT_ONCE 0
+#define BIT_ACTIVE 1
+#define BIT_CLK_ENABLED 2
+
+struct pm_runtime_data {
+       unsigned long flags;
+       struct clk *clk;
+};
+
+static void __devres_release(struct device *dev, void *res)
+{
+       struct pm_runtime_data *prd = res;
+
+       dev_dbg(dev, "__devres_release()\n");
+
+       if (test_bit(BIT_CLK_ENABLED, &prd->flags))
+               clk_disable(prd->clk);
+
+       if (test_bit(BIT_ACTIVE, &prd->flags))
+               clk_put(prd->clk);
+}
+
+static struct pm_runtime_data *__to_prd(struct device *dev)
+{
+       return devres_find(dev, __devres_release, NULL, NULL);
+}
+
+static void platform_pm_runtime_init(struct device *dev,
+                                    struct pm_runtime_data *prd)
+{
+       if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) {
+               prd->clk = clk_get(dev, NULL);
+               if (!IS_ERR(prd->clk)) {
+                       set_bit(BIT_ACTIVE, &prd->flags);
+                       dev_info(dev, "clocks managed by runtime pm\n");
+               }
+       }
+}
+
+static void platform_pm_runtime_bug(struct device *dev,
+                                   struct pm_runtime_data *prd)
+{
+       if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags))
+               dev_err(dev, "runtime pm suspend before resume\n");
+}
+
+int platform_pm_runtime_suspend(struct device *dev)
+{
+       struct pm_runtime_data *prd = __to_prd(dev);
+
+       dev_dbg(dev, "platform_pm_runtime_suspend()\n");
+
+       platform_pm_runtime_bug(dev, prd);
+
+       if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
+               clk_disable(prd->clk);
+               clear_bit(BIT_CLK_ENABLED, &prd->flags);
+       }
+
+       return 0;
+}
+
+int platform_pm_runtime_resume(struct device *dev)
+{
+       struct pm_runtime_data *prd = __to_prd(dev);
+
+       dev_dbg(dev, "platform_pm_runtime_resume()\n");
+
+       platform_pm_runtime_init(dev, prd);
+
+       if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
+               clk_enable(prd->clk);
+               set_bit(BIT_CLK_ENABLED, &prd->flags);
+       }
+
+       return 0;
+}
+
+int platform_pm_runtime_idle(struct device *dev)
+{
+       /* suspend synchronously to disable clocks immediately */
+       return pm_runtime_suspend(dev);
+}
+
+static int platform_bus_notify(struct notifier_block *nb,
+                              unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct pm_runtime_data *prd;
+
+       dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
+
+       if (action == BUS_NOTIFY_BIND_DRIVER) {
+               prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL);
+               if (prd)
+                       devres_add(dev, prd);
+               else
+                       dev_err(dev, "unable to alloc memory for runtime pm\n");
+       }
+
+       return 0;
+}
+
+#else /* CONFIG_PM_RUNTIME */
+
+static int platform_bus_notify(struct notifier_block *nb,
+                              unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct clk *clk;
+
+       dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
+
+       switch (action) {
+       case BUS_NOTIFY_BIND_DRIVER:
+               clk = clk_get(dev, NULL);
+               if (!IS_ERR(clk)) {
+                       clk_enable(clk);
+                       clk_put(clk);
+                       dev_info(dev, "runtime pm disabled, clock forced on\n");
+               }
+               break;
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               clk = clk_get(dev, NULL);
+               if (!IS_ERR(clk)) {
+                       clk_disable(clk);
+                       clk_put(clk);
+                       dev_info(dev, "runtime pm disabled, clock forced off\n");
+               }
+               break;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct notifier_block platform_bus_notifier = {
+       .notifier_call = platform_bus_notify
+};
+
+static int __init sh_pm_runtime_init(void)
+{
+       bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
+       return 0;
+}
+core_initcall(sh_pm_runtime_init);
index 90d8fe6f10fe996a1d71d631ccfd2d1b0cc92af1..06158848afd9584f60cb04690d33dc232d0c1fa3 100644 (file)
@@ -324,8 +324,6 @@ static void __init stmp378x_devb_init(void)
 }
 
 MACHINE_START(STMP378X, "STMP378X")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,
        .boot_params    = 0x40000100,
        .map_io         = stmp378x_map_io,
        .init_irq       = stmp378x_init_irq,
index 394f21ab59e63485f76b4b6840e20276609d8436..311d8552d3628a7b8af45f58984e93340dfaab9d 100644 (file)
@@ -91,8 +91,6 @@ static void __init stmp37xx_devb_init(void)
 }
 
 MACHINE_START(STMP37XX, "STMP37XX")
-       .phys_io        = 0x80000000,
-       .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,
        .boot_params    = 0x40000100,
        .map_io         = stmp37xx_map_io,
        .init_irq       = stmp37xx_init_irq,
diff --git a/arch/arm/mach-tcc8k/Kconfig b/arch/arm/mach-tcc8k/Kconfig
new file mode 100644 (file)
index 0000000..ad86415
--- /dev/null
@@ -0,0 +1,11 @@
+if ARCH_TCC8K
+
+comment "TCC8000 systems:"
+
+config MACH_TCC8000_SDK
+       bool "Telechips TCC8000-SDK development kit"
+       default y
+       help
+         Support for the Telechips TCC8000-SDK board.
+
+endif
diff --git a/arch/arm/mach-tcc8k/Makefile b/arch/arm/mach-tcc8k/Makefile
new file mode 100644 (file)
index 0000000..9bacf31
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for TCC8K boards and common files.
+#
+
+# Common support
+obj-y += clock.o irq.o time.o io.o devices.o
+
+# Board specific support
+obj-$(CONFIG_MACH_TCC8000_SDK) += board-tcc8000-sdk.o
diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot
new file mode 100644 (file)
index 0000000..f135c9d
--- /dev/null
@@ -0,0 +1,3 @@
+   zreladdr-y          := 0x20008000
+params_phys-y          := 0x20000100
+initrd_phys-y          := 0x20800000
diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
new file mode 100644 (file)
index 0000000..7991415
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/clock.h>
+
+#include "common.h"
+
+#define XI_FREQUENCY   12000000
+#define XTI_FREQUENCY  32768
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND */
+static struct tcc_nand_platform_data tcc8k_sdk_nand_data = {
+       .width = 1,
+       .hw_ecc = 0,
+};
+#endif
+
+static void __init tcc8k_init(void)
+{
+#ifdef CONFIG_MTD_NAND_TCC
+       tcc_nand_device.dev.platform_data = &tcc8k_sdk_nand_data;
+       platform_device_register(&tcc_nand_device);
+#endif
+}
+
+static void __init tcc8k_init_timer(void)
+{
+       tcc_clocks_init(XI_FREQUENCY, XTI_FREQUENCY);
+}
+
+static struct sys_timer tcc8k_timer = {
+       .init   = tcc8k_init_timer,
+};
+
+static void __init tcc8k_map_io(void)
+{
+       tcc8k_map_common_io();
+}
+
+MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
+       .boot_params    = PHYS_OFFSET + 0x00000100,
+       .map_io         = tcc8k_map_io,
+       .init_irq       = tcc8k_init_irq,
+       .init_machine   = tcc8k_init,
+       .timer          = &tcc8k_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
new file mode 100644 (file)
index 0000000..ba32a15
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * Lowlevel clock handling for Telechips TCC8xxx SoCs
+ *
+ * Copyright (C) 2010 by Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/irqs.h>
+#include <mach/tcc8k-regs.h>
+
+#include "common.h"
+
+#define BCLKCTR0       (CKC_BASE + BCLKCTR0_OFFS)
+#define BCLKCTR1       (CKC_BASE + BCLKCTR1_OFFS)
+
+#define ACLKREF                (CKC_BASE + ACLKREF_OFFS)
+#define ACLKUART0      (CKC_BASE + ACLKUART0_OFFS)
+#define ACLKUART1      (CKC_BASE + ACLKUART1_OFFS)
+#define ACLKUART2      (CKC_BASE + ACLKUART2_OFFS)
+#define ACLKUART3      (CKC_BASE + ACLKUART3_OFFS)
+#define ACLKUART4      (CKC_BASE + ACLKUART4_OFFS)
+#define ACLKI2C                (CKC_BASE + ACLKI2C_OFFS)
+#define ACLKADC                (CKC_BASE + ACLKADC_OFFS)
+#define ACLKUSBH       (CKC_BASE + ACLKUSBH_OFFS)
+#define ACLKLCD                (CKC_BASE + ACLKLCD_OFFS)
+#define ACLKSDH0       (CKC_BASE + ACLKSDH0_OFFS)
+#define ACLKSDH1       (CKC_BASE + ACLKSDH1_OFFS)
+#define ACLKSPI0       (CKC_BASE + ACLKSPI0_OFFS)
+#define ACLKSPI1       (CKC_BASE + ACLKSPI1_OFFS)
+#define ACLKSPDIF      (CKC_BASE + ACLKSPDIF_OFFS)
+#define ACLKC3DEC      (CKC_BASE + ACLKC3DEC_OFFS)
+#define ACLKCAN0       (CKC_BASE + ACLKCAN0_OFFS)
+#define ACLKCAN1       (CKC_BASE + ACLKCAN1_OFFS)
+#define ACLKGSB0       (CKC_BASE + ACLKGSB0_OFFS)
+#define ACLKGSB1       (CKC_BASE + ACLKGSB1_OFFS)
+#define ACLKGSB2       (CKC_BASE + ACLKGSB2_OFFS)
+#define ACLKGSB3       (CKC_BASE + ACLKGSB3_OFFS)
+#define ACLKUSBH       (CKC_BASE + ACLKUSBH_OFFS)
+#define ACLKTCT                (CKC_BASE + ACLKTCT_OFFS)
+#define ACLKTCX                (CKC_BASE + ACLKTCX_OFFS)
+#define ACLKTCZ                (CKC_BASE + ACLKTCZ_OFFS)
+
+/* Crystal frequencies */
+static unsigned long xi_rate, xti_rate;
+
+static void __iomem *pll_cfg_addr(int pll)
+{
+       switch (pll) {
+       case 0: return (CKC_BASE + PLL0CFG_OFFS);
+       case 1: return (CKC_BASE + PLL1CFG_OFFS);
+       case 2: return (CKC_BASE + PLL2CFG_OFFS);
+       default:
+               BUG();
+       }
+}
+
+static int pll_enable(int pll, int enable)
+{
+       u32 reg;
+       void __iomem *addr = pll_cfg_addr(pll);
+
+       reg = __raw_readl(addr);
+       if (enable)
+               reg &= ~PLLxCFG_PD;
+       else
+               reg |= PLLxCFG_PD;
+
+       __raw_writel(reg, addr);
+       return 0;
+}
+
+static int xi_enable(int enable)
+{
+       u32 reg;
+
+       reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+       if (enable)
+               reg |= CLKCTRL_XE;
+       else
+               reg &= ~CLKCTRL_XE;
+
+       __raw_writel(reg, CKC_BASE + CLKCTRL_OFFS);
+       return 0;
+}
+
+static int root_clk_enable(enum root_clks src)
+{
+       switch (src) {
+       case CLK_SRC_PLL0: return pll_enable(0, 1);
+       case CLK_SRC_PLL1: return pll_enable(1, 1);
+       case CLK_SRC_PLL2: return pll_enable(2, 1);
+       case CLK_SRC_XI: return xi_enable(1);
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static int root_clk_disable(enum root_clks root_src)
+{
+       switch (root_src) {
+       case CLK_SRC_PLL0: return pll_enable(0, 0);
+       case CLK_SRC_PLL1: return pll_enable(1, 0);
+       case CLK_SRC_PLL2: return pll_enable(2, 0);
+       case CLK_SRC_XI: return xi_enable(0);
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static int enable_clk(struct clk *clk)
+{
+       u32 reg;
+
+       if (clk->root_id != CLK_SRC_NOROOT)
+               return root_clk_enable(clk->root_id);
+
+       if (clk->aclkreg) {
+               reg = __raw_readl(clk->aclkreg);
+               reg |= ACLK_EN;
+               __raw_writel(reg, clk->aclkreg);
+       }
+       if (clk->bclkctr) {
+               reg = __raw_readl(clk->bclkctr);
+               reg |= 1 << clk->bclk_shift;
+               __raw_writel(reg, clk->bclkctr);
+       }
+       return 0;
+}
+
+static void disable_clk(struct clk *clk)
+{
+       u32 reg;
+
+       if (clk->root_id != CLK_SRC_NOROOT) {
+               root_clk_disable(clk->root_id);
+               return;
+       }
+
+       if (clk->bclkctr) {
+               reg = __raw_readl(clk->bclkctr);
+               reg &= ~(1 << clk->bclk_shift);
+               __raw_writel(reg, clk->bclkctr);
+       }
+       if (clk->aclkreg) {
+               reg = __raw_readl(clk->aclkreg);
+               reg &= ~ACLK_EN;
+               __raw_writel(reg, clk->aclkreg);
+       }
+}
+
+static unsigned long get_rate_pll(int pll)
+{
+       u32 reg;
+       unsigned long s, m, p;
+       void __iomem *addr = pll_cfg_addr(pll);
+
+       reg = __raw_readl(addr);
+       s = (reg >> 16) & 0x07;
+       m = (reg >> 8) & 0xff;
+       p = reg & 0x3f;
+
+       return (m * xi_rate) / (p * (1 << s));
+}
+
+static unsigned long get_rate_pll_div(int pll)
+{
+       u32 reg;
+       unsigned long div = 0;
+       void __iomem *addr;
+
+       switch (pll) {
+       case 0:
+               addr = CKC_BASE + CLKDIVC0_OFFS;
+               reg = __raw_readl(addr);
+               if (reg & CLKDIVC0_P0E)
+                       div = (reg >> 24) & 0x3f;
+               break;
+       case 1:
+               addr = CKC_BASE + CLKDIVC0_OFFS;
+               reg = __raw_readl(addr);
+               if (reg & CLKDIVC0_P1E)
+                       div = (reg >> 16) & 0x3f;
+               break;
+       case 2:
+               addr = CKC_BASE + CLKDIVC1_OFFS;
+               reg = __raw_readl(addr);
+               if (reg & CLKDIVC1_P2E)
+                       div = __raw_readl(addr) & 0x3f;
+               break;
+       }
+       return get_rate_pll(pll) / (div + 1);
+}
+
+static unsigned long get_rate_xi_div(void)
+{
+       unsigned long div = 0;
+       u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+       if (reg & CLKDIVC0_XE)
+               div = (reg >> 8) & 0x3f;
+
+       return xi_rate / (div + 1);
+}
+
+static unsigned long get_rate_xti_div(void)
+{
+       unsigned long div = 0;
+       u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+       if (reg & CLKDIVC0_XTE)
+               div = reg & 0x3f;
+
+       return xti_rate / (div + 1);
+}
+
+static unsigned long root_clk_get_rate(enum root_clks src)
+{
+       switch (src) {
+       case CLK_SRC_PLL0: return get_rate_pll(0);
+       case CLK_SRC_PLL1: return get_rate_pll(1);
+       case CLK_SRC_PLL2: return get_rate_pll(2);
+       case CLK_SRC_PLL0DIV: return get_rate_pll_div(0);
+       case CLK_SRC_PLL1DIV: return get_rate_pll_div(1);
+       case CLK_SRC_PLL2DIV: return get_rate_pll_div(2);
+       case CLK_SRC_XI: return xi_rate;
+       case CLK_SRC_XTI: return xti_rate;
+       case CLK_SRC_XIDIV: return get_rate_xi_div();
+       case CLK_SRC_XTIDIV: return get_rate_xti_div();
+       default: return 0;
+       }
+}
+
+static unsigned long aclk_get_rate(struct clk *clk)
+{
+       u32 reg;
+       unsigned long div;
+       unsigned int src;
+
+       reg = __raw_readl(clk->aclkreg);
+       div = reg & 0x0fff;
+       src = (reg >> ACLK_SEL_SHIFT) & CLK_SRC_MASK;
+       return root_clk_get_rate(src) / (div + 1);
+}
+
+static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
+{
+       unsigned long div, src, freq, r1, r2;
+
+       src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+       src &= CLK_SRC_MASK;
+       freq = root_clk_get_rate(src);
+       div = freq / rate + 1;
+       r1 = freq / div;
+       r2 = freq / (div + 1);
+       if (r2 >= rate)
+               return div + 1;
+       if ((rate - r2) < (r1 - rate))
+               return div + 1;
+
+       return div;
+}
+
+static unsigned long aclk_round_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int src;
+
+       src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+       src &= CLK_SRC_MASK;
+
+       return root_clk_get_rate(src) / aclk_best_div(clk, rate);
+}
+
+static int aclk_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg;
+
+       reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
+       reg |= aclk_best_div(clk, rate);
+       return 0;
+}
+
+static unsigned long get_rate_sys(struct clk *clk)
+{
+       unsigned int src;
+
+       src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK;
+               return root_clk_get_rate(src);
+}
+
+static unsigned long get_rate_bus(struct clk *clk)
+{
+       unsigned int div;
+
+       div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff;
+       return get_rate_sys(clk) / (div + 1);
+}
+
+static unsigned long get_rate_cpu(struct clk *clk)
+{
+       unsigned int reg, div, fsys, fbus;
+
+       fbus = get_rate_bus(clk);
+       reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+       if (reg & (1 << 29))
+               return fbus;
+       fsys = get_rate_sys(clk);
+       div = (reg >> 16) & 0x0f;
+       return fbus + ((fsys - fbus) * (div + 1)) / 16;
+}
+
+static unsigned long get_rate_root(struct clk *clk)
+{
+       return root_clk_get_rate(clk->root_id);
+}
+
+static int aclk_set_parent(struct clk *clock, struct clk *parent)
+{
+       u32 reg;
+
+       if (clock->parent == parent)
+               return 0;
+
+       clock->parent = parent;
+
+       if (!parent)
+               return 0;
+
+       if (parent->root_id == CLK_SRC_NOROOT)
+               return 0;
+       reg = __raw_readl(clock->aclkreg);
+       reg &= ~ACLK_SEL_MASK;
+       reg |= (parent->root_id << ACLK_SEL_SHIFT) & ACLK_SEL_MASK;
+       __raw_writel(reg, clock->aclkreg);
+
+       return 0;
+}
+
+#define DEFINE_ROOT_CLOCK(name, ri, p) \
+       static struct clk name = {              \
+               .root_id = ri,                  \
+               .get_rate = get_rate_root,                      \
+               .enable = enable_clk,           \
+               .disable = disable_clk,         \
+               .parent = p,                    \
+       };
+
+#define DEFINE_SPECIAL_CLOCK(name, gr, p)      \
+       static struct clk name = {              \
+               .root_id = CLK_SRC_NOROOT,      \
+               .get_rate = gr,                 \
+               .parent = p,                    \
+       };
+
+#define DEFINE_ACLOCK(name, bc, bs, ar)                \
+       static struct clk name = {              \
+               .root_id = CLK_SRC_NOROOT,      \
+               .bclkctr = bc,                  \
+               .bclk_shift = bs,               \
+               .aclkreg = ar,                  \
+               .get_rate = aclk_get_rate,      \
+               .set_rate = aclk_set_rate,      \
+               .round_rate = aclk_round_rate,  \
+               .enable = enable_clk,           \
+               .disable = disable_clk,         \
+               .set_parent = aclk_set_parent,  \
+       };
+
+#define DEFINE_BCLOCK(name, bc, bs, gr, p)     \
+       static struct clk name = {              \
+               .root_id = CLK_SRC_NOROOT,      \
+               .bclkctr = bc,                  \
+               .bclk_shift = bs,               \
+               .get_rate = gr,                 \
+               .enable = enable_clk,           \
+               .disable = disable_clk,         \
+               .parent = p,                    \
+       };
+
+DEFINE_ROOT_CLOCK(xi, CLK_SRC_XI, NULL)
+DEFINE_ROOT_CLOCK(xti, CLK_SRC_XTI, NULL)
+DEFINE_ROOT_CLOCK(xidiv, CLK_SRC_XIDIV, &xi)
+DEFINE_ROOT_CLOCK(xtidiv, CLK_SRC_XTIDIV, &xti)
+DEFINE_ROOT_CLOCK(pll0, CLK_SRC_PLL0, &xi)
+DEFINE_ROOT_CLOCK(pll1, CLK_SRC_PLL1, &xi)
+DEFINE_ROOT_CLOCK(pll2, CLK_SRC_PLL2, &xi)
+DEFINE_ROOT_CLOCK(pll0div, CLK_SRC_PLL0DIV, &pll0)
+DEFINE_ROOT_CLOCK(pll1div, CLK_SRC_PLL1DIV, &pll1)
+DEFINE_ROOT_CLOCK(pll2div, CLK_SRC_PLL2DIV, &pll2)
+
+/* The following 3 clocks are special and are initialized explicitly later */
+DEFINE_SPECIAL_CLOCK(sys, get_rate_sys, NULL)
+DEFINE_SPECIAL_CLOCK(bus, get_rate_bus, &sys)
+DEFINE_SPECIAL_CLOCK(cpu, get_rate_cpu, &sys)
+
+DEFINE_ACLOCK(tct, NULL, 0, ACLKTCT)
+DEFINE_ACLOCK(tcx, NULL, 0, ACLKTCX)
+DEFINE_ACLOCK(tcz, NULL, 0, ACLKTCZ)
+DEFINE_ACLOCK(ref, NULL, 0, ACLKREF)
+DEFINE_ACLOCK(uart0, BCLKCTR0, 5, ACLKUART0)
+DEFINE_ACLOCK(uart1, BCLKCTR0, 23, ACLKUART1)
+DEFINE_ACLOCK(uart2, BCLKCTR0, 6, ACLKUART2)
+DEFINE_ACLOCK(uart3, BCLKCTR0, 8, ACLKUART3)
+DEFINE_ACLOCK(uart4, BCLKCTR1, 6, ACLKUART4)
+DEFINE_ACLOCK(i2c, BCLKCTR0, 7, ACLKI2C)
+DEFINE_ACLOCK(adc, BCLKCTR0, 10, ACLKADC)
+DEFINE_ACLOCK(usbh0, BCLKCTR0, 11, ACLKUSBH)
+DEFINE_ACLOCK(lcd, BCLKCTR0, 13, ACLKLCD)
+DEFINE_ACLOCK(sd0, BCLKCTR0, 17, ACLKSDH0)
+DEFINE_ACLOCK(sd1, BCLKCTR1, 5, ACLKSDH1)
+DEFINE_ACLOCK(spi0, BCLKCTR0, 24, ACLKSPI0)
+DEFINE_ACLOCK(spi1, BCLKCTR0, 30, ACLKSPI1)
+DEFINE_ACLOCK(spdif, BCLKCTR1, 2, ACLKSPDIF)
+DEFINE_ACLOCK(c3dec, BCLKCTR1, 9, ACLKC3DEC)
+DEFINE_ACLOCK(can0, BCLKCTR1, 10, ACLKCAN0)
+DEFINE_ACLOCK(can1, BCLKCTR1, 11, ACLKCAN1)
+DEFINE_ACLOCK(gsb0, BCLKCTR1, 13, ACLKGSB0)
+DEFINE_ACLOCK(gsb1, BCLKCTR1, 14, ACLKGSB1)
+DEFINE_ACLOCK(gsb2, BCLKCTR1, 15, ACLKGSB2)
+DEFINE_ACLOCK(gsb3, BCLKCTR1, 16, ACLKGSB3)
+DEFINE_ACLOCK(usbh1, BCLKCTR1, 20, ACLKUSBH)
+
+DEFINE_BCLOCK(dai0, BCLKCTR0, 0, NULL, NULL)
+DEFINE_BCLOCK(pic, BCLKCTR0, 1, NULL, NULL)
+DEFINE_BCLOCK(tc, BCLKCTR0, 2, NULL, NULL)
+DEFINE_BCLOCK(gpio, BCLKCTR0, 3, NULL, NULL)
+DEFINE_BCLOCK(usbd, BCLKCTR0, 4, NULL, NULL)
+DEFINE_BCLOCK(ecc, BCLKCTR0, 9, NULL, NULL)
+DEFINE_BCLOCK(gdma0, BCLKCTR0, 12, NULL, NULL)
+DEFINE_BCLOCK(rtc, BCLKCTR0, 15, NULL, NULL)
+DEFINE_BCLOCK(nfc, BCLKCTR0, 16, NULL, NULL)
+DEFINE_BCLOCK(g2d, BCLKCTR0, 18, NULL, NULL)
+DEFINE_BCLOCK(gdma1, BCLKCTR0, 22, NULL, NULL)
+DEFINE_BCLOCK(mscl, BCLKCTR0, 25, NULL, NULL)
+DEFINE_BCLOCK(bdma, BCLKCTR1, 0, NULL, NULL)
+DEFINE_BCLOCK(adma0, BCLKCTR1, 1, NULL, NULL)
+DEFINE_BCLOCK(scfg, BCLKCTR1, 3, NULL, NULL)
+DEFINE_BCLOCK(cid, BCLKCTR1, 4, NULL, NULL)
+DEFINE_BCLOCK(dai1, BCLKCTR1, 7, NULL, NULL)
+DEFINE_BCLOCK(adma1, BCLKCTR1, 8, NULL, NULL)
+DEFINE_BCLOCK(gps, BCLKCTR1, 12, NULL, NULL)
+DEFINE_BCLOCK(gdma2, BCLKCTR1, 17, NULL, NULL)
+DEFINE_BCLOCK(gdma3, BCLKCTR1, 18, NULL, NULL)
+DEFINE_BCLOCK(ddrc, BCLKCTR1, 19, NULL, NULL)
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+               .dev_id = d, \
+               .con_id = n, \
+               .clk = &c, \
+       },
+
+static struct clk_lookup lookups[] = {
+       _REGISTER_CLOCK(NULL, "bus", bus)
+       _REGISTER_CLOCK(NULL, "cpu", cpu)
+       _REGISTER_CLOCK(NULL, "tct", tct)
+       _REGISTER_CLOCK(NULL, "tcx", tcx)
+       _REGISTER_CLOCK(NULL, "tcz", tcz)
+       _REGISTER_CLOCK(NULL, "ref", ref)
+       _REGISTER_CLOCK(NULL, "dai0", dai0)
+       _REGISTER_CLOCK(NULL, "pic", pic)
+       _REGISTER_CLOCK(NULL, "tc", tc)
+       _REGISTER_CLOCK(NULL, "gpio", gpio)
+       _REGISTER_CLOCK(NULL, "usbd", usbd)
+       _REGISTER_CLOCK("tcc-uart.0", NULL, uart0)
+       _REGISTER_CLOCK("tcc-uart.2", NULL, uart2)
+       _REGISTER_CLOCK("tcc-i2c", NULL, i2c)
+       _REGISTER_CLOCK("tcc-uart.3", NULL, uart3)
+       _REGISTER_CLOCK(NULL, "ecc", ecc)
+       _REGISTER_CLOCK(NULL, "adc", adc)
+       _REGISTER_CLOCK("tcc-usbh.0", "usb", usbh0)
+       _REGISTER_CLOCK(NULL, "gdma0", gdma0)
+       _REGISTER_CLOCK(NULL, "lcd", lcd)
+       _REGISTER_CLOCK(NULL, "rtc", rtc)
+       _REGISTER_CLOCK(NULL, "nfc", nfc)
+       _REGISTER_CLOCK("tcc-mmc.0", NULL, sd0)
+       _REGISTER_CLOCK(NULL, "g2d", g2d)
+       _REGISTER_CLOCK(NULL, "gdma1", gdma1)
+       _REGISTER_CLOCK("tcc-uart.1", NULL, uart1)
+       _REGISTER_CLOCK("tcc-spi.0", NULL, spi0)
+       _REGISTER_CLOCK(NULL, "mscl", mscl)
+       _REGISTER_CLOCK("tcc-spi.1", NULL, spi1)
+       _REGISTER_CLOCK(NULL, "bdma", bdma)
+       _REGISTER_CLOCK(NULL, "adma0", adma0)
+       _REGISTER_CLOCK(NULL, "spdif", spdif)
+       _REGISTER_CLOCK(NULL, "scfg", scfg)
+       _REGISTER_CLOCK(NULL, "cid", cid)
+       _REGISTER_CLOCK("tcc-mmc.1", NULL, sd1)
+       _REGISTER_CLOCK("tcc-uart.4", NULL, uart4)
+       _REGISTER_CLOCK(NULL, "dai1", dai1)
+       _REGISTER_CLOCK(NULL, "adma1", adma1)
+       _REGISTER_CLOCK(NULL, "c3dec", c3dec)
+       _REGISTER_CLOCK("tcc-can.0", NULL, can0)
+       _REGISTER_CLOCK("tcc-can.1", NULL, can1)
+       _REGISTER_CLOCK(NULL, "gps", gps)
+       _REGISTER_CLOCK("tcc-gsb.0", NULL, gsb0)
+       _REGISTER_CLOCK("tcc-gsb.1", NULL, gsb1)
+       _REGISTER_CLOCK("tcc-gsb.2", NULL, gsb2)
+       _REGISTER_CLOCK("tcc-gsb.3", NULL, gsb3)
+       _REGISTER_CLOCK(NULL, "gdma2", gdma2)
+       _REGISTER_CLOCK(NULL, "gdma3", gdma3)
+       _REGISTER_CLOCK(NULL, "ddrc", ddrc)
+       _REGISTER_CLOCK("tcc-usbh.1", "usb", usbh1)
+};
+
+static struct clk *root_clk_by_index(enum root_clks src)
+{
+       switch (src) {
+       case CLK_SRC_PLL0: return &pll0;
+       case CLK_SRC_PLL1: return &pll1;
+       case CLK_SRC_PLL2: return &pll2;
+       case CLK_SRC_PLL0DIV: return &pll0div;
+       case CLK_SRC_PLL1DIV: return &pll1div;
+       case CLK_SRC_PLL2DIV: return &pll2div;
+       case CLK_SRC_XI: return &xi;
+       case CLK_SRC_XTI: return &xti;
+       case CLK_SRC_XIDIV: return &xidiv;
+       case CLK_SRC_XTIDIV: return &xtidiv;
+       default: return NULL;
+       }
+}
+
+static void find_aclk_parent(struct clk *clk)
+{
+       unsigned int src;
+       struct clk *clock;
+
+       if (!clk->aclkreg)
+               return;
+
+       src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+       src &= CLK_SRC_MASK;
+
+       clock = root_clk_by_index(src);
+       if (!clock)
+               return;
+
+       clk->parent = clock;
+       clk->set_parent = aclk_set_parent;
+}
+
+void __init tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq)
+{
+       int i;
+
+       xi_rate = xi_freq;
+       xti_rate = xti_freq;
+
+       /* fixup parents and add the clock */
+       for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+               find_aclk_parent(lookups[i].clk);
+               clkdev_add(&lookups[i]);
+       }
+       tcc8k_timer_init(&tcz, (void __iomem *)TIMER_BASE, INT_TC32);
+}
diff --git a/arch/arm/mach-tcc8k/common.h b/arch/arm/mach-tcc8k/common.h
new file mode 100644 (file)
index 0000000..705690a
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef MACH_TCC8K_COMMON_H
+#define MACH_TCC8K_COMMON_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device tcc_nand_device;
+
+struct clk;
+
+extern void tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq);
+extern void tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq);
+extern void tcc8k_init_irq(void);
+extern void tcc8k_map_common_io(void);
+
+#endif
diff --git a/arch/arm/mach-tcc8k/devices.c b/arch/arm/mach-tcc8k/devices.c
new file mode 100644 (file)
index 0000000..6722ad7
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * linux/arch/arm/mach-tcc8k/devices.c
+ *
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of GPL v2.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static u64 tcc8k_dmamask = DMA_BIT_MASK(32);
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND controller */
+static struct resource tcc_nand_resources[] = {
+       {
+               .start  = (resource_size_t)NFC_BASE,
+               .end    = (resource_size_t)NFC_BASE + 0x7f,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = INT_NFC,
+               .end    = INT_NFC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device tcc_nand_device = {
+       .name = "tcc_nand",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(tcc_nand_resources),
+       .resource = tcc_nand_resources,
+};
+#endif
+
+#ifdef CONFIG_MMC_TCC8K
+/* MMC controller */
+static struct resource tcc8k_mmc0_resource[] = {
+       {
+               .start = INT_SD0,
+               .end   = INT_SD0,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource tcc8k_mmc1_resource[] = {
+       {
+               .start = INT_SD1,
+               .end   = INT_SD1,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device tcc8k_mmc0_device = {
+       .name           = "tcc-mmc",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(tcc8k_mmc0_resource),
+       .resource       = tcc8k_mmc0_resource,
+       .dev            = {
+               .dma_mask               = &tcc8k_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+struct platform_device tcc8k_mmc1_device = {
+       .name           = "tcc-mmc",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(tcc8k_mmc1_resource),
+       .resource       = tcc8k_mmc1_resource,
+       .dev            = {
+               .dma_mask               = &tcc8k_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+static inline void tcc8k_init_mmc(void)
+{
+       u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+       reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS;
+       __raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+       platform_device_register(&tcc8k_mmc0_device);
+       platform_device_register(&tcc8k_mmc1_device);
+}
+#else
+static inline void tcc8k_init_mmc(void) { }
+#endif
+
+#ifdef CONFIG_USB_OHCI_HCD
+static int tcc8k_ohci_init(struct device *dev)
+{
+       u32 reg;
+
+       /* Use GPIO PK19 as VBUS control output */
+       reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS);
+       reg &= ~(1 << 19);
+       __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS);
+       reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS);
+       reg &= ~(1 << 19);
+       __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS);
+
+       reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS);
+       reg |= (1 << 19);
+       __raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS);
+       /* Turn on VBUS */
+       reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS);
+       reg |= (1 << 19);
+       __raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS);
+
+       return 0;
+}
+
+static struct resource tcc8k_ohci0_resources[] = {
+       [0] = {
+               .start = (resource_size_t)USBH0_BASE,
+               .end   = (resource_size_t)USBH0_BASE + 0x5c,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = INT_USBH0,
+               .end   = INT_USBH0,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource tcc8k_ohci1_resources[] = {
+       [0] = {
+               .start = (resource_size_t)USBH1_BASE,
+               .end   = (resource_size_t)USBH1_BASE + 0x5c,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = INT_USBH1,
+               .end   = INT_USBH1,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct tccohci_platform_data tcc8k_ohci0_platform_data = {
+       .controller     = 0,
+       .port_mode      = PMM_PERPORT_MODE,
+       .init           = tcc8k_ohci_init,
+};
+
+static struct tccohci_platform_data tcc8k_ohci1_platform_data = {
+       .controller     = 1,
+       .port_mode      = PMM_PERPORT_MODE,
+       .init           = tcc8k_ohci_init,
+};
+
+static struct platform_device ohci0_device = {
+       .name = "tcc-ohci",
+       .id = 0,
+       .dev = {
+               .dma_mask = &tcc8k_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &tcc8k_ohci0_platform_data,
+       },
+       .num_resources  = ARRAY_SIZE(tcc8k_ohci0_resources),
+       .resource       = tcc8k_ohci0_resources,
+};
+
+static struct platform_device ohci1_device = {
+       .name = "tcc-ohci",
+       .id = 1,
+       .dev = {
+               .dma_mask = &tcc8k_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &tcc8k_ohci1_platform_data,
+       },
+       .num_resources  = ARRAY_SIZE(tcc8k_ohci1_resources),
+       .resource       = tcc8k_ohci1_resources,
+};
+
+static void __init tcc8k_init_usbhost(void)
+{
+       platform_device_register(&ohci0_device);
+       platform_device_register(&ohci1_device);
+}
+#else
+static void __init tcc8k_init_usbhost(void) { }
+#endif
+
+/* USB device controller*/
+#ifdef CONFIG_USB_GADGET_TCC8K
+static struct resource udc_resources[] = {
+       [0] = {
+               .start = INT_USBD,
+               .end   = INT_USBD,
+               .flags = IORESOURCE_IRQ,
+       },
+       [1] = {
+               .start = INT_UDMA,
+               .end   = INT_UDMA,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tcc8k_udc_device = {
+       .name = "tcc-udc",
+       .id = 0,
+       .resource = udc_resources,
+       .num_resources = ARRAY_SIZE(udc_resources),
+       .dev = {
+                .dma_mask = &tcc8k_dmamask,
+                .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+};
+
+static void __init tcc8k_init_usb_gadget(void)
+{
+       platform_device_register(&tcc8k_udc_device);
+}
+#else
+static void __init tcc8k_init_usb_gadget(void) { }
+#endif /* CONFIG_USB_GADGET_TCC83X */
+
+static int __init tcc8k_init_devices(void)
+{
+       tcc8k_init_mmc();
+       tcc8k_init_usbhost();
+       tcc8k_init_usb_gadget();
+       return 0;
+}
+
+arch_initcall(tcc8k_init_devices);
diff --git a/arch/arm/mach-tcc8k/io.c b/arch/arm/mach-tcc8k/io.c
new file mode 100644 (file)
index 0000000..9b39d7f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/arm/mach-tcc8k/io.c
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * derived from TCC83xx io.c
+ * Copyright (C) Telechips, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc tcc8k_io_desc[] __initdata = {
+       {
+               .virtual        = (unsigned long)CS1_BASE_VIRT,
+               .pfn            = __phys_to_pfn(CS1_BASE),
+               .length         = CS1_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)AHB_PERI_BASE_VIRT,
+               .pfn            = __phys_to_pfn(AHB_PERI_BASE),
+               .length         = AHB_PERI_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)APB0_PERI_BASE_VIRT,
+               .pfn            = __phys_to_pfn(APB0_PERI_BASE),
+               .length         = APB0_PERI_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)APB1_PERI_BASE_VIRT,
+               .pfn            = __phys_to_pfn(APB1_PERI_BASE),
+               .length         = APB1_PERI_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)EXT_MEM_CTRL_BASE_VIRT,
+               .pfn            = __phys_to_pfn(EXT_MEM_CTRL_BASE),
+               .length         = EXT_MEM_CTRL_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+/*
+ * Maps common IO regions for tcc8k.
+ *
+ */
+void __init tcc8k_map_common_io(void)
+{
+       iotable_init(tcc8k_io_desc, ARRAY_SIZE(tcc8k_io_desc));
+}
diff --git a/arch/arm/mach-tcc8k/irq.c b/arch/arm/mach-tcc8k/irq.c
new file mode 100644 (file)
index 0000000..34575c4
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009-2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU GPL version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+/* Disable IRQ */
+static void tcc8000_mask_ack_irq0(unsigned int irq)
+{
+       PIC0_IEN &= ~(1 << irq);
+       PIC0_CREQ |=  (1 << irq);
+}
+
+static void tcc8000_mask_ack_irq1(unsigned int irq)
+{
+       PIC1_IEN &= ~(1 << (irq - 32));
+       PIC1_CREQ |= (1 << (irq - 32));
+}
+
+static void tcc8000_mask_irq0(unsigned int irq)
+{
+       PIC0_IEN &= ~(1 << irq);
+}
+
+static void tcc8000_mask_irq1(unsigned int irq)
+{
+       PIC1_IEN &= ~(1 << (irq - 32));
+}
+
+static void tcc8000_ack_irq0(unsigned int irq)
+{
+       PIC0_CREQ |=  (1 << irq);
+}
+
+static void tcc8000_ack_irq1(unsigned int irq)
+{
+       PIC1_CREQ |= (1 << (irq - 32));
+}
+
+/* Enable IRQ */
+static void tcc8000_unmask_irq0(unsigned int irq)
+{
+       PIC0_IEN |= (1 << irq);
+       PIC0_INTOEN |= (1 << irq);
+}
+
+static void tcc8000_unmask_irq1(unsigned int irq)
+{
+       PIC1_IEN |= (1 << (irq - 32));
+       PIC1_INTOEN |= (1 << (irq - 32));
+}
+
+static struct irq_chip tcc8000_irq_chip0 = {
+       .name           = "tcc_irq0",
+       .mask           = tcc8000_mask_irq0,
+       .ack            = tcc8000_ack_irq0,
+       .mask_ack       = tcc8000_mask_ack_irq0,
+       .unmask         = tcc8000_unmask_irq0,
+};
+
+static struct irq_chip tcc8000_irq_chip1 = {
+       .name           = "tcc_irq1",
+       .mask           = tcc8000_mask_irq1,
+       .ack            = tcc8000_ack_irq1,
+       .mask_ack       = tcc8000_mask_ack_irq1,
+       .unmask         = tcc8000_unmask_irq1,
+};
+
+void __init tcc8k_init_irq(void)
+{
+       int irqno;
+
+       /* Mask and clear all interrupts */
+       PIC0_IEN = 0x00000000;
+       PIC0_CREQ = 0xffffffff;
+       PIC1_IEN = 0x00000000;
+       PIC1_CREQ = 0xffffffff;
+
+       PIC0_MEN0 = 0x00000003;
+       PIC1_MEN1 = 0x00000003;
+       PIC1_MEN = 0x00000003;
+
+       /* let all IRQs be level triggered */
+       PIC0_TMODE = 0xffffffff;
+       PIC1_TMODE = 0xffffffff;
+       /* all IRQs are IRQs (not FIQs) */
+       PIC0_IRQSEL = 0xffffffff;
+       PIC1_IRQSEL = 0xffffffff;
+
+       for (irqno = 0; irqno < NR_IRQS; irqno++) {
+               if (irqno < 32)
+                       set_irq_chip(irqno, &tcc8000_irq_chip0);
+               else
+                       set_irq_chip(irqno, &tcc8000_irq_chip1);
+               set_irq_handler(irqno, handle_level_irq);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+}
diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c
new file mode 100644 (file)
index 0000000..78d0600
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * TCC8000 system timer setup
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL version 2.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static void __iomem *timer_base;
+
+static cycle_t tcc_get_cycles(struct clocksource *cs)
+{
+       return __raw_readl(timer_base + TC32MCNT_OFFS);
+}
+
+static struct clocksource clocksource_tcc = {
+       .name           = "tcc_tc32",
+       .rating         = 200,
+       .read           = tcc_get_cycles,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 28,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int tcc_set_next_event(unsigned long evt,
+                             struct clock_event_device *unused)
+{
+       unsigned long reg = __raw_readl(timer_base + TC32MCNT_OFFS);
+
+       __raw_writel(reg + evt, timer_base + TC32CMP0_OFFS);
+       return 0;
+}
+
+static void tcc_set_mode(enum clock_event_mode mode,
+                               struct clock_event_device *evt)
+{
+       unsigned long tc32irq;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_ONESHOT:
+               tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+               tc32irq |= TC32IRQ_IRQEN0;
+               __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+               tc32irq &= ~TC32IRQ_IRQEN0;
+               __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+               break;
+       case CLOCK_EVT_MODE_PERIODIC:
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static irqreturn_t tcc8k_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = dev_id;
+
+       /* Acknowledge TC32 interrupt by reading TC32IRQ */
+       __raw_readl(timer_base + TC32IRQ_OFFS);
+
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static struct clock_event_device clockevent_tcc = {
+       .name           = "tcc_timer1",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_mode       = tcc_set_mode,
+       .set_next_event = tcc_set_next_event,
+       .rating         = 200,
+};
+
+static struct irqaction tcc8k_timer_irq = {
+       .name           = "TC32_timer",
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .handler        = tcc8k_timer_interrupt,
+       .dev_id         = &clockevent_tcc,
+};
+
+static int __init tcc_clockevent_init(struct clk *clock)
+{
+       unsigned int c = clk_get_rate(clock);
+
+       clocksource_tcc.mult = clocksource_hz2mult(c,
+                                       clocksource_tcc.shift);
+       clocksource_register(&clocksource_tcc);
+
+       clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
+                                       clockevent_tcc.shift);
+       clockevent_tcc.max_delta_ns =
+                       clockevent_delta2ns(0xfffffffe, &clockevent_tcc);
+       clockevent_tcc.min_delta_ns =
+                       clockevent_delta2ns(0xff, &clockevent_tcc);
+
+       clockevent_tcc.cpumask = cpumask_of(0);
+
+       clockevents_register_device(&clockevent_tcc);
+
+       return 0;
+}
+
+void __init tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq)
+{
+       u32 reg;
+
+       timer_base = base;
+       tcc8k_timer_irq.irq = irq;
+
+       /* Enable clocks */
+       clk_enable(clock);
+
+       /* Initialize 32-bit timer */
+       reg = __raw_readl(timer_base + TC32EN_OFFS);
+       reg &= ~TC32EN_ENABLE; /* Disable timer */
+       __raw_writel(reg, timer_base + TC32EN_OFFS);
+       /* Free running timer, counting from 0 to 0xffffffff */
+       __raw_writel(0, timer_base + TC32EN_OFFS);
+       __raw_writel(0, timer_base + TC32LDV_OFFS);
+       reg = __raw_readl(timer_base + TC32IRQ_OFFS);
+       reg |= TC32IRQ_IRQEN0; /* irq at match with CMP0 */
+       __raw_writel(reg, timer_base + TC32IRQ_OFFS);
+
+       __raw_writel(TC32EN_ENABLE, timer_base + TC32EN_OFFS);
+
+       tcc_clockevent_init(clock);
+       setup_irq(irq, &tcc8k_timer_irq);
+}
index 05e78dd9b50ca22ef7b20e91f8a21e6e92c8021d..b9dbdb1289d045339df802c8c5e1c94390650b47 100644 (file)
@@ -91,10 +91,8 @@ static void __init tegra_harmony_fixup(struct machine_desc *desc,
 {
        mi->nr_banks = 2;
        mi->bank[0].start = PHYS_OFFSET;
-       mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET);
        mi->bank[0].size = 448 * SZ_1M;
        mi->bank[1].start = SZ_512M;
-       mi->bank[1].node = PHYS_TO_NID(SZ_512M);
        mi->bank[1].size = SZ_512M;
 }
 
@@ -117,8 +115,6 @@ static void __init tegra_harmony_init(void)
 
 MACHINE_START(HARMONY, "harmony")
        .boot_params  = 0x00000100,
-       .phys_io        = IO_APB_PHYS,
-       .io_pg_offst    = ((IO_APB_VIRT) >> 18) & 0xfffc,
        .fixup          = tegra_harmony_fixup,
        .init_irq       = tegra_init_irq,
        .init_machine   = tegra_harmony_init,
index 55a39564b43c476e2002b806a8bdff6f6e7c6f44..8ea3bffb4e009f39b56b2262a762b8b28131c814 100644 (file)
 
 #include <mach/io.h>
 
-       .macro  addruart,rx, tmp
-        mrc     p15, 0, \rx, c1, c0
-        tst     \rx, #1                 @ MMU enabled?
-        ldreq   \rx, =IO_APB_PHYS       @ physical
-        ldrne   \rx, =IO_APB_VIRT        @ virtual
+       .macro  addruart, rp, rv
+        ldreq   \rp, =IO_APB_PHYS       @ physical
+        ldrne   \rv, =IO_APB_VIRT        @ virtual
 #if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
 #error "A debug UART must be selected in the kernel config to use DEBUG_LL"
 #elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-        orr     \rx, \rx, #0x6000
+        orr     \rp, \rp, #0x6000
+        orr     \rv, \rv, #0x6000
 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-       ldr     \tmp, =0x6040
-        orr     \rx, \rx, \tmp
+        orr     \rp, \rp, #0x6000
+       orr     \rp, \rp, #0x40
+        orr     \rv, \rv, #0x6000
+       orr     \rv, \rv, #0x40
 #elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-        orr     \rx, \rx, #0x6200
+        orr     \rp, \rp, #0x6200
+        orr     \rv, \rv, #0x6200
 #elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-        orr     \rx, \rx, #0x6300
+        orr     \rp, \rp, #0x6300
+        orr     \rv, \rv, #0x6300
 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-        orr     \rx, \rx, #0x6400
+        orr     \rp, \rp, #0x6400
+        orr     \rv, \rv, #0x6400
 #endif
        .endm
 
index 8b42dab79a70ca17499b55c0ba9042e278428de5..e4a34a35a54466a1aecc7b3ea0ffe67c9dcee3df 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()                        \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x0F;                         \
-       })
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
index 267a141730d9c94fa59a7c0acbd5bbc6426e79d2..fd6aa65b2dc6ab433cc7a3f2ca45cf9128294f38 100644 (file)
@@ -23,6 +23,6 @@
 
 #include <asm/sizes.h>
 
-#define VMALLOC_END        0xFE000000
+#define VMALLOC_END        0xFE000000UL
 
 #endif
index 5f55012b7c9edb99d32c5bcb89358686908773d7..03f79361259400596a790949073e1ce617e99bff 100644 (file)
@@ -46,7 +46,6 @@ static ssize_t dummy_looptest(struct device *dev,
         * struct, this is just used here to alter the behaviour of the chip
         * in order to perform tests.
         */
-       struct pl022_config_chip *chip_info = spi->controller_data;
        int status;
        u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD,
                        0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05,
@@ -72,7 +71,7 @@ static ssize_t dummy_looptest(struct device *dev,
         * Force chip to 8 bit mode
         * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
         */
-       chip_info->data_size = SSP_DATA_BITS_8;
+       spi->bits_per_word = 8;
        /* You should NOT DO THIS EITHER */
        spi->master->setup(spi);
 
@@ -159,7 +158,7 @@ static ssize_t dummy_looptest(struct device *dev,
         * Force chip to 16 bit mode
         * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
         */
-       chip_info->data_size = SSP_DATA_BITS_16;
+       spi->bits_per_word = 16;
        /* You should NOT DO THIS EITHER */
        spi->master->setup(spi);
 
index 92c12420256ffdc518d8a4102198e42365039032..df715707bead4144f2650974a0c8998145757877 100644 (file)
  */
 #include <mach/hardware.h>
 
-       .macro  addruart, rx, tmp
+       .macro  addruart, rp, rv
        /* If we move the address using MMU, use this. */
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                 @ MMU enabled?
-       ldreq   \rx,      = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
-       ldrne   \rx,      = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
-       orr     \rx, \rx, #0x00003000
+       ldr     \rp,      = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
+       ldr     \rv,      = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
+       orr     \rp, \rp, #0x00003000
+       orr     \rv, \rv, #0x00003000
        .endm
 
 #include <asm/hardware/debug-pl01x.S>
index 7b1fc984abb64c85dd3124eba6b6b108000835b9..d5a71abcbaeaf5a8da0255e50e89f5982fd447d4 100644 (file)
@@ -273,6 +273,9 @@ extern void gpio_pullup(unsigned gpio, int value);
 extern int gpio_get_value(unsigned gpio);
 extern void gpio_set_value(unsigned gpio, int value);
 
+#define gpio_get_value_cansleep gpio_get_value
+#define gpio_set_value_cansleep gpio_set_value
+
 /* wrappers to sleep-enable the previous two functions */
 static inline unsigned gpio_to_irq(unsigned gpio)
 {
index f0e887bea30e6b18218c2bac2e6c4f1d8a1b50bb..edb2c0d255c2a1671cae12e6704da28e6b66cb8d 100644 (file)
@@ -30,8 +30,6 @@ static void select_dummy_chip(u32 chipselect)
 }
 
 struct pl022_config_chip dummy_chip_info = {
-       /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
-       .lbm = LOOPBACK_ENABLED,
        /*
         * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
         * DMA_TRANSFER does not work
@@ -42,14 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
        .hierarchy = SSP_MASTER,
        /* 0 = drive TX even as slave, 1 = do not drive TX as slave */
        .slave_tx_disable = 0,
-       /* LSB first */
-       .endian_tx = SSP_TX_LSB,
-       .endian_rx = SSP_RX_LSB,
-       .data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
        .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
        .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-       .clk_phase = SSP_CLK_SECOND_EDGE,
-       .clk_pol = SSP_CLK_POL_IDLE_LOW,
        .ctrl_len = SSP_BITS_12,
        .wait_state = SSP_MWIRE_WAIT_ZERO,
        .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -75,7 +67,7 @@ static struct spi_board_info u300_spi_devices[] = {
                .bus_num        = 0, /* Only one bus on this chip */
                .chip_select    = 0,
                /* Means SPI_CS_HIGH, change if e.g low CS */
-               .mode           = 0,
+               .mode           = SPI_MODE_1 | SPI_LSB_FIRST | SPI_LOOP,
        },
 #endif
 };
index bfcda9820888b6083fd10779b63fe89580f76036..07c35a846424f5736b33f365efb70b7248f61a1e 100644 (file)
@@ -61,8 +61,6 @@ static void __init u300_init_machine(void)
 
 MACHINE_START(U300, MACH_U300_STRING)
        /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-       .phys_io        = U300_AHB_PER_PHYS_BASE,
-       .io_pg_offst    = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = BOOT_PARAMS_OFFSET,
        .map_io         = u300_map_io,
        .reserve        = u300_reserve,
index 6625e5bbf4d6384cdbbde138dc3a22b30a66b549..2dd44a0b461562fb5062902f72c1e6c8d4da2612 100644 (file)
@@ -21,9 +21,7 @@ config MACH_U8500_MOP
        bool "U8500 Development platform"
        select UX500_SOC_DB8500
        help
-         Include support for mop500 development platform
-         based on U8500 architecture. The platform is based
-         on early drop silicon version of 8500.
+         Include support for the mop500 development platform.
 
 config MACH_U5500
        bool "U5500 Development platform"
@@ -39,4 +37,18 @@ config UX500_DEBUG_UART
          Choose the UART on which kernel low-level debug messages should be
          output.
 
+config U5500_MODEM_IRQ
+       bool "Modem IRQ support"
+       depends on MACH_U5500
+       default y
+       help
+         Add support for handling IRQ:s from modem side
+
+config U5500_MBOX
+       bool "Mailbox support"
+       depends on MACH_U5500 && U5500_MODEM_IRQ
+       default y
+       help
+         Add support for U5500 mailbox communication with modem side
+
 endif
index 4556aea9c3c5acfcd1aa9ed860dffcd9e06cabaf..9e27a84433cbd27829e3099b120c39099bee56cf 100644 (file)
@@ -4,8 +4,12 @@
 
 obj-y                          := clock.o cpu.o devices.o
 obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o
-obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
-obj-$(CONFIG_MACH_U8500_MOP)   += board-mop500.o
+obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
+obj-$(CONFIG_MACH_U8500_MOP)   += board-mop500.o board-mop500-sdi.o
 obj-$(CONFIG_MACH_U5500)       += board-u5500.o
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)     += localtimer.o
+obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o
+obj-$(CONFIG_U5500_MODEM_IRQ)  += modem_irq.o
+obj-$(CONFIG_U5500_MBOX)       += mbox.o
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
new file mode 100644 (file)
index 0000000..1187f1f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * MOP500 board specific initialization for regulators
+ */
+#include <linux/kernel.h>
+#include <linux/regulator/machine.h>
+
+/* supplies to the display/camera */
+static struct regulator_init_data ab8500_vaux1_regulator = {
+       .constraints = {
+               .name = "V-DISPLAY",
+               .min_uV = 2500000,
+               .max_uV = 2900000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+                                       REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supplies to the on-board eMMC */
+static struct regulator_init_data ab8500_vaux2_regulator = {
+       .constraints = {
+               .name = "V-eMMC1",
+               .min_uV = 1100000,
+               .max_uV = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+                                       REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for VAUX3, supplies to SDcard slots */
+static struct regulator_init_data ab8500_vaux3_regulator = {
+       .constraints = {
+               .name = "V-MMC-SD",
+               .min_uV = 1100000,
+               .max_uV = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+                                       REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for tvout, gpadc, TVOUT LDO */
+static struct regulator_init_data ab8500_vtvout_init = {
+       .constraints = {
+               .name = "V-TVOUT",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for ab8500-vaudio, VAUDIO LDO */
+static struct regulator_init_data ab8500_vaudio_init = {
+       .constraints = {
+               .name = "V-AUD",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for v-anamic1 VAMic1-LDO */
+static struct regulator_init_data ab8500_vamic1_init = {
+       .constraints = {
+               .name = "V-AMIC1",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+static struct regulator_init_data ab8500_vamic2_init = {
+       .constraints = {
+               .name = "V-AMIC2",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for v-dmic, VDMIC LDO */
+static struct regulator_init_data ab8500_vdmic_init = {
+       .constraints = {
+               .name = "V-DMIC",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for v-intcore12, VINTCORE12 LDO */
+static struct regulator_init_data ab8500_vintcore_init = {
+       .constraints = {
+               .name = "V-INTCORE",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
+/* supply for U8500 CSI/DSI, VANA LDO */
+static struct regulator_init_data ab8500_vana_init = {
+       .constraints = {
+               .name = "V-CSI/DSI",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
+
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
new file mode 100644 (file)
index 0000000..bac9956
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+
+#include <plat/pincfg.h>
+#include <mach/devices.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+#include "board-mop500.h"
+
+static pin_cfg_t mop500_sdi_pins[] = {
+       /* SDI4 (on-board eMMC) */
+       GPIO197_MC4_DAT3,
+       GPIO198_MC4_DAT2,
+       GPIO199_MC4_DAT1,
+       GPIO200_MC4_DAT0,
+       GPIO201_MC4_CMD,
+       GPIO202_MC4_FBCLK,
+       GPIO203_MC4_CLK,
+       GPIO204_MC4_DAT7,
+       GPIO205_MC4_DAT6,
+       GPIO206_MC4_DAT5,
+       GPIO207_MC4_DAT4,
+};
+
+static pin_cfg_t mop500_sdi2_pins[] = {
+       /* SDI2 (POP eMMC) */
+       GPIO128_MC2_CLK,
+       GPIO129_MC2_CMD,
+       GPIO130_MC2_FBCLK,
+       GPIO131_MC2_DAT0,
+       GPIO132_MC2_DAT1,
+       GPIO133_MC2_DAT2,
+       GPIO134_MC2_DAT3,
+       GPIO135_MC2_DAT4,
+       GPIO136_MC2_DAT5,
+       GPIO137_MC2_DAT6,
+       GPIO138_MC2_DAT7,
+};
+
+/*
+ * SDI 2 (POP eMMC, not on DB8500ed)
+ */
+
+static struct mmci_platform_data mop500_sdi2_data = {
+       .ocr_mask       = MMC_VDD_165_195,
+       .f_max          = 100000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+       .gpio_cd        = -1,
+       .gpio_wp        = -1,
+};
+
+/*
+ * SDI 4 (on-board eMMC)
+ */
+
+static struct mmci_platform_data mop500_sdi4_data = {
+       .ocr_mask       = MMC_VDD_29_30,
+       .f_max          = 100000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
+                         MMC_CAP_MMC_HIGHSPEED,
+       .gpio_cd        = -1,
+       .gpio_wp        = -1,
+};
+
+void mop500_sdi_init(void)
+{
+       nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
+
+       u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
+       u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+
+       if (!cpu_is_u8500ed()) {
+               nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
+               amba_device_register(&u8500_sdi2_device, &iomem_resource);
+       }
+
+       /* On-board eMMC */
+       amba_device_register(&u8500_sdi4_device, &iomem_resource);
+}
index 0e8fd135a57dee1d56afb200208d62bf7d756fa8..fcb587f825ccf6c7b195277365e29e5aa58d2710 100644 (file)
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/irqs.h>
 
 #include "pins-db8500.h"
+#include "board-mop500.h"
 
 static pin_cfg_t mop500_pins[] = {
        /* SSP0 */
@@ -55,19 +57,13 @@ static void ab4500_spi_cs_control(u32 command)
 }
 
 struct pl022_config_chip ab4500_chip_info = {
-       .lbm = LOOPBACK_DISABLED,
        .com_mode = INTERRUPT_TRANSFER,
        .iface = SSP_INTERFACE_MOTOROLA_SPI,
        /* we can act as master only */
        .hierarchy = SSP_MASTER,
        .slave_tx_disable = 0,
-       .endian_rx = SSP_RX_MSB,
-       .endian_tx = SSP_TX_MSB,
-       .data_size = SSP_DATA_BITS_24,
        .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
        .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-       .clk_phase = SSP_CLK_SECOND_EDGE,
-       .clk_pol = SSP_CLK_POL_IDLE_HIGH,
        .cs_control = ab4500_spi_cs_control,
 };
 
@@ -75,15 +71,33 @@ static struct ab8500_platform_data ab8500_platdata = {
        .irq_base       = MOP500_AB8500_IRQ_BASE,
 };
 
-static struct spi_board_info u8500_spi_devices[] = {
+static struct resource ab8500_resources[] = {
+       [0] = {
+               .start = IRQ_AB8500,
+               .end = IRQ_AB8500,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+struct platform_device ab8500_device = {
+       .name = "ab8500-i2c",
+       .id = 0,
+       .dev = {
+               .platform_data = &ab8500_platdata,
+       },
+       .num_resources = 1,
+       .resource = ab8500_resources,
+};
+
+static struct spi_board_info ab8500_spi_devices[] = {
        {
-               .modalias = "ab8500",
+               .modalias = "ab8500-spi",
                .controller_data = &ab4500_chip_info,
                .platform_data = &ab8500_platdata,
                .max_speed_hz = 12000000,
                .bus_num = 0,
                .chip_select = 0,
-               .mode = SPI_MODE_0,
+               .mode = SPI_MODE_3,
                .irq = IRQ_DB8500_AB8500,
        },
 };
@@ -163,14 +177,18 @@ static void __init u8500_init_machine(void)
 
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
-       spi_register_board_info(u8500_spi_devices,
-                       ARRAY_SIZE(u8500_spi_devices));
+       mop500_sdi_init();
+
+       /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */
+       if (cpu_is_u8500ed() || cpu_is_u8500v10())
+               spi_register_board_info(ab8500_spi_devices,
+                       ARRAY_SIZE(ab8500_spi_devices));
+       else /* If HW is v.1.1 or later use I2C to access AB8500 */
+               platform_device_register(&ab8500_device);
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
        /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-       .phys_io        = U8500_UART2_BASE,
-       .io_pg_offst    = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x100,
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
new file mode 100644 (file)
index 0000000..2d24032
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __BOARD_MOP500_H
+#define __BOARD_MOP500_H
+
+extern void mop500_sdi_init(void);
+
+#endif
index 4430e69cf538b5b8a1b7d95950b715789c8ac1ba..1ca094a45e71df68ebd123ecd03092f8eedb89f1 100644 (file)
@@ -31,8 +31,6 @@ static void __init u5500_init_machine(void)
 }
 
 MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
-       .phys_io        = UX500_UART0_BASE,
-       .io_pg_offst    = (IO_ADDRESS(UX500_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = u5500_map_io,
        .init_irq       = ux500_init_irq,
index e9278f6d67aa7529f2408fd15fd5eab1bfecdb20..2f87075e9d6f02a21a08c28f7c4ae3a04e69257e 100644 (file)
@@ -14,6 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
+#include <mach/irqs.h>
 
 static struct map_desc u5500_io_desc[] __initdata = {
        __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
@@ -24,6 +25,90 @@ static struct map_desc u5500_io_desc[] __initdata = {
        __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
 };
 
+static struct resource mbox0_resources[] = {
+       {
+               .name = "mbox_peer",
+               .start = U5500_MBOX0_PEER_START,
+               .end = U5500_MBOX0_PEER_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_local",
+               .start = U5500_MBOX0_LOCAL_START,
+               .end = U5500_MBOX0_LOCAL_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_irq",
+               .start = MBOX_PAIR0_VIRT_IRQ,
+               .end = MBOX_PAIR0_VIRT_IRQ,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource mbox1_resources[] = {
+       {
+               .name = "mbox_peer",
+               .start = U5500_MBOX1_PEER_START,
+               .end = U5500_MBOX1_PEER_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_local",
+               .start = U5500_MBOX1_LOCAL_START,
+               .end = U5500_MBOX1_LOCAL_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_irq",
+               .start = MBOX_PAIR1_VIRT_IRQ,
+               .end = MBOX_PAIR1_VIRT_IRQ,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource mbox2_resources[] = {
+       {
+               .name = "mbox_peer",
+               .start = U5500_MBOX2_PEER_START,
+               .end = U5500_MBOX2_PEER_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_local",
+               .start = U5500_MBOX2_LOCAL_START,
+               .end = U5500_MBOX2_LOCAL_END,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name = "mbox_irq",
+               .start = MBOX_PAIR2_VIRT_IRQ,
+               .end = MBOX_PAIR2_VIRT_IRQ,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device mbox0_device = {
+       .id = 0,
+       .name = "mbox",
+       .resource = mbox0_resources,
+       .num_resources = ARRAY_SIZE(mbox0_resources),
+};
+
+static struct platform_device mbox1_device = {
+       .id = 1,
+       .name = "mbox",
+       .resource = mbox1_resources,
+       .num_resources = ARRAY_SIZE(mbox1_resources),
+};
+
+static struct platform_device mbox2_device = {
+       .id = 2,
+       .name = "mbox",
+       .resource = mbox2_resources,
+       .num_resources = ARRAY_SIZE(mbox2_resources),
+};
+
 static struct platform_device *u5500_platform_devs[] __initdata = {
        &u5500_gpio_devs[0],
        &u5500_gpio_devs[1],
@@ -33,6 +118,9 @@ static struct platform_device *u5500_platform_devs[] __initdata = {
        &u5500_gpio_devs[5],
        &u5500_gpio_devs[6],
        &u5500_gpio_devs[7],
+       &mbox0_device,
+       &mbox1_device,
+       &mbox2_device,
 };
 
 void __init u5500_map_io(void)
index f21c444edd99f76db8b78ccd1b1bcfc1464c181b..4acab7544b3c1e95ea9a9f2c73cf0f1ffd34847d 100644 (file)
@@ -38,10 +38,12 @@ static struct platform_device *platform_devs[] __initdata = {
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
+       __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+       __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
 };
 
 static struct map_desc u8500ed_io_desc[] __initdata = {
@@ -53,6 +55,69 @@ static struct map_desc u8500v1_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
 };
 
+/*
+ * Functions to differentiate between later ASICs
+ * We look into the end of the ROM to locate the hardcoded ASIC ID.
+ * This is only needed to differentiate between minor revisions and
+ * process variants of an ASIC, the major revisions are encoded in
+ * the cpuid.
+ */
+#define U8500_ASIC_ID_LOC_ED_V1        (U8500_BOOT_ROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2   (U8500_BOOT_ROM_BASE + 0x1DBF4)
+#define U8500_ASIC_REV_ED      0x01
+#define U8500_ASIC_REV_V10     0xA0
+#define U8500_ASIC_REV_V11     0xA1
+#define U8500_ASIC_REV_V20     0xB0
+
+/**
+ * struct db8500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm
+ *  0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ * This field definion is not formally defined but makes
+ * sense.
+ */
+struct db8500_asic_id {
+       u8 process;
+       u16 partnumber;
+       u8 revision;
+};
+
+/* This isn't going to change at runtime */
+static struct db8500_asic_id db8500_id;
+
+static void __init get_db8500_asic_id(void)
+{
+       u32 asicid;
+
+       if (cpu_is_u8500v1() || cpu_is_u8500ed())
+               asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
+       else if (cpu_is_u8500v2())
+               asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
+       else
+               BUG();
+
+       db8500_id.process = (asicid >> 24);
+       db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
+       db8500_id.revision = asicid & 0xFFU;
+}
+
+bool cpu_is_u8500v10(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V10);
+}
+
+bool cpu_is_u8500v11(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V11);
+}
+
+bool cpu_is_u8500v20(void)
+{
+       return (db8500_id.revision == U8500_ASIC_REV_V20);
+}
+
 void __init u8500_map_io(void)
 {
        ux500_map_io();
@@ -63,6 +128,9 @@ void __init u8500_map_io(void)
                iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
        else
                iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+
+       /* Read out the ASIC ID as early as we can */
+       get_db8500_asic_id();
 }
 
 /*
@@ -70,6 +138,20 @@ void __init u8500_map_io(void)
  */
 void __init u8500_init_devices(void)
 {
+       /* Display some ASIC boilerplate */
+       pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
+               db8500_id.process, db8500_id.revision);
+       if (cpu_is_u8500ed())
+               pr_info("DB8500: Early Drop (ED)\n");
+       else if (cpu_is_u8500v10())
+               pr_info("DB8500: version 1.0\n");
+       else if (cpu_is_u8500v11())
+               pr_info("DB8500: version 1.1\n");
+       else if (cpu_is_u8500v20())
+               pr_info("DB8500: version 2.0\n");
+       else
+               pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
+
        ux500_init_devices();
 
        if (cpu_is_u8500ed())
index 9280d25611117d1224ad48811c7bc85597c18fce..40032fecbc165538c9822fac801d7e72780d4c3b 100644 (file)
@@ -110,6 +110,82 @@ struct platform_device u8500_i2c4_device = {
        .num_resources  = ARRAY_SIZE(u8500_i2c4_resources),
 };
 
+/*
+ * SD/MMC
+ */
+
+struct amba_device u8500_sdi0_device = {
+       .dev            = {
+               .init_name = "sdi0",
+       },
+       .res            = {
+               .start  = U8500_SDI0_BASE,
+               .end    = U8500_SDI0_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC0, NO_IRQ},
+};
+
+struct amba_device u8500_sdi1_device = {
+       .dev            = {
+               .init_name = "sdi1",
+       },
+       .res            = {
+               .start  = U8500_SDI1_BASE,
+               .end    = U8500_SDI1_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC1, NO_IRQ},
+};
+
+struct amba_device u8500_sdi2_device = {
+       .dev            = {
+               .init_name = "sdi2",
+       },
+       .res            = {
+               .start  = U8500_SDI2_BASE,
+               .end    = U8500_SDI2_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC2, NO_IRQ},
+};
+
+struct amba_device u8500_sdi3_device = {
+       .dev            = {
+               .init_name = "sdi3",
+       },
+       .res            = {
+               .start  = U8500_SDI3_BASE,
+               .end    = U8500_SDI3_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC3, NO_IRQ},
+};
+
+struct amba_device u8500_sdi4_device = {
+       .dev            = {
+               .init_name = "sdi4",
+       },
+       .res            = {
+               .start  = U8500_SDI4_BASE,
+               .end    = U8500_SDI4_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC4, NO_IRQ},
+};
+
+struct amba_device u8500_sdi5_device = {
+       .dev            = {
+               .init_name = "sdi5",
+       },
+       .res            = {
+               .start  = U8500_SDI5_BASE,
+               .end    = U8500_SDI5_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = {IRQ_DB8500_SDMMC5, NO_IRQ},
+};
+
 static struct resource dma40_resources[] = {
        [0] = {
                .start = U8500_DMA_BASE,
@@ -170,23 +246,23 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = {
  * Mapping between destination event lines and physical device address.
  * The event line is tied to a device and therefor the address is constant.
  */
-static const dma_addr_t dma40_tx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
 
 /* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
 
 /* Reserved event lines for memcpy only */
 static int dma40_memcpy_event[] = {
-       STEDMA40_MEMCPY_TX_0,
-       STEDMA40_MEMCPY_TX_1,
-       STEDMA40_MEMCPY_TX_2,
-       STEDMA40_MEMCPY_TX_3,
-       STEDMA40_MEMCPY_TX_4,
-       STEDMA40_MEMCPY_TX_5,
+       DB8500_DMA_MEMCPY_TX_0,
+       DB8500_DMA_MEMCPY_TX_1,
+       DB8500_DMA_MEMCPY_TX_2,
+       DB8500_DMA_MEMCPY_TX_3,
+       DB8500_DMA_MEMCPY_TX_4,
+       DB8500_DMA_MEMCPY_TX_5,
 };
 
 static struct stedma40_platform_data dma40_plat_data = {
-       .dev_len = STEDMA40_NR_DEV,
+       .dev_len = DB8500_DMA_NR_DEV,
        .dev_rx = dma40_rx_map,
        .dev_tx = dma40_tx_map,
        .memcpy = dma40_memcpy_event,
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
new file mode 100644 (file)
index 0000000..b782a03
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *     Based on ARM realview platform
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+       flush_cache_all();
+
+       /* we put the platform to just WFI */
+       for (;;) {
+               __asm__ __volatile__("dsb\n\t" "wfi\n\t"
+                               : : : "memory");
+               if (pen_release == cpu) {
+                       /*
+                        * OK, proper wakeup, we're done
+                        */
+                       break;
+               }
+       }
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+       return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+       unsigned int this_cpu = hard_smp_processor_id();
+
+       if (cpu != this_cpu) {
+               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+                          this_cpu, cpu);
+               BUG();
+       }
+#endif
+
+       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+       complete(&cpu_killed);
+
+       /* directly enter low power state, skipping secure registers */
+       platform_do_lowpower(cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+       /*
+        * we don't allow CPU 0 to be shutdown (it is still too special
+        * e.g. clock tick interrupts)
+        */
+       return cpu == 0 ? -EPERM : 0;
+}
index 545c80fc802484250f1eb9e7550f456a4e07b800..3eafc0e24ba58d75671221a60bdcafbb68388a27 100644 (file)
 #define U5500_GPIOBANK6_BASE   (U5500_GPIO4_BASE + 0x80)
 #define U5500_GPIOBANK7_BASE   (U5500_GPIO4_BASE + 0x100)
 
+#define U5500_MBOX_BASE                (U5500_MODEM_BASE + 0xFFD1000)
+#define U5500_MBOX0_PEER_START (U5500_MBOX_BASE + 0x40)
+#define U5500_MBOX0_PEER_END   (U5500_MBOX_BASE + 0x5F)
+#define U5500_MBOX0_LOCAL_START        (U5500_MBOX_BASE + 0x60)
+#define U5500_MBOX0_LOCAL_END  (U5500_MBOX_BASE + 0x7F)
+#define U5500_MBOX1_PEER_START (U5500_MBOX_BASE + 0x80)
+#define U5500_MBOX1_PEER_END   (U5500_MBOX_BASE + 0x9F)
+#define U5500_MBOX1_LOCAL_START        (U5500_MBOX_BASE + 0xA0)
+#define U5500_MBOX1_LOCAL_END  (U5500_MBOX_BASE + 0xBF)
+#define U5500_MBOX2_PEER_START (U5500_MBOX_BASE + 0x00)
+#define U5500_MBOX2_PEER_END   (U5500_MBOX_BASE + 0x1F)
+#define U5500_MBOX2_LOCAL_START        (U5500_MBOX_BASE + 0x20)
+#define U5500_MBOX2_LOCAL_END  (U5500_MBOX_BASE + 0x3F)
+
 #endif
index f000218210c947ea406692ee1663ee7ac5395ab9..f07d0986409d2341771a39e1298538d466192f36 100644 (file)
@@ -30,8 +30,6 @@
 #define U8500_ICN_BASE         0x81000000
 
 #define U8500_BOOT_ROM_BASE    0x90000000
-/* ASIC ID is at 0xff4 offset within this region */
-#define U8500_ASIC_ID_BASE     0x9001F000
 
 #define U8500_PER6_BASE                0xa03c0000
 #define U8500_PER5_BASE                0xa03e0000
index c5203b7ea5521596f929bde20cd35708a2419e5c..be7c0f14e310abed1fd65267f07142beda12ee0c 100644 (file)
 #define UX500_UART(n)  __UX500_UART(n)
 #define UART_BASE      UX500_UART(CONFIG_UX500_DEBUG_UART)
 
-       .macro  addruart, rx, tmp
-       mrc     p15, 0, \rx, c1, c0
-       tst     \rx, #1                                 @ MMU enabled?
-       ldreq   \rx, =UART_BASE                         @ no, physical address
-       ldrne   \rx, =IO_ADDRESS(UART_BASE)             @ yes, virtual address
+       .macro  addruart, rp, rv
+       ldr     \rp, =UART_BASE                         @ no, physical address
+       ldr     \rv, =IO_ADDRESS(UART_BASE)             @ yes, virtual address
        .endm
 
 #include <asm/hardware/debug-pl01x.S>
index c2b2f257494760ae33d4d41645d85395c12dac1a..33a120c2e82eaf0749e480149cdd2539c671aab8 100644 (file)
@@ -27,6 +27,13 @@ extern struct platform_device u8500_i2c0_device;
 extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
 
+extern struct amba_device u8500_sdi0_device;
+extern struct amba_device u8500_sdi1_device;
+extern struct amba_device u8500_sdi2_device;
+extern struct amba_device u8500_sdi3_device;
+extern struct amba_device u8500_sdi4_device;
+extern struct amba_device u8500_sdi5_device;
+
 void dma40_u8500ed_fixup(void);
 
 #endif
index 8656379a83093c475c9eaf3b40b8cabb051f771d..32e883a8f2a22af6f122a9d529a6d85541d70b64 100644 (file)
@@ -104,16 +104,35 @@ static inline bool cpu_is_u8500(void)
 #endif
 }
 
+#define CPUID_DB8500ED 0x410fc090
+#define CPUID_DB8500V1 0x411fc091
+#define CPUID_DB8500V2 0x412fc091
+
 static inline bool cpu_is_u8500ed(void)
 {
-       return cpu_is_u8500() && (read_cpuid_id() & 15) == 0;
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
 }
 
 static inline bool cpu_is_u8500v1(void)
 {
-       return cpu_is_u8500() && (read_cpuid_id() & 15) == 1;
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
+}
+
+static inline bool cpu_is_u8500v2(void)
+{
+       return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
 }
 
+#ifdef CONFIG_UX500_SOC_DB8500
+bool cpu_is_u8500v10(void);
+bool cpu_is_u8500v11(void);
+bool cpu_is_u8500v20(void);
+#else
+static inline bool cpu_is_u8500v10(void) { return false; }
+static inline bool cpu_is_u8500v11(void) { return false; }
+static inline bool cpu_is_u8500v20(void) { return false; }
+#endif
+
 static inline bool cpu_is_u5500(void)
 {
 #ifdef CONFIG_UX500_SOC_DB5500
index 6fbfe5e2065a76618f8fa88dcb24e5918ad205f6..bfa123dbec3b15d993d76f24509773c7e9777141 100644 (file)
@@ -61,6 +61,7 @@
 #define IRQ_DB5500_SDMMC0              (IRQ_SHPI_START + 60)
 #define IRQ_DB5500_HSEM                        (IRQ_SHPI_START + 61)
 #define IRQ_DB5500_SBAG                        (IRQ_SHPI_START + 63)
+#define IRQ_DB5500_MODEM               (IRQ_SHPI_START + 65)
 #define IRQ_DB5500_SPI1                        (IRQ_SHPI_START + 96)
 #define IRQ_DB5500_MSP2                        (IRQ_SHPI_START + 98)
 #define IRQ_DB5500_SRPTIMER            (IRQ_SHPI_START + 101)
index 10385bdc2b7760506af333077fd1fd34fe5972fc..693aa57de88d995375db54b3d9cefbffc25679c1 100644 (file)
@@ -40,7 +40,8 @@
 #define IRQ_HSIR_CH1_OVRRUN    (IRQ_SHPI_START + 33)
 #define IRQ_HSIR_CH2_OVRRUN    (IRQ_SHPI_START + 34)
 #define IRQ_HSIR_CH3_OVRRUN    (IRQ_SHPI_START + 35)
-#define IRQ_AB4500             (IRQ_SHPI_START + 40)
+#define IRQ_AB8500             (IRQ_SHPI_START + 40)
+#define IRQ_PRCMU               (IRQ_SHPI_START + 47)
 #define IRQ_DISP               (IRQ_SHPI_START + 48)
 #define IRQ_SiPI3              (IRQ_SHPI_START + 49)
 #define IRQ_I2C4               (IRQ_SHPI_START + 51)
 #include <mach/irqs-board-mop500.h>
 #endif
 
-#define NR_IRQS                                IRQ_BOARD_END
+/*
+ * After the board specific IRQ:s we reserve a range of IRQ:s in which virtual
+ * IRQ:s representing modem IRQ:s can be allocated
+ */
+#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1)
+#define IRQ_MODEM_EVENTS_NBR 72
+#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
+
+/* List of virtual IRQ:s that are allocated from the range above */
+#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
+#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
+#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
+
+#define NR_IRQS                                IRQ_MODEM_EVENTS_END
 
 #endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox.h
new file mode 100644 (file)
index 0000000..7f9da4d
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_STE_MBOX_H
+#define __INC_STE_MBOX_H
+
+#define MBOX_BUF_SIZE 16
+#define MBOX_NAME_SIZE 8
+
+/**
+  * mbox_recv_cb_t - Definition of the mailbox callback.
+  * @mbox_msg: The mailbox message.
+  * @priv:     The clients private data as specified in the call to mbox_setup.
+  *
+  * This function will be called upon reception of new mailbox messages.
+  */
+typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
+
+/**
+  * struct mbox - Mailbox instance struct
+  * @list:             Linked list head.
+  * @pdev:             Pointer to device struct.
+  * @cb:               Callback function. Will be called
+  *                    when new data is received.
+  * @client_data:      Clients private data. Will be sent back
+  *                    in the callback function.
+  * @virtbase_peer:    Virtual address for outgoing mailbox.
+  * @virtbase_local:   Virtual address for incoming mailbox.
+  * @buffer:           Then internal queue for outgoing messages.
+  * @name:             Name of this mailbox.
+  * @buffer_available: Completion variable to achieve "blocking send".
+  *                    This variable will be signaled when there is
+  *                    internal buffer space available.
+  * @client_blocked:   To keep track if any client is currently
+  *                    blocked.
+  * @lock:             Spinlock to protect this mailbox instance.
+  * @write_index:      Index in internal buffer to write to.
+  * @read_index:       Index in internal buffer to read from.
+  * @allocated:                Indicates whether this particular mailbox
+  *                    id has been allocated by someone.
+  */
+struct mbox {
+       struct list_head list;
+       struct platform_device *pdev;
+       mbox_recv_cb_t *cb;
+       void *client_data;
+       void __iomem *virtbase_peer;
+       void __iomem *virtbase_local;
+       u32 buffer[MBOX_BUF_SIZE];
+       char name[MBOX_NAME_SIZE];
+       struct completion buffer_available;
+       u8 client_blocked;
+       spinlock_t lock;
+       u8 write_index;
+       u8 read_index;
+       bool allocated;
+};
+
+/**
+  * mbox_setup - Set up a mailbox and return its instance.
+  * @mbox_id:  The ID number of the mailbox. 0 or 1 for modem CPU,
+  *            2 for modem DSP.
+  * @mbox_cb:  Pointer to the callback function to be called when a new message
+  *            is received.
+  * @priv:     Client user data which will be returned in the callback.
+  *
+  * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
+  */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
+
+/**
+  * mbox_send - Send a mailbox message.
+  * @mbox:     Mailbox instance (returned by mbox_setup)
+  * @mbox_msg: The mailbox message to send.
+  * @block:    Specifies whether this call will block until send is possible,
+  *            or return an error if the mailbox buffer is full.
+  *
+  * Returns 0 on success or a negative error code on error. -ENOMEM indicates
+  * that the internal buffer is full and you have to try again later (or
+  * specify "block" in order to block until send is possible).
+  */
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
+
+#endif /*INC_STE_MBOX_H*/
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
new file mode 100644 (file)
index 0000000..8885f39
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 ST-Ericsson SA
+ *
+ * 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.
+ */
+#ifndef __MACH_PRCMU_REGS_H
+#define __MACH_PRCMU_REGS_H
+
+#include <mach/hardware.h>
+
+#define _PRCMU_BASE            IO_ADDRESS(U8500_PRCMU_BASE)
+
+#define PRCM_ARM_PLLDIVPS      (_PRCMU_BASE + 0x118)
+#define PRCM_ARM_CHGCLKREQ     (_PRCMU_BASE + 0x114)
+#define PRCM_PLLARM_ENABLE     (_PRCMU_BASE + 0x98)
+#define PRCM_ARMCLKFIX_MGT     (_PRCMU_BASE + 0x0)
+#define PRCM_A9_RESETN_CLR     (_PRCMU_BASE + 0x1f4)
+#define PRCM_A9_RESETN_SET     (_PRCMU_BASE + 0x1f0)
+#define PRCM_ARM_LS_CLAMP      (_PRCMU_BASE + 0x30c)
+#define PRCM_SRAM_A9           (_PRCMU_BASE + 0x308)
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
+#define PRCMU_IOCR              (_PRCMU_BASE + 0x310)
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL      (_PRCMU_BASE + 0x0fc)
+#define PRCM_MBOX_CPU_SET      (_PRCMU_BASE + 0x100)
+#define PRCM_MBOX_CPU_CLR      (_PRCMU_BASE + 0x104)
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ       (_PRCMU_BASE + 0x328)
+#define PRCM_A9_MASK_ACK       (_PRCMU_BASE + 0x32c)
+#define PRCM_ARMITMSK31TO0     (_PRCMU_BASE + 0x11c)
+#define PRCM_ARMITMSK63TO32    (_PRCMU_BASE + 0x120)
+#define PRCM_ARMITMSK95TO64    (_PRCMU_BASE + 0x124)
+#define PRCM_ARMITMSK127TO96   (_PRCMU_BASE + 0x128)
+#define PRCM_POWER_STATE_VAL   (_PRCMU_BASE + 0x25C)
+#define PRCM_ARMITVAL31TO0     (_PRCMU_BASE + 0x260)
+#define PRCM_ARMITVAL63TO32    (_PRCMU_BASE + 0x264)
+#define PRCM_ARMITVAL95TO64    (_PRCMU_BASE + 0x268)
+#define PRCM_ARMITVAL127TO96   (_PRCMU_BASE + 0x26C)
+
+#define PRCM_HOSTACCESS_REQ    (_PRCMU_BASE + 0x334)
+#define ARM_WAKEUP_MODEM       0x1
+
+#define PRCM_ARM_IT1_CLEAR     (_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_VAL       (_PRCMU_BASE + 0x494)
+#define PRCM_HOLD_EVT          (_PRCMU_BASE + 0x174)
+
+#define PRCM_ITSTATUS0         (_PRCMU_BASE + 0x148)
+#define PRCM_ITSTATUS1         (_PRCMU_BASE + 0x150)
+#define PRCM_ITSTATUS2         (_PRCMU_BASE + 0x158)
+#define PRCM_ITSTATUS3         (_PRCMU_BASE + 0x160)
+#define PRCM_ITSTATUS4         (_PRCMU_BASE + 0x168)
+#define PRCM_ITSTATUS5         (_PRCMU_BASE + 0x484)
+#define PRCM_ITCLEAR5          (_PRCMU_BASE + 0x488)
+#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST       (_PRCMU_BASE + 0x228)
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
+#define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
+#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + 0x044)
+#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + 0x064)
+#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + 0x058)
+#define PRCM_TVCLK_MGT             (_PRCMU_BASE + 0x07c)
+#define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
+#define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
+#define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
+#define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET            (_PRCMU_BASE + 0x410)
+#define PRCM_SRAM_LS_SLEEP         (_PRCMU_BASE + 0x304)
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET       (_PRCMU_BASE + 0x254)
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
+
+#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h
new file mode 100644 (file)
index 0000000..549843f
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCMU f/w APIs
+ */
+#ifndef __MACH_PRCMU_H
+#define __MACH_PRCMU_H
+
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#endif /* __MACH_PRCMU_H */
index e978dbd9e2109a042c5984ad3e64edc87ffd81a0..54bbe648bf583575d390866d6b405e58a899abec 100644 (file)
@@ -38,4 +38,11 @@ extern struct sys_timer ux500_timer;
        .type           = MT_DEVICE,            \
 }
 
+#define __MEM_DEV_DESC(x, sz)  {               \
+       .virtual        = IO_ADDRESS(x),        \
+       .pfn            = __phys_to_pfn(x),     \
+       .length         = sz,                   \
+       .type           = MT_MEMORY,            \
+}
+
 #endif /*  __ASM_ARCH_SETUP_H */
index b59f7bc9725d251812f102b0443f1f714270afe8..197e8417375e17f38942e443a963a686cb90905b 100644 (file)
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
 
 /* This is required to wakeup the secondary core */
 extern void u8500_secondary_startup(void);
 
-#define hard_smp_processor_id()                                \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x0F;                         \
-       })
-
 /*
  * We use IRQ1 as the IPI
  */
diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox.c
new file mode 100644 (file)
index 0000000..6343538
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+/*
+ * Mailbox nomenclature:
+ *
+ *       APE           MODEM
+ *           mbox pairX
+ *   ..........................
+ *   .                       .
+ *   .           peer        .
+ *   .     send  ----        .
+ *   .      -->  |  |        .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .                       .
+ *   .           local       .
+ *   .     rec   ----        .
+ *   .           |  | <--    .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .........................
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/completion.h>
+#include <mach/mbox.h>
+
+#define MBOX_NAME "mbox"
+
+#define MBOX_FIFO_DATA        0x000
+#define MBOX_FIFO_ADD         0x004
+#define MBOX_FIFO_REMOVE      0x008
+#define MBOX_FIFO_THRES_FREE  0x00C
+#define MBOX_FIFO_THRES_OCCUP 0x010
+#define MBOX_FIFO_STATUS      0x014
+
+#define MBOX_DISABLE_IRQ 0x4
+#define MBOX_ENABLE_IRQ  0x0
+#define MBOX_LATCH 1
+
+/* Global list of all mailboxes */
+static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
+
+static struct mbox *get_mbox_with_id(u8 id)
+{
+       u8 i;
+       struct list_head *pos = &mboxs;
+       for (i = 0; i <= id; i++)
+               pos = pos->next;
+
+       return (struct mbox *) list_entry(pos, struct mbox, list);
+}
+
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
+{
+       int res = 0;
+
+       spin_lock(&mbox->lock);
+
+       dev_dbg(&(mbox->pdev->dev),
+               "About to buffer 0x%X to mailbox 0x%X."
+               " ri = %d, wi = %d\n",
+               mbox_msg, (u32)mbox, mbox->read_index,
+               mbox->write_index);
+
+       /* Check if write buffer is full */
+       while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
+               if (!block) {
+                       dev_dbg(&(mbox->pdev->dev),
+                       "Buffer full in non-blocking call! "
+                       "Returning -ENOMEM!\n");
+                       res = -ENOMEM;
+                       goto exit;
+               }
+               spin_unlock(&mbox->lock);
+               dev_dbg(&(mbox->pdev->dev),
+                       "Buffer full in blocking call! Sleeping...\n");
+               mbox->client_blocked = 1;
+               wait_for_completion(&mbox->buffer_available);
+               dev_dbg(&(mbox->pdev->dev),
+                       "Blocking send was woken up! Trying again...\n");
+               spin_lock(&mbox->lock);
+       }
+
+       mbox->buffer[mbox->write_index] = mbox_msg;
+       mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
+
+       /*
+        * Indicate that we want an IRQ as soon as there is a slot
+        * in the FIFO
+        */
+       writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+exit:
+       spin_unlock(&mbox->lock);
+       return res;
+}
+EXPORT_SYMBOL(mbox_send);
+
+#if defined(CONFIG_DEBUG_FS)
+/*
+ * Expected input: <value> <nbr sends>
+ * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
+ */
+static ssize_t mbox_write_fifo(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf,
+                              size_t count)
+{
+       unsigned long mbox_mess;
+       unsigned long nbr_sends;
+       unsigned long i;
+       char int_buf[16];
+       char *token;
+       char *val;
+
+       struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+       strncpy((char *) &int_buf, buf, sizeof(int_buf));
+       token = (char *) &int_buf;
+
+       /* Parse message */
+       val = strsep(&token, " ");
+       if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
+               mbox_mess = 0xDEADBEEF;
+
+       val = strsep(&token, " ");
+       if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
+               nbr_sends = 1;
+
+       dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
+               mbox_mess, nbr_sends, (u32) mbox);
+
+       for (i = 0; i < nbr_sends; i++)
+               mbox_send(mbox, mbox_mess, true);
+
+       return count;
+}
+
+static ssize_t mbox_read_fifo(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       int mbox_value;
+       struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+       if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
+               return sprintf(buf, "Mailbox is empty\n");
+
+       mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+       writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+       return sprintf(buf, "0x%X\n", mbox_value);
+}
+
+static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+
+static int mbox_show(struct seq_file *s, void *data)
+{
+       struct list_head *pos;
+       u8 mbox_index = 0;
+
+       list_for_each(pos, &mboxs) {
+               struct mbox *m =
+                       (struct mbox *) list_entry(pos, struct mbox, list);
+               if (m == NULL) {
+                       seq_printf(s,
+                                  "Unable to retrieve mailbox %d\n",
+                                  mbox_index);
+                       continue;
+               }
+
+               spin_lock(&m->lock);
+               if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
+                       seq_printf(s, "MAILBOX %d not setup or corrupt\n",
+                                  mbox_index);
+                       spin_unlock(&m->lock);
+                       continue;
+               }
+
+               seq_printf(s,
+               "===========================\n"
+               " MAILBOX %d\n"
+               " PEER MAILBOX DUMP\n"
+               "---------------------------\n"
+               "FIFO:                 0x%X (%d)\n"
+               "Free     Threshold:   0x%.2X (%d)\n"
+               "Occupied Threshold:   0x%.2X (%d)\n"
+               "Status:               0x%.2X (%d)\n"
+               "   Free spaces  (ot):    %d (%d)\n"
+               "   Occup spaces (ot):    %d (%d)\n"
+               "===========================\n"
+               " LOCAL MAILBOX DUMP\n"
+               "---------------------------\n"
+               "FIFO:                 0x%.X (%d)\n"
+               "Free     Threshold:   0x%.2X (%d)\n"
+               "Occupied Threshold:   0x%.2X (%d)\n"
+               "Status:               0x%.2X (%d)\n"
+               "   Free spaces  (ot):    %d (%d)\n"
+               "   Occup spaces (ot):    %d (%d)\n"
+               "===========================\n"
+               "write_index: %d\n"
+               "read_index : %d\n"
+               "===========================\n"
+               "\n",
+               mbox_index,
+               readl(m->virtbase_peer + MBOX_FIFO_DATA),
+               readl(m->virtbase_peer + MBOX_FIFO_DATA),
+               readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+               readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+               readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+               readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+               readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+               readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+               (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
+               (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
+               (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
+               (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
+               readl(m->virtbase_local + MBOX_FIFO_DATA),
+               readl(m->virtbase_local + MBOX_FIFO_DATA),
+               readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+               readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+               readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+               readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+               readl(m->virtbase_local + MBOX_FIFO_STATUS),
+               readl(m->virtbase_local + MBOX_FIFO_STATUS),
+               (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
+               (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
+               (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
+               (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
+               m->write_index, m->read_index);
+               mbox_index++;
+               spin_unlock(&m->lock);
+       }
+
+       return 0;
+}
+
+static int mbox_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mbox_show, NULL);
+}
+
+static const struct file_operations mbox_operations = {
+       .owner = THIS_MODULE,
+       .open = mbox_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+#endif
+
+static irqreturn_t mbox_irq(int irq, void *arg)
+{
+       u32 mbox_value;
+       int nbr_occup;
+       int nbr_free;
+       struct mbox *mbox = (struct mbox *) arg;
+
+       spin_lock(&mbox->lock);
+
+       dev_dbg(&(mbox->pdev->dev),
+               "mbox IRQ [%d] received. ri = %d, wi = %d\n",
+               irq, mbox->read_index, mbox->write_index);
+
+       /*
+        * Check if we have any outgoing messages, and if there is space for
+        * them in the FIFO.
+        */
+       if (mbox->read_index != mbox->write_index) {
+               /*
+                * Check by reading FREE for LOCAL since that indicates
+                * OCCUP for PEER
+                */
+               nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
+                           >> 4) & 0x7;
+               dev_dbg(&(mbox->pdev->dev),
+                       "Status indicates %d empty spaces in the FIFO!\n",
+                       nbr_free);
+
+               while ((nbr_free > 0) &&
+                      (mbox->read_index != mbox->write_index)) {
+                       /* Write the message and latch it into the FIFO */
+                       writel(mbox->buffer[mbox->read_index],
+                              (mbox->virtbase_peer + MBOX_FIFO_DATA));
+                       writel(MBOX_LATCH,
+                              (mbox->virtbase_peer + MBOX_FIFO_ADD));
+                       dev_dbg(&(mbox->pdev->dev),
+                               "Wrote message 0x%X to addr 0x%X\n",
+                               mbox->buffer[mbox->read_index],
+                               (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
+
+                       nbr_free--;
+                       mbox->read_index =
+                               (mbox->read_index + 1) % MBOX_BUF_SIZE;
+               }
+
+               /*
+                * Check if we still want IRQ:s when there is free
+                * space to send
+                */
+               if (mbox->read_index != mbox->write_index) {
+                       dev_dbg(&(mbox->pdev->dev),
+                               "Still have messages to send, but FIFO full. "
+                               "Request IRQ again!\n");
+                       writel(MBOX_ENABLE_IRQ,
+                              mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+               } else {
+                       dev_dbg(&(mbox->pdev->dev),
+                               "No more messages to send. "
+                               "Do not request IRQ again!\n");
+                       writel(MBOX_DISABLE_IRQ,
+                              mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+               }
+
+               /*
+                * Check if we can signal any blocked clients that it is OK to
+                * start buffering again
+                */
+               if (mbox->client_blocked &&
+                   (((mbox->write_index + 1) % MBOX_BUF_SIZE)
+                    != mbox->read_index)) {
+                       dev_dbg(&(mbox->pdev->dev),
+                               "Waking up blocked client\n");
+                       complete(&mbox->buffer_available);
+                       mbox->client_blocked = 0;
+               }
+       }
+
+       /* Check if we have any incoming messages */
+       nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
+       if (nbr_occup == 0)
+               goto exit;
+
+       if (mbox->cb == NULL) {
+               dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
+                       "leaving %d incoming messages in fifo!\n", nbr_occup);
+               goto exit;
+       }
+
+       /* Read and acknowledge the message */
+       mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+       writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+       /* Notify consumer of new mailbox message */
+       dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
+               mbox_value);
+       mbox->cb(mbox_value, mbox->client_data);
+
+exit:
+       dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
+               mbox->read_index, mbox->write_index);
+       spin_unlock(&mbox->lock);
+
+       return IRQ_HANDLED;
+}
+
+/* Setup is executed once for each mbox pair */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
+{
+       struct resource *resource;
+       int irq;
+       int res;
+       struct mbox *mbox;
+
+       mbox = get_mbox_with_id(mbox_id);
+       if (mbox == NULL) {
+               dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
+                       mbox_id);
+               goto exit;
+       }
+
+       /*
+        * Check if mailbox has been allocated to someone else,
+        * otherwise allocate it
+        */
+       if (mbox->allocated) {
+               dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
+                       mbox_id);
+               mbox = NULL;
+               goto exit;
+       }
+       mbox->allocated = true;
+
+       dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
+               mbox_id, (u32)mbox);
+
+       mbox->client_data = priv;
+       mbox->cb = mbox_cb;
+
+       /* Get addr for peer mailbox and ioremap it */
+       resource = platform_get_resource_byname(mbox->pdev,
+                                               IORESOURCE_MEM,
+                                               "mbox_peer");
+       if (resource == NULL) {
+               dev_err(&(mbox->pdev->dev),
+                       "Unable to retrieve mbox peer resource\n");
+               mbox = NULL;
+               goto exit;
+       }
+       dev_dbg(&(mbox->pdev->dev),
+               "Resource name: %s start: 0x%X, end: 0x%X\n",
+               resource->name, resource->start, resource->end);
+       mbox->virtbase_peer =
+               ioremap(resource->start, resource->end - resource->start);
+       if (!mbox->virtbase_peer) {
+               dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
+               mbox = NULL;
+               goto exit;
+       }
+       dev_dbg(&(mbox->pdev->dev),
+               "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
+               resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+       /* Get addr for local mailbox and ioremap it */
+       resource = platform_get_resource_byname(mbox->pdev,
+                                               IORESOURCE_MEM,
+                                               "mbox_local");
+       if (resource == NULL) {
+               dev_err(&(mbox->pdev->dev),
+                       "Unable to retrieve mbox local resource\n");
+               mbox = NULL;
+               goto exit;
+       }
+       dev_dbg(&(mbox->pdev->dev),
+               "Resource name: %s start: 0x%X, end: 0x%X\n",
+               resource->name, resource->start, resource->end);
+       mbox->virtbase_local =
+               ioremap(resource->start, resource->end - resource->start);
+       if (!mbox->virtbase_local) {
+               dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
+               mbox = NULL;
+               goto exit;
+       }
+       dev_dbg(&(mbox->pdev->dev),
+               "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
+               resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+       init_completion(&mbox->buffer_available);
+       mbox->client_blocked = 0;
+
+       /* Get IRQ for mailbox and allocate it */
+       irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
+       if (irq < 0) {
+               dev_err(&(mbox->pdev->dev),
+                       "Unable to retrieve mbox irq resource\n");
+               mbox = NULL;
+               goto exit;
+       }
+
+       dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
+       res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
+       if (res < 0) {
+               dev_err(&(mbox->pdev->dev),
+                       "Unable to allocate mbox irq %d\n", irq);
+               mbox = NULL;
+               goto exit;
+       }
+
+       /* Set up mailbox to not launch IRQ on free space in mailbox */
+       writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+       /*
+        * Set up mailbox to launch IRQ on new message if we have
+        * a callback set. If not, do not raise IRQ, but keep message
+        * in FIFO for manual retrieval
+        */
+       if (mbox_cb != NULL)
+               writel(MBOX_ENABLE_IRQ,
+                      mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+       else
+               writel(MBOX_DISABLE_IRQ,
+                      mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+
+#if defined(CONFIG_DEBUG_FS)
+       res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
+       if (res != 0)
+               dev_warn(&(mbox->pdev->dev),
+                        "Unable to create mbox sysfs entry");
+
+       (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
+                                  NULL, &mbox_operations);
+#endif
+
+       dev_info(&(mbox->pdev->dev),
+                "Mailbox driver with index %d initated!\n", mbox_id);
+
+exit:
+       return mbox;
+}
+EXPORT_SYMBOL(mbox_setup);
+
+
+int __init mbox_probe(struct platform_device *pdev)
+{
+       struct mbox local_mbox;
+       struct mbox *mbox;
+       int res = 0;
+       dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
+
+       memset(&local_mbox, 0x0, sizeof(struct mbox));
+
+       /* Associate our mbox data with the platform device */
+       res = platform_device_add_data(pdev,
+                                      (void *) &local_mbox,
+                                      sizeof(struct mbox));
+       if (res != 0) {
+               dev_err(&(pdev->dev),
+                       "Unable to allocate driver platform data!\n");
+               goto exit;
+       }
+
+       mbox = (struct mbox *) pdev->dev.platform_data;
+       mbox->pdev = pdev;
+       mbox->write_index = 0;
+       mbox->read_index = 0;
+
+       INIT_LIST_HEAD(&(mbox->list));
+       list_add_tail(&(mbox->list), &mboxs);
+
+       sprintf(mbox->name, "%s", MBOX_NAME);
+       spin_lock_init(&mbox->lock);
+
+       dev_info(&(pdev->dev), "Mailbox driver loaded\n");
+
+exit:
+       return res;
+}
+
+static struct platform_driver mbox_driver = {
+       .driver = {
+               .name = MBOX_NAME,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init mbox_init(void)
+{
+       return platform_driver_probe(&mbox_driver, mbox_probe);
+}
+
+module_init(mbox_init);
+
+void __exit mbox_exit(void)
+{
+       platform_driver_unregister(&mbox_driver);
+}
+
+module_exit(mbox_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MBOX driver");
diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem_irq.c
new file mode 100644 (file)
index 0000000..3187f88
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
+#define MODEM_INTCON_SIZE 0xFFF
+
+#define DEST_IRQ41_OFFSET 0x2A4
+#define DEST_IRQ43_OFFSET 0x2AC
+#define DEST_IRQ45_OFFSET 0x2B4
+
+#define PRIO_IRQ41_OFFSET 0x6A4
+#define PRIO_IRQ43_OFFSET 0x6AC
+#define PRIO_IRQ45_OFFSET 0x6B4
+
+#define ALLOW_IRQ_OFFSET 0x104
+
+#define MODEM_INTCON_CPU_NBR 0x1
+#define MODEM_INTCON_PRIO_HIGH 0x0
+
+#define MODEM_INTCON_ALLOW_IRQ41 0x0200
+#define MODEM_INTCON_ALLOW_IRQ43 0x0800
+#define MODEM_INTCON_ALLOW_IRQ45 0x2000
+
+#define MODEM_IRQ_REG_OFFSET 0x4
+
+struct modem_irq {
+       void __iomem *modem_intcon_base;
+};
+
+
+static void setup_modem_intcon(void __iomem *modem_intcon_base)
+{
+       /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
+       writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
+       writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
+       writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
+
+       /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
+       writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
+       writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
+       writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
+
+       /* IC_ALLOW_ARRAY - IRQ enable */
+       writel(MODEM_INTCON_ALLOW_IRQ41 |
+                  MODEM_INTCON_ALLOW_IRQ43 |
+                  MODEM_INTCON_ALLOW_IRQ45,
+                  modem_intcon_base + ALLOW_IRQ_OFFSET);
+}
+
+static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
+{
+       int real_irq;
+       int virt_irq;
+       struct modem_irq *mi = (struct modem_irq *)data;
+
+       /* Read modem side IRQ number from modem IRQ controller */
+       real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
+       virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
+
+       pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
+                "which will be 0x%X (%d) which translates to "
+                "virtual IRQ 0x%X (%d)!\n",
+                  (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
+                  real_irq,
+                  real_irq & 0xFF,
+                  real_irq & 0xFF,
+                  virt_irq,
+                  virt_irq);
+
+       if (virt_irq != 0)
+               generic_handle_irq(virt_irq);
+
+       pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
+
+       return IRQ_HANDLED;
+}
+
+static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
+{
+       set_irq_chip(irq, modem_irq_chip);
+       set_irq_handler(irq, handle_simple_irq);
+       set_irq_flags(irq, IRQF_VALID);
+
+       pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
+}
+
+static int modem_irq_init(void)
+{
+       int err;
+       static struct irq_chip  modem_irq_chip;
+       struct modem_irq *mi;
+
+       pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
+                  IRQ_DB5500_MODEM);
+
+       mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
+       if (!mi) {
+               pr_err("modem_irq: Could not allocate device\n");
+               return -ENOMEM;
+       }
+
+       mi->modem_intcon_base =
+               ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
+       pr_debug("modem_irq: ioremapped modem_intcon_base from "
+                "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
+                (u32)mi->modem_intcon_base);
+
+       setup_modem_intcon(mi->modem_intcon_base);
+
+       modem_irq_chip = dummy_irq_chip;
+       modem_irq_chip.name = "modem_irq";
+
+       /* Create the virtual IRQ:s needed */
+       create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
+       create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
+       create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
+
+       err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
+                                  modem_cpu_irq_handler, IRQF_ONESHOT,
+                                  "modem_irq", mi);
+       if (err)
+               pr_err("modem_irq: Could not register IRQ %d\n",
+                      IRQ_DB5500_MODEM);
+
+       return 0;
+}
+
+arch_initcall(modem_irq_init);
diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h
new file mode 100644 (file)
index 0000000..bf50c21
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ */
+
+#ifndef __MACH_DB5500_PINS_H
+#define __MACH_DB5500_PINS_H
+
+#define GPIO0_GPIO             PIN_CFG(0, GPIO)
+#define GPIO0_SM_CS3n          PIN_CFG(0, ALT_A)
+
+#define GPIO1_GPIO             PIN_CFG(1, GPIO)
+#define GPIO1_SM_A3            PIN_CFG(1, ALT_A)
+
+#define GPIO2_GPIO             PIN_CFG(2, GPIO)
+#define GPIO2_SM_A4            PIN_CFG(2, ALT_A)
+#define GPIO2_SM_AVD           PIN_CFG(2, ALT_B)
+
+#define GPIO3_GPIO             PIN_CFG(3, GPIO)
+#define GPIO3_I2C1_SCL         PIN_CFG(3, ALT_A)
+
+#define GPIO4_GPIO             PIN_CFG(4, GPIO)
+#define GPIO4_I2C1_SDA         PIN_CFG(4, ALT_A)
+
+#define GPIO5_GPIO             PIN_CFG(5, GPIO)
+#define GPIO5_MC0_DAT0         PIN_CFG(5, ALT_A)
+#define GPIO5_SM_ADQ8          PIN_CFG(5, ALT_B)
+
+#define GPIO6_GPIO             PIN_CFG(6, GPIO)
+#define GPIO6_MC0_DAT1         PIN_CFG(6, ALT_A)
+#define GPIO6_SM_ADQ0          PIN_CFG(6, ALT_B)
+
+#define GPIO7_GPIO             PIN_CFG(7, GPIO)
+#define GPIO7_MC0_DAT2         PIN_CFG(7, ALT_A)
+#define GPIO7_SM_ADQ9          PIN_CFG(7, ALT_B)
+
+#define GPIO8_GPIO             PIN_CFG(8, GPIO)
+#define GPIO8_MC0_DAT3         PIN_CFG(8, ALT_A)
+#define GPIO8_SM_ADQ1          PIN_CFG(8, ALT_B)
+
+#define GPIO9_GPIO             PIN_CFG(9, GPIO)
+#define GPIO9_MC0_DAT4         PIN_CFG(9, ALT_A)
+#define GPIO9_SM_ADQ10         PIN_CFG(9, ALT_B)
+
+#define GPIO10_GPIO            PIN_CFG(10, GPIO)
+#define GPIO10_MC0_DAT5                PIN_CFG(10, ALT_A)
+#define GPIO10_SM_ADQ2         PIN_CFG(10, ALT_B)
+
+#define GPIO11_GPIO            PIN_CFG(11, GPIO)
+#define GPIO11_MC0_DAT6                PIN_CFG(11, ALT_A)
+#define GPIO11_SM_ADQ11                PIN_CFG(11, ALT_B)
+
+#define GPIO12_GPIO            PIN_CFG(12, GPIO)
+#define GPIO12_MC0_DAT7                PIN_CFG(12, ALT_A)
+#define GPIO12_SM_ADQ3         PIN_CFG(12, ALT_B)
+
+#define GPIO13_GPIO            PIN_CFG(13, GPIO)
+#define GPIO13_MC0_CMD         PIN_CFG(13, ALT_A)
+#define GPIO13_SM_BUSY0n       PIN_CFG(13, ALT_B)
+#define GPIO13_SM_WAIT0n       PIN_CFG(13, ALT_C)
+
+#define GPIO14_GPIO            PIN_CFG(14, GPIO)
+#define GPIO14_MC0_CLK         PIN_CFG(14, ALT_A)
+#define GPIO14_SM_CS1n         PIN_CFG(14, ALT_B)
+#define GPIO14_SM_CKO          PIN_CFG(14, ALT_C)
+
+#define GPIO15_GPIO            PIN_CFG(15, GPIO)
+#define GPIO15_SM_A5           PIN_CFG(15, ALT_A)
+#define GPIO15_SM_CLE          PIN_CFG(15, ALT_B)
+
+#define GPIO16_GPIO            PIN_CFG(16, GPIO)
+#define GPIO16_MC2_CMD         PIN_CFG(16, ALT_A)
+#define GPIO16_SM_OEn          PIN_CFG(16, ALT_B)
+
+#define GPIO17_GPIO            PIN_CFG(17, GPIO)
+#define GPIO17_MC2_CLK         PIN_CFG(17, ALT_A)
+#define GPIO17_SM_WEn          PIN_CFG(17, ALT_B)
+
+#define GPIO18_GPIO            PIN_CFG(18, GPIO)
+#define GPIO18_SM_A6           PIN_CFG(18, ALT_A)
+#define GPIO18_SM_ALE          PIN_CFG(18, ALT_B)
+#define GPIO18_SM_AVDn         PIN_CFG(18, ALT_C)
+
+#define GPIO19_GPIO            PIN_CFG(19, GPIO)
+#define GPIO19_MC2_DAT1                PIN_CFG(19, ALT_A)
+#define GPIO19_SM_ADQ4         PIN_CFG(19, ALT_B)
+
+#define GPIO20_GPIO            PIN_CFG(20, GPIO)
+#define GPIO20_MC2_DAT3                PIN_CFG(20, ALT_A)
+#define GPIO20_SM_ADQ5         PIN_CFG(20, ALT_B)
+
+#define GPIO21_GPIO            PIN_CFG(21, GPIO)
+#define GPIO21_MC2_DAT5                PIN_CFG(21, ALT_A)
+#define GPIO21_SM_ADQ6         PIN_CFG(21, ALT_B)
+
+#define GPIO22_GPIO            PIN_CFG(22, GPIO)
+#define GPIO22_MC2_DAT7                PIN_CFG(22, ALT_A)
+#define GPIO22_SM_ADQ7         PIN_CFG(22, ALT_B)
+
+#define GPIO23_GPIO            PIN_CFG(23, GPIO)
+#define GPIO23_MC2_DAT0                PIN_CFG(23, ALT_A)
+#define GPIO23_SM_ADQ12                PIN_CFG(23, ALT_B)
+#define GPIO23_MC0_DAT1                PIN_CFG(23, ALT_C)
+
+#define GPIO24_GPIO            PIN_CFG(24, GPIO)
+#define GPIO24_MC2_DAT2                PIN_CFG(24, ALT_A)
+#define GPIO24_SM_ADQ13                PIN_CFG(24, ALT_B)
+#define GPIO24_MC0_DAT3                PIN_CFG(24, ALT_C)
+
+#define GPIO25_GPIO            PIN_CFG(25, GPIO)
+#define GPIO25_MC2_DAT4                PIN_CFG(25, ALT_A)
+#define GPIO25_SM_ADQ14                PIN_CFG(25, ALT_B)
+#define GPIO25_MC0_CMD         PIN_CFG(25, ALT_C)
+
+#define GPIO26_GPIO            PIN_CFG(26, GPIO)
+#define GPIO26_MC2_DAT6                PIN_CFG(26, ALT_A)
+#define GPIO26_SM_ADQ15                PIN_CFG(26, ALT_B)
+
+#define GPIO27_GPIO            PIN_CFG(27, GPIO)
+#define GPIO27_SM_CS0n         PIN_CFG(27, ALT_A)
+#define GPIO27_SM_PS0n         PIN_CFG(27, ALT_B)
+
+#define GPIO28_GPIO            PIN_CFG(28, GPIO)
+#define GPIO28_U0_TXD          PIN_CFG(28, ALT_A)
+#define GPIO28_SM_A0           PIN_CFG(28, ALT_B)
+
+#define GPIO29_GPIO            PIN_CFG(29, GPIO)
+#define GPIO29_U0_RXD          PIN_CFG(29, ALT_A)
+#define GPIO29_SM_A1           PIN_CFG(29, ALT_B)
+#define GPIO29_PWM_0           PIN_CFG(29, ALT_C)
+
+#define GPIO30_GPIO            PIN_CFG(30, GPIO)
+#define GPIO30_MC0_DAT5                PIN_CFG(30, ALT_A)
+#define GPIO30_SM_A2           PIN_CFG(30, ALT_B)
+#define GPIO30_PWM_1           PIN_CFG(30, ALT_C)
+
+#define GPIO31_GPIO            PIN_CFG(31, GPIO)
+#define GPIO31_MC0_DAT7                PIN_CFG(31, ALT_A)
+#define GPIO31_SM_CS2n         PIN_CFG(31, ALT_B)
+#define GPIO31_PWM_2           PIN_CFG(31, ALT_C)
+
+#define GPIO32_GPIO            PIN_CFG(32, GPIO)
+#define GPIO32_MSP0_TCK                PIN_CFG(32, ALT_A)
+#define GPIO32_ACCI2S0_SCK     PIN_CFG(32, ALT_B)
+
+#define GPIO33_GPIO            PIN_CFG(33, GPIO)
+#define GPIO33_MSP0_TFS                PIN_CFG(33, ALT_A)
+#define GPIO33_ACCI2S0_WS      PIN_CFG(33, ALT_B)
+
+#define GPIO34_GPIO            PIN_CFG(34, GPIO)
+#define GPIO34_MSP0_TXD                PIN_CFG(34, ALT_A)
+#define GPIO34_ACCI2S0_DLD     PIN_CFG(34, ALT_B)
+
+#define GPIO35_GPIO            PIN_CFG(35, GPIO)
+#define GPIO35_MSP0_RXD                PIN_CFG(35, ALT_A)
+#define GPIO35_ACCI2S0_ULD     PIN_CFG(35, ALT_B)
+
+#define GPIO64_GPIO            PIN_CFG(64, GPIO)
+#define GPIO64_USB_DAT0                PIN_CFG(64, ALT_A)
+#define GPIO64_U0_TXD          PIN_CFG(64, ALT_B)
+
+#define GPIO65_GPIO            PIN_CFG(65, GPIO)
+#define GPIO65_USB_DAT1                PIN_CFG(65, ALT_A)
+#define GPIO65_U0_RXD          PIN_CFG(65, ALT_B)
+
+#define GPIO66_GPIO            PIN_CFG(66, GPIO)
+#define GPIO66_USB_DAT2                PIN_CFG(66, ALT_A)
+
+#define GPIO67_GPIO            PIN_CFG(67, GPIO)
+#define GPIO67_USB_DAT3                PIN_CFG(67, ALT_A)
+
+#define GPIO68_GPIO            PIN_CFG(68, GPIO)
+#define GPIO68_USB_DAT4                PIN_CFG(68, ALT_A)
+
+#define GPIO69_GPIO            PIN_CFG(69, GPIO)
+#define GPIO69_USB_DAT5                PIN_CFG(69, ALT_A)
+
+#define GPIO70_GPIO            PIN_CFG(70, GPIO)
+#define GPIO70_USB_DAT6                PIN_CFG(70, ALT_A)
+
+#define GPIO71_GPIO            PIN_CFG(71, GPIO)
+#define GPIO71_USB_DAT7                PIN_CFG(71, ALT_A)
+
+#define GPIO72_GPIO            PIN_CFG(72, GPIO)
+#define GPIO72_USB_STP         PIN_CFG(72, ALT_A)
+
+#define GPIO73_GPIO            PIN_CFG(73, GPIO)
+#define GPIO73_USB_DIR         PIN_CFG(73, ALT_A)
+
+#define GPIO74_GPIO            PIN_CFG(74, GPIO)
+#define GPIO74_USB_NXT         PIN_CFG(74, ALT_A)
+
+#define GPIO75_GPIO            PIN_CFG(75, GPIO)
+#define GPIO75_USB_XCLK                PIN_CFG(75, ALT_A)
+
+#define GPIO76_GPIO            PIN_CFG(76, GPIO)
+
+#define GPIO77_GPIO            PIN_CFG(77, GPIO)
+#define GPIO77_ACCTX_ON                PIN_CFG(77, ALT_A)
+
+#define GPIO78_GPIO            PIN_CFG(78, GPIO)
+#define GPIO78_IRQn            PIN_CFG(78, ALT_A)
+
+#define GPIO79_GPIO            PIN_CFG(79, GPIO)
+#define GPIO79_ACCSIM_Clk      PIN_CFG(79, ALT_A)
+
+#define GPIO80_GPIO            PIN_CFG(80, GPIO)
+#define GPIO80_ACCSIM_Da       PIN_CFG(80, ALT_A)
+
+#define GPIO81_GPIO            PIN_CFG(81, GPIO)
+#define GPIO81_ACCSIM_Reset    PIN_CFG(81, ALT_A)
+
+#define GPIO82_GPIO            PIN_CFG(82, GPIO)
+#define GPIO82_ACCSIM_DDir     PIN_CFG(82, ALT_A)
+
+#define GPIO96_GPIO            PIN_CFG(96, GPIO)
+#define GPIO96_MSP1_TCK                PIN_CFG(96, ALT_A)
+#define GPIO96_PRCMU_DEBUG3    PIN_CFG(96, ALT_B)
+#define GPIO96_PRCMU_DEBUG7    PIN_CFG(96, ALT_C)
+
+#define GPIO97_GPIO            PIN_CFG(97, GPIO)
+#define GPIO97_MSP1_TFS                PIN_CFG(97, ALT_A)
+#define GPIO97_PRCMU_DEBUG2    PIN_CFG(97, ALT_B)
+#define GPIO97_PRCMU_DEBUG6    PIN_CFG(97, ALT_C)
+
+#define GPIO98_GPIO            PIN_CFG(98, GPIO)
+#define GPIO98_MSP1_TXD                PIN_CFG(98, ALT_A)
+#define GPIO98_PRCMU_DEBUG1    PIN_CFG(98, ALT_B)
+#define GPIO98_PRCMU_DEBUG5    PIN_CFG(98, ALT_C)
+
+#define GPIO99_GPIO            PIN_CFG(99, GPIO)
+#define GPIO99_MSP1_RXD                PIN_CFG(99, ALT_A)
+#define GPIO99_PRCMU_DEBUG0    PIN_CFG(99, ALT_B)
+#define GPIO99_PRCMU_DEBUG4    PIN_CFG(99, ALT_C)
+
+#define GPIO100_GPIO           PIN_CFG(100, GPIO)
+#define GPIO100_I2C0_SCL       PIN_CFG(100, ALT_A)
+
+#define GPIO101_GPIO           PIN_CFG(101, GPIO)
+#define GPIO101_I2C0_SDA       PIN_CFG(101, ALT_A)
+
+#define GPIO128_GPIO           PIN_CFG(128, GPIO)
+#define GPIO128_KP_I0          PIN_CFG(128, ALT_A)
+#define GPIO128_BUSMON_D0      PIN_CFG(128, ALT_B)
+
+#define GPIO129_GPIO           PIN_CFG(129, GPIO)
+#define GPIO129_KP_O0          PIN_CFG(129, ALT_A)
+#define GPIO129_BUSMON_D1      PIN_CFG(129, ALT_B)
+
+#define GPIO130_GPIO           PIN_CFG(130, GPIO)
+#define GPIO130_KP_I1          PIN_CFG(130, ALT_A)
+#define GPIO130_BUSMON_D2      PIN_CFG(130, ALT_B)
+
+#define GPIO131_GPIO           PIN_CFG(131, GPIO)
+#define GPIO131_KP_O1          PIN_CFG(131, ALT_A)
+#define GPIO131_BUSMON_D3      PIN_CFG(131, ALT_B)
+
+#define GPIO132_GPIO           PIN_CFG(132, GPIO)
+#define GPIO132_KP_I2          PIN_CFG(132, ALT_A)
+#define GPIO132_ETM_D15                PIN_CFG(132, ALT_B)
+#define GPIO132_STMAPE_CLK     PIN_CFG(132, ALT_C)
+
+#define GPIO133_GPIO           PIN_CFG(133, GPIO)
+#define GPIO133_KP_O2          PIN_CFG(133, ALT_A)
+#define GPIO133_ETM_D14                PIN_CFG(133, ALT_B)
+#define GPIO133_U0_RXD         PIN_CFG(133, ALT_C)
+
+#define GPIO134_GPIO           PIN_CFG(134, GPIO)
+#define GPIO134_KP_I3          PIN_CFG(134, ALT_A)
+#define GPIO134_ETM_D13                PIN_CFG(134, ALT_B)
+#define GPIO134_STMAPE_DAT0    PIN_CFG(134, ALT_C)
+
+#define GPIO135_GPIO           PIN_CFG(135, GPIO)
+#define GPIO135_KP_O3          PIN_CFG(135, ALT_A)
+#define GPIO135_ETM_D12                PIN_CFG(135, ALT_B)
+#define GPIO135_STMAPE_DAT1    PIN_CFG(135, ALT_C)
+
+#define GPIO136_GPIO           PIN_CFG(136, GPIO)
+#define GPIO136_KP_I4          PIN_CFG(136, ALT_A)
+#define GPIO136_ETM_D11                PIN_CFG(136, ALT_B)
+#define GPIO136_STMAPE_DAT2    PIN_CFG(136, ALT_C)
+
+#define GPIO137_GPIO           PIN_CFG(137, GPIO)
+#define GPIO137_KP_O4          PIN_CFG(137, ALT_A)
+#define GPIO137_ETM_D10                PIN_CFG(137, ALT_B)
+#define GPIO137_STMAPE_DAT3    PIN_CFG(137, ALT_C)
+
+#define GPIO138_GPIO           PIN_CFG(138, GPIO)
+#define GPIO138_KP_I5          PIN_CFG(138, ALT_A)
+#define GPIO138_ETM_D9         PIN_CFG(138, ALT_B)
+#define GPIO138_U0_TXD         PIN_CFG(138, ALT_C)
+
+#define GPIO139_GPIO           PIN_CFG(139, GPIO)
+#define GPIO139_KP_O5          PIN_CFG(139, ALT_A)
+#define GPIO139_ETM_D8         PIN_CFG(139, ALT_B)
+#define GPIO139_BUSMON_D11     PIN_CFG(139, ALT_C)
+
+#define GPIO140_GPIO           PIN_CFG(140, GPIO)
+#define GPIO140_KP_I6          PIN_CFG(140, ALT_A)
+#define GPIO140_ETM_D7         PIN_CFG(140, ALT_B)
+#define GPIO140_STMAPE_CLK     PIN_CFG(140, ALT_C)
+
+#define GPIO141_GPIO           PIN_CFG(141, GPIO)
+#define GPIO141_KP_O6          PIN_CFG(141, ALT_A)
+#define GPIO141_ETM_D6         PIN_CFG(141, ALT_B)
+#define GPIO141_U0_RXD         PIN_CFG(141, ALT_C)
+
+#define GPIO142_GPIO           PIN_CFG(142, GPIO)
+#define GPIO142_KP_I7          PIN_CFG(142, ALT_A)
+#define GPIO142_ETM_D5         PIN_CFG(142, ALT_B)
+#define GPIO142_STMAPE_DAT0    PIN_CFG(142, ALT_C)
+
+#define GPIO143_GPIO           PIN_CFG(143, GPIO)
+#define GPIO143_KP_O7          PIN_CFG(143, ALT_A)
+#define GPIO143_ETM_D4         PIN_CFG(143, ALT_B)
+#define GPIO143_STMAPE_DAT1    PIN_CFG(143, ALT_C)
+
+#define GPIO144_GPIO           PIN_CFG(144, GPIO)
+#define GPIO144_I2C3_SCL       PIN_CFG(144, ALT_A)
+#define GPIO144_ETM_D3         PIN_CFG(144, ALT_B)
+#define GPIO144_STMAPE_DAT2    PIN_CFG(144, ALT_C)
+
+#define GPIO145_GPIO           PIN_CFG(145, GPIO)
+#define GPIO145_I2C3_SDA       PIN_CFG(145, ALT_A)
+#define GPIO145_ETM_D2         PIN_CFG(145, ALT_B)
+#define GPIO145_STMAPE_DAT3    PIN_CFG(145, ALT_C)
+
+#define GPIO146_GPIO           PIN_CFG(146, GPIO)
+#define GPIO146_PWM_0          PIN_CFG(146, ALT_A)
+#define GPIO146_ETM_D1         PIN_CFG(146, ALT_B)
+
+#define GPIO147_GPIO           PIN_CFG(147, GPIO)
+#define GPIO147_PWM_1          PIN_CFG(147, ALT_A)
+#define GPIO147_ETM_D0         PIN_CFG(147, ALT_B)
+
+#define GPIO148_GPIO           PIN_CFG(148, GPIO)
+#define GPIO148_PWM_2          PIN_CFG(148, ALT_A)
+#define GPIO148_ETM_CLK                PIN_CFG(148, ALT_B)
+
+#define GPIO160_GPIO           PIN_CFG(160, GPIO)
+#define GPIO160_CLKOUT_REQn    PIN_CFG(160, ALT_A)
+
+#define GPIO161_GPIO           PIN_CFG(161, GPIO)
+#define GPIO161_CLKOUT_0       PIN_CFG(161, ALT_A)
+
+#define GPIO162_GPIO           PIN_CFG(162, GPIO)
+#define GPIO162_CLKOUT_1       PIN_CFG(162, ALT_A)
+
+#define GPIO163_GPIO           PIN_CFG(163, GPIO)
+
+#define GPIO164_GPIO           PIN_CFG(164, GPIO)
+#define GPIO164_GPS_START      PIN_CFG(164, ALT_A)
+
+#define GPIO165_GPIO           PIN_CFG(165, GPIO)
+#define GPIO165_SPI1_CS2n      PIN_CFG(165, ALT_A)
+#define GPIO165_U3_RXD         PIN_CFG(165, ALT_B)
+#define GPIO165_BUSMON_D20     PIN_CFG(165, ALT_C)
+
+#define GPIO166_GPIO           PIN_CFG(166, GPIO)
+#define GPIO166_SPI1_CS1n      PIN_CFG(166, ALT_A)
+#define GPIO166_U3_TXD         PIN_CFG(166, ALT_B)
+#define GPIO166_BUSMON_D21     PIN_CFG(166, ALT_C)
+
+#define GPIO167_GPIO           PIN_CFG(167, GPIO)
+#define GPIO167_SPI1_CS0n      PIN_CFG(167, ALT_A)
+#define GPIO167_U3_RTSn                PIN_CFG(167, ALT_B)
+#define GPIO167_BUSMON_D22     PIN_CFG(167, ALT_C)
+
+#define GPIO168_GPIO           PIN_CFG(168, GPIO)
+#define GPIO168_SPI1_RXD       PIN_CFG(168, ALT_A)
+#define GPIO168_U3_CTSn                PIN_CFG(168, ALT_B)
+#define GPIO168_BUSMON_D23     PIN_CFG(168, ALT_C)
+
+#define GPIO169_GPIO           PIN_CFG(169, GPIO)
+#define GPIO169_SPI1_TXD       PIN_CFG(169, ALT_A)
+#define GPIO169_DDR_RC         PIN_CFG(169, ALT_B)
+#define GPIO169_BUSMON_D24     PIN_CFG(169, ALT_C)
+
+#define GPIO170_GPIO           PIN_CFG(170, GPIO)
+#define GPIO170_SPI1_CLK       PIN_CFG(170, ALT_A)
+
+#define GPIO171_GPIO           PIN_CFG(171, GPIO)
+#define GPIO171_MC3_DAT0       PIN_CFG(171, ALT_A)
+#define GPIO171_SPI3_RXD       PIN_CFG(171, ALT_B)
+#define GPIO171_BUSMON_D25     PIN_CFG(171, ALT_C)
+
+#define GPIO172_GPIO           PIN_CFG(172, GPIO)
+#define GPIO172_MC3_DAT1       PIN_CFG(172, ALT_A)
+#define GPIO172_SPI3_CS1n      PIN_CFG(172, ALT_B)
+#define GPIO172_BUSMON_D26     PIN_CFG(172, ALT_C)
+
+#define GPIO173_GPIO           PIN_CFG(173, GPIO)
+#define GPIO173_MC3_DAT2       PIN_CFG(173, ALT_A)
+#define GPIO173_SPI3_CS2n      PIN_CFG(173, ALT_B)
+#define GPIO173_BUSMON_D27     PIN_CFG(173, ALT_C)
+
+#define GPIO174_GPIO           PIN_CFG(174, GPIO)
+#define GPIO174_MC3_DAT3       PIN_CFG(174, ALT_A)
+#define GPIO174_SPI3_CS0n      PIN_CFG(174, ALT_B)
+#define GPIO174_BUSMON_D28     PIN_CFG(174, ALT_C)
+
+#define GPIO175_GPIO           PIN_CFG(175, GPIO)
+#define GPIO175_MC3_CMD                PIN_CFG(175, ALT_A)
+#define GPIO175_SPI3_TXD       PIN_CFG(175, ALT_B)
+#define GPIO175_BUSMON_D29     PIN_CFG(175, ALT_C)
+
+#define GPIO176_GPIO           PIN_CFG(176, GPIO)
+#define GPIO176_MC3_CLK                PIN_CFG(176, ALT_A)
+#define GPIO176_SPI3_CLK       PIN_CFG(176, ALT_B)
+
+#define GPIO177_GPIO           PIN_CFG(177, GPIO)
+#define GPIO177_U2_RXD         PIN_CFG(177, ALT_A)
+#define GPIO177_I2C3_SCL       PIN_CFG(177, ALT_B)
+#define GPIO177_BUSMON_D30     PIN_CFG(177, ALT_C)
+
+#define GPIO178_GPIO           PIN_CFG(178, GPIO)
+#define GPIO178_U2_TXD         PIN_CFG(178, ALT_A)
+#define GPIO178_I2C3_SDA       PIN_CFG(178, ALT_B)
+#define GPIO178_BUSMON_D31     PIN_CFG(178, ALT_C)
+
+#define GPIO179_GPIO           PIN_CFG(179, GPIO)
+#define GPIO179_U2_CTSn                PIN_CFG(179, ALT_A)
+#define GPIO179_U3_RXD         PIN_CFG(179, ALT_B)
+#define GPIO179_BUSMON_D32     PIN_CFG(179, ALT_C)
+
+#define GPIO180_GPIO           PIN_CFG(180, GPIO)
+#define GPIO180_U2_RTSn                PIN_CFG(180, ALT_A)
+#define GPIO180_U3_TXD         PIN_CFG(180, ALT_B)
+#define GPIO180_BUSMON_D33     PIN_CFG(180, ALT_C)
+
+#define GPIO185_GPIO           PIN_CFG(185, GPIO)
+#define GPIO185_SPI3_CS2n      PIN_CFG(185, ALT_A)
+#define GPIO185_MC4_DAT0       PIN_CFG(185, ALT_B)
+
+#define GPIO186_GPIO           PIN_CFG(186, GPIO)
+#define GPIO186_SPI3_CS1n      PIN_CFG(186, ALT_A)
+#define GPIO186_MC4_DAT1       PIN_CFG(186, ALT_B)
+
+#define GPIO187_GPIO           PIN_CFG(187, GPIO)
+#define GPIO187_SPI3_CS0n      PIN_CFG(187, ALT_A)
+#define GPIO187_MC4_DAT2       PIN_CFG(187, ALT_B)
+
+#define GPIO188_GPIO           PIN_CFG(188, GPIO)
+#define GPIO188_SPI3_RXD       PIN_CFG(188, ALT_A)
+#define GPIO188_MC4_DAT3       PIN_CFG(188, ALT_B)
+
+#define GPIO189_GPIO           PIN_CFG(189, GPIO)
+#define GPIO189_SPI3_TXD       PIN_CFG(189, ALT_A)
+#define GPIO189_MC4_CMD                PIN_CFG(189, ALT_B)
+
+#define GPIO190_GPIO           PIN_CFG(190, GPIO)
+#define GPIO190_SPI3_CLK       PIN_CFG(190, ALT_A)
+#define GPIO190_MC4_CLK                PIN_CFG(190, ALT_B)
+
+#define GPIO191_GPIO           PIN_CFG(191, GPIO)
+#define GPIO191_MC1_DAT0       PIN_CFG(191, ALT_A)
+#define GPIO191_MC4_DAT4       PIN_CFG(191, ALT_B)
+#define GPIO191_STMAPE_DAT0    PIN_CFG(191, ALT_C)
+
+#define GPIO192_GPIO           PIN_CFG(192, GPIO)
+#define GPIO192_MC1_DAT1       PIN_CFG(192, ALT_A)
+#define GPIO192_MC4_DAT5       PIN_CFG(192, ALT_B)
+#define GPIO192_STMAPE_DAT1    PIN_CFG(192, ALT_C)
+
+#define GPIO193_GPIO           PIN_CFG(193, GPIO)
+#define GPIO193_MC1_DAT2       PIN_CFG(193, ALT_A)
+#define GPIO193_MC4_DAT6       PIN_CFG(193, ALT_B)
+#define GPIO193_STMAPE_DAT2    PIN_CFG(193, ALT_C)
+
+#define GPIO194_GPIO           PIN_CFG(194, GPIO)
+#define GPIO194_MC1_DAT3       PIN_CFG(194, ALT_A)
+#define GPIO194_MC4_DAT7       PIN_CFG(194, ALT_B)
+#define GPIO194_STMAPE_DAT3    PIN_CFG(194, ALT_C)
+
+#define GPIO195_GPIO           PIN_CFG(195, GPIO)
+#define GPIO195_MC1_CLK                PIN_CFG(195, ALT_A)
+#define GPIO195_STMAPE_CLK     PIN_CFG(195, ALT_B)
+#define GPIO195_BUSMON_CLK     PIN_CFG(195, ALT_C)
+
+#define GPIO196_GPIO           PIN_CFG(196, GPIO)
+#define GPIO196_MC1_CMD                PIN_CFG(196, ALT_A)
+#define GPIO196_U0_RXD         PIN_CFG(196, ALT_B)
+#define GPIO196_BUSMON_D38     PIN_CFG(196, ALT_C)
+
+#define GPIO197_GPIO           PIN_CFG(197, GPIO)
+#define GPIO197_MC1_CMDDIR     PIN_CFG(197, ALT_A)
+#define GPIO197_BUSMON_D39     PIN_CFG(197, ALT_B)
+
+#define GPIO198_GPIO           PIN_CFG(198, GPIO)
+#define GPIO198_MC1_FBCLK      PIN_CFG(198, ALT_A)
+
+#define GPIO199_GPIO           PIN_CFG(199, GPIO)
+#define GPIO199_MC1_DAT0DIR    PIN_CFG(199, ALT_A)
+#define GPIO199_BUSMON_D40     PIN_CFG(199, ALT_B)
+
+#define GPIO200_GPIO           PIN_CFG(200, GPIO)
+#define GPIO200_U1_TXD         PIN_CFG(200, ALT_A)
+#define GPIO200_ACCU0_RTSn     PIN_CFG(200, ALT_B)
+
+#define GPIO201_GPIO           PIN_CFG(201, GPIO)
+#define GPIO201_U1_RXD         PIN_CFG(201, ALT_A)
+#define GPIO201_ACCU0_CTSn     PIN_CFG(201, ALT_B)
+
+#define GPIO202_GPIO           PIN_CFG(202, GPIO)
+#define GPIO202_U1_CTSn                PIN_CFG(202, ALT_A)
+#define GPIO202_ACCU0_RXD      PIN_CFG(202, ALT_B)
+
+#define GPIO203_GPIO           PIN_CFG(203, GPIO)
+#define GPIO203_U1_RTSn                PIN_CFG(203, ALT_A)
+#define GPIO203_ACCU0_TXD      PIN_CFG(203, ALT_B)
+
+#define GPIO204_GPIO           PIN_CFG(204, GPIO)
+#define GPIO204_SPI0_CS2n      PIN_CFG(204, ALT_A)
+#define GPIO204_ACCGPIO_000    PIN_CFG(204, ALT_B)
+#define GPIO204_LCD_VSI1       PIN_CFG(204, ALT_C)
+
+#define GPIO205_GPIO           PIN_CFG(205, GPIO)
+#define GPIO205_SPI0_CS1n      PIN_CFG(205, ALT_A)
+#define GPIO205_ACCGPIO_001    PIN_CFG(205, ALT_B)
+#define GPIO205_LCD_D3         PIN_CFG(205, ALT_C)
+
+#define GPIO206_GPIO           PIN_CFG(206, GPIO)
+#define GPIO206_SPI0_CS0n      PIN_CFG(206, ALT_A)
+#define GPIO206_ACCGPIO_002    PIN_CFG(206, ALT_B)
+#define GPIO206_LCD_D2         PIN_CFG(206, ALT_C)
+
+#define GPIO207_GPIO           PIN_CFG(207, GPIO)
+#define GPIO207_SPI0_RXD       PIN_CFG(207, ALT_A)
+#define GPIO207_ACCGPIO_003    PIN_CFG(207, ALT_B)
+#define GPIO207_LCD_D1         PIN_CFG(207, ALT_C)
+
+#define GPIO208_GPIO           PIN_CFG(208, GPIO)
+#define GPIO208_SPI0_TXD       PIN_CFG(208, ALT_A)
+#define GPIO208_ACCGPIO_004    PIN_CFG(208, ALT_B)
+#define GPIO208_LCD_D0         PIN_CFG(208, ALT_C)
+
+#define GPIO209_GPIO           PIN_CFG(209, GPIO)
+#define GPIO209_SPI0_CLK       PIN_CFG(209, ALT_A)
+#define GPIO209_ACCGPIO_005    PIN_CFG(209, ALT_B)
+#define GPIO209_LCD_CLK                PIN_CFG(209, ALT_C)
+
+#define GPIO210_GPIO           PIN_CFG(210, GPIO)
+#define GPIO210_LCD_VSO                PIN_CFG(210, ALT_A)
+#define GPIO210_PRCMU_PWRCTRL1 PIN_CFG(210, ALT_B)
+
+#define GPIO211_GPIO           PIN_CFG(211, GPIO)
+#define GPIO211_LCD_VSI0       PIN_CFG(211, ALT_A)
+#define GPIO211_PRCMU_PWRCTRL2 PIN_CFG(211, ALT_B)
+
+#define GPIO212_GPIO           PIN_CFG(212, GPIO)
+#define GPIO212_SPI2_CS2n      PIN_CFG(212, ALT_A)
+#define GPIO212_LCD_HSO                PIN_CFG(212, ALT_B)
+
+#define GPIO213_GPIO           PIN_CFG(213, GPIO)
+#define GPIO213_SPI2_CS1n      PIN_CFG(213, ALT_A)
+#define GPIO213_LCD_DE         PIN_CFG(213, ALT_B)
+#define GPIO213_BUSMON_D16     PIN_CFG(213, ALT_C)
+
+#define GPIO214_GPIO           PIN_CFG(214, GPIO)
+#define GPIO214_SPI2_CS0n      PIN_CFG(214, ALT_A)
+#define GPIO214_LCD_D7         PIN_CFG(214, ALT_B)
+#define GPIO214_BUSMON_D17     PIN_CFG(214, ALT_C)
+
+#define GPIO215_GPIO           PIN_CFG(215, GPIO)
+#define GPIO215_SPI2_RXD       PIN_CFG(215, ALT_A)
+#define GPIO215_LCD_D6         PIN_CFG(215, ALT_B)
+#define GPIO215_BUSMON_D18     PIN_CFG(215, ALT_C)
+
+#define GPIO216_GPIO           PIN_CFG(216, GPIO)
+#define GPIO216_SPI2_CLK       PIN_CFG(216, ALT_A)
+#define GPIO216_LCD_D5         PIN_CFG(216, ALT_B)
+
+#define GPIO217_GPIO           PIN_CFG(217, GPIO)
+#define GPIO217_SPI2_TXD       PIN_CFG(217, ALT_A)
+#define GPIO217_LCD_D4         PIN_CFG(217, ALT_B)
+#define GPIO217_BUSMON_D19     PIN_CFG(217, ALT_C)
+
+#define GPIO218_GPIO           PIN_CFG(218, GPIO)
+#define GPIO218_I2C2_SCL       PIN_CFG(218, ALT_A)
+#define GPIO218_LCD_VSO                PIN_CFG(218, ALT_B)
+
+#define GPIO219_GPIO           PIN_CFG(219, GPIO)
+#define GPIO219_I2C2_SDA       PIN_CFG(219, ALT_A)
+#define GPIO219_LCD_D3         PIN_CFG(219, ALT_B)
+
+#define GPIO220_GPIO           PIN_CFG(220, GPIO)
+#define GPIO220_MSP2_TCK       PIN_CFG(220, ALT_A)
+#define GPIO220_LCD_D2         PIN_CFG(220, ALT_B)
+
+#define GPIO221_GPIO           PIN_CFG(221, GPIO)
+#define GPIO221_MSP2_TFS       PIN_CFG(221, ALT_A)
+#define GPIO221_LCD_D1         PIN_CFG(221, ALT_B)
+
+#define GPIO222_GPIO           PIN_CFG(222, GPIO)
+#define GPIO222_MSP2_TXD       PIN_CFG(222, ALT_A)
+#define GPIO222_LCD_D0         PIN_CFG(222, ALT_B)
+
+#define GPIO223_GPIO           PIN_CFG(223, GPIO)
+#define GPIO223_MSP2_RXD       PIN_CFG(223, ALT_A)
+#define GPIO223_LCD_CLK                PIN_CFG(223, ALT_B)
+
+#define GPIO224_GPIO           PIN_CFG(224, GPIO)
+#define GPIO224_PRCMU_PWRCTRL0 PIN_CFG(224, ALT_A)
+#define GPIO224_LCD_VSI1       PIN_CFG(224, ALT_B)
+
+#define GPIO225_GPIO           PIN_CFG(225, GPIO)
+#define GPIO225_PRCMU_PWRCTRL1 PIN_CFG(225, ALT_A)
+#define GPIO225_IRDA_RXD       PIN_CFG(225, ALT_B)
+
+#define GPIO226_GPIO           PIN_CFG(226, GPIO)
+#define GPIO226_PRCMU_PWRCTRL2 PIN_CFG(226, ALT_A)
+#define GPIO226_IRRC_DAT       PIN_CFG(226, ALT_B)
+
+#define GPIO227_GPIO           PIN_CFG(227, GPIO)
+#define GPIO227_IRRC_DAT       PIN_CFG(227, ALT_A)
+#define GPIO227_IRDA_TXD       PIN_CFG(227, ALT_B)
+
+#endif
index 9055d5d3233c90c906ded7b8030c54db64289839..66f8761cc823cfd5a3670c773da50b087822bb94 100644 (file)
 #define GPIO17_SLIM0_CLK       PIN_CFG(17, ALT_C)
 
 #define GPIO18_GPIO            PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR      PIN_CFG(18, ALT_A)
+#define GPIO18_MC0_CMDDIR      PIN_CFG_PULL(18, ALT_A, UP)
 #define GPIO18_U2_RXD          PIN_CFG(18, ALT_B)
 #define GPIO18_MS_IEP          PIN_CFG(18, ALT_C)
 
 #define GPIO19_GPIO            PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR     PIN_CFG(19, ALT_A)
+#define GPIO19_MC0_DAT0DIR     PIN_CFG_PULL(19, ALT_A, UP)
 #define GPIO19_U2_TXD          PIN_CFG(19, ALT_B)
 #define GPIO19_MS_DAT0DIR      PIN_CFG(19, ALT_C)
 
 #define GPIO20_GPIO            PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR     PIN_CFG(20, ALT_A)
+#define GPIO20_MC0_DAT2DIR     PIN_CFG_PULL(20, ALT_A, UP)
 #define GPIO20_UARTMOD_TXD     PIN_CFG(20, ALT_B)
 #define GPIO20_IP_TRIGOUT      PIN_CFG(20, ALT_C)
 
 #define GPIO21_GPIO            PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR    PIN_CFG(21, ALT_A)
+#define GPIO21_MC0_DAT31DIR    PIN_CFG_PULL(21, ALT_A, UP)
 #define GPIO21_MSP0_SCK                PIN_CFG(21, ALT_B)
 #define GPIO21_MS_DAT31DIR     PIN_CFG(21, ALT_C)
 
 #define GPIO22_GPIO            PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK       PIN_CFG(22, ALT_A)
+#define GPIO22_MC0_FBCLK       PIN_CFG_PULL(22, ALT_A, UP)
 #define GPIO22_UARTMOD_RXD     PIN_CFG(22, ALT_B)
 #define GPIO22_MS_FBCLK                PIN_CFG(22, ALT_C)
 
 #define GPIO23_GPIO            PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK         PIN_CFG(23, ALT_A)
+#define GPIO23_MC0_CLK         PIN_CFG_PULL(23, ALT_A, UP)
 #define GPIO23_STMMOD_CLK      PIN_CFG(23, ALT_B)
 #define GPIO23_MS_CLK          PIN_CFG(23, ALT_C)
 
 #define GPIO24_GPIO            PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD         PIN_CFG(24, ALT_A)
+#define GPIO24_MC0_CMD         PIN_CFG_PULL(24, ALT_A, UP)
 #define GPIO24_UARTMOD_RXD     PIN_CFG(24, ALT_B)
 #define GPIO24_MS_BS           PIN_CFG(24, ALT_C)
 
 #define GPIO25_GPIO            PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0                PIN_CFG(25, ALT_A)
+#define GPIO25_MC0_DAT0                PIN_CFG_PULL(25, ALT_A, UP)
 #define GPIO25_STMMOD_DAT0     PIN_CFG(25, ALT_B)
 #define GPIO25_MS_DAT0         PIN_CFG(25, ALT_C)
 
 #define GPIO26_GPIO            PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1                PIN_CFG(26, ALT_A)
+#define GPIO26_MC0_DAT1                PIN_CFG_PULL(26, ALT_A, UP)
 #define GPIO26_STMMOD_DAT1     PIN_CFG(26, ALT_B)
 #define GPIO26_MS_DAT1         PIN_CFG(26, ALT_C)
 
 #define GPIO27_GPIO            PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2                PIN_CFG(27, ALT_A)
+#define GPIO27_MC0_DAT2                PIN_CFG_PULL(27, ALT_A, UP)
 #define GPIO27_STMMOD_DAT2     PIN_CFG(27, ALT_B)
 #define GPIO27_MS_DAT2         PIN_CFG(27, ALT_C)
 
 #define GPIO28_GPIO            PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3                PIN_CFG(28, ALT_A)
+#define GPIO28_MC0_DAT3                PIN_CFG_PULL(28, ALT_A, UP)
 #define GPIO28_STMMOD_DAT3     PIN_CFG(28, ALT_B)
 #define GPIO28_MS_DAT3         PIN_CFG(28, ALT_C)
 
 #define GPIO97_MC5_DAT7                PIN_CFG(97, ALT_C)
 
 #define GPIO128_GPIO           PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK                PIN_CFG(128, ALT_A)
+#define GPIO128_MC2_CLK                PIN_CFG_PULL(128, ALT_A, UP)
 #define GPIO128_SM_CKO         PIN_CFG(128, ALT_B)
 
 #define GPIO129_GPIO           PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD                PIN_CFG(129, ALT_A)
+#define GPIO129_MC2_CMD                PIN_CFG_PULL(129, ALT_A, UP)
 #define GPIO129_SM_WAIT0n      PIN_CFG(129, ALT_B)
 
 #define GPIO130_GPIO           PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK      PIN_CFG(130, ALT_A)
+#define GPIO130_MC2_FBCLK      PIN_CFG_PULL(130, ALT_A, UP)
 #define GPIO130_SM_FBCLK       PIN_CFG(130, ALT_B)
 #define GPIO130_MC2_RSTN       PIN_CFG(130, ALT_C)
 
 #define GPIO131_GPIO           PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0       PIN_CFG(131, ALT_A)
+#define GPIO131_MC2_DAT0       PIN_CFG_PULL(131, ALT_A, UP)
 #define GPIO131_SM_ADQ8                PIN_CFG(131, ALT_B)
 
 #define GPIO132_GPIO           PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1       PIN_CFG(132, ALT_A)
+#define GPIO132_MC2_DAT1       PIN_CFG_PULL(132, ALT_A, UP)
 #define GPIO132_SM_ADQ9                PIN_CFG(132, ALT_B)
 
 #define GPIO133_GPIO           PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2       PIN_CFG(133, ALT_A)
+#define GPIO133_MC2_DAT2       PIN_CFG_PULL(133, ALT_A, UP)
 #define GPIO133_SM_ADQ10       PIN_CFG(133, ALT_B)
 
 #define GPIO134_GPIO           PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3       PIN_CFG(134, ALT_A)
+#define GPIO134_MC2_DAT3       PIN_CFG_PULL(134, ALT_A, UP)
 #define GPIO134_SM_ADQ11       PIN_CFG(134, ALT_B)
 
 #define GPIO135_GPIO           PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4       PIN_CFG(135, ALT_A)
+#define GPIO135_MC2_DAT4       PIN_CFG_PULL(135, ALT_A, UP)
 #define GPIO135_SM_ADQ12       PIN_CFG(135, ALT_B)
 
 #define GPIO136_GPIO           PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5       PIN_CFG(136, ALT_A)
+#define GPIO136_MC2_DAT5       PIN_CFG_PULL(136, ALT_A, UP)
 #define GPIO136_SM_ADQ13       PIN_CFG(136, ALT_B)
 
 #define GPIO137_GPIO           PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6       PIN_CFG(137, ALT_A)
+#define GPIO137_MC2_DAT6       PIN_CFG_PULL(137, ALT_A, UP)
 #define GPIO137_SM_ADQ14       PIN_CFG(137, ALT_B)
 
 #define GPIO138_GPIO           PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7       PIN_CFG(138, ALT_A)
+#define GPIO138_MC2_DAT7       PIN_CFG_PULL(138, ALT_A, UP)
 #define GPIO138_SM_ADQ15       PIN_CFG(138, ALT_B)
 
 #define GPIO139_GPIO           PIN_CFG(139, GPIO)
 #define GPIO196_MSP2_RXD       PIN_CFG(196, ALT_A)
 
 #define GPIO197_GPIO           PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3       PIN_CFG(197, ALT_A)
+#define GPIO197_MC4_DAT3       PIN_CFG_PULL(197, ALT_A, UP)
 
 #define GPIO198_GPIO           PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2       PIN_CFG(198, ALT_A)
+#define GPIO198_MC4_DAT2       PIN_CFG_PULL(198, ALT_A, UP)
 
 #define GPIO199_GPIO           PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1       PIN_CFG(199, ALT_A)
+#define GPIO199_MC4_DAT1       PIN_CFG_PULL(199, ALT_A, UP)
 
 #define GPIO200_GPIO           PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0       PIN_CFG(200, ALT_A)
+#define GPIO200_MC4_DAT0       PIN_CFG_PULL(200, ALT_A, UP)
 
 #define GPIO201_GPIO           PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD                PIN_CFG(201, ALT_A)
+#define GPIO201_MC4_CMD                PIN_CFG_PULL(201, ALT_A, UP)
 
 #define GPIO202_GPIO           PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK      PIN_CFG(202, ALT_A)
+#define GPIO202_MC4_FBCLK      PIN_CFG_PULL(202, ALT_A, UP)
 #define GPIO202_PWL            PIN_CFG(202, ALT_B)
 #define GPIO202_MC4_RSTN       PIN_CFG(202, ALT_C)
 
 #define GPIO203_GPIO           PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK                PIN_CFG(203, ALT_A)
+#define GPIO203_MC4_CLK                PIN_CFG_PULL(203, ALT_A, UP)
 
 #define GPIO204_GPIO           PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7       PIN_CFG(204, ALT_A)
+#define GPIO204_MC4_DAT7       PIN_CFG_PULL(204, ALT_A, UP)
 
 #define GPIO205_GPIO           PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6       PIN_CFG(205, ALT_A)
+#define GPIO205_MC4_DAT6       PIN_CFG_PULL(205, ALT_A, UP)
 
 #define GPIO206_GPIO           PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5       PIN_CFG(206, ALT_A)
+#define GPIO206_MC4_DAT5       PIN_CFG_PULL(206, ALT_A, UP)
 
 #define GPIO207_GPIO           PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4       PIN_CFG(207, ALT_A)
+#define GPIO207_MC4_DAT4       PIN_CFG_PULL(207, ALT_A, UP)
 
 #define GPIO208_GPIO           PIN_CFG(208, GPIO)
 #define GPIO208_MC1_CLK                PIN_CFG(208, ALT_A)
index 438ef16aec901e2e11a4d0b6ebb9b5bae165fb1b..9e4c678de78593a248c9010a4eb8e0edcb4cb4dc 100644 (file)
@@ -78,6 +78,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
        __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
        outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
 
+       smp_cross_call(cpumask_of(cpu));
+
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
                if (pen_release == -1)
diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c
new file mode 100644 (file)
index 0000000..293274d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) ST Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
+ * U8500 PRCMU driver.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-regs.h>
+
+#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE)
+
+#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44)
+#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4)
+
+#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
+#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
+#define REQ_MB5_I2C_REG (REQ_MB5 + 2)
+#define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
+
+#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
+#define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
+
+#define I2C_WRITE(slave) ((slave) << 1)
+#define I2C_READ(slave) (((slave) << 1) | BIT(0))
+#define I2C_STOP_EN BIT(3)
+
+enum ack_mb5_status {
+       I2C_WR_OK = 0x01,
+       I2C_RD_OK = 0x02,
+};
+
+#define MBOX_BIT BIT
+#define NUM_MBOX 8
+
+static struct {
+       struct mutex lock;
+       struct completion work;
+       bool failed;
+       struct {
+               u8 status;
+               u8 value;
+       } ack;
+} mb5_transfer;
+
+/**
+ * prcmu_abb_read() - Read register value(s) from the ABB.
+ * @slave:     The I2C slave address.
+ * @reg:       The (start) register address.
+ * @value:     The read out value(s).
+ * @size:      The number of registers to read.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       int r;
+
+       if (size != 1)
+               return -EINVAL;
+
+       r = mutex_lock_interruptible(&mb5_transfer.lock);
+       if (r)
+               return r;
+
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+               cpu_relax();
+
+       writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
+       writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+       writeb(reg, REQ_MB5_I2C_REG);
+
+       writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+       if (!wait_for_completion_timeout(&mb5_transfer.work,
+                       msecs_to_jiffies(500))) {
+               pr_err("prcmu: prcmu_abb_read timed out.\n");
+               r = -EIO;
+               goto unlock_and_return;
+       }
+       r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
+       if (!r)
+               *value = mb5_transfer.ack.value;
+
+unlock_and_return:
+       mutex_unlock(&mb5_transfer.lock);
+       return r;
+}
+EXPORT_SYMBOL(prcmu_abb_read);
+
+/**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave:     The I2C slave address.
+ * @reg:       The (start) register address.
+ * @value:     The value(s) to write.
+ * @size:      The number of registers to write.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       int r;
+
+       if (size != 1)
+               return -EINVAL;
+
+       r = mutex_lock_interruptible(&mb5_transfer.lock);
+       if (r)
+               return r;
+
+
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+               cpu_relax();
+
+       writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
+       writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+       writeb(reg, REQ_MB5_I2C_REG);
+       writeb(*value, REQ_MB5_I2C_VAL);
+
+       writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+       if (!wait_for_completion_timeout(&mb5_transfer.work,
+                       msecs_to_jiffies(500))) {
+               pr_err("prcmu: prcmu_abb_write timed out.\n");
+               r = -EIO;
+               goto unlock_and_return;
+       }
+       r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
+
+unlock_and_return:
+       mutex_unlock(&mb5_transfer.lock);
+       return r;
+}
+EXPORT_SYMBOL(prcmu_abb_write);
+
+static void read_mailbox_0(void)
+{
+       writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_1(void)
+{
+       writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_2(void)
+{
+       writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_3(void)
+{
+       writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_4(void)
+{
+       writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_5(void)
+{
+       mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
+       mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
+       complete(&mb5_transfer.work);
+       writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_6(void)
+{
+       writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_7(void)
+{
+       writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+}
+
+static void (* const read_mailbox[NUM_MBOX])(void) = {
+       read_mailbox_0,
+       read_mailbox_1,
+       read_mailbox_2,
+       read_mailbox_3,
+       read_mailbox_4,
+       read_mailbox_5,
+       read_mailbox_6,
+       read_mailbox_7
+};
+
+static irqreturn_t prcmu_irq_handler(int irq, void *data)
+{
+       u32 bits;
+       u8 n;
+
+       bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
+       if (unlikely(!bits))
+               return IRQ_NONE;
+
+       for (n = 0; bits; n++) {
+               if (bits & MBOX_BIT(n)) {
+                       bits -= MBOX_BIT(n);
+                       read_mailbox[n]();
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+static int __init prcmu_init(void)
+{
+       mutex_init(&mb5_transfer.lock);
+       init_completion(&mb5_transfer.work);
+
+       /* Clean up the mailbox interrupts after pre-kernel code. */
+       writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
+
+       return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
+}
+
+arch_initcall(prcmu_init);
diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/ste-dma40-db5500.h
new file mode 100644 (file)
index 0000000..cb2110c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * DB5500-SoC-specific configuration for DMA40
+ */
+
+#ifndef STE_DMA40_DB5500_H
+#define STE_DMA40_DB5500_H
+
+#define DB5500_DMA_NR_DEV 64
+
+enum dma_src_dev_type {
+       DB5500_DMA_DEV0_SPI0_RX = 0,
+       DB5500_DMA_DEV1_SPI1_RX = 1,
+       DB5500_DMA_DEV2_SPI2_RX = 2,
+       DB5500_DMA_DEV3_SPI3_RX = 3,
+       DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4,
+       DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5,
+       DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6,
+       DB5500_DMA_DEV7_IRDA_RFS = 7,
+       DB5500_DMA_DEV8_IRDA_FIFO_RX = 8,
+       DB5500_DMA_DEV9_MSP0_RX = 9,
+       DB5500_DMA_DEV10_MSP1_RX = 10,
+       DB5500_DMA_DEV11_MSP2_RX = 11,
+       DB5500_DMA_DEV12_UART0_RX = 12,
+       DB5500_DMA_DEV13_UART1_RX = 13,
+       DB5500_DMA_DEV14_UART2_RX = 14,
+       DB5500_DMA_DEV15_UART3_RX = 15,
+       DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16,
+       DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17,
+       DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18,
+       DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19,
+       DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20,
+       DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21,
+       DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22,
+       DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23,
+       DB5500_DMA_DEV24_SDMMC0_RX = 24,
+       DB5500_DMA_DEV25_SDMMC1_RX = 25,
+       DB5500_DMA_DEV26_SDMMC2_RX = 26,
+       DB5500_DMA_DEV27_SDMMC3_RX = 27,
+       DB5500_DMA_DEV28_SDMMC4_RX = 28,
+       /* 29 - 32 not used */
+       DB5500_DMA_DEV33_SDMMC0_RX = 33,
+       DB5500_DMA_DEV34_SDMMC1_RX = 34,
+       DB5500_DMA_DEV35_SDMMC2_RX = 35,
+       DB5500_DMA_DEV36_SDMMC3_RX = 36,
+       DB5500_DMA_DEV37_SDMMC4_RX = 37,
+       DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38,
+       DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39,
+       DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40,
+       DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41,
+       DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42,
+       DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43,
+       DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44,
+       DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45,
+       /* 46 not used */
+       DB5500_DMA_DEV47_MCDE_RX = 47,
+       DB5500_DMA_DEV48_CRYPTO1_RX = 48,
+       /* 49, 50 not used */
+       DB5500_DMA_DEV49_I2C1_RX = 51,
+       DB5500_DMA_DEV50_I2C3_RX = 52,
+       DB5500_DMA_DEV51_I2C2_RX = 53,
+       /* 54 - 60 not used */
+       DB5500_DMA_DEV61_CRYPTO0_RX = 61,
+       /* 62, 63 not used */
+};
+
+enum dma_dest_dev_type {
+       DB5500_DMA_DEV0_SPI0_TX = 0,
+       DB5500_DMA_DEV1_SPI1_TX = 1,
+       DB5500_DMA_DEV2_SPI2_TX = 2,
+       DB5500_DMA_DEV3_SPI3_TX = 3,
+       DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4,
+       DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5,
+       DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6,
+       DB5500_DMA_DEV7_IRRC_TX = 7,
+       DB5500_DMA_DEV8_IRDA_FIFO_TX = 8,
+       DB5500_DMA_DEV9_MSP0_TX = 9,
+       DB5500_DMA_DEV10_MSP1_TX = 10,
+       DB5500_DMA_DEV11_MSP2_TX = 11,
+       DB5500_DMA_DEV12_UART0_TX = 12,
+       DB5500_DMA_DEV13_UART1_TX = 13,
+       DB5500_DMA_DEV14_UART2_TX = 14,
+       DB5500_DMA_DEV15_UART3_TX = 15,
+       DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16,
+       DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17,
+       DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18,
+       DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19,
+       DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20,
+       DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21,
+       DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22,
+       DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23,
+       DB5500_DMA_DEV24_SDMMC0_TX = 24,
+       DB5500_DMA_DEV25_SDMMC1_TX = 25,
+       DB5500_DMA_DEV26_SDMMC2_TX = 26,
+       DB5500_DMA_DEV27_SDMMC3_TX = 27,
+       DB5500_DMA_DEV28_SDMMC4_TX = 28,
+       /* 29 - 31 not used */
+       DB5500_DMA_DEV32_FSMC_TX = 32,
+       DB5500_DMA_DEV33_SDMMC0_TX = 33,
+       DB5500_DMA_DEV34_SDMMC1_TX = 34,
+       DB5500_DMA_DEV35_SDMMC2_TX = 35,
+       DB5500_DMA_DEV36_SDMMC3_TX = 36,
+       DB5500_DMA_DEV37_SDMMC4_TX = 37,
+       DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38,
+       DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39,
+       DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40,
+       DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41,
+       DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42,
+       DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43,
+       DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44,
+       DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45,
+       /* 46 not used */
+       DB5500_DMA_DEV47_STM_TX = 47,
+       DB5500_DMA_DEV48_CRYPTO1_TX = 48,
+       DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49,
+       DB5500_DMA_DEV50_HASH1_TX = 50,
+       DB5500_DMA_DEV51_I2C1_TX = 51,
+       DB5500_DMA_DEV52_I2C3_TX = 52,
+       DB5500_DMA_DEV53_I2C2_TX = 53,
+       /* 54, 55 not used */
+       DB5500_DMA_MEMCPY_TX_1 = 56,
+       DB5500_DMA_MEMCPY_TX_2 = 57,
+       DB5500_DMA_MEMCPY_TX_3 = 58,
+       DB5500_DMA_MEMCPY_TX_4 = 59,
+       DB5500_DMA_MEMCPY_TX_5 = 60,
+       DB5500_DMA_DEV61_CRYPTO0_TX = 61,
+       DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62,
+       DB5500_DMA_DEV63_HASH0_TX = 63,
+};
+
+#endif
index 9d9d3797b3b05a5cae83affcfe7817912b7bf651..a616419bea76f3f529578e86cd970a1528ee77ab 100644 (file)
 #ifndef STE_DMA40_DB8500_H
 #define STE_DMA40_DB8500_H
 
-#define STEDMA40_NR_DEV 64
+#define DB8500_DMA_NR_DEV 64
 
 enum dma_src_dev_type {
-       STEDMA40_DEV_SPI0_RX = 0,
-       STEDMA40_DEV_SD_MMC0_RX = 1,
-       STEDMA40_DEV_SD_MMC1_RX = 2,
-       STEDMA40_DEV_SD_MMC2_RX = 3,
-       STEDMA40_DEV_I2C1_RX = 4,
-       STEDMA40_DEV_I2C3_RX = 5,
-       STEDMA40_DEV_I2C2_RX = 6,
-       STEDMA40_DEV_I2C4_RX = 7, /* Only on V1 */
-       STEDMA40_DEV_SSP0_RX = 8,
-       STEDMA40_DEV_SSP1_RX = 9,
-       STEDMA40_DEV_MCDE_RX = 10,
-       STEDMA40_DEV_UART2_RX = 11,
-       STEDMA40_DEV_UART1_RX = 12,
-       STEDMA40_DEV_UART0_RX = 13,
-       STEDMA40_DEV_MSP2_RX = 14,
-       STEDMA40_DEV_I2C0_RX = 15,
-       STEDMA40_DEV_USB_OTG_IEP_8 = 16,
-       STEDMA40_DEV_USB_OTG_IEP_1_9 = 17,
-       STEDMA40_DEV_USB_OTG_IEP_2_10 = 18,
-       STEDMA40_DEV_USB_OTG_IEP_3_11 = 19,
-       STEDMA40_DEV_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
-       STEDMA40_DEV_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
-       STEDMA40_DEV_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
-       STEDMA40_DEV_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
-       STEDMA40_DEV_SRC_SXA0_RX_TX = 24,
-       STEDMA40_DEV_SRC_SXA1_RX_TX = 25,
-       STEDMA40_DEV_SRC_SXA2_RX_TX = 26,
-       STEDMA40_DEV_SRC_SXA3_RX_TX = 27,
-       STEDMA40_DEV_SD_MM2_RX = 28,
-       STEDMA40_DEV_SD_MM0_RX = 29,
-       STEDMA40_DEV_MSP1_RX = 30,
-       /*
-        * This channel is either SlimBus or MSP,
-        * never both at the same time.
-        */
-       STEDMA40_SLIM0_CH0_RX = 31,
-       STEDMA40_DEV_MSP0_RX = 31,
-       STEDMA40_DEV_SD_MM1_RX = 32,
-       STEDMA40_DEV_SPI2_RX = 33,
-       STEDMA40_DEV_I2C3_RX2 = 34,
-       STEDMA40_DEV_SPI1_RX = 35,
-       STEDMA40_DEV_USB_OTG_IEP_4_12 = 36,
-       STEDMA40_DEV_USB_OTG_IEP_5_13 = 37,
-       STEDMA40_DEV_USB_OTG_IEP_6_14 = 38,
-       STEDMA40_DEV_USB_OTG_IEP_7_15 = 39,
-       STEDMA40_DEV_SPI3_RX = 40,
-       STEDMA40_DEV_SD_MM3_RX = 41,
-       STEDMA40_DEV_SD_MM4_RX = 42,
-       STEDMA40_DEV_SD_MM5_RX = 43,
-       STEDMA40_DEV_SRC_SXA4_RX_TX = 44,
-       STEDMA40_DEV_SRC_SXA5_RX_TX = 45,
-       STEDMA40_DEV_SRC_SXA6_RX_TX = 46,
-       STEDMA40_DEV_SRC_SXA7_RX_TX = 47,
-       STEDMA40_DEV_CAC1_RX = 48,
-       /* RX channels 49 and 50 are unused */
-       STEDMA40_DEV_MSHC_RX = 51,
-       STEDMA40_DEV_SLIM1_CH0_RX_HSI_RX_CH4 = 52,
-       STEDMA40_DEV_SLIM1_CH1_RX_HSI_RX_CH5 = 53,
-       STEDMA40_DEV_SLIM1_CH2_RX_HSI_RX_CH6 = 54,
-       STEDMA40_DEV_SLIM1_CH3_RX_HSI_RX_CH7 = 55,
-       /* RX channels 56 thru 60 are unused */
-       STEDMA40_DEV_CAC0_RX = 61,
-       /* RX channels 62 and 63 are unused */
+       DB8500_DMA_DEV0_SPI0_RX = 0,
+       DB8500_DMA_DEV1_SD_MMC0_RX = 1,
+       DB8500_DMA_DEV2_SD_MMC1_RX = 2,
+       DB8500_DMA_DEV3_SD_MMC2_RX = 3,
+       DB8500_DMA_DEV4_I2C1_RX = 4,
+       DB8500_DMA_DEV5_I2C3_RX = 5,
+       DB8500_DMA_DEV6_I2C2_RX = 6,
+       DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */
+       DB8500_DMA_DEV8_SSP0_RX = 8,
+       DB8500_DMA_DEV9_SSP1_RX = 9,
+       DB8500_DMA_DEV10_MCDE_RX = 10,
+       DB8500_DMA_DEV11_UART2_RX = 11,
+       DB8500_DMA_DEV12_UART1_RX = 12,
+       DB8500_DMA_DEV13_UART0_RX = 13,
+       DB8500_DMA_DEV14_MSP2_RX = 14,
+       DB8500_DMA_DEV15_I2C0_RX = 15,
+       DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16,
+       DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17,
+       DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18,
+       DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19,
+       DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
+       DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
+       DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
+       DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
+       DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24,
+       DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25,
+       DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26,
+       DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27,
+       DB8500_DMA_DEV28_SD_MM2_RX = 28,
+       DB8500_DMA_DEV29_SD_MM0_RX = 29,
+       DB8500_DMA_DEV30_MSP1_RX = 30,
+       /* On DB8500v2, MSP3 RX replaces MSP1 RX */
+       DB8500_DMA_DEV30_MSP3_RX = 30,
+       DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31,
+       DB8500_DMA_DEV32_SD_MM1_RX = 32,
+       DB8500_DMA_DEV33_SPI2_RX = 33,
+       DB8500_DMA_DEV34_I2C3_RX2 = 34,
+       DB8500_DMA_DEV35_SPI1_RX = 35,
+       DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36,
+       DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37,
+       DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38,
+       DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39,
+       DB8500_DMA_DEV40_SPI3_RX = 40,
+       DB8500_DMA_DEV41_SD_MM3_RX = 41,
+       DB8500_DMA_DEV42_SD_MM4_RX = 42,
+       DB8500_DMA_DEV43_SD_MM5_RX = 43,
+       DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44,
+       DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45,
+       DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46,
+       DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47,
+       DB8500_DMA_DEV48_CAC1_RX = 48,
+       /* 49, 50 and 51 are not used */
+       DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52,
+       DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53,
+       DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54,
+       DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55,
+       /* 56, 57, 58, 59 and 60 are not used */
+       DB8500_DMA_DEV61_CAC0_RX = 61,
+       /* 62 and 63 are not used */
 };
 
 enum dma_dest_dev_type {
-       STEDMA40_DEV_SPI0_TX = 0,
-       STEDMA40_DEV_SD_MMC0_TX = 1,
-       STEDMA40_DEV_SD_MMC1_TX = 2,
-       STEDMA40_DEV_SD_MMC2_TX = 3,
-       STEDMA40_DEV_I2C1_TX = 4,
-       STEDMA40_DEV_I2C3_TX = 5,
-       STEDMA40_DEV_I2C2_TX = 6,
-       STEDMA50_DEV_I2C4_TX = 7, /* Only on V1 */
-       STEDMA40_DEV_SSP0_TX = 8,
-       STEDMA40_DEV_SSP1_TX = 9,
-       /* TX channel 10 is unused */
-       STEDMA40_DEV_UART2_TX = 11,
-       STEDMA40_DEV_UART1_TX = 12,
-       STEDMA40_DEV_UART0_TX= 13,
-       STEDMA40_DEV_MSP2_TX = 14,
-       STEDMA40_DEV_I2C0_TX = 15,
-       STEDMA40_DEV_USB_OTG_OEP_8 = 16,
-       STEDMA40_DEV_USB_OTG_OEP_1_9 = 17,
-       STEDMA40_DEV_USB_OTG_OEP_2_10= 18,
-       STEDMA40_DEV_USB_OTG_OEP_3_11 = 19,
-       STEDMA40_DEV_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
-       STEDMA40_DEV_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
-       STEDMA40_DEV_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
-       STEDMA40_DEV_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
-       STEDMA40_DEV_DST_SXA0_RX_TX = 24,
-       STEDMA40_DEV_DST_SXA1_RX_TX = 25,
-       STEDMA40_DEV_DST_SXA2_RX_TX = 26,
-       STEDMA40_DEV_DST_SXA3_RX_TX = 27,
-       STEDMA40_DEV_SD_MM2_TX = 28,
-       STEDMA40_DEV_SD_MM0_TX = 29,
-       STEDMA40_DEV_MSP1_TX = 30,
-       /*
-        * This channel is either SlimBus or MSP,
-        * never both at the same time.
-        */
-       STEDMA40_SLIM0_CH0_TX = 31,
-       STEDMA40_DEV_MSP0_TX = 31,
-       STEDMA40_DEV_SD_MM1_TX = 32,
-       STEDMA40_DEV_SPI2_TX = 33,
-       /* Secondary I2C3 channel */
-       STEDMA40_DEV_I2C3_TX2 = 34,
-       STEDMA40_DEV_SPI1_TX = 35,
-       STEDMA40_DEV_USB_OTG_OEP_4_12 = 36,
-       STEDMA40_DEV_USB_OTG_OEP_5_13 = 37,
-       STEDMA40_DEV_USB_OTG_OEP_6_14 = 38,
-       STEDMA40_DEV_USB_OTG_OEP_7_15 = 39,
-       STEDMA40_DEV_SPI3_TX = 40,
-       STEDMA40_DEV_SD_MM3_TX = 41,
-       STEDMA40_DEV_SD_MM4_TX = 42,
-       STEDMA40_DEV_SD_MM5_TX = 43,
-       STEDMA40_DEV_DST_SXA4_RX_TX = 44,
-       STEDMA40_DEV_DST_SXA5_RX_TX = 45,
-       STEDMA40_DEV_DST_SXA6_RX_TX = 46,
-       STEDMA40_DEV_DST_SXA7_RX_TX = 47,
-       STEDMA40_DEV_CAC1_TX = 48,
-       STEDMA40_DEV_CAC1_TX_HAC1_TX = 49,
-       STEDMA40_DEV_HAC1_TX = 50,
-       STEDMA40_MEMCPY_TX_0 = 51,
-       STEDMA40_DEV_SLIM1_CH0_TX_HSI_TX_CH4 = 52,
-       STEDMA40_DEV_SLIM1_CH1_TX_HSI_TX_CH5 = 53,
-       STEDMA40_DEV_SLIM1_CH2_TX_HSI_TX_CH6 = 54,
-       STEDMA40_DEV_SLIM1_CH3_TX_HSI_TX_CH7 = 55,
-       STEDMA40_MEMCPY_TX_1 = 56,
-       STEDMA40_MEMCPY_TX_2 = 57,
-       STEDMA40_MEMCPY_TX_3 = 58,
-       STEDMA40_MEMCPY_TX_4 = 59,
-       STEDMA40_MEMCPY_TX_5 = 60,
-       STEDMA40_DEV_CAC0_TX = 61,
-       STEDMA40_DEV_CAC0_TX_HAC0_TX = 62,
-       STEDMA40_DEV_HAC0_TX = 63,
+       DB8500_DMA_DEV0_SPI0_TX = 0,
+       DB8500_DMA_DEV1_SD_MMC0_TX = 1,
+       DB8500_DMA_DEV2_SD_MMC1_TX = 2,
+       DB8500_DMA_DEV3_SD_MMC2_TX = 3,
+       DB8500_DMA_DEV4_I2C1_TX = 4,
+       DB8500_DMA_DEV5_I2C3_TX = 5,
+       DB8500_DMA_DEV6_I2C2_TX = 6,
+       DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */
+       DB8500_DMA_DEV8_SSP0_TX = 8,
+       DB8500_DMA_DEV9_SSP1_TX = 9,
+       /* 10 is not used*/
+       DB8500_DMA_DEV11_UART2_TX = 11,
+       DB8500_DMA_DEV12_UART1_TX = 12,
+       DB8500_DMA_DEV13_UART0_TX = 13,
+       DB8500_DMA_DEV14_MSP2_TX = 14,
+       DB8500_DMA_DEV15_I2C0_TX = 15,
+       DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16,
+       DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17,
+       DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18,
+       DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19,
+       DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
+       DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
+       DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
+       DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
+       DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24,
+       DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25,
+       DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26,
+       DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27,
+       DB8500_DMA_DEV28_SD_MM2_TX = 28,
+       DB8500_DMA_DEV29_SD_MM0_TX = 29,
+       DB8500_DMA_DEV30_MSP1_TX = 30,
+       DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31,
+       DB8500_DMA_DEV32_SD_MM1_TX = 32,
+       DB8500_DMA_DEV33_SPI2_TX = 33,
+       DB8500_DMA_DEV34_I2C3_TX2 = 34,
+       DB8500_DMA_DEV35_SPI1_TX = 35,
+       DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36,
+       DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37,
+       DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38,
+       DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39,
+       DB8500_DMA_DEV40_SPI3_TX = 40,
+       DB8500_DMA_DEV41_SD_MM3_TX = 41,
+       DB8500_DMA_DEV42_SD_MM4_TX = 42,
+       DB8500_DMA_DEV43_SD_MM5_TX = 43,
+       DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44,
+       DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45,
+       DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46,
+       DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47,
+       DB8500_DMA_DEV48_CAC1_TX  = 48,
+       DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49,
+       DB8500_DMA_DEV50_HAC1_TX = 50,
+       DB8500_DMA_MEMCPY_TX_0 = 51,
+       DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52,
+       DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53,
+       DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54,
+       DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55,
+       DB8500_DMA_MEMCPY_TX_1 = 56,
+       DB8500_DMA_MEMCPY_TX_2 = 57,
+       DB8500_DMA_MEMCPY_TX_3 = 58,
+       DB8500_DMA_MEMCPY_TX_4 = 59,
+       DB8500_DMA_MEMCPY_TX_5 = 60,
+       DB8500_DMA_DEV61_CAC0_TX = 61,
+       DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62,
+       DB8500_DMA_DEV63_HAC0_TX = 63,
 };
 
 #endif
index 6fea7199c626742d4e39afcaadecd5e32ad39e99..eb2cf7dc5c4410e2b92f13a9e508a2b7bdd2bff5 100644 (file)
  *
 */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx,      #0x10000000
-               movne   \rx,      #0xf1000000   @ virtual base
-               orr     \rx, \rx, #0x001F0000
-               orr     \rx, \rx, #0x00001000
+               .macro  addruart, rp, rv
+               mov     \rp,      #0x001F0000
+               orr     \rp, \rp, #0x00001000
+               orr     \rv, \rp, #0xf1000000   @ virtual base
+               orr     \rp, \rp,  #0x10000000  @ physical base
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index 427e3612db5d1f48202cae06b310c1b9f5f03477..ebd8a2543d3b811f5be94118e1c9c9798f134275 100644 (file)
@@ -18,4 +18,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END            (PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END            0xd8000000
index bb8ec7724f79b3cc27a3dc40bf2b6efb5d11736c..aa9730fb13bfa287efcf8c53161da1bd97e6cf20 100644 (file)
@@ -35,8 +35,6 @@
 
 MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = 0x101f1000,
-       .io_pg_offst    = ((0xf11f1000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = versatile_map_io,
        .init_irq       = versatile_init_irq,
index 239cd30fc4f5abea904735789b41de7a02d34167..bf469642a3f811c9032dc34358d8f9ef556ffa10 100644 (file)
@@ -108,8 +108,6 @@ static void __init versatile_pb_init(void)
 
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = 0x101f1000,
-       .io_pg_offst    = ((0xf11f1000) >> 18) & 0xfffc,
        .boot_params    = 0x00000100,
        .map_io         = versatile_map_io,
        .init_irq       = versatile_init_irq,
index 577df6cccb0891503bf0188f3c0f33103c159000..c2e405a9e0256141d62dfad2f359bfa7bac87555 100644 (file)
@@ -68,7 +68,7 @@ static void __init ct_ca9x4_init_irq(void)
 }
 
 #if 0
-static void ct_ca9x4_timer_init(void)
+static void __init ct_ca9x4_timer_init(void)
 {
        writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
        writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
@@ -222,12 +222,18 @@ static struct platform_device pmu_device = {
        .resource       = pmu_resources,
 };
 
-static void ct_ca9x4_init(void)
+static void __init ct_ca9x4_init(void)
 {
        int i;
 
 #ifdef CONFIG_CACHE_L2X0
-       l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff);
+       void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC);
+
+       /* set RAM latencies to 1 cycle for this core tile. */
+       writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
+       writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+       l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
@@ -239,8 +245,6 @@ static void ct_ca9x4_init(void)
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-       .phys_io        = V2M_UART0 & SECTION_MASK,
-       .io_pg_offst    = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .map_io         = ct_ca9x4_map_io,
        .init_irq       = ct_ca9x4_init_irq,
index 5167e2aceeba9f8a070db5c8b91b3c0936f4f59f..050d65e02a42a9dc4e6923bde6eb474a9a7da41a 100644 (file)
 
 #define DEBUG_LL_UART_OFFSET   0x00009000
 
-               .macro  addruart,rx,tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx,      #0x10000000
-               movne   \rx,      #0xf8000000   @ virtual base
-               orr     \rx, \rx, #DEBUG_LL_UART_OFFSET
+               .macro  addruart,rp,rv
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rv, \rp, #0xf8000000   @ virtual base
+               orr     \rp, \rp, #0x10000000   @ physical base
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
index 72a9621ed087369eb265de17535e3d34d3693326..5a6da4fd247e86268c660d82ff8c4a4325021ffa 100644 (file)
@@ -2,14 +2,7 @@
 #define __MACH_SMP_H
 
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()                                \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x0F;                         \
-       })
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
index 817f0ad38a0b5100ec0884e8c908c84af471bec4..7eaa232180a5ae627c3639ba642755444a5d3e27 100644 (file)
@@ -48,7 +48,7 @@ void __init v2m_map_io(struct map_desc *tile, size_t num)
 }
 
 
-static void v2m_timer_init(void)
+static void __init v2m_timer_init(void)
 {
        writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
        writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
index ec05bda946f315d4bf5ebb5ae8d6d616f4a4d60d..30fccde94fb89f8e29939b67261695db3bc9da3b 100644 (file)
@@ -34,8 +34,6 @@ static void __init nuc910evb_init(void)
 
 MACHINE_START(W90P910EVB, "W90P910EVB")
        /* Maintainer: Wan ZongShun */
-       .phys_io        = W90X900_PA_UART,
-       .io_pg_offst    = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
        .boot_params    = 0,
        .map_io         = nuc910evb_map_io,
        .init_irq       = nuc900_init_irq,
index 04d295f89eb049f86ed0b8c6ba8386c5d0c0c09e..590c99b96dc18170a3df165c45e66b60338e5626 100644 (file)
@@ -37,8 +37,6 @@ static void __init nuc950evb_init(void)
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
        /* Maintainer: Wan ZongShun */
-       .phys_io        = W90X900_PA_UART,
-       .io_pg_offst    = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
        .boot_params    = 0,
        .map_io         = nuc950evb_map_io,
        .init_irq       = nuc900_init_irq,
index e3a46f19f2bc593e90af6f443033dab59612f1de..e09c645d61b6a1ea06db9d79f25e1d654aee91db 100644 (file)
@@ -34,8 +34,6 @@ static void __init nuc960evb_init(void)
 
 MACHINE_START(W90N960EVB, "W90N960EVB")
        /* Maintainer: Wan ZongShun */
-       .phys_io        = W90X900_PA_UART,
-       .io_pg_offst    = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
        .boot_params    = 0,
        .map_io         = nuc960evb_map_io,
        .init_irq       = nuc900_init_irq,
index 33c3f570aaa06c2a56f6a6d70eb7f558a883b0b1..a0a2928ae4dd7670a1342863040791833b57dbab 100644 (file)
@@ -398,7 +398,7 @@ config CPU_V6
 # ARMv6k
 config CPU_32v6K
        bool "Support ARM V6K processor extensions" if !SMP
-       depends on CPU_V6
+       depends on CPU_V6 || CPU_V7
        default y if SMP && !(ARCH_MX3 || ARCH_OMAP2)
        help
          Say Y here if your ARMv6 processor supports the 'K' extension.
index d073b64ae87ec4f6652c67959244292dbb3e69ad..724ba3bce72c952ff44645d2a50e5566b568c943 100644 (file)
@@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
        if (ai_usermode & UM_SIGNAL)
                force_sig(SIGBUS, current);
-       else
-               set_cr(cr_no_alignment);
+       else {
+               /*
+                * We're about to disable the alignment trap and return to
+                * user space.  But if an interrupt occurs before actually
+                * reaching user space, then the IRQ vector entry code will
+                * notice that we were still in kernel space and therefore
+                * the alignment trap won't be re-enabled in that case as it
+                * is presumed to be always on from kernel space.
+                * Let's prevent that race by disabling interrupts here (they
+                * are disabled on the way back to user space anyway in
+                * entry-common.S) and disable the alignment trap only if
+                * there is no work pending for this thread.
+                */
+               raw_local_irq_disable();
+               if (!(current_thread_info()->flags & _TIF_WORK_MASK))
+                       set_cr(cr_no_alignment);
+       }
 
        return 0;
 }
index 86aa689ef1aa2f6b53cf84a717427df11a25ce1e..99fa688dfadd305113670aa48ea185a9899f8e5b 100644 (file)
 #define D_CACHE_LINE_SIZE      32
 #define BTB_FLUSH_SIZE         8
 
-#ifdef CONFIG_ARM_ERRATA_411920
 /*
- * Invalidate the entire I cache (this code is a workaround for the ARM1136
- * erratum 411920 - Invalidate Instruction Cache operation can fail. This
- * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
+ *     v6_flush_icache_all()
+ *
+ *     Flush the whole I-cache.
  *
- * Registers:
- *   r0 - set to 0
- *   r1 - corrupted
+ *     ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail.
+ *     This erratum is present in 1136, 1156 and 1176. It does not affect the
+ *     MPCore.
+ *
+ *     Registers:
+ *     r0 - set to 0
+ *     r1 - corrupted
  */
-ENTRY(v6_icache_inval_all)
+ENTRY(v6_flush_icache_all)
        mov     r0, #0
+#ifdef CONFIG_ARM_ERRATA_411920
        mrs     r1, cpsr
        cpsid   ifa                             @ disable interrupts
        mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
@@ -43,8 +47,11 @@ ENTRY(v6_icache_inval_all)
        .rept   11                              @ ARM Ltd recommends at least
        nop                                     @ 11 NOPs
        .endr
-       mov     pc, lr
+#else
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I-cache
 #endif
+       mov     pc, lr
+ENDPROC(v6_flush_icache_all)
 
 /*
  *     v6_flush_cache_all()
@@ -60,7 +67,7 @@ ENTRY(v6_flush_kern_cache_all)
 #ifndef CONFIG_ARM_ERRATA_411920
        mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
 #else
-       b       v6_icache_inval_all
+       b       v6_flush_icache_all
 #endif
 #else
        mcr     p15, 0, r0, c7, c15, 0          @ Cache clean+invalidate
@@ -138,7 +145,7 @@ ENTRY(v6_coherent_user_range)
 #ifndef CONFIG_ARM_ERRATA_411920
        mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
 #else
-       b       v6_icache_inval_all
+       b       v6_flush_icache_all
 #endif
 #else
        mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
@@ -312,6 +319,7 @@ ENDPROC(v6_dma_unmap_area)
 
        .type   v6_cache_fns, #object
 ENTRY(v6_cache_fns)
+       .long   v6_flush_icache_all
        .long   v6_flush_kern_cache_all
        .long   v6_flush_user_cache_all
        .long   v6_flush_user_cache_range
index 37c8157e116e8aa54dc8cdf4ffddf1e4f8bda0f3..a3ebf7a4f49b2b404da115a58e7fdf6923792625 100644 (file)
 
 #include "proc-macros.S"
 
+/*
+ *     v7_flush_icache_all()
+ *
+ *     Flush the whole I-cache.
+ *
+ *     Registers:
+ *     r0 - set to 0
+ */
+ENTRY(v7_flush_icache_all)
+       mov     r0, #0
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 0)          @ invalidate I-cache inner shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 0)          @ I+BTB cache invalidate
+       mov     pc, lr
+ENDPROC(v7_flush_icache_all)
+
 /*
  *     v7_flush_dcache_all()
  *
@@ -91,11 +106,8 @@ ENTRY(v7_flush_kern_cache_all)
  THUMB(        stmfd   sp!, {r4-r7, r9-r11, lr}        )
        bl      v7_flush_dcache_all
        mov     r0, #0
-#ifdef CONFIG_SMP
-       mcr     p15, 0, r0, c7, c1, 0           @ invalidate I-cache inner shareable
-#else
-       mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
-#endif
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 0)  @ invalidate I-cache inner shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 0)  @ I+BTB cache invalidate
  ARM(  ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
  THUMB(        ldmfd   sp!, {r4-r7, r9-r11, lr}        )
        mov     pc, lr
@@ -171,11 +183,8 @@ ENTRY(v7_coherent_user_range)
        cmp     r0, r1
        blo     1b
        mov     r0, #0
-#ifdef CONFIG_SMP
-       mcr     p15, 0, r0, c7, c1, 6           @ invalidate BTB Inner Shareable
-#else
-       mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
-#endif
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 6)  @ invalidate BTB Inner Shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 6)  @ invalidate BTB
        dsb
        isb
        mov     pc, lr
@@ -309,6 +318,7 @@ ENDPROC(v7_dma_unmap_area)
 
        .type   v7_cache_fns, #object
 ENTRY(v7_cache_fns)
+       .long   v7_flush_icache_all
        .long   v7_flush_kern_cache_all
        .long   v7_flush_user_cache_all
        .long   v7_flush_user_cache_range
index 598c51ad50717f28d00202a9f8fd185b6a58b6a8..b8061519ce776b7dbc049815c4fbff21daa073ef 100644 (file)
@@ -73,7 +73,7 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
 {
        void *kto = kmap_atomic(to, KM_USER1);
 
-       if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+       if (!test_and_set_bit(PG_dcache_clean, &from->flags))
                __flush_dcache_page(page_mapping(from), from);
 
        spin_lock(&minicache_lock);
index f55fa1044f72b829d0c307683f9ab12d768a4893..bdba6c65c901a1c682f1aaf0fce3875ad8fa448b 100644 (file)
@@ -79,7 +79,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
        unsigned int offset = CACHE_COLOUR(vaddr);
        unsigned long kfrom, kto;
 
-       if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+       if (!test_and_set_bit(PG_dcache_clean, &from->flags))
                __flush_dcache_page(page_mapping(from), from);
 
        /* FIXME: not highmem safe */
index 9920c0ae2096cc2c6b8c9e535dc63ab5d400afb0..649bbcd325bffb27b263d0e43a484cc279c12a05 100644 (file)
@@ -95,7 +95,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 {
        void *kto = kmap_atomic(to, KM_USER1);
 
-       if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+       if (!test_and_set_bit(PG_dcache_clean, &from->flags))
                __flush_dcache_page(page_mapping(from), from);
 
        spin_lock(&minicache_lock);
index c704eed63c5ddba4c5f849f7ab7b6420008cef21..e4dd0646e85978b89a164c40100d0561bd1005f7 100644 (file)
@@ -229,6 +229,8 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
                        }
                } while (size -= PAGE_SIZE);
 
+               dsb();
+
                return (void *)c->vm_start;
        }
        return NULL;
@@ -521,6 +523,12 @@ void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
                outer_inv_range(paddr, paddr + size);
 
        dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+
+       /*
+        * Mark the D-cache clean for this page to avoid extra flushing.
+        */
+       if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
+               set_bit(PG_dcache_clean, &page->flags);
 }
 EXPORT_SYMBOL(___dma_page_dev_to_cpu);
 
index 9b906dec1ca1abc0ec308472dc39a7684c6c3b01..8440d952ba6dd1266628678f016bdf5f41a3002a 100644 (file)
@@ -28,6 +28,7 @@
 
 static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;
 
+#if __LINUX_ARM_ARCH__ < 6
 /*
  * We take the easy way out of this problem - we make the
  * PTE uncacheable.  However, we leave the write buffer on.
@@ -141,7 +142,7 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
  * a page table, or changing an existing PTE.  Basically, there are two
  * things that we need to take care of:
  *
- *  1. If PG_dcache_dirty is set for the page, we need to ensure
+ *  1. If PG_dcache_clean is not set for the page, we need to ensure
  *     that any cache entries for the kernels virtual memory
  *     range are written back to the page.
  *  2. If we have multiple shared mappings of the same space in
@@ -168,10 +169,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
                return;
 
        mapping = page_mapping(page);
-#ifndef CONFIG_SMP
-       if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+       if (!test_and_set_bit(PG_dcache_clean, &page->flags))
                __flush_dcache_page(mapping, page);
-#endif
        if (mapping) {
                if (cache_is_vivt())
                        make_coherent(mapping, vma, addr, ptep, pfn);
@@ -179,6 +178,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
                        __flush_icache_all();
        }
 }
+#endif /* __LINUX_ARM_ARCH__ < 6 */
 
 /*
  * Check whether the write buffer has physical address aliasing
index 23b0b03af5ea84b8a01e10c59a97091d92f4618b..1e21e125fe3a833fadcc932c8fcf01177d7ba8f2 100644 (file)
@@ -581,6 +581,19 @@ static struct fsr_info ifsr_info[] = {
        { do_bad,               SIGBUS,  0,             "unknown 31"                       },
 };
 
+void __init
+hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
+                int sig, int code, const char *name)
+{
+       if (nr < 0 || nr >= ARRAY_SIZE(ifsr_info))
+               BUG();
+
+       ifsr_info[nr].fn   = fn;
+       ifsr_info[nr].sig  = sig;
+       ifsr_info[nr].code = code;
+       ifsr_info[nr].name = name;
+}
+
 asmlinkage void __exception
 do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
 {
index c6844cb9b508dde69c49af40bb0d2956b126b8d3..391ffae750986404df8658d53e93fdc69b970ba4 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/smp_plat.h>
 #include <asm/system.h>
 #include <asm/tlbflush.h>
+#include <asm/smp_plat.h>
 
 #include "mm.h"
 
@@ -39,6 +40,18 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
            : "cc");
 }
 
+static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
+{
+       unsigned long colour = CACHE_COLOUR(vaddr);
+       unsigned long offset = vaddr & (PAGE_SIZE - 1);
+       unsigned long to;
+
+       set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0);
+       to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset;
+       flush_tlb_kernel_page(to);
+       flush_icache_range(to, to + len);
+}
+
 void flush_cache_mm(struct mm_struct *mm)
 {
        if (cache_is_vivt()) {
@@ -89,16 +102,16 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
        if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())
                __flush_icache_all();
 }
+
 #else
-#define flush_pfn_alias(pfn,vaddr)     do { } while (0)
+#define flush_pfn_alias(pfn,vaddr)             do { } while (0)
+#define flush_icache_alias(pfn,vaddr,len)      do { } while (0)
 #endif
 
-#ifdef CONFIG_SMP
 static void flush_ptrace_access_other(void *args)
 {
        __flush_icache_all();
 }
-#endif
 
 static
 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
@@ -118,15 +131,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
                return;
        }
 
-       /* VIPT non-aliasing cache */
+       /* VIPT non-aliasing D-cache */
        if (vma->vm_flags & VM_EXEC) {
                unsigned long addr = (unsigned long)kaddr;
-               __cpuc_coherent_kern_range(addr, addr + len);
-#ifdef CONFIG_SMP
+               if (icache_is_vipt_aliasing())
+                       flush_icache_alias(page_to_pfn(page), uaddr, len);
+               else
+                       __cpuc_coherent_kern_range(addr, addr + len);
                if (cache_ops_need_broadcast())
                        smp_call_function(flush_ptrace_access_other,
                                          NULL, 1);
-#endif
        }
 }
 
@@ -215,6 +229,36 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
        flush_dcache_mmap_unlock(mapping);
 }
 
+#if __LINUX_ARM_ARCH__ >= 6
+void __sync_icache_dcache(pte_t pteval)
+{
+       unsigned long pfn;
+       struct page *page;
+       struct address_space *mapping;
+
+       if (!pte_present_user(pteval))
+               return;
+       if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
+               /* only flush non-aliasing VIPT caches for exec mappings */
+               return;
+       pfn = pte_pfn(pteval);
+       if (!pfn_valid(pfn))
+               return;
+
+       page = pfn_to_page(pfn);
+       if (cache_is_vipt_aliasing())
+               mapping = page_mapping(page);
+       else
+               mapping = NULL;
+
+       if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+               __flush_dcache_page(mapping, page);
+       /* pte_exec() already checked above for non-aliasing VIPT cache */
+       if (cache_is_vipt_nonaliasing() || pte_exec(pteval))
+               __flush_icache_all();
+}
+#endif
+
 /*
  * Ensure cache coherency between kernel mapping and userspace mapping
  * of this page.
@@ -246,17 +290,16 @@ void flush_dcache_page(struct page *page)
 
        mapping = page_mapping(page);
 
-#ifndef CONFIG_SMP
-       if (!PageHighMem(page) && mapping && !mapping_mapped(mapping))
-               set_bit(PG_dcache_dirty, &page->flags);
-       else
-#endif
-       {
+       if (!cache_ops_need_broadcast() &&
+           mapping && !mapping_mapped(mapping))
+               clear_bit(PG_dcache_clean, &page->flags);
+       else {
                __flush_dcache_page(mapping, page);
                if (mapping && cache_is_vivt())
                        __flush_dcache_aliases(mapping, page);
                else if (mapping)
                        __flush_icache_all();
+               set_bit(PG_dcache_clean, &page->flags);
        }
 }
 EXPORT_SYMBOL(flush_dcache_page);
index 7185b00650fe419d0fa0f43b3e79e2e0d90cf6e6..7fd9b5eb177fa02c56acd3444da0e3752e702913 100644 (file)
@@ -150,6 +150,7 @@ static void __init find_limits(struct meminfo *mi,
 static void __init arm_bootmem_init(struct meminfo *mi,
        unsigned long start_pfn, unsigned long end_pfn)
 {
+       struct memblock_region *reg;
        unsigned int boot_pages;
        phys_addr_t bitmap;
        pg_data_t *pgdat;
@@ -180,13 +181,13 @@ static void __init arm_bootmem_init(struct meminfo *mi,
        /*
         * Reserve the memblock reserved regions in bootmem.
         */
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
-               if (start >= start_pfn &&
-                   memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
+       for_each_memblock(reserved, reg) {
+               phys_addr_t start = memblock_region_reserved_base_pfn(reg);
+               phys_addr_t end = memblock_region_reserved_end_pfn(reg);
+               if (start >= start_pfn && end <= end_pfn)
                        reserve_bootmem_node(pgdat, __pfn_to_phys(start),
-                               memblock_size_bytes(&memblock.reserved, i),
-                               BOOTMEM_DEFAULT);
+                                            (end - start) << PAGE_SHIFT,
+                                            BOOTMEM_DEFAULT);
        }
 }
 
@@ -237,20 +238,7 @@ static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
 #ifndef CONFIG_SPARSEMEM
 int pfn_valid(unsigned long pfn)
 {
-       struct memblock_region *mem = &memblock.memory;
-       unsigned int left = 0, right = mem->cnt;
-
-       do {
-               unsigned int mid = (right + left) / 2;
-
-               if (pfn < memblock_start_pfn(mem, mid))
-                       right = mid;
-               else if (pfn >= memblock_end_pfn(mem, mid))
-                       left = mid + 1;
-               else
-                       return 1;
-       } while (left < right);
-       return 0;
+       return memblock_is_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 
@@ -260,10 +248,11 @@ static void arm_memory_present(void)
 #else
 static void arm_memory_present(void)
 {
-       int i;
-       for (i = 0; i < memblock.memory.cnt; i++)
-               memory_present(0, memblock_start_pfn(&memblock.memory, i),
-                                 memblock_end_pfn(&memblock.memory, i));
+       struct memblock_region *reg;
+
+       for_each_memblock(memory, reg)
+               memory_present(0, memblock_region_memory_base_pfn(reg),
+                              memblock_region_memory_end_pfn(reg));
 }
 #endif
 
@@ -277,7 +266,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 
        /* Register the kernel text, kernel data and initrd with memblock. */
 #ifdef CONFIG_XIP_KERNEL
-       memblock_reserve(__pa(_data), _end - _data);
+       memblock_reserve(__pa(_sdata), _end - _sdata);
 #else
        memblock_reserve(__pa(_stext), _end - _stext);
 #endif
@@ -545,7 +534,7 @@ void __init mem_init(void)
 
                        MLK_ROUNDUP(__init_begin, __init_end),
                        MLK_ROUNDUP(_text, _etext),
-                       MLK_ROUNDUP(_data, _edata));
+                       MLK_ROUNDUP(_sdata, _edata));
 
 #undef MLK
 #undef MLM
index ab506272b2d3ef459b264b7741d61af46f6aa6b8..17e7b0b57e49f80e6e30c8bbe65ea9d1ebcf14a6 100644 (file)
@@ -204,8 +204,12 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
        /*
         * Don't allow RAM to be mapped - this causes problems with ARMv6+
         */
-       if (WARN_ON(pfn_valid(pfn)))
-               return NULL;
+       if (pfn_valid(pfn)) {
+               printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
+                      KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
+                      KERN_WARNING "will fail in the next kernel release.  Please fix your driver.\n");
+               WARN_ON(1);
+       }
 
        type = get_mem_type(mtype);
        if (!type)
index 4f5b39687df541a417d4c3a9ac888fc53a31b999..b0a98305055c53e54cc9be3edda6c82afb6275b8 100644 (file)
@@ -144,3 +144,25 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 {
        return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
 }
+
+#ifdef CONFIG_STRICT_DEVMEM
+
+#include <linux/ioport.h>
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain
+ * address is valid. The argument is a physical page number.
+ * We mimic x86 here by disallowing access to system RAM as well as
+ * device-exclusive MMIO regions. This effectively disable read()/write()
+ * on /dev/mem.
+ */
+int devmem_is_allowed(unsigned long pfn)
+{
+       if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+               return 0;
+       if (!page_is_ram(pfn))
+               return 1;
+       return 0;
+}
+
+#endif
index 6e1c4f6a2b3f3a09ed3f10be9aeafab36c9a0924..c32f731d56d3db4ad51453718c5d1c43f6053f2e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/nodemask.h>
 #include <linux/memblock.h>
 #include <linux/sort.h>
+#include <linux/fs.h>
 
 #include <asm/cputype.h>
 #include <asm/sections.h>
@@ -246,6 +247,9 @@ static struct mem_type mem_types[] = {
                .domain    = DOMAIN_USER,
        },
        [MT_MEMORY] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_WRITE | L_PTE_EXEC,
+               .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
@@ -254,6 +258,9 @@ static struct mem_type mem_types[] = {
                .domain    = DOMAIN_KERNEL,
        },
        [MT_MEMORY_NONCACHED] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
+               .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
@@ -303,9 +310,8 @@ static void __init build_mem_type_table(void)
                        cachepolicy = CPOLICY_WRITEBACK;
                ecc_mask = 0;
        }
-#ifdef CONFIG_SMP
-       cachepolicy = CPOLICY_WRITEALLOC;
-#endif
+       if (is_smp())
+               cachepolicy = CPOLICY_WRITEALLOC;
 
        /*
         * Strip out features not present on earlier architectures.
@@ -399,21 +405,22 @@ static void __init build_mem_type_table(void)
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
 
-#ifndef CONFIG_SMP
        /*
         * Only use write-through for non-SMP systems
         */
-       if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
+       if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
                vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte;
-#endif
 
        /*
         * Enable CPU-specific coherency if supported.
         * (Only available on XSC3 at the moment.)
         */
-       if (arch_is_coherent() && cpu_is_xsc3())
+       if (arch_is_coherent() && cpu_is_xsc3()) {
                mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-
+               mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+               mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+               mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+       }
        /*
         * ARMv6 and above have extended page tables.
         */
@@ -426,20 +433,23 @@ static void __init build_mem_type_table(void)
                mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
                mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 
-#ifdef CONFIG_SMP
-               /*
-                * Mark memory with the "shared" attribute for SMP systems
-                */
-               user_pgprot |= L_PTE_SHARED;
-               kern_pgprot |= L_PTE_SHARED;
-               vecs_pgprot |= L_PTE_SHARED;
-               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
-               mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
-               mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
-               mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
-               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-               mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
-#endif
+               if (is_smp()) {
+                       /*
+                        * Mark memory with the "shared" attribute
+                        * for SMP systems
+                        */
+                       user_pgprot |= L_PTE_SHARED;
+                       kern_pgprot |= L_PTE_SHARED;
+                       vecs_pgprot |= L_PTE_SHARED;
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+               }
        }
 
        /*
@@ -475,6 +485,8 @@ static void __init build_mem_type_table(void)
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
+       mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
+       mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
        mem_types[MT_ROM].prot_sect |= cp->pmd;
 
        switch (cp->pmd) {
@@ -498,6 +510,19 @@ static void __init build_mem_type_table(void)
        }
 }
 
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                             unsigned long size, pgprot_t vma_prot)
+{
+       if (!pfn_valid(pfn))
+               return pgprot_noncached(vma_prot);
+       else if (file->f_flags & O_SYNC)
+               return pgprot_writecombine(vma_prot);
+       return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
+#endif
+
 #define vectors_base() (vectors_high() ? 0xffff0000 : 0)
 
 static void __init *early_alloc(unsigned long sz)
@@ -802,8 +827,7 @@ static void __init sanity_check_meminfo(void)
                         * rather difficult.
                         */
                        reason = "with VIPT aliasing cache";
-#ifdef CONFIG_SMP
-               } else if (tlb_ops_need_broadcast()) {
+               } else if (is_smp() && tlb_ops_need_broadcast()) {
                        /*
                         * kmap_high needs to occasionally flush TLB entries,
                         * however, if the TLB entries need to be broadcast
@@ -813,7 +837,6 @@ static void __init sanity_check_meminfo(void)
                         *   (must not be called with irqs off)
                         */
                        reason = "without hardware TLB ops broadcasting";
-#endif
                }
                if (reason) {
                        printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
index 203a4e944d9e43c53051725c084f542cceb8b7a3..a6f5f8475b96c6400a3aa26e03875a329ff771b1 100644 (file)
@@ -430,7 +430,7 @@ ENTRY(cpu_arm1020_set_pte_ext)
 #endif /* CONFIG_MMU */
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm1020_setup, #function
 __arm1020_setup:
index 1a511e765909957d81b463c17f0000b8893d3770..afc06b9c31332bf7dc25222855d61dcb391bc42d 100644 (file)
@@ -412,7 +412,7 @@ ENTRY(cpu_arm1020e_set_pte_ext)
 #endif /* CONFIG_MMU */
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm1020e_setup, #function
 __arm1020e_setup:
index 1ffa4eb9c34f7d7d2f1b5ad5e3825daf67d14156..8915e0ba3fe53e1225bbb422b19f22c8a0d4c085 100644 (file)
@@ -394,7 +394,7 @@ ENTRY(cpu_arm1022_set_pte_ext)
 #endif /* CONFIG_MMU */
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm1022_setup, #function
 __arm1022_setup:
index 5697c34b95b0cdb38c31aad752c172b6990b5567..ff446c5d476f029aefb8a57da2fd4a4987e890e3 100644 (file)
@@ -384,7 +384,7 @@ ENTRY(cpu_arm1026_set_pte_ext)
        mov     pc, lr
 
 
-       __INIT
+       __CPUINIT
 
        .type   __arm1026_setup, #function
 __arm1026_setup:
index 64e0b327c7c5f504ec00757dcfd832d1fe56ac9e..6a7be1863eddaf317640fc41b25ecfdfc1b089f1 100644 (file)
@@ -238,7 +238,7 @@ ENTRY(cpu_arm7_reset)
                mcr     p15, 0, r1, c1, c0, 0           @ turn off MMU etc
                mov     pc, r0
 
-               __INIT
+               __CPUINIT
 
                .type   __arm6_setup, #function
 __arm6_setup:  mov     r0, #0
index 9d96824134fc4db4b0cd24f9df65c405717b4341..c285395f44b24e5f5dfb7bc92be1e7f4bd3935be 100644 (file)
@@ -113,7 +113,7 @@ ENTRY(cpu_arm720_reset)
                mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
                mov     pc, r0
 
-       __INIT
+       __CPUINIT
 
        .type   __arm710_setup, #function
 __arm710_setup:
index 6c1a9ab059aedb2f48e0d2bff8b823b3bb306dab..38b27dcba7275bd1038c62990bd49a9d35908f70 100644 (file)
@@ -55,7 +55,7 @@ ENTRY(cpu_arm740_reset)
        mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
        mov     pc, r0
 
-       __INIT
+       __CPUINIT
 
        .type   __arm740_setup, #function
 __arm740_setup:
index 6a850dbba22e5ff7be9aae70476489feeaaeef18..0c9786de20af3575100f21b3e3de6d1e006e4f71 100644 (file)
@@ -46,7 +46,7 @@ ENTRY(cpu_arm7tdmi_proc_fin)
 ENTRY(cpu_arm7tdmi_reset)
                mov     pc, r0
 
-               __INIT
+               __CPUINIT
 
                .type   __arm7tdmi_setup, #function
 __arm7tdmi_setup:
index 86f80aa56216b8ecf3159c090a83eeb2da372820..fecf570939f39553dcc4959a6a963a06827aadc2 100644 (file)
@@ -375,7 +375,7 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm920_setup, #function
 __arm920_setup:
index f76ce9b62883be61a1abe9baf67ae1a4ca4d8324..e3cbf87c9480c97e8b65086638ef6b6b72e3217c 100644 (file)
@@ -379,7 +379,7 @@ ENTRY(cpu_arm922_set_pte_ext)
 #endif /* CONFIG_MMU */
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm922_setup, #function
 __arm922_setup:
index 657bd3f7c153bf033f704636a323339129bb5d11..572424c867b5e8560401e7cf40d895a77f140fbe 100644 (file)
@@ -428,7 +428,7 @@ ENTRY(cpu_arm925_set_pte_ext)
 #endif /* CONFIG_MMU */
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm925_setup, #function
 __arm925_setup:
index 73f1f3c689108fcade13d8dbb26e057105247645..63d168b4ebe671316ff3add437c26da418dd596f 100644 (file)
@@ -389,7 +389,7 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm926_setup, #function
 __arm926_setup:
index fffb061a45a558ee8dc5883dcba4a0e64ef53311..f6a62822418e3573d8af5629f7f088f7ce24652d 100644 (file)
@@ -264,7 +264,7 @@ ENTRY(arm940_cache_fns)
        .long   arm940_dma_unmap_area
        .long   arm940_dma_flush_range
 
-       __INIT
+       __CPUINIT
 
        .type   __arm940_setup, #function
 __arm940_setup:
index 249a6053760a357baa0dca13c3d67bf49ebf975e..ea2e7f2eb95b1e6f86f4770c2e1ebca292f11f81 100644 (file)
@@ -317,7 +317,7 @@ ENTRY(cpu_arm946_dcache_clean_area)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __arm946_setup, #function
 __arm946_setup:
index db475667fac2c95df3ab30fdabda084eab94c3f3..db67e3134d7a50447268e815908e443206d0a7a4 100644 (file)
@@ -46,7 +46,7 @@ ENTRY(cpu_arm9tdmi_proc_fin)
 ENTRY(cpu_arm9tdmi_reset)
                mov     pc, r0
 
-               __INIT
+               __CPUINIT
 
                .type   __arm9tdmi_setup, #function
 __arm9tdmi_setup:
index 7803fdf7002933da8e63a3383f9da818ecea724c..7c9ad621f0e65ab031be819b303528341f7d2356 100644 (file)
@@ -134,7 +134,7 @@ ENTRY(cpu_fa526_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __fa526_setup, #function
 __fa526_setup:
index b304d0104a4ef9c240191e42b7e08460706408b8..578da69200cfc2694a2359c18ead388dfd4a7353 100644 (file)
@@ -494,7 +494,7 @@ ENTRY(cpu_feroceon_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __feroceon_setup, #function
 __feroceon_setup:
index 5f6892fcc1671f28070f175bc6eeda03bbe614c5..4458ee6aa7133343764792b79c9f87f0f7b67ff2 100644 (file)
@@ -338,7 +338,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __mohawk_setup, #function
 __mohawk_setup:
index a201eb04b5e1a6327d1a5375c00b669ee7fc439c..5aa8d59c2e8546675d132fc48306c89b2d9380da 100644 (file)
@@ -156,7 +156,7 @@ ENTRY(cpu_sa110_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __sa110_setup, #function
 __sa110_setup:
index 7ddc4805bf97a6fe722f54b3a769974bfaa42a1b..2ac4e6f1071378d3f27482483a0e041d540ec648 100644 (file)
@@ -169,7 +169,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
        mov     pc, lr
 
-       __INIT
+       __CPUINIT
 
        .type   __sa1100_setup, #function
 __sa1100_setup:
index 22aac85151966d3058ace5cdb24eb4a608605e16..59a7e1ffe7bc02c3fc180c464506ce273f5e9590 100644 (file)
 #define TTB_RGN_WT     (2 << 3)
 #define TTB_RGN_WB     (3 << 3)
 
-#ifndef CONFIG_SMP
-#define TTB_FLAGS      TTB_RGN_WBWA
-#define PMD_FLAGS      PMD_SECT_WB
-#else
-#define TTB_FLAGS      TTB_RGN_WBWA|TTB_S
-#define PMD_FLAGS      PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_UP   TTB_RGN_WBWA
+#define PMD_FLAGS_UP   PMD_SECT_WB
+#define TTB_FLAGS_SMP  TTB_RGN_WBWA|TTB_S
+#define PMD_FLAGS_SMP  PMD_SECT_WBWA|PMD_SECT_S
 
 ENTRY(cpu_v6_proc_init)
        mov     pc, lr
@@ -97,7 +94,8 @@ ENTRY(cpu_v6_switch_mm)
 #ifdef CONFIG_MMU
        mov     r2, #0
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
-       orr     r0, r0, #TTB_FLAGS
+       ALT_SMP(orr     r0, r0, #TTB_FLAGS_SMP)
+       ALT_UP(orr      r0, r0, #TTB_FLAGS_UP)
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
        mcr     p15, 0, r2, c7, c10, 4          @ drain write buffer
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
@@ -137,7 +135,7 @@ cpu_pj4_name:
 
        .align
 
-       __INIT
+       __CPUINIT
 
 /*
  *     __v6_setup
@@ -156,9 +154,11 @@ cpu_pj4_name:
  */
 __v6_setup:
 #ifdef CONFIG_SMP
-       mrc     p15, 0, r0, c1, c0, 1           @ Enable SMP/nAMP mode
+       ALT_SMP(mrc     p15, 0, r0, c1, c0, 1)  @ Enable SMP/nAMP mode
+       ALT_UP(nop)
        orr     r0, r0, #0x20
-       mcr     p15, 0, r0, c1, c0, 1
+       ALT_SMP(mcr     p15, 0, r0, c1, c0, 1)
+       ALT_UP(nop)
 #endif
 
        mov     r0, #0
@@ -169,7 +169,8 @@ __v6_setup:
 #ifdef CONFIG_MMU
        mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
        mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
-       orr     r4, r4, #TTB_FLAGS
+       ALT_SMP(orr     r4, r4, #TTB_FLAGS_SMP)
+       ALT_UP(orr      r4, r4, #TTB_FLAGS_UP)
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
 #endif /* CONFIG_MMU */
        adr     r5, v6_crval
@@ -192,6 +193,8 @@ __v6_setup:
 v6_crval:
        crval   clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c
 
+       __INITDATA
+
        .type   v6_processor_functions, #object
 ENTRY(v6_processor_functions)
        .word   v6_early_abort
@@ -205,6 +208,8 @@ ENTRY(v6_processor_functions)
        .word   cpu_v6_set_pte_ext
        .size   v6_processor_functions, . - v6_processor_functions
 
+       .section ".rodata"
+
        .type   cpu_arch_name, #object
 cpu_arch_name:
        .asciz  "armv6"
@@ -225,10 +230,16 @@ cpu_elf_name:
 __v6_proc_info:
        .long   0x0007b000
        .long   0x0007f000
-       .long   PMD_TYPE_SECT | \
+       ALT_SMP(.long \
+               PMD_TYPE_SECT | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ | \
-               PMD_FLAGS
+               PMD_FLAGS_SMP)
+       ALT_UP(.long \
+               PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS_UP)
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
@@ -249,10 +260,16 @@ __v6_proc_info:
 __pj4_v6_proc_info:
        .long   0x560f5810
        .long   0xff0ffff0
-       .long   PMD_TYPE_SECT | \
+       ALT_SMP(.long \
+               PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS_SMP)
+       ALT_UP(.long \
+               PMD_TYPE_SECT | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ | \
-               PMD_FLAGS
+               PMD_FLAGS_UP)
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
index 6a8506d99ee9abbb0845f39d94d663f802c56885..53cbe2225153de55cf6848394d63d1fb1ea00a18 100644 (file)
 #define TTB_IRGN_WT    ((1 << 0) | (0 << 6))
 #define TTB_IRGN_WB    ((1 << 0) | (1 << 6))
 
-#ifndef CONFIG_SMP
 /* PTWs cacheable, inner WB not shareable, outer WB not shareable */
-#define TTB_FLAGS      TTB_IRGN_WB|TTB_RGN_OC_WB
-#define PMD_FLAGS      PMD_SECT_WB
-#else
+#define TTB_FLAGS_UP   TTB_IRGN_WB|TTB_RGN_OC_WB
+#define PMD_FLAGS_UP   PMD_SECT_WB
+
 /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
-#define TTB_FLAGS      TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
-#define PMD_FLAGS      PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_SMP  TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
+#define PMD_FLAGS_SMP  PMD_SECT_WBWA|PMD_SECT_S
 
 ENTRY(cpu_v7_proc_init)
        mov     pc, lr
@@ -105,7 +103,8 @@ ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_MMU
        mov     r2, #0
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
-       orr     r0, r0, #TTB_FLAGS
+       ALT_SMP(orr     r0, r0, #TTB_FLAGS_SMP)
+       ALT_UP(orr      r0, r0, #TTB_FLAGS_UP)
 #ifdef CONFIG_ARM_ERRATA_430973
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
 #endif
@@ -169,7 +168,7 @@ cpu_v7_name:
        .ascii  "ARMv7 Processor"
        .align
 
-       __INIT
+       __CPUINIT
 
 /*
  *     __v7_setup
@@ -186,13 +185,15 @@ cpu_v7_name:
  *     It is assumed that:
  *     - cache type register is implemented
  */
-__v7_setup:
+__v7_ca9mp_setup:
 #ifdef CONFIG_SMP
-       mrc     p15, 0, r0, c1, c0, 1
+       ALT_SMP(mrc     p15, 0, r0, c1, c0, 1)
+       ALT_UP(mov      r0, #(1 << 6))          @ fake it for UP
        tst     r0, #(1 << 6)                   @ SMP/nAMP mode enabled?
        orreq   r0, r0, #(1 << 6) | (1 << 0)    @ Enable SMP/nAMP mode and
        mcreq   p15, 0, r0, c1, c0, 1           @ TLB ops broadcasting
 #endif
+__v7_setup:
        adr     r12, __v7_setup_stack           @ the local stack
        stmia   r12, {r0-r5, r7, r9, r11, lr}
        bl      v7_flush_dcache_all
@@ -201,11 +202,16 @@ __v7_setup:
        mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
        and     r10, r0, #0xff000000            @ ARM?
        teq     r10, #0x41000000
-       bne     2f
+       bne     3f
        and     r5, r0, #0x00f00000             @ variant
        and     r6, r0, #0x0000000f             @ revision
-       orr     r0, r6, r5, lsr #20-4           @ combine variant and revision
+       orr     r6, r6, r5, lsr #20-4           @ combine variant and revision
+       ubfx    r0, r0, #4, #12                 @ primary part number
 
+       /* Cortex-A8 Errata */
+       ldr     r10, =0x00000c08                @ Cortex-A8 primary part number
+       teq     r0, r10
+       bne     2f
 #ifdef CONFIG_ARM_ERRATA_430973
        teq     r5, #0x00100000                 @ only present in r1p*
        mrceq   p15, 0, r10, c1, c0, 1          @ read aux control register
@@ -213,21 +219,50 @@ __v7_setup:
        mcreq   p15, 0, r10, c1, c0, 1          @ write aux control register
 #endif
 #ifdef CONFIG_ARM_ERRATA_458693
-       teq     r0, #0x20                       @ only present in r2p0
+       teq     r6, #0x20                       @ only present in r2p0
        mrceq   p15, 0, r10, c1, c0, 1          @ read aux control register
        orreq   r10, r10, #(1 << 5)             @ set L1NEON to 1
        orreq   r10, r10, #(1 << 9)             @ set PLDNOP to 1
        mcreq   p15, 0, r10, c1, c0, 1          @ write aux control register
 #endif
 #ifdef CONFIG_ARM_ERRATA_460075
-       teq     r0, #0x20                       @ only present in r2p0
+       teq     r6, #0x20                       @ only present in r2p0
        mrceq   p15, 1, r10, c9, c0, 2          @ read L2 cache aux ctrl register
        tsteq   r10, #1 << 22
        orreq   r10, r10, #(1 << 22)            @ set the Write Allocate disable bit
        mcreq   p15, 1, r10, c9, c0, 2          @ write the L2 cache aux ctrl register
 #endif
+       b       3f
+
+       /* Cortex-A9 Errata */
+2:     ldr     r10, =0x00000c09                @ Cortex-A9 primary part number
+       teq     r0, r10
+       bne     3f
+#ifdef CONFIG_ARM_ERRATA_742230
+       cmp     r6, #0x22                       @ only present up to r2p2
+       mrcle   p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orrle   r10, r10, #1 << 4               @ set bit #4
+       mcrle   p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_742231
+       teq     r6, #0x20                       @ present in r2p0
+       teqne   r6, #0x21                       @ present in r2p1
+       teqne   r6, #0x22                       @ present in r2p2
+       mrceq   p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orreq   r10, r10, #1 << 12              @ set bit #12
+       orreq   r10, r10, #1 << 22              @ set bit #22
+       mcreq   p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_743622
+       teq     r6, #0x20                       @ present in r2p0
+       teqne   r6, #0x21                       @ present in r2p1
+       teqne   r6, #0x22                       @ present in r2p2
+       mrceq   p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orreq   r10, r10, #1 << 6               @ set bit #6
+       mcreq   p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
 
-2:     mov     r10, #0
+3:     mov     r10, #0
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
 #endif
@@ -235,7 +270,8 @@ __v7_setup:
 #ifdef CONFIG_MMU
        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
        mcr     p15, 0, r10, c2, c0, 2          @ TTB control register
-       orr     r4, r4, #TTB_FLAGS
+       ALT_SMP(orr     r4, r4, #TTB_FLAGS_SMP)
+       ALT_UP(orr      r4, r4, #TTB_FLAGS_UP)
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
        mov     r10, #0x1f                      @ domains 0, 1 = manager
        mcr     p15, 0, r10, c3, c0, 0          @ load domain access register
@@ -297,6 +333,8 @@ v7_crval:
 __v7_setup_stack:
        .space  4 * 11                          @ 11 registers
 
+       __INITDATA
+
        .type   v7_processor_functions, #object
 ENTRY(v7_processor_functions)
        .word   v7_early_abort
@@ -310,6 +348,8 @@ ENTRY(v7_processor_functions)
        .word   cpu_v7_set_pte_ext
        .size   v7_processor_functions, . - v7_processor_functions
 
+       .section ".rodata"
+
        .type   cpu_arch_name, #object
 cpu_arch_name:
        .asciz  "armv7"
@@ -323,6 +363,35 @@ cpu_elf_name:
 
        .section ".proc.info.init", #alloc, #execinstr
 
+       .type   __v7_ca9mp_proc_info, #object
+__v7_ca9mp_proc_info:
+       .long   0x410fc090              @ Required ID value
+       .long   0xff0ffff0              @ Mask for ID
+       ALT_SMP(.long \
+               PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS_SMP)
+       ALT_UP(.long \
+               PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS_UP)
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_XN | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __v7_ca9mp_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
+       .long   cpu_v7_name
+       .long   v7_processor_functions
+       .long   v7wbi_tlb_fns
+       .long   v6_user_fns
+       .long   v7_cache_fns
+       .size   __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
+
        /*
         * Match any ARMv7 processor core.
         */
@@ -330,10 +399,16 @@ cpu_elf_name:
 __v7_proc_info:
        .long   0x000f0000              @ Required ID value
        .long   0x000f0000              @ Mask for ID
-       .long   PMD_TYPE_SECT | \
+       ALT_SMP(.long \
+               PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS_SMP)
+       ALT_UP(.long \
+               PMD_TYPE_SECT | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ | \
-               PMD_FLAGS
+               PMD_FLAGS_UP)
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
index 361a51e4903063ffc82f6831f3bee47e3a957860..cad07e403044f3a2ba3b62b0812d4b37c6b4ff9f 100644 (file)
@@ -404,7 +404,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 
        .align
 
-       __INIT
+       __CPUINIT
 
        .type   __xsc3_setup, #function
 __xsc3_setup:
index 14075979bcbac1a4bfe7ae346e97058de819d448..cb245edb2c2bc2e25aa355473f8ceab9dc35d493 100644 (file)
@@ -506,7 +506,7 @@ ENTRY(cpu_xscale_set_pte_ext)
 
        .align
 
-       __INIT
+       __CPUINIT
 
        .type   __xscale_setup, #function
 __xscale_setup:
index f3f288a9546d2a89f4f6d940c6387062ef8ff143..53cd5b45467318e7fae97127bcdead01e3f4e8eb 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
@@ -41,20 +42,15 @@ ENTRY(v7wbi_flush_user_tlb_range)
        orr     r0, r3, r0, lsl #PAGE_SHIFT     @ Create initial MVA
        mov     r1, r1, lsl #PAGE_SHIFT
 1:
-#ifdef CONFIG_SMP
-       mcr     p15, 0, r0, c8, c3, 1           @ TLB invalidate U MVA (shareable) 
-#else
-       mcr     p15, 0, r0, c8, c7, 1           @ TLB invalidate U MVA
-#endif
+       ALT_SMP(mcr     p15, 0, r0, c8, c3, 1)  @ TLB invalidate U MVA (shareable)
+       ALT_UP(mcr      p15, 0, r0, c8, c7, 1)  @ TLB invalidate U MVA
+
        add     r0, r0, #PAGE_SZ
        cmp     r0, r1
        blo     1b
        mov     ip, #0
-#ifdef CONFIG_SMP
-       mcr     p15, 0, ip, c7, c1, 6           @ flush BTAC/BTB Inner Shareable
-#else
-       mcr     p15, 0, ip, c7, c5, 6           @ flush BTAC/BTB
-#endif
+       ALT_SMP(mcr     p15, 0, ip, c7, c1, 6)  @ flush BTAC/BTB Inner Shareable
+       ALT_UP(mcr      p15, 0, ip, c7, c5, 6)  @ flush BTAC/BTB
        dsb
        mov     pc, lr
 ENDPROC(v7wbi_flush_user_tlb_range)
@@ -74,20 +70,14 @@ ENTRY(v7wbi_flush_kern_tlb_range)
        mov     r0, r0, lsl #PAGE_SHIFT
        mov     r1, r1, lsl #PAGE_SHIFT
 1:
-#ifdef CONFIG_SMP
-       mcr     p15, 0, r0, c8, c3, 1           @ TLB invalidate U MVA (shareable)
-#else
-       mcr     p15, 0, r0, c8, c7, 1           @ TLB invalidate U MVA
-#endif
+       ALT_SMP(mcr     p15, 0, r0, c8, c3, 1)  @ TLB invalidate U MVA (shareable)
+       ALT_UP(mcr      p15, 0, r0, c8, c7, 1)  @ TLB invalidate U MVA
        add     r0, r0, #PAGE_SZ
        cmp     r0, r1
        blo     1b
        mov     r2, #0
-#ifdef CONFIG_SMP
-       mcr     p15, 0, r2, c7, c1, 6           @ flush BTAC/BTB Inner Shareable
-#else
-       mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
-#endif
+       ALT_SMP(mcr     p15, 0, r2, c7, c1, 6)  @ flush BTAC/BTB Inner Shareable
+       ALT_UP(mcr      p15, 0, r2, c7, c5, 6)  @ flush BTAC/BTB
        dsb
        isb
        mov     pc, lr
@@ -99,5 +89,6 @@ ENDPROC(v7wbi_flush_kern_tlb_range)
 ENTRY(v7wbi_tlb_fns)
        .long   v7wbi_flush_user_tlb_range
        .long   v7wbi_flush_kern_tlb_range
-       .long   v7wbi_tlb_flags
+       ALT_SMP(.long   v7wbi_tlb_flags_smp)
+       ALT_UP(.long    v7wbi_tlb_flags_up)
        .size   v7wbi_tlb_fns, . - v7wbi_tlb_fns
index e666eafed15295aa5feeedf60d374a704b2caa15..b2215c61cdf02a18df71849611007d97cfea4470 100644 (file)
@@ -6,4 +6,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                oprofilefs.o oprofile_stats.o \
                timer_int.o )
 
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
 oprofile-y                             := $(DRIVER_OBJS) common.o
index 0691176899ffc24f0a176d154a34f5b7200c6047..8aa974491dfcd555a6962461c0d2aa5f3287b653 100644 (file)
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_HW_PERF_EVENTS
-/*
- * Per performance monitor configuration as set via oprofilefs.
- */
-struct op_counter_config {
-       unsigned long count;
-       unsigned long enabled;
-       unsigned long event;
-       unsigned long unit_mask;
-       unsigned long kernel;
-       unsigned long user;
-       struct perf_event_attr attr;
-};
-
-static int op_arm_enabled;
-static DEFINE_MUTEX(op_arm_mutex);
-
-static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[nr_cpumask_bits];
-static int perf_num_counters;
-
-/*
- * Overflow callback for oprofile.
- */
-static void op_overflow_handler(struct perf_event *event, int unused,
-                       struct perf_sample_data *data, struct pt_regs *regs)
-{
-       int id;
-       u32 cpu = smp_processor_id();
-
-       for (id = 0; id < perf_num_counters; ++id)
-               if (perf_events[cpu][id] == event)
-                       break;
-
-       if (id != perf_num_counters)
-               oprofile_add_sample(regs, id);
-       else
-               pr_warning("oprofile: ignoring spurious overflow "
-                               "on cpu %u\n", cpu);
-}
-
-/*
- * Called by op_arm_setup to create perf attributes to mirror the oprofile
- * settings in counter_config. Attributes are created as `pinned' events and
- * so are permanently scheduled on the PMU.
- */
-static void op_perf_setup(void)
-{
-       int i;
-       u32 size = sizeof(struct perf_event_attr);
-       struct perf_event_attr *attr;
-
-       for (i = 0; i < perf_num_counters; ++i) {
-               attr = &counter_config[i].attr;
-               memset(attr, 0, size);
-               attr->type              = PERF_TYPE_RAW;
-               attr->size              = size;
-               attr->config            = counter_config[i].event;
-               attr->sample_period     = counter_config[i].count;
-               attr->pinned            = 1;
-       }
-}
-
-static int op_create_counter(int cpu, int event)
-{
-       int ret = 0;
-       struct perf_event *pevent;
-
-       if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL))
-               return ret;
-
-       pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
-                                                 cpu, -1,
-                                                 op_overflow_handler);
-
-       if (IS_ERR(pevent)) {
-               ret = PTR_ERR(pevent);
-       } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
-               pr_warning("oprofile: failed to enable event %d "
-                               "on CPU %d\n", event, cpu);
-               ret = -EBUSY;
-       } else {
-               perf_events[cpu][event] = pevent;
-       }
-
-       return ret;
-}
-
-static void op_destroy_counter(int cpu, int event)
-{
-       struct perf_event *pevent = perf_events[cpu][event];
-
-       if (pevent) {
-               perf_event_release_kernel(pevent);
-               perf_events[cpu][event] = NULL;
-       }
-}
-
-/*
- * Called by op_arm_start to create active perf events based on the
- * perviously configured attributes.
- */
-static int op_perf_start(void)
-{
-       int cpu, event, ret = 0;
-
-       for_each_online_cpu(cpu) {
-               for (event = 0; event < perf_num_counters; ++event) {
-                       ret = op_create_counter(cpu, event);
-                       if (ret)
-                               goto out;
-               }
-       }
-
-out:
-       return ret;
-}
-
-/*
- * Called by op_arm_stop at the end of a profiling run.
- */
-static void op_perf_stop(void)
+char *op_name_from_perf_id(void)
 {
-       int cpu, event;
+       enum arm_perf_pmu_ids id = armpmu_get_pmu_id();
 
-       for_each_online_cpu(cpu)
-               for (event = 0; event < perf_num_counters; ++event)
-                       op_destroy_counter(cpu, event);
-}
-
-
-static char *op_name_from_perf_id(enum arm_perf_pmu_ids id)
-{
        switch (id) {
        case ARM_PERF_PMU_ID_XSCALE1:
                return "arm/xscale1";
@@ -175,116 +47,6 @@ static char *op_name_from_perf_id(enum arm_perf_pmu_ids id)
        }
 }
 
-static int op_arm_create_files(struct super_block *sb, struct dentry *root)
-{
-       unsigned int i;
-
-       for (i = 0; i < perf_num_counters; i++) {
-               struct dentry *dir;
-               char buf[4];
-
-               snprintf(buf, sizeof buf, "%d", i);
-               dir = oprofilefs_mkdir(sb, root, buf);
-               oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
-               oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
-               oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
-               oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
-               oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
-               oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
-       }
-
-       return 0;
-}
-
-static int op_arm_setup(void)
-{
-       spin_lock(&oprofilefs_lock);
-       op_perf_setup();
-       spin_unlock(&oprofilefs_lock);
-       return 0;
-}
-
-static int op_arm_start(void)
-{
-       int ret = -EBUSY;
-
-       mutex_lock(&op_arm_mutex);
-       if (!op_arm_enabled) {
-               ret = 0;
-               op_perf_start();
-               op_arm_enabled = 1;
-       }
-       mutex_unlock(&op_arm_mutex);
-       return ret;
-}
-
-static void op_arm_stop(void)
-{
-       mutex_lock(&op_arm_mutex);
-       if (op_arm_enabled)
-               op_perf_stop();
-       op_arm_enabled = 0;
-       mutex_unlock(&op_arm_mutex);
-}
-
-#ifdef CONFIG_PM
-static int op_arm_suspend(struct platform_device *dev, pm_message_t state)
-{
-       mutex_lock(&op_arm_mutex);
-       if (op_arm_enabled)
-               op_perf_stop();
-       mutex_unlock(&op_arm_mutex);
-       return 0;
-}
-
-static int op_arm_resume(struct platform_device *dev)
-{
-       mutex_lock(&op_arm_mutex);
-       if (op_arm_enabled && op_perf_start())
-               op_arm_enabled = 0;
-       mutex_unlock(&op_arm_mutex);
-       return 0;
-}
-
-static struct platform_driver oprofile_driver = {
-       .driver         = {
-               .name           = "arm-oprofile",
-       },
-       .resume         = op_arm_resume,
-       .suspend        = op_arm_suspend,
-};
-
-static struct platform_device *oprofile_pdev;
-
-static int __init init_driverfs(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&oprofile_driver);
-       if (ret)
-               goto out;
-
-       oprofile_pdev = platform_device_register_simple(
-                               oprofile_driver.driver.name, 0, NULL, 0);
-       if (IS_ERR(oprofile_pdev)) {
-               ret = PTR_ERR(oprofile_pdev);
-               platform_driver_unregister(&oprofile_driver);
-       }
-
-out:
-       return ret;
-}
-
-static void  exit_driverfs(void)
-{
-       platform_device_unregister(oprofile_pdev);
-       platform_driver_unregister(&oprofile_driver);
-}
-#else
-static int __init init_driverfs(void) { return 0; }
-#define exit_driverfs() do { } while (0)
-#endif /* CONFIG_PM */
-
 static int report_trace(struct stackframe *frame, void *d)
 {
        unsigned int *depth = d;
@@ -349,72 +111,14 @@ static void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-       int cpu, ret = 0;
-
-       perf_num_counters = armpmu_get_max_events();
-
-       counter_config = kcalloc(perf_num_counters,
-                       sizeof(struct op_counter_config), GFP_KERNEL);
-
-       if (!counter_config) {
-               pr_info("oprofile: failed to allocate %d "
-                               "counters\n", perf_num_counters);
-               return -ENOMEM;
-       }
-
-       ret = init_driverfs();
-       if (ret) {
-               kfree(counter_config);
-               return ret;
-       }
-
-       for_each_possible_cpu(cpu) {
-               perf_events[cpu] = kcalloc(perf_num_counters,
-                               sizeof(struct perf_event *), GFP_KERNEL);
-               if (!perf_events[cpu]) {
-                       pr_info("oprofile: failed to allocate %d perf events "
-                                       "for cpu %d\n", perf_num_counters, cpu);
-                       while (--cpu >= 0)
-                               kfree(perf_events[cpu]);
-                       return -ENOMEM;
-               }
-       }
-
        ops->backtrace          = arm_backtrace;
-       ops->create_files       = op_arm_create_files;
-       ops->setup              = op_arm_setup;
-       ops->start              = op_arm_start;
-       ops->stop               = op_arm_stop;
-       ops->shutdown           = op_arm_stop;
-       ops->cpu_type           = op_name_from_perf_id(armpmu_get_pmu_id());
-
-       if (!ops->cpu_type)
-               ret = -ENODEV;
-       else
-               pr_info("oprofile: using %s\n", ops->cpu_type);
 
-       return ret;
+       return oprofile_perf_init(ops);
 }
 
-void oprofile_arch_exit(void)
+void __exit oprofile_arch_exit(void)
 {
-       int cpu, id;
-       struct perf_event *event;
-
-       if (*perf_events) {
-               exit_driverfs();
-               for_each_possible_cpu(cpu) {
-                       for (id = 0; id < perf_num_counters; ++id) {
-                               event = perf_events[cpu][id];
-                               if (event != NULL)
-                                       perf_event_release_kernel(event);
-                       }
-                       kfree(perf_events[cpu]);
-               }
-       }
-
-       if (counter_config)
-               kfree(counter_config);
+       oprofile_perf_exit();
 }
 #else
 int __init oprofile_arch_init(struct oprofile_operations *ops)
@@ -422,5 +126,5 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        pr_info("oprofile: hardware counters not available\n");
        return -ENODEV;
 }
-void oprofile_arch_exit(void) {}
+void __exit oprofile_arch_exit(void) {}
 #endif /* CONFIG_HW_PERF_EVENTS */
index 0527e65318f4a647b5b00192ce08ba47368ce5f8..64e3a64520e086cf24e57b10f2716b8bd852b0fd 100644 (file)
@@ -43,6 +43,7 @@ config ARCH_MXC91231
 config ARCH_MX5
        bool "MX5-based"
        select CPU_V7
+       select ARM_L1_CACHE_SHIFT_6
        help
          This enables support for systems based on the Freescale i.MX51 family
 
@@ -91,6 +92,18 @@ config MXC_DEBUG_BOARD
          data/address de-multiplexing and decode, signal level shift,
          interrupt control and various board functions.
 
+config HAVE_EPIT
+       bool
+
+config MXC_USE_EPIT
+       bool "Use EPIT instead of GPT"
+       depends on HAVE_EPIT
+       help
+         Use EPIT as the system timer on systems that have it. Normally you
+         don't have a reason to do so as the EPIT has the same features and
+         uses the same clocks as the GPT. Anyway, on some systems the GPT
+         may be in use for other purposes.
+
 config MXC_ULPI
        bool
 
@@ -109,4 +122,8 @@ config ARCH_MXC_AUDMUX_V1
 config ARCH_MXC_AUDMUX_V2
        bool
 
+config IRAM_ALLOC
+       bool
+       select GENERIC_ALLOCATOR
+
 endif
index 78d405ed861656ef83182a7242c385dcab805ce0..06875b4dd70fb2999da998299238aaf1e460d07b 100644 (file)
@@ -10,9 +10,11 @@ obj-$(CONFIG_MXC_TZIC) += tzic.o
 
 obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
+obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
 obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
+obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
index f9e7cdbd000568a562ac4bd062a550df73f3a853..0be1ac7f421b0ab2f5a244e5185cd23a5b792da2 100644 (file)
@@ -137,6 +137,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 static const struct file_operations audmux_debugfs_fops = {
        .open = audmux_open_file,
        .read = audmux_read_file,
+       .llseek = default_llseek,
 };
 
 static void audmux_debugfs_init(void)
@@ -186,7 +187,13 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
 static int mxc_audmux_v2_init(void)
 {
        int ret;
-
+#if defined(CONFIG_ARCH_MX5)
+       if (cpu_is_mx51()) {
+               audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
+               ret = 0;
+               return ret;
+       }
+#endif
 #if defined(CONFIG_ARCH_MX3)
        if (cpu_is_mx31())
                audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
index 9ab784b776f9192a33feaff37ff21be99b0a3691..404799487f1760b5eb9cec4e0636753830b54566 100644 (file)
@@ -1,3 +1,10 @@
+config IMX_HAVE_PLATFORM_ESDHC
+       bool
+
+config IMX_HAVE_PLATFORM_FEC
+       bool
+       default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51
+
 config IMX_HAVE_PLATFORM_FLEXCAN
        select HAVE_CAN_FLEXCAN
        bool
@@ -5,6 +12,9 @@ config IMX_HAVE_PLATFORM_FLEXCAN
 config IMX_HAVE_PLATFORM_IMX_I2C
        bool
 
+config IMX_HAVE_PLATFORM_IMX_SSI
+       bool
+
 config IMX_HAVE_PLATFORM_IMX_UART
        bool
 
index 347da5161f7e82521c0b6f4d930742267068fcdc..0a3c1f089413e2e2a896326612e3dd080e02818f 100644 (file)
@@ -1,8 +1,9 @@
-ifdef CONFIG_CAN_FLEXCAN
-# the ifdef can be removed once the flexcan driver has been merged
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) +=  platform-flexcan.o
-endif
+obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-y += platform-imx-dma.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-esdhc.c b/arch/arm/plat-mxc/devices/platform-esdhc.c
new file mode 100644 (file)
index 0000000..2605bfa
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <mach/esdhc.h>
+
+#define imx_esdhc_imx_data_entry_single(soc, _id, hwid) \
+       {                                                               \
+               .id = _id,                                              \
+               .iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,  \
+               .irq = soc ## _INT_ESDHC ## hwid,                       \
+       }
+
+#define imx_esdhc_imx_data_entry(soc, id, hwid)        \
+       [id] = imx_esdhc_imx_data_entry_single(soc, id, hwid)
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst = {
+#define imx25_esdhc_data_entry(_id, _hwid)                             \
+       imx_esdhc_imx_data_entry(MX25, _id, _hwid)
+       imx25_esdhc_data_entry(0, 1),
+       imx25_esdhc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst = {
+#define imx35_esdhc_data_entry(_id, _hwid)                           \
+       imx_esdhc_imx_data_entry(MX35, _id, _hwid)
+       imx35_esdhc_data_entry(0, 1),
+       imx35_esdhc_data_entry(1, 2),
+       imx35_esdhc_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst = {
+#define imx51_esdhc_data_entry(_id, _hwid)                             \
+       imx_esdhc_imx_data_entry(MX51, _id, _hwid)
+       imx51_esdhc_data_entry(0, 1),
+       imx51_esdhc_data_entry(1, 2),
+       imx51_esdhc_data_entry(2, 3),
+       imx51_esdhc_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_esdhc(
+               const struct imx_esdhc_imx_data *data,
+               const struct esdhc_platform_data *pdata)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + SZ_16K - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
+                       .flags = IORESOURCE_IRQ,
+               },
+       };
+
+       return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+                       ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
new file mode 100644 (file)
index 0000000..11d087f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_fec_data_entry_single(soc)                                 \
+       {                                                               \
+               .iobase = soc ## _FEC_BASE_ADDR,                        \
+               .irq = soc ## _INT_FEC,                                 \
+       }
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_fec_data imx25_fec_data __initconst =
+       imx_fec_data_entry_single(MX25);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fec_data imx27_fec_data __initconst =
+       imx_fec_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_fec_data imx35_fec_data __initconst =
+       imx_fec_data_entry_single(MX35);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_fec_data imx51_fec_data __initconst =
+       imx_fec_data_entry_single(MX51);
+#endif
+
+struct platform_device *__init imx_add_fec(
+               const struct imx_fec_data *data,
+               const struct fec_platform_data *pdata)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + SZ_4K,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
+                       .flags = IORESOURCE_IRQ,
+               },
+       };
+
+       return imx_add_platform_device("fec", 0 /* -1? */,
+                       res, ARRAY_SIZE(res),
+                       pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
new file mode 100644 (file)
index 0000000..02d9890
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#ifdef SDMA_IS_MERGED
+#include <mach/sdma.h>
+#else
+struct sdma_platform_data {
+       int sdma_version;
+       char *cpu_name;
+       int to_version;
+};
+#endif
+
+struct imx_imx_sdma_data {
+       resource_size_t iobase;
+       resource_size_t irq;
+       struct sdma_platform_data pdata;
+};
+
+#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
+       {                                                               \
+               .iobase = soc ## _SDMA ## _BASE_ADDR,                   \
+               .irq = soc ## _INT_SDMA,                                \
+               .pdata = {                                              \
+                       .sdma_version = _sdma_version,                  \
+                       .cpu_name = _cpu_name,                          \
+                       .to_version = _to_version,                      \
+               },                                                      \
+       }
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
+       imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX31
+struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
+       imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
+       imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
+       imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+               const struct imx_imx_sdma_data *data)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + SZ_4K - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
+                       .flags = IORESOURCE_IRQ,
+               },
+       };
+
+       return imx_add_platform_device("imx-sdma", -1,
+                       res, ARRAY_SIZE(res),
+                       &data->pdata, sizeof(data->pdata));
+}
+
+static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+       return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
+}
+
+static int __init imxXX_add_imx_dma(void)
+{
+       struct platform_device *ret;
+
+#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
+       if (cpu_is_mx21() || cpu_is_mx27())
+               ret = imx_add_imx_dma();
+       else
+#endif
+
+#if defined(CONFIG_ARCH_MX25)
+       if (cpu_is_mx25())
+               ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
+       else
+#endif
+
+#if defined(CONFIG_ARCH_MX31)
+       if (cpu_is_mx31()) {
+               imx31_imx_sdma_data.pdata.to_version = mx31_revision() >> 4;
+               ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
+       } else
+#endif
+
+#if defined(CONFIG_ARCH_MX35)
+       if (cpu_is_mx35()) {
+               imx35_imx_sdma_data.pdata.to_version = mx35_revision() >> 4;
+               ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
+       } else
+#endif
+
+#if defined(CONFIG_ARCH_MX51)
+       if (cpu_is_mx51())
+               ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
+       else
+#endif
+               ret = ERR_PTR(-ENODEV);
+
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       return 0;
+}
+arch_initcall(imxXX_add_imx_dma);
index d0af9f7d8aed06439f3e2978b9969595b0d3eaa6..679588453aad330004bd7c1fc13d2a371c281922 100644 (file)
@@ -6,24 +6,95 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_imx_i2c(int id,
-               resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)          \
+       {                                                               \
+               .id = _id,                                              \
+               .iobase = soc ## _I2C ## _hwid ## _BASE_ADDR,           \
+               .iosize = _size,                                        \
+               .irq = soc ## _INT_I2C ## _hwid,                        \
+       }
+
+#define imx_imx_i2c_data_entry(soc, _id, _hwid, _size)                 \
+       [_id] = imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
+       imx_imx_i2c_data_entry_single(MX1, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
+       imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
+#define imx25_imx_i2c_data_entry(_id, _hwid)                           \
+       imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
+       imx25_imx_i2c_data_entry(0, 1),
+       imx25_imx_i2c_data_entry(1, 2),
+       imx25_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
+#define imx27_imx_i2c_data_entry(_id, _hwid)                           \
+       imx_imx_i2c_data_entry(MX27, _id, _hwid, SZ_4K)
+       imx27_imx_i2c_data_entry(0, 1),
+       imx27_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
+#define imx31_imx_i2c_data_entry(_id, _hwid)                           \
+       imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
+       imx31_imx_i2c_data_entry(0, 1),
+       imx31_imx_i2c_data_entry(1, 2),
+       imx31_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
+#define imx35_imx_i2c_data_entry(_id, _hwid)                           \
+       imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
+       imx35_imx_i2c_data_entry(0, 1),
+       imx35_imx_i2c_data_entry(1, 2),
+       imx35_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
+#define imx51_imx_i2c_data_entry(_id, _hwid)                           \
+       imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
+       imx51_imx_i2c_data_entry(0, 1),
+       imx51_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_i2c(
+               const struct imx_imx_i2c_data *data,
                const struct imxi2c_platform_data *pdata)
 {
        struct resource res[] = {
                {
-                       .start = iobase,
-                       .end = iobase + iosize - 1,
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = irq,
-                       .end = irq,
+                       .start = data->irq,
+                       .end = data->irq,
                        .flags = IORESOURCE_IRQ,
                },
        };
 
-       return imx_add_platform_device("imx-i2c", id, res, ARRAY_SIZE(res),
+       return imx_add_platform_device("imx-i2c", data->id,
+                       res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
new file mode 100644 (file)
index 0000000..38a7a0b
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_ssi_data_entry(soc, _id, _hwid, _size)                 \
+       [_id] = {                                                       \
+               .id = _id,                                              \
+               .iobase = soc ## _SSI ## _hwid ## _BASE_ADDR,           \
+               .iosize = _size,                                        \
+               .irq = soc ## _INT_SSI ## _hwid,                        \
+               .dmatx0 = soc ## _DMA_REQ_SSI ## _hwid ## _TX0,         \
+               .dmarx0 = soc ## _DMA_REQ_SSI ## _hwid ## _RX0,         \
+               .dmatx1 = soc ## _DMA_REQ_SSI ## _hwid ## _TX1,         \
+               .dmarx1 = soc ## _DMA_REQ_SSI ## _hwid ## _RX1,         \
+       }
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
+#define imx21_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX21, _id, _hwid, SZ_4K)
+       imx21_imx_ssi_data_entry(0, 1),
+       imx21_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
+#define imx25_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
+       imx25_imx_ssi_data_entry(0, 1),
+       imx25_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
+#define imx27_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX27, _id, _hwid, SZ_4K)
+       imx27_imx_ssi_data_entry(0, 1),
+       imx27_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
+#define imx31_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
+       imx31_imx_ssi_data_entry(0, 1),
+       imx31_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
+#define imx35_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
+       imx35_imx_ssi_data_entry(0, 1),
+       imx35_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
+#define imx51_imx_ssi_data_entry(_id, _hwid)                           \
+       imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
+       imx51_imx_ssi_data_entry(0, 1),
+       imx51_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_ssi(
+               const struct imx_imx_ssi_data *data,
+               const struct imx_ssi_platform_data *pdata)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
+                       .flags = IORESOURCE_IRQ,
+               },
+#define DMARES(_name) {                                                        \
+       .name = #_name,                                                 \
+       .start = data->dma ## _name,                                    \
+       .end = data->dma ## _name,                                      \
+       .flags = IORESOURCE_DMA,                                        \
+}
+               DMARES(tx0),
+               DMARES(rx0),
+               DMARES(tx1),
+               DMARES(rx1),
+       };
+
+       return imx_add_platform_device("imx-ssi", data->id,
+                       res, ARRAY_SIZE(res),
+                       pdata, sizeof(*pdata));
+}
index fa3dff1433e8e86afe8570f96cd6a780310604e8..2039640adf27ffa8b126788754570ccf81355c24 100644 (file)
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
-               resource_size_t iobase, resource_size_t iosize,
-               resource_size_t irqrx, resource_size_t irqtx,
-               resource_size_t irqrts,
+#define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size)           \
+       [_id] = {                                                       \
+               .id = _id,                                              \
+               .iobase = soc ## _UART ## _hwid ## _BASE_ADDR,          \
+               .iosize = _size,                                        \
+               .irqrx = soc ## _INT_UART ## _hwid ## RX,               \
+               .irqtx = soc ## _INT_UART ## _hwid ## TX,               \
+               .irqrts = soc ## _INT_UART ## _hwid ## RTS,             \
+       }
+
+#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size)           \
+       [_id] = {                                                       \
+               .id = _id,                                              \
+               .iobase = soc ## _UART ## _hwid ## _BASE_ADDR,          \
+               .iosize = _size,                                        \
+               .irq = soc ## _INT_UART ## _hwid,                       \
+       }
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst = {
+#define imx1_imx_uart_data_entry(_id, _hwid)                           \
+       imx_imx_uart_3irq_data_entry(MX1, _id, _hwid, 0xd0)
+       imx1_imx_uart_data_entry(0, 1),
+       imx1_imx_uart_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
+#define imx21_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX21, _id, _hwid, SZ_4K)
+       imx21_imx_uart_data_entry(0, 1),
+       imx21_imx_uart_data_entry(1, 2),
+       imx21_imx_uart_data_entry(2, 3),
+       imx21_imx_uart_data_entry(3, 4),
+};
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
+#define imx25_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
+       imx25_imx_uart_data_entry(0, 1),
+       imx25_imx_uart_data_entry(1, 2),
+       imx25_imx_uart_data_entry(2, 3),
+       imx25_imx_uart_data_entry(3, 4),
+       imx25_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
+#define imx27_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX27, _id, _hwid, SZ_4K)
+       imx27_imx_uart_data_entry(0, 1),
+       imx27_imx_uart_data_entry(1, 2),
+       imx27_imx_uart_data_entry(2, 3),
+       imx27_imx_uart_data_entry(3, 4),
+       imx27_imx_uart_data_entry(4, 5),
+       imx27_imx_uart_data_entry(5, 6),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
+#define imx31_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
+       imx31_imx_uart_data_entry(0, 1),
+       imx31_imx_uart_data_entry(1, 2),
+       imx31_imx_uart_data_entry(2, 3),
+       imx31_imx_uart_data_entry(3, 4),
+       imx31_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
+#define imx35_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_16K)
+       imx35_imx_uart_data_entry(0, 1),
+       imx35_imx_uart_data_entry(1, 2),
+       imx35_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
+#define imx51_imx_uart_data_entry(_id, _hwid)                          \
+       imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
+       imx51_imx_uart_data_entry(0, 1),
+       imx51_imx_uart_data_entry(1, 2),
+       imx51_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_uart_3irq(
+               const struct imx_imx_uart_3irq_data *data,
                const struct imxuart_platform_data *pdata)
 {
        struct resource res[] = {
                {
-                       .start = iobase,
-                       .end = iobase + iosize - 1,
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = irqrx,
-                       .end = irqrx,
+                       .start = data->irqrx,
+                       .end = data->irqrx,
                        .flags = IORESOURCE_IRQ,
                }, {
-                       .start = irqtx,
-                       .end = irqtx,
+                       .start = data->irqtx,
+                       .end = data->irqtx,
                        .flags = IORESOURCE_IRQ,
                }, {
-                       .start = irqrts,
-                       .end = irqrx,
+                       .start = data->irqrts,
+                       .end = data->irqrx,
                        .flags = IORESOURCE_IRQ,
                },
        };
 
-       return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
-                       pdata, sizeof(*pdata));
+       return imx_add_platform_device("imx-uart", data->id, res,
+                       ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
-               resource_size_t iobase, resource_size_t iosize,
-               resource_size_t irq,
+struct platform_device *__init imx_add_imx_uart_1irq(
+               const struct imx_imx_uart_1irq_data *data,
                const struct imxuart_platform_data *pdata)
 {
        struct resource res[] = {
                {
-                       .start = iobase,
-                       .end = iobase + iosize - 1,
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = irq,
-                       .end = irq,
+                       .start = data->irq,
+                       .end = data->irq,
                        .flags = IORESOURCE_IRQ,
                },
        };
 
-       return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
+       return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata));
 }
index 1c286418d12335140a2d466ca5532e388f42022c..3fdcc32e3d679b5170da47681935c470a8462abb 100644 (file)
@@ -7,38 +7,77 @@
  * Free Software Foundation.
  */
 #include <asm/sizes.h>
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-static struct platform_device *__init imx_add_mxc_nand(resource_size_t iobase,
-               int irq, const struct mxc_nand_platform_data *pdata,
-               resource_size_t iosize)
+#define imx_mxc_nand_data_entry_single(soc, _size)                     \
+       {                                                               \
+               .iobase = soc ## _NFC_BASE_ADDR,                        \
+               .iosize = _size,                                        \
+               .irq = soc ## _INT_NFC                                  \
+       }
+
+#define imx_mxc_nandv3_data_entry_single(soc, _size)                   \
+       {                                                               \
+               .id = -1,                                               \
+               .iobase = soc ## _NFC_BASE_ADDR,                        \
+               .iosize = _size,                                        \
+               .axibase = soc ## _NFC_AXI_BASE_ADDR,                   \
+               .irq = soc ## _INT_NFC                                  \
+       }
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
+       imx_mxc_nand_data_entry_single(MX21, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
+       imx_mxc_nand_data_entry_single(MX25, SZ_8K);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
+       imx_mxc_nand_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
+       imx_mxc_nand_data_entry_single(MX31, SZ_4K);
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
+       imx_mxc_nand_data_entry_single(MX35, SZ_8K);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
+       imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
+#endif
+
+struct platform_device *__init imx_add_mxc_nand(
+               const struct imx_mxc_nand_data *data,
+               const struct mxc_nand_platform_data *pdata)
 {
-       static int id = 0;
-       
+       /* AXI has to come first, that's how the mxc_nand driver expect it */
        struct resource res[] = {
                {
-                       .start = iobase,
-                       .end = iobase + iosize - 1,
+                       .start = data->axibase,
+                       .end = data->axibase + SZ_16K - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = irq,
-                       .end = irq,
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
                        .flags = IORESOURCE_IRQ,
                },
        };
-
-       return imx_add_platform_device("mxc_nand", id++, res, ARRAY_SIZE(res),
+       return imx_add_platform_device("mxc_nand", data->id,
+                       res + !data->axibase,
+                       ARRAY_SIZE(res) - !data->axibase,
                        pdata, sizeof(*pdata));
 }
-
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
-               int irq, const struct mxc_nand_platform_data *pdata)
-{
-       return imx_add_mxc_nand(iobase, irq, pdata, SZ_4K);
-}
-
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
-               int irq, const struct mxc_nand_platform_data *pdata)
-{
-       return imx_add_mxc_nand(iobase, irq, pdata, SZ_8K);
-}
index 2831a6d3eb4bf726f78a956960fc75d0fc436774..e48340ec331e4a8ca376b96c25b36faa0a7eafe0 100644 (file)
@@ -6,25 +6,96 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <asm/sizes.h>
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_spi_imx(int id,
-               resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
+       {                                                               \
+               .devid = _devid,                                        \
+               .id = _id,                                              \
+               .iobase = soc ## _ ## type ## hwid ## _BASE_ADDR,       \
+               .iosize = _size,                                        \
+               .irq = soc ## _INT_ ## type ## hwid,                    \
+       }
+
+#define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size)       \
+       [id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
+#define imx21_cspi_data_entry(_id, _hwid)                            \
+       imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
+       imx21_cspi_data_entry(0, 1),
+       imx21_cspi_data_entry(1, 2),
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
+#define imx25_cspi_data_entry(_id, _hwid)                              \
+       imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
+       imx25_cspi_data_entry(0, 1),
+       imx25_cspi_data_entry(1, 2),
+       imx25_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
+#define imx27_cspi_data_entry(_id, _hwid)                              \
+       imx_spi_imx_data_entry(MX27, CSPI, "imx27-cspi", _id, _hwid, SZ_4K)
+       imx27_cspi_data_entry(0, 1),
+       imx27_cspi_data_entry(1, 2),
+       imx27_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
+#define imx31_cspi_data_entry(_id, _hwid)                              \
+       imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
+       imx31_cspi_data_entry(0, 1),
+       imx31_cspi_data_entry(1, 2),
+       imx31_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
+#define imx35_cspi_data_entry(_id, _hwid)                           \
+       imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
+       imx35_cspi_data_entry(0, 1),
+       imx35_cspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_spi_imx_data imx51_cspi_data __initconst =
+       imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 0, , SZ_4K);
+
+const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
+#define imx51_ecspi_data_entry(_id, _hwid)                             \
+       imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
+       imx51_ecspi_data_entry(0, 1),
+       imx51_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_spi_imx(
+               const struct imx_spi_imx_data *data,
                const struct spi_imx_master *pdata)
 {
        struct resource res[] = {
                {
-                       .start = iobase,
-                       .end = iobase + iosize - 1,
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
-                       .start = irq,
-                       .end = irq,
+                       .start = data->irq,
+                       .end = data->irq,
                        .flags = IORESOURCE_IRQ,
                },
        };
 
-       return imx_add_platform_device("spi_imx", id, res, ARRAY_SIZE(res),
-                       pdata, sizeof(*pdata));
+       return imx_add_platform_device(data->devid, data->id,
+                       res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
index 35a064ff02ba61a66b4f0425728baa4b7f74cda6..9915607683de39e08d1145b115bd289fec360da2 100644 (file)
@@ -249,8 +249,8 @@ int mxc_initialize_usb_hw(int port, unsigned int flags)
 #ifdef CONFIG_ARCH_MX51
        if (cpu_is_mx51()) {
                void __iomem *usb_base;
-               u32 usbotg_base;
-               u32 usbother_base;
+               void __iomem *usbotg_base;
+               void __iomem *usbother_base;
                int ret = 0;
 
                usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c
new file mode 100644 (file)
index 0000000..ee9582f
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ *  linux/arch/arm/plat-mxc/epit.c
+ *
+ *  Copyright (C) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define EPITCR         0x00
+#define EPITSR         0x04
+#define EPITLR         0x08
+#define EPITCMPR       0x0c
+#define EPITCNR                0x10
+
+#define EPITCR_EN                      (1 << 0)
+#define EPITCR_ENMOD                   (1 << 1)
+#define EPITCR_OCIEN                   (1 << 2)
+#define EPITCR_RLD                     (1 << 3)
+#define EPITCR_PRESC(x)                        (((x) & 0xfff) << 4)
+#define EPITCR_SWR                     (1 << 16)
+#define EPITCR_IOVW                    (1 << 17)
+#define EPITCR_DBGEN                   (1 << 18)
+#define EPITCR_WAITEN                  (1 << 19)
+#define EPITCR_RES                     (1 << 20)
+#define EPITCR_STOPEN                  (1 << 21)
+#define EPITCR_OM_DISCON               (0 << 22)
+#define EPITCR_OM_TOGGLE               (1 << 22)
+#define EPITCR_OM_CLEAR                        (2 << 22)
+#define EPITCR_OM_SET                  (3 << 22)
+#define EPITCR_CLKSRC_OFF              (0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL       (1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH         (1 << 24)
+#define EPITCR_CLKSRC_REF_LOW          (3 << 24)
+
+#define EPITSR_OCIF                    (1 << 0)
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+
+static struct clock_event_device clockevent_epit;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *timer_base;
+
+static inline void epit_irq_disable(void)
+{
+       u32 val;
+
+       val = __raw_readl(timer_base + EPITCR);
+       val &= ~EPITCR_OCIEN;
+       __raw_writel(val, timer_base + EPITCR);
+}
+
+static inline void epit_irq_enable(void)
+{
+       u32 val;
+
+       val = __raw_readl(timer_base + EPITCR);
+       val |= EPITCR_OCIEN;
+       __raw_writel(val, timer_base + EPITCR);
+}
+
+static void epit_irq_acknowledge(void)
+{
+       __raw_writel(EPITSR_OCIF, timer_base + EPITSR);
+}
+
+static cycle_t epit_read(struct clocksource *cs)
+{
+       return 0 - __raw_readl(timer_base + EPITCNR);
+}
+
+static struct clocksource clocksource_epit = {
+       .name           = "epit",
+       .rating         = 200,
+       .read           = epit_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 20,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init epit_clocksource_init(struct clk *timer_clk)
+{
+       unsigned int c = clk_get_rate(timer_clk);
+
+       clocksource_epit.mult = clocksource_hz2mult(c,
+                                       clocksource_epit.shift);
+       clocksource_register(&clocksource_epit);
+
+       return 0;
+}
+
+/* clock event */
+
+static int epit_set_next_event(unsigned long evt,
+                             struct clock_event_device *unused)
+{
+       unsigned long tcmp;
+
+       tcmp = __raw_readl(timer_base + EPITCNR);
+
+       __raw_writel(tcmp - evt, timer_base + EPITCMPR);
+
+       return 0;
+}
+
+static void epit_set_mode(enum clock_event_mode mode,
+                               struct clock_event_device *evt)
+{
+       unsigned long flags;
+
+       /*
+        * The timer interrupt generation is disabled at least
+        * for enough time to call epit_set_next_event()
+        */
+       local_irq_save(flags);
+
+       /* Disable interrupt in GPT module */
+       epit_irq_disable();
+
+       if (mode != clockevent_mode) {
+               /* Set event time into far-far future */
+
+               /* Clear pending interrupt */
+               epit_irq_acknowledge();
+       }
+
+       /* Remember timer mode */
+       clockevent_mode = mode;
+       local_irq_restore(flags);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               printk(KERN_ERR "epit_set_mode: Periodic mode is not "
+                               "supported for i.MX EPIT\n");
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+       /*
+        * Do not put overhead of interrupt enable/disable into
+        * epit_set_next_event(), the core has about 4 minutes
+        * to call epit_set_next_event() or shutdown clock after
+        * mode switching
+        */
+               local_irq_save(flags);
+               epit_irq_enable();
+               local_irq_restore(flags);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_RESUME:
+               /* Left event sources disabled, no more interrupts appear */
+               break;
+       }
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = &clockevent_epit;
+
+       epit_irq_acknowledge();
+
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction epit_timer_irq = {
+       .name           = "i.MX EPIT Timer Tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = epit_timer_interrupt,
+};
+
+static struct clock_event_device clockevent_epit = {
+       .name           = "epit",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_mode       = epit_set_mode,
+       .set_next_event = epit_set_next_event,
+       .rating         = 200,
+};
+
+static int __init epit_clockevent_init(struct clk *timer_clk)
+{
+       unsigned int c = clk_get_rate(timer_clk);
+
+       clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
+                                       clockevent_epit.shift);
+       clockevent_epit.max_delta_ns =
+                       clockevent_delta2ns(0xfffffffe, &clockevent_epit);
+       clockevent_epit.min_delta_ns =
+                       clockevent_delta2ns(0x800, &clockevent_epit);
+
+       clockevent_epit.cpumask = cpumask_of(0);
+
+       clockevents_register_device(&clockevent_epit);
+
+       return 0;
+}
+
+void __init epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
+{
+       clk_enable(timer_clk);
+
+       timer_base = base;
+
+       /*
+        * Initialise to a known state (all timers off, and timing reset)
+        */
+       __raw_writel(0x0, timer_base + EPITCR);
+
+       __raw_writel(0xffffffff, timer_base + EPITLR);
+       __raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN,
+                       timer_base + EPITCR);
+
+       /* init and register the timer to the framework */
+       epit_clocksource_init(timer_clk);
+       epit_clockevent_init(timer_clk);
+
+       /* Make irqs happen */
+       setup_irq(irq, &epit_timer_irq);
+}
index 57ec4a896a5d983556ebae058dbf52293ebe669e..9d38da077edb121cfbcb065322be5e7251975463 100644 (file)
@@ -235,7 +235,7 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        unsigned long flags;
 
        spin_lock_irqsave(&port->lock, flags);
-       l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
+       l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
        __raw_writel(l, reg);
        spin_unlock_irqrestore(&port->lock, flags);
 }
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
new file mode 100644 (file)
index 0000000..94b60dd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+#define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+
+#include <mach/hardware.h>
+
+/*
+ * These symbols are used by drivers/net/cs89x0.c.
+ * This is ugly as hell, but we have to provide them until
+ * someone fixed the driver.
+ */
+
+/* Base address of PBC controller */
+#define PBC_BASE_ADDRESS        MX31_CS4_BASE_ADDR_VIRT
+/* Offsets for the PBC Controller register */
+
+/* Ethernet Controller IO base address */
+#define PBC_CS8900A_IOBASE      0x020000
+
+#define MXC_EXP_IO_BASE                (MXC_BOARD_IRQ_START)
+
+#define EXPIO_INT_ENET_INT     (MXC_EXP_IO_BASE + 8)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
index 2941472582d2a2e63e08627bdd0abd97792c698c..7a1e1f89ff0934f36eeebd0dae3b5e0c356a8ea5 100644 (file)
@@ -32,6 +32,7 @@ extern void mx31_init_irq(void);
 extern void mx35_init_irq(void);
 extern void mx51_init_irq(void);
 extern void mxc91231_init_irq(void);
+extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
 extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
index 25606409aabcfb7de02a3dbce55e7221b68d2ece..d56213fb901ba14e54be3a1dba0963b42ffc1183 100644 (file)
 #define UART_PADDR     MXC91231_UART2_BASE_ADDR
 #define UART_VADDR     MXC91231_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
 #endif
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               ldreq   \rx, =UART_PADDR        @ physical
-               ldrne   \rx, =UART_VADDR        @ virtual
+               .macro  addruart, rp, rv
+               ldr     \rp, =UART_PADDR        @ physical
+               ldr     \rv, =UART_VADDR        @ virtual
                .endm
 
                .macro  senduart,rd,rx
index c5f68c587309e2f37949f61c540fcf7826587f70..86d7575a564dba0c550e93d668fe35e0b44b1dff 100644 (file)
@@ -14,47 +14,105 @@ struct platform_device *imx_add_platform_device(const char *name, int id,
                const struct resource *res, unsigned int num_resources,
                const void *data, size_t size_data);
 
-#if defined (CONFIG_CAN_FLEXCAN) || defined (CONFIG_CAN_FLEXCAN_MODULE)
+#include <linux/fec.h>
+struct imx_fec_data {
+       resource_size_t iobase;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_fec(
+               const struct imx_fec_data *data,
+               const struct fec_platform_data *pdata);
+
 #include <linux/can/platform/flexcan.h>
 struct platform_device *__init imx_add_flexcan(int id,
                resource_size_t iobase, resource_size_t iosize,
                resource_size_t irq,
                const struct flexcan_platform_data *pdata);
-#else
-/* the ifdef can be removed once the flexcan driver has been merged */
-struct flexcan_platform_data;
-static inline struct platform_device *__init imx_add_flexcan(int id,
-               resource_size_t iobase, resource_size_t iosize,
-               resource_size_t irq,
-               const struct flexcan_platform_data *pdata)
-{
-       return NULL;
-}
-#endif
 
 #include <mach/i2c.h>
-struct platform_device *__init imx_add_imx_i2c(int id,
-               resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_imx_i2c_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_i2c(
+               const struct imx_imx_i2c_data *data,
                const struct imxi2c_platform_data *pdata);
 
+#include <mach/ssi.h>
+struct imx_imx_ssi_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t irq;
+       resource_size_t dmatx0;
+       resource_size_t dmarx0;
+       resource_size_t dmatx1;
+       resource_size_t dmarx1;
+};
+struct platform_device *__init imx_add_imx_ssi(
+               const struct imx_imx_ssi_data *data,
+               const struct imx_ssi_platform_data *pdata);
+
 #include <mach/imx-uart.h>
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
-               resource_size_t iobase, resource_size_t iosize,
-               resource_size_t irqrx, resource_size_t irqtx,
-               resource_size_t irqrts,
+struct imx_imx_uart_3irq_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t irqrx;
+       resource_size_t irqtx;
+       resource_size_t irqrts;
+};
+struct platform_device *__init imx_add_imx_uart_3irq(
+               const struct imx_imx_uart_3irq_data *data,
                const struct imxuart_platform_data *pdata);
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
-               resource_size_t iobase, resource_size_t iosize,
-               resource_size_t irq,
+
+struct imx_imx_uart_1irq_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_uart_1irq(
+               const struct imx_imx_uart_1irq_data *data,
                const struct imxuart_platform_data *pdata);
 
 #include <mach/mxc_nand.h>
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
-               int irq, const struct mxc_nand_platform_data *pdata);
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
-               int irq, const struct mxc_nand_platform_data *pdata);
+struct imx_mxc_nand_data {
+       /*
+        * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
+        * machines but don't change existing devices as the nand device usually
+        * appears in the kernel command line to pass its partitioning.
+        */
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t axibase;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_nand(
+               const struct imx_mxc_nand_data *data,
+               const struct mxc_nand_platform_data *pdata);
 
 #include <mach/spi.h>
-struct platform_device *__init imx_add_spi_imx(int id,
-               resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_spi_imx_data {
+       const char *devid;
+       int id;
+       resource_size_t iobase;
+       resource_size_t iosize;
+       int irq;
+};
+struct platform_device *__init imx_add_spi_imx(
+               const struct imx_spi_imx_data *data,
                const struct spi_imx_master *pdata);
+
+#include <mach/esdhc.h>
+struct imx_esdhc_imx_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_esdhc(
+               const struct imx_esdhc_imx_data *data,
+               const struct esdhc_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
new file mode 100644 (file)
index 0000000..a48a9aa
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2010 Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef __ASM_ARCH_IMX_ESDHC_H
+#define __ASM_ARCH_IMX_ESDHC_H
+
+struct esdhc_platform_data {
+       unsigned int wp_gpio;   /* write protect pin */
+};
+#endif /* __ASM_ARCH_IMX_ESDHC_H */
index 634e3f4c454df222728aa678bdcd657967286dbc..a21d3313f9942eeb5233e74490d2f68c78ae1b4b 100644 (file)
  * its own devices, it calls baseboard's init function.
  * TODO: Add your own baseboard init function and call it from
  * inside eukrea_cpuimx25_init() eukrea_cpuimx27_init()
- * eukrea_cpuimx35_init() or eukrea_cpuimx51_init().
+ * eukrea_cpuimx35_init() eukrea_cpuimx51_init()
+ * or eukrea_cpuimx51sd_init().
  *
  * This example here is for the development board. Refer
  * mach-mx25/eukrea_mbimxsd-baseboard.c for cpuimx25
  * mach-imx/eukrea_mbimx27-baseboard.c for cpuimx27
  * mach-mx3/eukrea_mbimxsd-baseboard.c for cpuimx35
  * mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51
+ * mach-mx5/eukrea_mbimxsd-baseboard.c for cpuimx51sd
  */
 
-extern void eukrea_mbimx25_baseboard_init(void);
+extern void eukrea_mbimxsd25_baseboard_init(void);
 extern void eukrea_mbimx27_baseboard_init(void);
-extern void eukrea_mbimx35_baseboard_init(void);
+extern void eukrea_mbimxsd35_baseboard_init(void);
 extern void eukrea_mbimx51_baseboard_init(void);
+extern void eukrea_mbimxsd51_baseboard_init(void);
 
 #endif
 
index 21bfa46785bb5254e16ed1cfd8f36d7e384dbfcc..e46b1c2836d4c6d42a095eeae4a06ccc15f8d896 100644 (file)
@@ -45,6 +45,18 @@ typedef enum iomux_config {
                                PAD_CTL_PKE | PAD_CTL_HYS)
 #define MX51_GPIO_PAD_CTRL             (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
                                PAD_CTL_SRE_FAST)
+#define MX51_ECSPI_PAD_CTRL    (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
+                               PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL    (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
+                               PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
+                               PAD_CTL_DVS)
+
+#define MX51_PAD_CTRL_1        (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
+                                       PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_2        (PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_3        (PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_CTRL_4        (PAD_CTL_DVS | PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_5        (PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
 
 /*
  * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
@@ -106,14 +118,20 @@ typedef enum iomux_config {
 #define MX51_PAD_EIM_EB0__EIM_EB0               IOMUX_PAD(0x460, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_EB1__EIM_EB1               IOMUX_PAD(0x464, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_EB2__GPIO_2_22             IOMUX_PAD(0x468, 0x0d4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO             IOMUX_PAD(0x468, 0x0d4, 3, 0x0,   0, MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
 #define MX51_PAD_EIM_EB3__GPIO_2_23             IOMUX_PAD(0x46c, 0x0d8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDAT1            IOMUX_PAD(0x46c, 0x0d8, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_OE__GPIO_2_24              IOMUX_PAD(0x470, 0x0dc, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS0__GPIO_2_25             IOMUX_PAD(0x474, 0x0e0, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS1__GPIO_2_26             IOMUX_PAD(0x478, 0x0e4, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS2__GPIO_2_27             IOMUX_PAD(0x47c, 0x0e8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDAT2            IOMUX_PAD(0x47c, 0x0e8, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS3__GPIO_2_28             IOMUX_PAD(0x480, 0x0ec, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDAT3            IOMUX_PAD(0x480, 0x0ec, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS4__GPIO_2_29             IOMUX_PAD(0x484, 0x0f0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER            IOMUX_PAD(0x484, 0x0f0, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS5__GPIO_2_30             IOMUX_PAD(0x488, 0x0f4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS              IOMUX_PAD(0x488, 0x0f4, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_DTACK__GPIO_2_31           IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_LBA__GPIO_3_1              IOMUX_PAD(0x494, 0x0FC, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__GPIO_3_2              IOMUX_PAD(0x4A0, 0x100, 1, 0x0,   0, NO_PAD_CTRL)
@@ -126,18 +144,32 @@ typedef enum iomux_config {
 #define MX51_PAD_NANDF_RB0__GPIO_3_8            IOMUX_PAD(0x4F8, 0x11C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__GPIO_3_9            IOMUX_PAD(0x4FC, 0x120, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__GPIO_3_10           IOMUX_PAD(0x500, 0x124, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK         IOMUX_PAD(0x500, 0x124, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL            IOMUX_PAD(0x500, 0x124, 1, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_NANDF_RB3__GPIO_3_11           IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO         IOMUX_PAD(0x504, 0x128, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RXCLK          IOMUX_PAD(0x504, 0x128, 1, 0x0,   0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB6__FEC_RDAT0          IOMUX_PAD(0x5DC, 0x134, 1, 0x0,   0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RB7__FEC_TDAT0          IOMUX_PAD(0x5E0, 0x138, 1, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_GPIO_NAND__GPIO_3_12           IOMUX_PAD(0x514, 0x12C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS0__GPIO_3_16           IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS1__GPIO_3_17           IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS2__GPIO_3_18           IOMUX_PAD(0x520, 0x138, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER          IOMUX_PAD(0x520, 0x138, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS3__GPIO_3_19           IOMUX_PAD(0x524, 0x13C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC            IOMUX_PAD(0x524, 0x13C, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS4__GPIO_3_20           IOMUX_PAD(0x528, 0x140, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDAT1          IOMUX_PAD(0x528, 0x140, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS5__GPIO_3_21           IOMUX_PAD(0x52C, 0x144, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDAT2          IOMUX_PAD(0x52C, 0x144, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS6__GPIO_3_22           IOMUX_PAD(0x530, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDAT3          IOMUX_PAD(0x530, 0x148, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS7__GPIO_3_23           IOMUX_PAD(0x534, 0x14C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN          IOMUX_PAD(0x534, 0x14C, 1, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_RDY_INT__GPIO_3_24       IOMUX_PAD(0x538, 0x150, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK     IOMUX_PAD(0x538, 0x150, 1, 0x0,   0, MX51_PAD_CTRL_4)
 #define MX51_PAD_NANDF_D15__GPIO_3_25           IOMUX_PAD(0x53C, 0x154, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI         IOMUX_PAD(0x53C, 0x154, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_NANDF_D14__GPIO_3_26           IOMUX_PAD(0x540, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_D13__GPIO_3_27           IOMUX_PAD(0x544, 0x15C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_D12__GPIO_3_28           IOMUX_PAD(0x548, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
@@ -185,15 +217,25 @@ typedef enum iomux_config {
 #define MX51_PAD_I2C1_CLK__HSI2C_CLK           IOMUX_PAD(0x5E8, 0x1F8, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_I2C1_DAT__GPIO_4_17            IOMUX_PAD(0x5EC, 0x1FC, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_I2C1_DAT__HSI2C_DAT           IOMUX_PAD(0x5EC, 0x1FC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_BB_TXD       IOMUX_PAD(0x5F0, 0x200, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_TXD__GPIO_4_18         IOMUX_PAD(0x5F0, 0x200, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_BB_RXD       IOMUX_PAD(0x5F4, 0x204, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_RXD__GPIO_4_19         IOMUX_PAD(0x5F4, 0x204, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_BB_CK         IOMUX_PAD(0x5F8, 0x208, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_CK__GPIO_4_20          IOMUX_PAD(0x5F8, 0x208, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_BB_FS         IOMUX_PAD(0x5FC, 0x20C, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_FS__GPIO_4_21          IOMUX_PAD(0x5FC, 0x20C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI        IOMUX_PAD(0x600, 0x210, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_MOSI__GPIO_4_22          IOMUX_PAD(0x600, 0x210, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO        IOMUX_PAD(0x604, 0x214, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_MISO__GPIO_4_23          IOMUX_PAD(0x604, 0x214, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0          IOMUX_PAD(0x608, 0x218, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SS0__GPIO_4_24           IOMUX_PAD(0x608, 0x218, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1          IOMUX_PAD(0x60C, 0x21C, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SS1__GPIO_4_25           IOMUX_PAD(0x60C, 0x21C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY          IOMUX_PAD(0x610, 0x220, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_RDY__GPIO_4_26           IOMUX_PAD(0x610, 0x220, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK        IOMUX_PAD(0x614, 0x224, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SCLK__GPIO_4_27          IOMUX_PAD(0x614, 0x224, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_UART1_RXD__UART1_RXD           IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
 #define MX51_PAD_UART1_TXD__UART1_TXD           IOMUX_PAD(0x61C, 0x22C, 0, 0x0,   0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
@@ -236,14 +278,14 @@ typedef enum iomux_config {
 #define MX51_PAD_USBH1_DATA6__USBH1_DATA6       IOMUX_PAD(0x6A0, 0x2A0, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
 #define MX51_PAD_USBH1_DATA7__USBH1_DATA7       IOMUX_PAD(0x6A4, 0x2A4, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
 #define MX51_PAD_DI1_PIN11__GPIO_3_0            IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO_3_1            IOMUX_PAD(0x6AC, 0x2AC, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO_3_2            IOMUX_PAD(0x6B0, 0x2B0, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO_3_3            IOMUX_PAD(0x6B4, 0x2B4, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO_3_4            IOMUX_PAD(0x6B8, 0x2B8, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5       IOMUX_PAD(0x6BC, 0x2BC, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6       IOMUX_PAD(0x6C0, 0x2C0, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7       IOMUX_PAD(0x6C4, 0x2C4, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8        IOMUX_PAD(0x6C8, 0x2C8, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO_3_1            IOMUX_PAD(0x6AC, 0x2AC, 4, 0x978, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO_3_2            IOMUX_PAD(0x6B0, 0x2B0, 4, 0x97c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO_3_3            IOMUX_PAD(0x6B4, 0x2B4, 4, 0x980, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO_3_4            IOMUX_PAD(0x6B8, 0x2B8, 4, 0x984, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5       IOMUX_PAD(0x6BC, 0x2BC, 4, 0x988, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6       IOMUX_PAD(0x6C0, 0x2C0, 4, 0x98c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7       IOMUX_PAD(0x6C4, 0x2C4, 4, 0x990, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8        IOMUX_PAD(0x6C8, 0x2C8, 4, 0x994, 1, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT0__DISP1_DAT0         IOMUX_PAD(0x6CC, 0x2CC, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT1__DISP1_DAT1         IOMUX_PAD(0x6D0, 0x2D0, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT2__DISP1_DAT2         IOMUX_PAD(0x6D4, 0x2D4, 0, 0x0,   0, NO_PAD_CTRL)
@@ -294,32 +336,50 @@ typedef enum iomux_config {
 #define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD               IOMUX_PAD(0x79C, 0x394, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK               IOMUX_PAD(0x7A0, 0x398, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0           IOMUX_PAD(0x7A4, 0x39C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1           IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2           IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3           IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_0__GPIO_1_0            IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1            IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD               IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK               IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0           IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1           IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2           IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3           IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_2__GPIO_1_2            IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD              IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS             IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK              IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_CLK__AUD5_RXC              IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0          IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD            IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1          IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD            IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2          IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC            IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3          IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS           IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD              IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK              IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0          IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1          IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2          IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3          IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
+                                                       MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO_1_0__GPIO_1_0            IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO_1_1            IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_2__GPIO_1_2            IOMUX_PAD(0x7D4, 0x3CC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__I2C2_SCL            IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
                                                        0x9b8,   3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO_1_3__GPIO_1_3            IOMUX_PAD(0x7D8, 0x3D0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_3__GPIO_1_3            IOMUX_PAD(0x7D8, 0x3D0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_3__I2C2_SDA            IOMUX_PAD(0x7D8, 0x3D0, (2 | IOMUX_CONFIG_SION), \
                                                        0x9bc,   3, MX51_I2C_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ    IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_4__GPIO_1_4            IOMUX_PAD(0x804, 0x3D8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5            IOMUX_PAD(0x808, 0x3DC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_6__GPIO_1_6            IOMUX_PAD(0x80C, 0x3E0, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_7__GPIO_1_7            IOMUX_PAD(0x810, 0x3E4, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_8__GPIO_1_8            IOMUX_PAD(0x814, 0x3E8, 0, 0x0,   1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_9__GPIO_1_9            IOMUX_PAD(0x818, 0x3EC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_4__GPIO_1_4            IOMUX_PAD(0x804, 0x3D8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO_1_5            IOMUX_PAD(0x808, 0x3DC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_6__GPIO_1_6            IOMUX_PAD(0x80C, 0x3E0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_7__GPIO_1_7            IOMUX_PAD(0x810, 0x3E4, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_8__GPIO_1_8            IOMUX_PAD(0x814, 0x3E8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_9__GPIO_1_9            IOMUX_PAD(0x818, 0x3EC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iram.h b/arch/arm/plat-mxc/include/mach/iram.h
new file mode 100644 (file)
index 0000000..022690c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/errno.h>
+
+#ifdef CONFIG_IRAM_ALLOC
+
+int __init iram_init(unsigned long base, unsigned long size);
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
+void iram_free(unsigned long dma_addr, unsigned int size);
+
+#else
+
+static inline int __init iram_init(unsigned long base, unsigned long size)
+{
+       return -ENOMEM;
+}
+
+static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+       return NULL;
+}
+
+static inline void iram_free(unsigned long base, unsigned long size) {}
+
+#endif
index ed98b9c9f389c622db6c3fc9c41c5730852be1f9..8bc59720b6e4be8ed7b52c08bece17cf35c0cfb1 100644 (file)
 #define MX21_INT_GPT1          26
 #define MX21_INT_WDOG          27
 #define MX21_INT_PCMCIA                28
-#define MX21_INT_NANDFC                29
+#define MX21_INT_NFC           29
 #define MX21_INT_BMI           30
 #define MX21_INT_CSI           31
 #define MX21_INT_DMACH0                32
index 4a6f800990f83a826e687ae6a8d8776def7a3689..cf46a45b0d4e54971d3fe829bfc8a7c7942aaebc 100644 (file)
 #define MX25_SSI1_BASE_ADDR            0x50034000
 #define MX25_NFC_BASE_ADDR             0xbb000000
 #define MX25_DRYICE_BASE_ADDR          0x53ffc000
+#define MX25_ESDHC1_BASE_ADDR          0x53fb4000
+#define MX25_ESDHC2_BASE_ADDR          0x53fb8000
 #define MX25_LCDC_BASE_ADDR            0x53fbc000
 #define MX25_KPP_BASE_ADDR             0x43fa8000
+#define MX25_SDMA_BASE_ADDR            0x53fd4000
 #define MX25_OTG_BASE_ADDR             0x53ff4000
 #define MX25_CSI_BASE_ADDR             0x53ff8000
 
@@ -59,6 +62,8 @@
 #define MX25_INT_I2C1          3
 #define MX25_INT_I2C2          4
 #define MX25_INT_UART4         5
+#define MX25_INT_ESDHC2                8
+#define MX25_INT_ESDHC1                9
 #define MX25_INT_I2C3          10
 #define MX25_INT_SSI2          11
 #define MX25_INT_SSI1          12
@@ -69,7 +74,8 @@
 #define MX25_INT_KPP           24
 #define MX25_INT_DRYICE                25
 #define MX25_INT_UART2         32
-#define MX25_INT_NANDFC                33
+#define MX25_INT_NFC           33
+#define MX25_INT_SDMA          34
 #define MX25_INT_LCDC          39
 #define MX25_INT_UART5         40
 #define MX25_INT_CAN1          43
 #define MX25_INT_UART1         45
 #define MX25_INT_FEC           57
 
+#define MX25_DMA_REQ_SSI2_RX1  22
+#define MX25_DMA_REQ_SSI2_TX1  23
+#define MX25_DMA_REQ_SSI2_RX0  24
+#define MX25_DMA_REQ_SSI2_TX0  25
+#define MX25_DMA_REQ_SSI1_RX1  26
+#define MX25_DMA_REQ_SSI1_TX1  27
+#define MX25_DMA_REQ_SSI1_RX0  28
+#define MX25_DMA_REQ_SSI1_TX0  29
+
 #endif /* ifndef __MACH_MX25_H__ */
index a8ab2e02a8caf36460591865237e6d6c34d534de..2237ba2e53519230f2d8986af241558b6822925c 100644 (file)
@@ -167,7 +167,7 @@ static inline void mx27_setup_weimcs(size_t cs,
 #define MX27_INT_GPT1          26
 #define MX27_INT_WDOG          27
 #define MX27_INT_PCMCIA                28
-#define MX27_INT_NANDFC                29
+#define MX27_INT_NFC           29
 #define MX27_INT_ATA           30
 #define MX27_INT_CSI           31
 #define MX27_INT_DMACH0                32
index afee3ab9d62e2aef32a366f21c82350a562dab22..03e2afabc9fc15b662e1bc444c3ff6df4890f519 100644 (file)
@@ -168,7 +168,7 @@ static inline void mx31_setup_weimcs(size_t cs,
 #define MX31_INT_POWER_FAIL    30
 #define MX31_INT_CCM_DVFS      31
 #define MX31_INT_UART2         32
-#define MX31_INT_NANDFC                33
+#define MX31_INT_NFC           33
 #define MX31_INT_SDMA          34
 #define MX31_INT_USB1          35
 #define MX31_INT_USB2          36
@@ -197,6 +197,15 @@ static inline void mx31_setup_weimcs(size_t cs,
 #define MX31_INT_EXT_WDOG      62
 #define MX31_INT_EXT_TV                63
 
+#define MX31_DMA_REQ_SSI2_RX1  22
+#define MX31_DMA_REQ_SSI2_TX1  23
+#define MX31_DMA_REQ_SSI2_RX0  24
+#define MX31_DMA_REQ_SSI2_TX0  25
+#define MX31_DMA_REQ_SSI1_RX1  26
+#define MX31_DMA_REQ_SSI1_TX1  27
+#define MX31_DMA_REQ_SSI1_RX0  28
+#define MX31_DMA_REQ_SSI1_TX0  29
+
 #define MX31_PROD_SIGNATURE            0x1     /* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
index af3038c12e39c03b16d00855e5f5f40b75ba9b97..ff905cb324589f6c163aa9cd2d7996a017afe6bc 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef __MACH_MX35_H__
 #define __MACH_MX35_H__
+
 /*
  * IRAM
  */
@@ -52,6 +53,9 @@
 #define MX35_GPIO3_BASE_ADDR                   (MX35_AIPS2_BASE_ADDR + 0xa4000)
 #define MX35_SCC_BASE_ADDR                     (MX35_AIPS2_BASE_ADDR + 0xac000)
 #define MX35_RNGA_BASE_ADDR                    (MX35_AIPS2_BASE_ADDR + 0xb0000)
+#define MX35_ESDHC1_BASE_ADDR                  (MX35_AIPS2_BASE_ADDR + 0xb4000)
+#define MX35_ESDHC2_BASE_ADDR                  (MX35_AIPS2_BASE_ADDR + 0xb8000)
+#define MX35_ESDHC3_BASE_ADDR                  (MX35_AIPS2_BASE_ADDR + 0xbc000)
 #define MX35_IPU_CTRL_BASE_ADDR                        (MX35_AIPS2_BASE_ADDR + 0xc0000)
 #define MX35_AUDMUX_BASE_ADDR                  (MX35_AIPS2_BASE_ADDR + 0xc4000)
 #define MX35_GPIO1_BASE_ADDR                   (MX35_AIPS2_BASE_ADDR + 0xcc000)
@@ -63,6 +67,8 @@
 #define MX35_CAN1_BASE_ADDR                    (MX35_AIPS2_BASE_ADDR + 0xe4000)
 #define MX35_CAN2_BASE_ADDR                    (MX35_AIPS2_BASE_ADDR + 0xe8000)
 #define MX35_RTIC_BASE_ADDR                    (MX35_AIPS2_BASE_ADDR + 0xec000)
+#define MX35_IIM_BASE_ADDR                     (MX35_AIPS2_BASE_ADDR + 0xf0000)
+
 #define MX35_OTG_BASE_ADDR             0x53ff4000
 
 #define MX35_ROMP_BASE_ADDR            0x60000000
 #define MX35_INT_I2C3          3
 #define MX35_INT_I2C2          4
 #define MX35_INT_RTIC          6
-#define MX35_INT_MMC_SDHC1     7
-#define MX35_INT_MMC_SDHC2     8
-#define MX35_INT_MMC_SDHC3     9
+#define MX35_INT_ESDHC1                7
+#define MX35_INT_ESDHC2                8
+#define MX35_INT_ESDHC3                9
 #define MX35_INT_I2C1          10
 #define MX35_INT_SSI1          11
 #define MX35_INT_SSI2          12
 #define MX35_INT_GPT           29
 #define MX35_INT_POWER_FAIL    30
 #define MX35_INT_UART2         32
-#define MX35_INT_NANDFC                33
+#define MX35_INT_NFC           33
 #define MX35_INT_SDMA          34
 #define MX35_INT_USBHS         35
 #define MX35_INT_USBOTG                37
 #define MX35_INT_EXT_WDOG      62
 #define MX35_INT_EXT_TV                63
 
+#define MX35_DMA_REQ_SSI2_RX1   22
+#define MX35_DMA_REQ_SSI2_TX1   23
+#define MX35_DMA_REQ_SSI2_RX0   24
+#define MX35_DMA_REQ_SSI2_TX0   25
+#define MX35_DMA_REQ_SSI1_RX1   26
+#define MX35_DMA_REQ_SSI1_TX1   27
+#define MX35_DMA_REQ_SSI1_RX0   28
+#define MX35_DMA_REQ_SSI1_TX0   29
+
 #define MX35_PROD_SIGNATURE            0x1     /* For MX31 */
 
-/* silicon revisions specific to i.MX31 */
-#define MX35_CHIP_REV_1_0              0x10
-#define MX35_CHIP_REV_1_1              0x11
-#define MX35_CHIP_REV_1_2              0x12
-#define MX35_CHIP_REV_1_3              0x13
-#define MX35_CHIP_REV_2_0              0x20
-#define MX35_CHIP_REV_2_1              0x21
-#define MX35_CHIP_REV_2_2              0x22
-#define MX35_CHIP_REV_2_3              0x23
-#define MX35_CHIP_REV_3_0              0x30
-#define MX35_CHIP_REV_3_1              0x31
-#define MX35_CHIP_REV_3_2              0x32
-
-#define MX35_SYSTEM_REV_MIN            MX35_CHIP_REV_1_0
+#define MX35_SYSTEM_REV_MIN            MX3x_CHIP_REV_1_0
 #define MX35_SYSTEM_REV_NUM            3
 
 #ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
index 7a356de385f5992166bf49861bad48a92f4c244b..d1bd26d7b8a694cb887ef19823a41f94300c5316 100644 (file)
 
 #define MX3x_PROD_SIGNATURE            0x1     /* For MX31 */
 
-/* silicon revisions specific to i.MX31 */
+/* silicon revisions specific to i.MX31 and i.MX35 */
 #define MX3x_CHIP_REV_1_0              0x10
 #define MX3x_CHIP_REV_1_1              0x11
 #define MX3x_CHIP_REV_1_2              0x12
@@ -267,6 +267,14 @@ static inline int mx31_revision(void)
 {
        return mx31_cpu_rev;
 }
+
+extern unsigned int mx35_cpu_rev;
+extern void mx35_read_cpu_rev(void);
+
+static inline int mx35_revision(void)
+{
+       return mx35_cpu_rev;
+}
 #endif
 
 #ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
@@ -389,19 +397,6 @@ static inline int mx31_revision(void)
 #define MXC_INT_EXT_WDOG MX3x_INT_EXT_WDOG
 #define MXC_INT_EXT_TV MX3x_INT_EXT_TV
 #define PROD_SIGNATURE MX3x_PROD_SIGNATURE
-#define CHIP_REV_1_0 MX3x_CHIP_REV_1_0
-#define CHIP_REV_1_1 MX3x_CHIP_REV_1_1
-#define CHIP_REV_1_2 MX3x_CHIP_REV_1_2
-#define CHIP_REV_1_3 MX3x_CHIP_REV_1_3
-#define CHIP_REV_2_0 MX3x_CHIP_REV_2_0
-#define CHIP_REV_2_1 MX3x_CHIP_REV_2_1
-#define CHIP_REV_2_2 MX3x_CHIP_REV_2_2
-#define CHIP_REV_2_3 MX3x_CHIP_REV_2_3
-#define CHIP_REV_3_0 MX3x_CHIP_REV_3_0
-#define CHIP_REV_3_1 MX3x_CHIP_REV_3_1
-#define CHIP_REV_3_2 MX3x_CHIP_REV_3_2
-#define SYSTEM_REV_MIN MX3x_SYSTEM_REV_MIN
-#define SYSTEM_REV_NUM MX3x_SYSTEM_REV_NUM
 #endif
 
 #endif /* ifndef __MACH_MX3x_H__ */
index 5aad344d56515c82a1ef7eaf0dd5e9248e15ab7c..2af7a1056fc17661d69e0ef900349aa317a98eba 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_ARCH_MXC_MX51_H__
-#define __ASM_ARCH_MXC_MX51_H__
+#ifndef __MACH_MX51_H__
+#define __MACH_MX51_H__
 
 /*
  * MX51 memory map:
@@ -7,24 +7,23 @@
  *
  * Virt                Phys            Size    What
  * ---------------------------------------------------------------------------
- * FA3E0000    1FFE0000        128K    IRAM (SCCv2 RAM)
+ * fa3e0000    1ffe0000        128K    IRAM (SCCv2 RAM)
  *             30000000        256M    GPU
  *             40000000        512M    IPU
- * FA200000    60000000        1M      DEBUG
- * FB100000    70000000        1M      SPBA 0
- * FB000000    73F00000        1M      AIPS 1
- * FB200000    83F00000        1M      AIPS 2
- *             8FFFC000        16K     TZIC (interrupt controller)
+ * fa200000    60000000        1M      DEBUG
+ * fb100000    70000000        1M      SPBA 0
+ * fb000000    73f00000        1M      AIPS 1
+ * fb200000    83f00000        1M      AIPS 2
+ *             8fffc000        16K     TZIC (interrupt controller)
  *             90000000        256M    CSD0 SDRAM/DDR
- *             A0000000        256M    CSD1 SDRAM/DDR
- *             B0000000        128M    CS0 Flash
- *             B8000000        128M    CS1 Flash
- *             C0000000        128M    CS2 Flash
- *             C8000000        64M     CS3 Flash
- *             CC000000        32M     CS4 SRAM
- *             CE000000        32M     CS5 SRAM
- *             CFFF0000        64K     NFC (NAND Flash AXI)
- *
+ *             a0000000        256M    CSD1 SDRAM/DDR
+ *             b0000000        128M    CS0 Flash
+ *             b8000000        128M    CS1 Flash
+ *             c0000000        128M    CS2 Flash
+ *             c8000000        64M     CS3 Flash
+ *             cc000000        32M     CS4 SRAM
+ *             ce000000        32M     CS5 SRAM
+ *             cfff0000        64K     NFC (NAND Flash AXI)
  */
 
 /*
 /*
  * IRAM
  */
-#define MX51_IRAM_BASE_ADDR            0x1FFE0000      /* internal ram */
-#define MX51_IRAM_BASE_ADDR_VIRT       0xFA3E0000
+#define MX51_IRAM_BASE_ADDR            0x1ffe0000      /* internal ram */
+#define MX51_IRAM_BASE_ADDR_VIRT       0xfa3e0000
 #define MX51_IRAM_PARTITIONS           16
-#define MX51_IRAM_PARTITIONS_TO1       12
 #define MX51_IRAM_SIZE         (MX51_IRAM_PARTITIONS * SZ_8K)  /* 128KB */
 
+#define MX51_GPU_BASE_ADDR             0x20000000
+#define MX51_GPU_CTRL_BASE_ADDR                0x30000000
+#define MX51_IPU_CTRL_BASE_ADDR                0x40000000
+
+#define MX51_DEBUG_BASE_ADDR           0x60000000
+#define MX51_DEBUG_BASE_ADDR_VIRT      0xfa200000
+#define MX51_DEBUG_SIZE                        SZ_1M
+
+#define MX51_ETB_BASE_ADDR             (MX51_DEBUG_BASE_ADDR + 0x01000)
+#define MX51_ETM_BASE_ADDR             (MX51_DEBUG_BASE_ADDR + 0x02000)
+#define MX51_TPIU_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x03000)
+#define MX51_CTI0_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x04000)
+#define MX51_CTI1_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x05000)
+#define MX51_CTI2_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x06000)
+#define MX51_CTI3_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x07000)
+#define MX51_CORTEX_DBG_BASE_ADDR      (MX51_DEBUG_BASE_ADDR + 0x08000)
+
 /*
- * NFC
+ * SPBA global module enabled #0
  */
-#define MX51_NFC_AXI_BASE_ADDR         0xCFFF0000      /* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE              SZ_64K
+#define MX51_SPBA0_BASE_ADDR           0x70000000
+#define MX51_SPBA0_BASE_ADDR_VIRT      0xfb100000
+#define MX51_SPBA0_SIZE                        SZ_1M
+
+#define MX51_ESDHC1_BASE_ADDR          (MX51_SPBA0_BASE_ADDR + 0x04000)
+#define MX51_ESDHC2_BASE_ADDR          (MX51_SPBA0_BASE_ADDR + 0x08000)
+#define MX51_UART3_BASE_ADDR           (MX51_SPBA0_BASE_ADDR + 0x0c000)
+#define MX51_ECSPI1_BASE_ADDR          (MX51_SPBA0_BASE_ADDR + 0x10000)
+#define MX51_SSI2_BASE_ADDR            (MX51_SPBA0_BASE_ADDR + 0x14000)
+#define MX51_ESDHC3_BASE_ADDR          (MX51_SPBA0_BASE_ADDR + 0x20000)
+#define MX51_ESDHC4_BASE_ADDR          (MX51_SPBA0_BASE_ADDR + 0x24000)
+#define MX51_SPDIF_BASE_ADDR           (MX51_SPBA0_BASE_ADDR + 0x28000)
+#define MX51_ATA_DMA_BASE_ADDR         (MX51_SPBA0_BASE_ADDR + 0x30000)
+#define MX51_SLIM_DMA_BASE_ADDR                (MX51_SPBA0_BASE_ADDR + 0x34000)
+#define MX51_HSI2C_DMA_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x38000)
+#define MX51_SPBA_CTRL_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x3c000)
 
 /*
- * Graphics Memory of GPU
+ * AIPS 1
  */
-#define MX51_GPU_BASE_ADDR             0x20000000
-#define MX51_GPU2D_BASE_ADDR           0xD0000000
+#define MX51_AIPS1_BASE_ADDR           0x73f00000
+#define MX51_AIPS1_BASE_ADDR_VIRT      0xfb000000
+#define MX51_AIPS1_SIZE                        SZ_1M
+
+#define MX51_OTG_BASE_ADDR             (MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_GPIO1_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0x84000)
+#define MX51_GPIO2_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0x88000)
+#define MX51_GPIO3_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0x8c000)
+#define MX51_GPIO4_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0x90000)
+#define MX51_KPP_BASE_ADDR             (MX51_AIPS1_BASE_ADDR + 0x94000)
+#define MX51_WDOG_BASE_ADDR            (MX51_AIPS1_BASE_ADDR + 0x98000)
+#define MX51_WDOG2_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0x9c000)
+#define MX51_GPT1_BASE_ADDR            (MX51_AIPS1_BASE_ADDR + 0xa0000)
+#define MX51_SRTC_BASE_ADDR            (MX51_AIPS1_BASE_ADDR + 0xa4000)
+#define MX51_IOMUXC_BASE_ADDR          (MX51_AIPS1_BASE_ADDR + 0xa8000)
+#define MX51_EPIT1_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0xac000)
+#define MX51_EPIT2_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0xb0000)
+#define MX51_PWM1_BASE_ADDR            (MX51_AIPS1_BASE_ADDR + 0xb4000)
+#define MX51_PWM2_BASE_ADDR            (MX51_AIPS1_BASE_ADDR + 0xb8000)
+#define MX51_UART1_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0xbc000)
+#define MX51_UART2_BASE_ADDR           (MX51_AIPS1_BASE_ADDR + 0xc0000)
+#define MX51_SRC_BASE_ADDR             (MX51_AIPS1_BASE_ADDR + 0xd0000)
+#define MX51_CCM_BASE_ADDR             (MX51_AIPS1_BASE_ADDR + 0xd4000)
+#define MX51_GPC_BASE_ADDR             (MX51_AIPS1_BASE_ADDR + 0xd8000)
 
-#define MX51_TZIC_BASE_ADDR_TO1                0x8FFFC000
-#define MX51_TZIC_BASE_ADDR            0xE0000000
+/*
+ * AIPS 2
+ */
+#define MX51_AIPS2_BASE_ADDR           0x83f00000
+#define MX51_AIPS2_BASE_ADDR_VIRT      0xfb200000
+#define MX51_AIPS2_SIZE                        SZ_1M
 
-#define MX51_DEBUG_BASE_ADDR           0x60000000
-#define MX51_DEBUG_BASE_ADDR_VIRT      0xFA200000
-#define MX51_DEBUG_SIZE                        SZ_1M
-#define MX51_ETB_BASE_ADDR             (MX51_DEBUG_BASE_ADDR + 0x00001000)
-#define MX51_ETM_BASE_ADDR             (MX51_DEBUG_BASE_ADDR + 0x00002000)
-#define MX51_TPIU_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x00003000)
-#define MX51_CTI0_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x00004000)
-#define MX51_CTI1_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x00005000)
-#define MX51_CTI2_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x00006000)
-#define MX51_CTI3_BASE_ADDR            (MX51_DEBUG_BASE_ADDR + 0x00007000)
-#define MX51_CORTEX_DBG_BASE_ADDR      (MX51_DEBUG_BASE_ADDR + 0x00008000)
+#define MX51_PLL1_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0x80000)
+#define MX51_PLL2_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0x84000)
+#define MX51_PLL3_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0x88000)
+#define MX51_AHBMAX_BASE_ADDR          (MX51_AIPS2_BASE_ADDR + 0x94000)
+#define MX51_IIM_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0x98000)
+#define MX51_CSU_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0x9c000)
+#define MX51_ARM_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xa0000)
+#define MX51_OWIRE_BASE_ADDR           (MX51_AIPS2_BASE_ADDR + 0xa4000)
+#define MX51_FIRI_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xa8000)
+#define MX51_ECSPI2_BASE_ADDR          (MX51_AIPS2_BASE_ADDR + 0xac000)
+#define MX51_SDMA_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xb0000)
+#define MX51_SCC_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xb4000)
+#define MX51_ROMCP_BASE_ADDR           (MX51_AIPS2_BASE_ADDR + 0xb8000)
+#define MX51_RTIC_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xbc000)
+#define MX51_CSPI_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xc0000)
+#define MX51_I2C2_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xc4000)
+#define MX51_I2C1_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xc8000)
+#define MX51_SSI1_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xcc000)
+#define MX51_AUDMUX_BASE_ADDR          (MX51_AIPS2_BASE_ADDR + 0xd0000)
+#define MX51_M4IF_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xd8000)
+#define MX51_ESDCTL_BASE_ADDR          (MX51_AIPS2_BASE_ADDR + 0xd9000)
+#define MX51_WEIM_BASE_ADDR            (MX51_AIPS2_BASE_ADDR + 0xda000)
+#define MX51_NFC_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xdb000)
+#define MX51_EMI_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xdbf00)
+#define MX51_MIPI_HSC_BASE_ADDR                (MX51_AIPS2_BASE_ADDR + 0xdc000)
+#define MX51_ATA_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xe0000)
+#define MX51_SIM_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xe4000)
+#define MX51_SSI3BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xe8000)
+#define MX51_FEC_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xec000)
+#define MX51_TVE_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xf0000)
+#define MX51_VPU_BASE_ADDR             (MX51_AIPS2_BASE_ADDR + 0xf4000)
+#define MX51_SAHARA_BASE_ADDR          (MX51_AIPS2_BASE_ADDR + 0xf8000)
+
+#define MX51_CSD0_BASE_ADDR            0x90000000
+#define MX51_CSD1_BASE_ADDR            0xa0000000
+#define MX51_CS0_BASE_ADDR             0xb0000000
+#define MX51_CS1_BASE_ADDR             0xb8000000
+#define MX51_CS2_BASE_ADDR             0xc0000000
+#define MX51_CS3_BASE_ADDR             0xc8000000
+#define MX51_CS4_BASE_ADDR             0xcc000000
+#define MX51_CS5_BASE_ADDR             0xce000000
 
 /*
- * SPBA global module enabled #0
+ * NFC
  */
-#define MX51_SPBA0_BASE_ADDR           0x70000000
-#define MX51_SPBA0_BASE_ADDR_VIRT      0xFB100000
-#define MX51_SPBA0_SIZE                        SZ_1M
+#define MX51_NFC_AXI_BASE_ADDR         0xcfff0000      /* NAND flash AXI */
+#define MX51_NFC_AXI_SIZE              SZ_64K
+
+#define MX51_GPU2D_BASE_ADDR           0xd0000000
+#define MX51_TZIC_BASE_ADDR            0xe0000000
 
-#define MX51_MMC_SDHC1_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x00004000)
-#define MX51_MMC_SDHC2_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x00008000)
-#define MX51_UART3_BASE_ADDR           (MX51_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX51_CSPI1_BASE_ADDR           (MX51_SPBA0_BASE_ADDR + 0x00010000)
-#define MX51_SSI2_BASE_ADDR            (MX51_SPBA0_BASE_ADDR + 0x00014000)
-#define MX51_MMC_SDHC3_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x00020000)
-#define MX51_MMC_SDHC4_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x00024000)
-#define MX51_SPDIF_BASE_ADDR           (MX51_SPBA0_BASE_ADDR + 0x00028000)
-#define MX51_ATA_DMA_BASE_ADDR         (MX51_SPBA0_BASE_ADDR + 0x00030000)
-#define MX51_SLIM_DMA_BASE_ADDR                (MX51_SPBA0_BASE_ADDR + 0x00034000)
-#define MX51_HSI2C_DMA_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x00038000)
-#define MX51_SPBA_CTRL_BASE_ADDR       (MX51_SPBA0_BASE_ADDR + 0x0003C000)
+#define MX51_IO_ADDRESS(x) (                                           \
+       IMX_IO_ADDRESS(x, MX51_IRAM) ?:                                 \
+       IMX_IO_ADDRESS(x, MX51_DEBUG) ?:                                \
+       IMX_IO_ADDRESS(x, MX51_SPBA0) ?:                                \
+       IMX_IO_ADDRESS(x, MX51_AIPS1) ?:                                \
+       IMX_IO_ADDRESS(x, MX51_AIPS2))
+
+/* This is currently used in <mach/debug-macro.S>, but should go away */
+#define MX51_AIPS1_IO_ADDRESS(x)  \
+       (((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
 
 /*
  * defines for SPBA modules
  */
 #define MX51_SPBA_SDHC1        0x04
 #define MX51_SPBA_SDHC2        0x08
-#define MX51_SPBA_UART3        0x0C
+#define MX51_SPBA_UART3        0x0c
 #define MX51_SPBA_CSPI1        0x10
 #define MX51_SPBA_SSI2 0x14
 #define MX51_SPBA_SDHC3        0x20
 #define MX51_SPBA_ATA  0x30
 #define MX51_SPBA_SLIM 0x34
 #define MX51_SPBA_HSI2C        0x38
-#define MX51_SPBA_CTRL 0x3C
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR   0x73F00000
-#define MX51_AIPS1_BASE_ADDR_VIRT      0xFB000000
-#define MX51_AIPS1_SIZE                SZ_1M
-
-#define MX51_OTG_BASE_ADDR     (MX51_AIPS1_BASE_ADDR + 0x00080000)
-#define MX51_GPIO1_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x00084000)
-#define MX51_GPIO2_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x00088000)
-#define MX51_GPIO3_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX51_GPIO4_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x00090000)
-#define MX51_KPP_BASE_ADDR     (MX51_AIPS1_BASE_ADDR + 0x00094000)
-#define MX51_WDOG_BASE_ADDR    (MX51_AIPS1_BASE_ADDR + 0x00098000)
-#define MX51_WDOG2_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX51_GPT1_BASE_ADDR    (MX51_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX51_SRTC_BASE_ADDR    (MX51_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX51_IOMUXC_BASE_ADDR  (MX51_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX51_EPIT1_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX51_EPIT2_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX51_PWM1_BASE_ADDR    (MX51_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX51_PWM2_BASE_ADDR    (MX51_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX51_UART1_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX51_UART2_BASE_ADDR   (MX51_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX51_SRC_BASE_ADDR     (MX51_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX51_CCM_BASE_ADDR     (MX51_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX51_GPC_BASE_ADDR     (MX51_AIPS1_BASE_ADDR + 0x000D8000)
+#define MX51_SPBA_CTRL 0x3c
 
 /*
  * Defines for modules using static and dynamic DMA channels
 #define MX51_MXC_DMA_CHANNEL_ATA_TX    MXC_DMA_DYNAMIC_CHANNEL
 #define MX51_MXC_DMA_CHANNEL_MEMORY    MXC_DMA_DYNAMIC_CHANNEL
 
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR           0x83F00000
-#define MX51_AIPS2_BASE_ADDR_VIRT      0xFB200000
-#define MX51_AIPS2_SIZE                        SZ_1M
-
-#define MX51_PLL1_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x00080000)
-#define MX51_PLL2_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x00084000)
-#define MX51_PLL3_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x00088000)
-#define MX51_AHBMAX_BASE_ADDR  (MX51_AIPS2_BASE_ADDR + 0x00094000)
-#define MX51_IIM_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x00098000)
-#define MX51_CSU_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX51_ARM_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX51_OWIRE_BASE_ADDR   (MX51_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX51_FIRI_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX51_CSPI2_BASE_ADDR   (MX51_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX51_SDMA_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX51_SCC_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX51_ROMCP_BASE_ADDR   (MX51_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX51_RTIC_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX51_CSPI3_BASE_ADDR   (MX51_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX51_I2C2_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX51_I2C1_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX51_SSI1_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX51_AUDMUX_BASE_ADDR  (MX51_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX51_M4IF_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX51_ESDCTL_BASE_ADDR  (MX51_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX51_WEIM_BASE_ADDR    (MX51_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX51_NFC_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX51_EMI_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX51_MIPI_HSC_BASE_ADDR        (MX51_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX51_ATA_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000E0000)
-#define MX51_SIM_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX51_SSI3BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX51_MXC_FEC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX51_TVE_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX51_VPU_BASE_ADDR     (MX51_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX51_SAHARA_BASE_ADDR  (MX51_AIPS2_BASE_ADDR + 0x000F8000)
-
-/*
- * Memory regions and CS
- */
-#define MX51_GPU_CTRL_BASE_ADDR                0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR                0x40000000
-#define MX51_CSD0_BASE_ADDR            0x90000000
-#define MX51_CSD1_BASE_ADDR            0xA0000000
-#define MX51_CS0_BASE_ADDR             0xB0000000
-#define MX51_CS1_BASE_ADDR             0xB8000000
-#define MX51_CS2_BASE_ADDR             0xC0000000
-#define MX51_CS3_BASE_ADDR             0xC8000000
-#define MX51_CS4_BASE_ADDR             0xCC000000
-#define MX51_CS5_BASE_ADDR             0xCE000000
-
-/* Does given address belongs to the specified memory region? */
-#define ADDRESS_IN_REGION(addr, start, size)                   \
-       (((addr) >= (start)) && ((addr) < (start)+(size)))
-
-/* Does given address belongs to the specified named `module'? */
-#define MX51_IS_MODULE(addr, module)                          \
-       ADDRESS_IN_REGION(addr, MX51_ ## module ## _BASE_ADDR, \
-                               MX51_ ## module ## _SIZE)
-/*
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-
-#define MX51_IO_ADDRESS(x)                                     \
-       (void __iomem *)                                        \
-       (MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) :    \
-       MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) :   \
-       MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) :   \
-       MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) :   \
-       MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \
-       0xDEADBEEF)
-
-/*
- * define the address mapping macros: in physical address order
- */
-#define MX51_IRAM_IO_ADDRESS(x)  \
-       (((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT)
-
-#define MX51_DEBUG_IO_ADDRESS(x)  \
-       (((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
-
-#define MX51_SPBA0_IO_ADDRESS(x)  \
-       (((x) - MX51_SPBA0_BASE_ADDR) + MX51_SPBA0_BASE_ADDR_VIRT)
-
-#define MX51_AIPS1_IO_ADDRESS(x)  \
-       (((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
-
-#define MX51_AIPS2_IO_ADDRESS(x)  \
-       (((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT)
-
 #define MX51_IS_MEM_DEVICE_NONSHARED(x)                0
 
 /*
  * DMA request assignments
  */
-#define MX51_DMA_REQ_SSI3_TX1  47
-#define MX51_DMA_REQ_SSI3_RX1  46
-#define MX51_DMA_REQ_SPDIF     45
-#define MX51_DMA_REQ_UART3_TX  44
-#define MX51_DMA_REQ_UART3_RX  43
-#define MX51_DMA_REQ_SLIM_B_TX 42
-#define MX51_DMA_REQ_SDHC4     41
-#define MX51_DMA_REQ_SDHC3     40
-#define MX51_DMA_REQ_CSPI_TX   39
-#define MX51_DMA_REQ_CSPI_RX   38
-#define MX51_DMA_REQ_SSI3_TX2  37
-#define MX51_DMA_REQ_IPU       36
-#define MX51_DMA_REQ_SSI3_RX2  35
-#define MX51_DMA_REQ_EPIT2     34
-#define MX51_DMA_REQ_CTI2_1    33
-#define MX51_DMA_REQ_EMI_WR    32
-#define MX51_DMA_REQ_CTI2_0    31
-#define MX51_DMA_REQ_EMI_RD    30
-#define MX51_DMA_REQ_SSI1_TX1  29
-#define MX51_DMA_REQ_SSI1_RX1  28
-#define MX51_DMA_REQ_SSI1_TX2  27
-#define MX51_DMA_REQ_SSI1_RX2  26
-#define MX51_DMA_REQ_SSI2_TX1  25
-#define MX51_DMA_REQ_SSI2_RX1  24
-#define MX51_DMA_REQ_SSI2_TX2  23
-#define MX51_DMA_REQ_SSI2_RX2  22
-#define MX51_DMA_REQ_SDHC2     21
-#define MX51_DMA_REQ_SDHC1     20
-#define MX51_DMA_REQ_UART1_TX  19
-#define MX51_DMA_REQ_UART1_RX  18
-#define MX51_DMA_REQ_UART2_TX  17
-#define MX51_DMA_REQ_UART2_RX  16
-#define MX51_DMA_REQ_GPU       15
-#define MX51_DMA_REQ_EXTREQ1   14
-#define MX51_DMA_REQ_FIRI_TX   13
-#define MX51_DMA_REQ_FIRI_RX   12
-#define MX51_DMA_REQ_HS_I2C_RX 11
-#define MX51_DMA_REQ_HS_I2C_TX 10
-#define MX51_DMA_REQ_CSPI2_TX  9
-#define MX51_DMA_REQ_CSPI2_RX  8
-#define MX51_DMA_REQ_CSPI1_TX  7
-#define MX51_DMA_REQ_CSPI1_RX  6
-#define MX51_DMA_REQ_SLIM_B    5
-#define MX51_DMA_REQ_ATA_TX_END        4
-#define MX51_DMA_REQ_ATA_TX    3
-#define MX51_DMA_REQ_ATA_RX    2
-#define MX51_DMA_REQ_GPC       1
-#define MX51_DMA_REQ_VPU       0
+#define MX51_DMA_REQ_VPU               0
+#define MX51_DMA_REQ_GPC               1
+#define MX51_DMA_REQ_ATA_RX            2
+#define MX51_DMA_REQ_ATA_TX            3
+#define MX51_DMA_REQ_ATA_TX_END                4
+#define MX51_DMA_REQ_SLIM_B            5
+#define MX51_DMA_REQ_CSPI1_RX          6
+#define MX51_DMA_REQ_CSPI1_TX          7
+#define MX51_DMA_REQ_CSPI2_RX          8
+#define MX51_DMA_REQ_CSPI2_TX          9
+#define MX51_DMA_REQ_HS_I2C_TX         10
+#define MX51_DMA_REQ_HS_I2C_RX         11
+#define MX51_DMA_REQ_FIRI_RX           12
+#define MX51_DMA_REQ_FIRI_TX           13
+#define MX51_DMA_REQ_EXTREQ1           14
+#define MX51_DMA_REQ_GPU               15
+#define MX51_DMA_REQ_UART2_RX          16
+#define MX51_DMA_REQ_UART2_TX          17
+#define MX51_DMA_REQ_UART1_RX          18
+#define MX51_DMA_REQ_UART1_TX          19
+#define MX51_DMA_REQ_SDHC1             20
+#define MX51_DMA_REQ_SDHC2             21
+#define MX51_DMA_REQ_SSI2_RX1          22
+#define MX51_DMA_REQ_SSI2_TX1          23
+#define MX51_DMA_REQ_SSI2_RX0          24
+#define MX51_DMA_REQ_SSI2_TX0          25
+#define MX51_DMA_REQ_SSI1_RX1          26
+#define MX51_DMA_REQ_SSI1_TX1          27
+#define MX51_DMA_REQ_SSI1_RX0          28
+#define MX51_DMA_REQ_SSI1_TX0          29
+#define MX51_DMA_REQ_EMI_RD            30
+#define MX51_DMA_REQ_CTI2_0            31
+#define MX51_DMA_REQ_EMI_WR            32
+#define MX51_DMA_REQ_CTI2_1            33
+#define MX51_DMA_REQ_EPIT2             34
+#define MX51_DMA_REQ_SSI3_RX2          35
+#define MX51_DMA_REQ_IPU               36
+#define MX51_DMA_REQ_SSI3_TX2          37
+#define MX51_DMA_REQ_CSPI_RX           38
+#define MX51_DMA_REQ_CSPI_TX           39
+#define MX51_DMA_REQ_SDHC3             40
+#define MX51_DMA_REQ_SDHC4             41
+#define MX51_DMA_REQ_SLIM_B_TX         42
+#define MX51_DMA_REQ_UART3_RX          43
+#define MX51_DMA_REQ_UART3_TX          44
+#define MX51_DMA_REQ_SPDIF             45
+#define MX51_DMA_REQ_SSI3_RX1          46
+#define MX51_DMA_REQ_SSI3_TX1          47
 
 /*
  * Interrupt numbers
  */
-#define MX51_MXC_INT_BASE      0
-#define MX51_MXC_INT_RESV0     0
-#define MX51_MXC_INT_MMC_SDHC1 1
-#define MX51_MXC_INT_MMC_SDHC2 2
-#define MX51_MXC_INT_MMC_SDHC3 3
-#define MX51_MXC_INT_MMC_SDHC4 4
-#define MX51_MXC_INT_RESV5     5
-#define MX51_MXC_INT_SDMA      6
-#define MX51_MXC_INT_IOMUX     7
-#define MX51_MXC_INT_NFC       8
-#define MX51_MXC_INT_VPU       9
-#define MX51_MXC_INT_IPU_ERR   10
-#define MX51_MXC_INT_IPU_SYN   11
-#define MX51_MXC_INT_GPU       12
-#define MX51_MXC_INT_RESV13    13
-#define MX51_MXC_INT_USB_H1    14
-#define MX51_MXC_INT_EMI       15
-#define MX51_MXC_INT_USB_H2    16
-#define MX51_MXC_INT_USB_H3    17
-#define MX51_MXC_INT_USB_OTG   18
-#define MX51_MXC_INT_SAHARA_H0 19
-#define MX51_MXC_INT_SAHARA_H1 20
-#define MX51_MXC_INT_SCC_SMN   21
-#define MX51_MXC_INT_SCC_STZ   22
-#define MX51_MXC_INT_SCC_SCM   23
-#define MX51_MXC_INT_SRTC_NTZ  24
-#define MX51_MXC_INT_SRTC_TZ   25
-#define MX51_MXC_INT_RTIC      26
-#define MX51_MXC_INT_CSU       27
-#define MX51_MXC_INT_SLIM_B    28
-#define MX51_MXC_INT_SSI1      29
-#define MX51_MXC_INT_SSI2      30
-#define MX51_MXC_INT_UART1     31
-#define MX51_MXC_INT_UART2     32
-#define MX51_MXC_INT_UART3     33
-#define MX51_MXC_INT_RESV34    34
-#define MX51_MXC_INT_RESV35    35
-#define MX51_MXC_INT_CSPI1     36
-#define MX51_MXC_INT_CSPI2     37
-#define MX51_MXC_INT_CSPI      38
-#define MX51_MXC_INT_GPT       39
-#define MX51_MXC_INT_EPIT1     40
-#define MX51_MXC_INT_EPIT2     41
-#define MX51_MXC_INT_GPIO1_INT7        42
-#define MX51_MXC_INT_GPIO1_INT6        43
-#define MX51_MXC_INT_GPIO1_INT5        44
-#define MX51_MXC_INT_GPIO1_INT4        45
-#define MX51_MXC_INT_GPIO1_INT3        46
-#define MX51_MXC_INT_GPIO1_INT2        47
-#define MX51_MXC_INT_GPIO1_INT1        48
-#define MX51_MXC_INT_GPIO1_INT0        49
-#define MX51_MXC_INT_GPIO1_LOW 50
-#define MX51_MXC_INT_GPIO1_HIGH        51
-#define MX51_MXC_INT_GPIO2_LOW 52
-#define MX51_MXC_INT_GPIO2_HIGH        53
-#define MX51_MXC_INT_GPIO3_LOW 54
-#define MX51_MXC_INT_GPIO3_HIGH        55
-#define MX51_MXC_INT_GPIO4_LOW 56
-#define MX51_MXC_INT_GPIO4_HIGH        57
-#define MX51_MXC_INT_WDOG1     58
-#define MX51_MXC_INT_WDOG2     59
-#define MX51_MXC_INT_KPP       60
-#define MX51_MXC_INT_PWM1      61
-#define MX51_MXC_INT_I2C1      62
-#define MX51_MXC_INT_I2C2      63
-#define MX51_MXC_INT_HS_I2C    64
-#define MX51_MXC_INT_RESV65    65
-#define MX51_MXC_INT_RESV66    66
-#define MX51_MXC_INT_SIM_IPB   67
-#define MX51_MXC_INT_SIM_DAT   68
-#define MX51_MXC_INT_IIM       69
-#define MX51_MXC_INT_ATA       70
-#define MX51_MXC_INT_CCM1      71
-#define MX51_MXC_INT_CCM2      72
-#define MX51_MXC_INT_GPC1      73
-#define MX51_MXC_INT_GPC2      74
-#define MX51_MXC_INT_SRC       75
-#define MX51_MXC_INT_NM                76
-#define MX51_MXC_INT_PMU       77
-#define MX51_MXC_INT_CTI_IRQ   78
-#define MX51_MXC_INT_CTI1_TG0  79
-#define MX51_MXC_INT_CTI1_TG1  80
-#define MX51_MXC_INT_MCG_ERR   81
-#define MX51_MXC_INT_MCG_TMR   82
-#define MX51_MXC_INT_MCG_FUNC  83
-#define MX51_MXC_INT_GPU2_IRQ  84
-#define MX51_MXC_INT_GPU2_BUSY 85
-#define MX51_MXC_INT_RESV86    86
-#define MX51_MXC_INT_FEC       87
-#define MX51_MXC_INT_OWIRE     88
-#define MX51_MXC_INT_CTI1_TG2  89
-#define MX51_MXC_INT_SJC       90
-#define MX51_MXC_INT_SPDIF     91
-#define MX51_MXC_INT_TVE       92
-#define MX51_MXC_INT_FIRI      93
-#define MX51_MXC_INT_PWM2      94
-#define MX51_MXC_INT_SLIM_EXP  95
-#define MX51_MXC_INT_SSI3      96
-#define MX51_MXC_INT_EMI_BOOT  97
-#define MX51_MXC_INT_CTI1_TG3  98
-#define MX51_MXC_INT_SMC_RX    99
-#define MX51_MXC_INT_VPU_IDLE  100
-#define MX51_MXC_INT_EMI_NFC   101
-#define MX51_MXC_INT_GPU_IDLE  102
+#define MX51_MXC_INT_BASE              0
+#define MX51_MXC_INT_RESV0             0
+#define MX51_INT_ESDHC1                        1
+#define MX51_INT_ESDHC2                        2
+#define MX51_INT_ESDHC3                        3
+#define MX51_INT_ESDHC4                        4
+#define MX51_MXC_INT_RESV5             5
+#define MX51_INT_SDMA                  6
+#define MX51_MXC_INT_IOMUX             7
+#define MX51_INT_NFC                   8
+#define MX51_MXC_INT_VPU               9
+#define MX51_MXC_INT_IPU_ERR           10
+#define MX51_MXC_INT_IPU_SYN           11
+#define MX51_MXC_INT_GPU               12
+#define MX51_MXC_INT_RESV13            13
+#define MX51_MXC_INT_USB_H1            14
+#define MX51_MXC_INT_EMI               15
+#define MX51_MXC_INT_USB_H2            16
+#define MX51_MXC_INT_USB_H3            17
+#define MX51_MXC_INT_USB_OTG           18
+#define MX51_MXC_INT_SAHARA_H0         19
+#define MX51_MXC_INT_SAHARA_H1         20
+#define MX51_MXC_INT_SCC_SMN           21
+#define MX51_MXC_INT_SCC_STZ           22
+#define MX51_MXC_INT_SCC_SCM           23
+#define MX51_MXC_INT_SRTC_NTZ          24
+#define MX51_MXC_INT_SRTC_TZ           25
+#define MX51_MXC_INT_RTIC              26
+#define MX51_MXC_INT_CSU               27
+#define MX51_MXC_INT_SLIM_B            28
+#define MX51_INT_SSI1                  29
+#define MX51_INT_SSI2                  30
+#define MX51_INT_UART1                 31
+#define MX51_INT_UART2                 32
+#define MX51_INT_UART3                 33
+#define MX51_MXC_INT_RESV34            34
+#define MX51_MXC_INT_RESV35            35
+#define MX51_INT_ECSPI1                        36
+#define MX51_INT_ECSPI2                        37
+#define MX51_INT_CSPI                  38
+#define MX51_MXC_INT_GPT               39
+#define MX51_MXC_INT_EPIT1             40
+#define MX51_MXC_INT_EPIT2             41
+#define MX51_MXC_INT_GPIO1_INT7                42
+#define MX51_MXC_INT_GPIO1_INT6                43
+#define MX51_MXC_INT_GPIO1_INT5                44
+#define MX51_MXC_INT_GPIO1_INT4                45
+#define MX51_MXC_INT_GPIO1_INT3                46
+#define MX51_MXC_INT_GPIO1_INT2                47
+#define MX51_MXC_INT_GPIO1_INT1                48
+#define MX51_MXC_INT_GPIO1_INT0                49
+#define MX51_MXC_INT_GPIO1_LOW         50
+#define MX51_MXC_INT_GPIO1_HIGH                51
+#define MX51_MXC_INT_GPIO2_LOW         52
+#define MX51_MXC_INT_GPIO2_HIGH                53
+#define MX51_MXC_INT_GPIO3_LOW         54
+#define MX51_MXC_INT_GPIO3_HIGH                55
+#define MX51_MXC_INT_GPIO4_LOW         56
+#define MX51_MXC_INT_GPIO4_HIGH                57
+#define MX51_MXC_INT_WDOG1             58
+#define MX51_MXC_INT_WDOG2             59
+#define MX51_MXC_INT_KPP               60
+#define MX51_MXC_INT_PWM1              61
+#define MX51_INT_I2C1                  62
+#define MX51_INT_I2C2                  63
+#define MX51_MXC_INT_HS_I2C            64
+#define MX51_MXC_INT_RESV65            65
+#define MX51_MXC_INT_RESV66            66
+#define MX51_MXC_INT_SIM_IPB           67
+#define MX51_MXC_INT_SIM_DAT           68
+#define MX51_MXC_INT_IIM               69
+#define MX51_MXC_INT_ATA               70
+#define MX51_MXC_INT_CCM1              71
+#define MX51_MXC_INT_CCM2              72
+#define MX51_MXC_INT_GPC1              73
+#define MX51_MXC_INT_GPC2              74
+#define MX51_MXC_INT_SRC               75
+#define MX51_MXC_INT_NM                        76
+#define MX51_MXC_INT_PMU               77
+#define MX51_MXC_INT_CTI_IRQ           78
+#define MX51_MXC_INT_CTI1_TG0          79
+#define MX51_MXC_INT_CTI1_TG1          80
+#define MX51_MXC_INT_MCG_ERR           81
+#define MX51_MXC_INT_MCG_TMR           82
+#define MX51_MXC_INT_MCG_FUNC          83
+#define MX51_MXC_INT_GPU2_IRQ          84
+#define MX51_MXC_INT_GPU2_BUSY         85
+#define MX51_MXC_INT_RESV86            86
+#define MX51_INT_FEC                   87
+#define MX51_MXC_INT_OWIRE             88
+#define MX51_MXC_INT_CTI1_TG2          89
+#define MX51_MXC_INT_SJC               90
+#define MX51_MXC_INT_SPDIF             91
+#define MX51_MXC_INT_TVE               92
+#define MX51_MXC_INT_FIRI              93
+#define MX51_MXC_INT_PWM2              94
+#define MX51_MXC_INT_SLIM_EXP          95
+#define MX51_MXC_INT_SSI3              96
+#define MX51_MXC_INT_EMI_BOOT          97
+#define MX51_MXC_INT_CTI1_TG3          98
+#define MX51_MXC_INT_SMC_RX            99
+#define MX51_MXC_INT_VPU_IDLE          100
+#define MX51_MXC_INT_EMI_NFC           101
+#define MX51_MXC_INT_GPU_IDLE          102
 
 /* silicon revisions specific to i.MX51 */
-#define MX51_CHIP_REV_1_0      0x10
-#define MX51_CHIP_REV_1_1      0x11
-#define MX51_CHIP_REV_1_2      0x12
-#define MX51_CHIP_REV_1_3      0x13
-#define MX51_CHIP_REV_2_0      0x20
-#define MX51_CHIP_REV_2_1      0x21
-#define MX51_CHIP_REV_2_2      0x22
-#define MX51_CHIP_REV_2_3      0x23
-#define MX51_CHIP_REV_3_0      0x30
-#define MX51_CHIP_REV_3_1      0x31
-#define MX51_CHIP_REV_3_2      0x32
-
-/* Mandatory defines used globally */
+#define MX51_CHIP_REV_1_0              0x10
+#define MX51_CHIP_REV_1_1              0x11
+#define MX51_CHIP_REV_1_2              0x12
+#define MX51_CHIP_REV_1_3              0x13
+#define MX51_CHIP_REV_2_0              0x20
+#define MX51_CHIP_REV_2_1              0x21
+#define MX51_CHIP_REV_2_2              0x22
+#define MX51_CHIP_REV_2_3              0x23
+#define MX51_CHIP_REV_3_0              0x30
+#define MX51_CHIP_REV_3_1              0x31
+#define MX51_CHIP_REV_3_2              0x32
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
 extern int mx51_revision(void);
 #endif
 
-#endif /*  __ASM_ARCH_MXC_MX51_H__ */
+/* tape-out 1 defines */
+#define MX51_TZIC_BASE_ADDR_TO1                0x8fffc000
+
+#endif /* ifndef __MACH_MX51_H__ */
index 4acd1143a9bdd7444c12ca547ed957b47ef302d6..95be51bfe9a966d5f30e94cdfa7607a43b3a8c58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *  Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,8 +28,34 @@ static inline void arch_idle(void)
                mxc91231_prepare_idle();
        }
 #endif
-
-       cpu_do_idle();
+       /* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
+       if (cpu_is_mx31() || cpu_is_mx35()) {
+               unsigned long reg = 0;
+               __asm__ __volatile__(
+                       /* disable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "bic %0, %0, #0x00001000\n"
+                       "bic %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       /* invalidate I cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c5, 0\n"
+                       /* clear and invalidate D cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c14, 0\n"
+                       /* WFI */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c0, 4\n"
+                       "nop\n" "nop\n" "nop\n" "nop\n"
+                       "nop\n" "nop\n" "nop\n"
+                       /* enable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "orr %0, %0, #0x00001000\n"
+                       "orr %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       : "=r" (reg));
+       } else
+               cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
index d9bd37e4667a23f04e3f20ba0fd4fcd8f599b6d6..9dd9c2085aad4f63b19f76e2277c2eb0ad72333c 100644 (file)
@@ -99,6 +99,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
                uart_base = MX3X_UART2_BASE_ADDR;
                break;
        case MACH_TYPE_MX51_BABBAGE:
+       case MACH_TYPE_EUKREA_CPUIMX51SD:
                uart_base = MX51_UART1_BASE_ADDR;
                break;
        default:
diff --git a/arch/arm/plat-mxc/iram_alloc.c b/arch/arm/plat-mxc/iram_alloc.c
new file mode 100644 (file)
index 0000000..074c386
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+#include <mach/iram.h>
+
+static unsigned long iram_phys_base;
+static void __iomem *iram_virt_base;
+static struct gen_pool *iram_pool;
+
+static inline void __iomem *iram_phys_to_virt(unsigned long p)
+{
+       return iram_virt_base + (p - iram_phys_base);
+}
+
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+       if (!iram_pool)
+               return NULL;
+
+       *dma_addr = gen_pool_alloc(iram_pool, size);
+       pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
+       if (!*dma_addr)
+               return NULL;
+       return iram_phys_to_virt(*dma_addr);
+}
+EXPORT_SYMBOL(iram_alloc);
+
+void iram_free(unsigned long addr, unsigned int size)
+{
+       if (!iram_pool)
+               return;
+
+       gen_pool_free(iram_pool, addr, size);
+}
+EXPORT_SYMBOL(iram_free);
+
+int __init iram_init(unsigned long base, unsigned long size)
+{
+       iram_phys_base = base;
+
+       iram_pool = gen_pool_create(PAGE_SHIFT, -1);
+       if (!iram_pool)
+               return -ENOMEM;
+
+       gen_pool_add(iram_pool, base, size, -1);
+       iram_virt_base = ioremap(iram_phys_base, size);
+       if (!iram_virt_base)
+               return -EIO;
+
+       pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
+       return 0;
+}
index b3da9aad4295704ef9ea8a4a43c95127d74e6d9e..3703ab28257fbbb55d3db89bee56877eebb38345 100644 (file)
@@ -164,8 +164,9 @@ int tzic_enable_wake(int is_idle)
                return -EAGAIN;
 
        for (i = 0; i < 4; i++) {
-               v = is_idle ? __raw_readl(TZIC_ENSET0(i)) : wakeup_intr[i];
-               __raw_writel(v, TZIC_WAKEUP0(i));
+               v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) :
+                       wakeup_intr[i];
+               __raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
        }
 
        return 0;
index 977c8f9a07a2194322deada32da2afd0481d50ad..85e6fd212a414efa02526762123b0b4d20653d9a 100644 (file)
@@ -102,6 +102,22 @@ static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
        writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
 }
 
+static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset, int val)
+{
+       if (val)
+               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+       else
+               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+}
+
+static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset, int val)
+{
+       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+       __nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
                             pin_cfg_t cfg)
 {
@@ -118,20 +134,29 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
                [3] /* illegal */       = "??"
        };
        static const char *slpmnames[] = {
-               [NMK_GPIO_SLPM_INPUT]           = "input",
-               [NMK_GPIO_SLPM_NOCHANGE]        = "no-change",
+               [NMK_GPIO_SLPM_INPUT]           = "input/wakeup",
+               [NMK_GPIO_SLPM_NOCHANGE]        = "no-change/no-wakeup",
        };
 
        int pin = PIN_NUM(cfg);
        int pull = PIN_PULL(cfg);
        int af = PIN_ALT(cfg);
        int slpm = PIN_SLPM(cfg);
+       int output = PIN_DIR(cfg);
+       int val = PIN_VAL(cfg);
 
-       dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n",
-               pin, afnames[af], pullnames[pull], slpmnames[slpm]);
+       dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
+               pin, afnames[af], pullnames[pull], slpmnames[slpm],
+               output ? "output " : "input",
+               output ? (val ? "high" : "low") : "");
+
+       if (output)
+               __nmk_gpio_make_output(nmk_chip, offset, val);
+       else {
+               __nmk_gpio_make_input(nmk_chip, offset);
+               __nmk_gpio_set_pull(nmk_chip, offset, pull);
+       }
 
-       __nmk_gpio_make_input(nmk_chip, offset);
-       __nmk_gpio_set_pull(nmk_chip, offset, pull);
        __nmk_gpio_set_slpm(nmk_chip, offset, slpm);
        __nmk_gpio_set_mode(nmk_chip, offset, af);
 }
@@ -200,6 +225,10 @@ EXPORT_SYMBOL(nmk_config_pins);
  * changed to an input (with pullup/down enabled) in sleep and deep sleep.  If
  * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
  * configured even when in sleep and deep sleep.
+ *
+ * On DB8500v2 onwards, this setting loses the previous meaning and instead
+ * indicates if wakeup detection is enabled on the pin.  Note that
+ * enable_irq_wake() will automatically enable wakeup detection.
  */
 int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
 {
@@ -367,7 +396,27 @@ static void nmk_gpio_irq_unmask(unsigned int irq)
 
 static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on)
 {
-       return nmk_gpio_irq_modify(irq, WAKE, on);
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+       int gpio;
+
+       gpio = NOMADIK_IRQ_TO_GPIO(irq);
+       nmk_chip = get_irq_chip_data(irq);
+       if (!nmk_chip)
+               return -EINVAL;
+
+       spin_lock_irqsave(&nmk_chip->lock, flags);
+#ifdef CONFIG_ARCH_U8500
+       if (cpu_is_u8500v2()) {
+               __nmk_gpio_set_slpm(nmk_chip, gpio,
+                                   on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
+                                      : NMK_GPIO_SLPM_WAKEUP_DISABLE);
+       }
+#endif
+       __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+       return 0;
 }
 
 static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type)
@@ -495,12 +544,8 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
 {
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
-       u32 bit = 1 << offset;
 
-       if (val)
-               writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
-       else
-               writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+       __nmk_gpio_set_output(nmk_chip, offset, val);
 }
 
 static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -509,8 +554,7 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
-       nmk_gpio_set_output(chip, offset, val);
+       __nmk_gpio_make_output(nmk_chip, offset, val);
 
        return 0;
 }
@@ -534,7 +578,7 @@ static struct gpio_chip nmk_gpio_template = {
        .can_sleep              = 0,
 };
 
-static int __init nmk_gpio_probe(struct platform_device *dev)
+static int __devinit nmk_gpio_probe(struct platform_device *dev)
 {
        struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
        struct nmk_gpio_chip *nmk_chip;
index aba355101f492687e39e303fff8b26ceb761541e..67b113d639d825f6072f2abe4f4251bccc480fda 100644 (file)
@@ -65,7 +65,9 @@ enum nmk_gpio_pull {
 /* Sleep mode */
 enum nmk_gpio_slpm {
        NMK_GPIO_SLPM_INPUT,
+       NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
        NMK_GPIO_SLPM_NOCHANGE,
+       NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
 };
 
 extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
index 7eed11c1038d768025998bcb55aab8b78f015df8..8c5ae3f2acf8dc6700079008c7058816808f9a62 100644 (file)
  *     bit  9..10 - Alternate Function Selection
  *     bit 11..12 - Pull up/down state
  *     bit     13 - Sleep mode behaviour
+ *     bit     14 - (sleep mode) Direction
+ *     bit     15 - (sleep mode) Value (if output)
  *
  * to facilitate the definition, the following macros are provided
  *
  * PIN_CFG_DEFAULT - default config (0):
  *                  pull up/down = disabled
- *                  sleep mode = input
+ *                  sleep mode = input/wakeup
+ *                  (sleep mode) direction = input
+ *                  (sleep mode) value = low
  *
  * PIN_CFG        - default config with alternate function
  * PIN_CFG_PULL           - default config with alternate function and pull up/down
@@ -53,8 +57,36 @@ typedef unsigned long pin_cfg_t;
 #define PIN_SLPM_SHIFT         13
 #define PIN_SLPM_MASK          (0x1 << PIN_SLPM_SHIFT)
 #define PIN_SLPM(x)            (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_INPUT         (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT    (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
 #define PIN_SLPM_NOCHANGE      (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE        (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+
+#define PIN_DIR_SHIFT          14
+#define PIN_DIR_MASK           (0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)             (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT          (0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT         (1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT          15
+#define PIN_VAL_MASK           (0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)             (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW            (0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH           (1 << PIN_VAL_SHIFT)
+
+/* Shortcuts.  Use these instead of separate DIR and VAL.  */
+#define PIN_INPUT              PIN_DIR_INPUT
+#define PIN_OUTPUT_LOW         (PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH                (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+/*
+ * These are the same as the ones above, but should make more sense to the
+ * reader when seen along with a setting a pin to AF mode.
+ */
+#define PIN_SLPM_INPUT         PIN_INPUT
+#define PIN_SLPM_OUTPUT_LOW    PIN_OUTPUT_LOW
+#define PIN_SLPM_OUTPUT_HIGH   PIN_OUTPUT_HIGH
 
 #define PIN_CFG_DEFAULT                (PIN_PULL_NONE | PIN_SLPM_INPUT)
 
index ea3ca86c52836ba1ec9fe780da9c1629db91723f..aedf9c1d645e4a820c8f1f9dd884fdf5fd1cebf5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/mach-nomadik/timer.c
+ *  linux/arch/arm/plat-nomadik/timer.c
  *
  * Copyright (C) 2008 STMicroelectronics
  * Copyright (C) 2010 Alessandro Rubini
@@ -75,7 +75,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
                cr = readl(mtu_base + MTU_CR(1));
                writel(0, mtu_base + MTU_LR(1));
                writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
-               writel(0x2, mtu_base + MTU_IMSC);
+               writel(1 << 1, mtu_base + MTU_IMSC);
                break;
        case CLOCK_EVT_MODE_SHUTDOWN:
        case CLOCK_EVT_MODE_UNUSED:
@@ -131,25 +131,23 @@ void __init nmdk_timer_init(void)
 {
        unsigned long rate;
        struct clk *clk0;
-       struct clk *clk1;
-       u32 cr;
+       u32 cr = MTU_CRn_32BITS;
 
        clk0 = clk_get_sys("mtu0", NULL);
        BUG_ON(IS_ERR(clk0));
 
-       clk1 = clk_get_sys("mtu1", NULL);
-       BUG_ON(IS_ERR(clk1));
-
        clk_enable(clk0);
-       clk_enable(clk1);
 
        /*
-        * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500:
-        * use a divide-by-16 counter if it's more than 16MHz
+        * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
+        * for ux500.
+        * Use a divide-by-16 counter if the tick rate is more than 32MHz.
+        * At 32 MHz, the timer (with 32 bit counter) can be programmed
+        * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
+        * with 16 gives too low timer resolution.
         */
-       cr = MTU_CRn_32BITS;;
        rate = clk_get_rate(clk0);
-       if (rate > 16 << 20) {
+       if (rate > 32000000) {
                rate /= 16;
                cr |= MTU_CRn_PRESCALE_16;
        } else {
@@ -170,15 +168,8 @@ void __init nmdk_timer_init(void)
                pr_err("timer: failed to initialize clock source %s\n",
                       nmdk_clksrc.name);
 
-       /* Timer 1 is used for events, fix according to rate */
-       cr = MTU_CRn_32BITS;
-       rate = clk_get_rate(clk1);
-       if (rate > 16 << 20) {
-               rate /= 16;
-               cr |= MTU_CRn_PRESCALE_16;
-       } else {
-               cr |= MTU_CRn_PRESCALE_1;
-       }
+       /* Timer 1 is used for events */
+
        clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
 
        writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
index e39a417a368dc92ad6776a68ef6fefc22a046b76..a92cb499313fdc9583890ebcc182ecae280cdc09 100644 (file)
@@ -33,7 +33,7 @@ config OMAP_DEBUG_DEVICES
 config OMAP_DEBUG_LEDS
        bool
        depends on OMAP_DEBUG_DEVICES
-       default y if LEDS
+       default y if LEDS_CLASS
 
 config OMAP_RESET_CLOCKS
        bool "Reset unused clocks during boot"
index 0054b9501a53976a384cde437b43be7c03cc582a..71934817e17228ffb01cfffc6a5fe2b872009964 100644 (file)
@@ -173,11 +173,7 @@ static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
 
 static int valid_sdram(unsigned long addr, unsigned long size)
 {
-       struct memblock_property res;
-
-       res.base = addr;
-       res.size = size;
-       return !memblock_find(&res) && res.base == addr && res.size == size;
+       return memblock_is_region_memory(addr, size);
 }
 
 static int reserve_sdram(unsigned long addr, unsigned long size)
index 6a3ff65c030350e121649f5bed7cb9d9f8d76724..ecd6a488c497c28fda8aea2c3412a95b67e05cc7 100644 (file)
 #define OMAP_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-
-/*
- * set_event() is used to wake up secondary core from wfe using sev. ROM
- * code puts the second core into wfe(standby).
- *
- */
-#define set_event()    __asm__ __volatile__ ("sev" : : : "memory")
+#include <asm/smp_mpidr.h>
 
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
@@ -40,15 +34,4 @@ static inline void smp_cross_call(const struct cpumask *mask)
        gic_raise_softirq(mask, 1);
 }
 
-/*
- * Read MPIDR: Multiprocessor affinity register
- */
-#define hard_smp_processor_id()                        \
-       ({                                              \
-               unsigned int cpunum;                    \
-               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
-                       : "=r" (cpunum));               \
-               cpunum &= 0x0F;                         \
-       })
-
 #endif
index e6c0d536899cb7a697e8db32e55bfa4301c93e53..f07cf2f08e09479045d3b7e3c8c6b1c0458c59f9 100644 (file)
@@ -328,12 +328,14 @@ static int debug_open_generic(struct inode *inode, struct file *file)
                .open = debug_open_generic,                             \
                .read = debug_read_##name,                              \
                .write = debug_write_##name,                            \
+               .llseek = generic_file_llseek,                          \
        };
 
 #define DEBUG_FOPS_RO(name)                                            \
        static const struct file_operations debug_##name##_fops = {     \
                .open = debug_open_generic,                             \
                .read = debug_read_##name,                              \
+               .llseek = generic_file_llseek,                          \
        };
 
 DEBUG_FOPS_RO(ver);
index a202a2ce6e3d0018ee3022ead0ba835527e3a4b0..6cd151b31bc5f7ee37afe54882737ddb60be1fbf 100644 (file)
@@ -320,6 +320,7 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
                if ((start <= da) && (da < start + bytes)) {
                        dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
                                __func__, start, da, bytes);
+                       iotlb_load_cr(obj, &cr);
                        iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
                }
        }
index e31496e35b0f452d4ff9e375855718fc0a078d40..0c8612fd831237164968b1f2120a1134618557e3 100644 (file)
@@ -156,7 +156,7 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
                /* Writing zero to RSYNC_ERR clears the IRQ */
                MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
        } else {
-               complete(&mcbsp_rx->tx_irq_completion);
+               complete(&mcbsp_rx->rx_irq_completion);
        }
 
        return IRQ_HANDLED;
index 226b2e858d6c9617243a91138821fb0e355daf56..10b3b4c63372f406e6ee206ce691977753017e56 100644 (file)
@@ -220,20 +220,7 @@ void __init omap_map_sram(void)
        if (omap_sram_size == 0)
                return;
 
-       if (cpu_is_omap24xx()) {
-               omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
-
-               base = OMAP2_SRAM_PA;
-               base = ROUND_DOWN(base, PAGE_SIZE);
-               omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-       }
-
        if (cpu_is_omap34xx()) {
-               omap_sram_io_desc[0].virtual = OMAP3_SRAM_VA;
-               base = OMAP3_SRAM_PA;
-               base = ROUND_DOWN(base, PAGE_SIZE);
-               omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-
                /*
                 * SRAM must be marked as non-cached on OMAP3 since the
                 * CORE DPLL M2 divider change code (in SRAM) runs with the
@@ -244,13 +231,11 @@ void __init omap_map_sram(void)
                omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
        }
 
-       if (cpu_is_omap44xx()) {
-               omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA;
-               base = OMAP4_SRAM_PA;
-               base = ROUND_DOWN(base, PAGE_SIZE);
-               omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-       }
-       omap_sram_io_desc[0].length = 1024 * 1024;      /* Use section desc */
+       omap_sram_io_desc[0].virtual = omap_sram_base;
+       base = omap_sram_start;
+       base = ROUND_DOWN(base, PAGE_SIZE);
+       omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
+       omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
        iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
        printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
similarity index 83%
rename from arch/arm/mach-pxa/include/mach/pxa27x_keypad.h
rename to arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
index 7b4eadc6df3a8c7762329304b1cec2fefbc900ff..abcc36eb12425ac04a28da7e61f6e9fa171ddac0 100644 (file)
  *
  * 4. matrix key and direct key will use the same debounce_interval by
  *    default, which should be sufficient in most cases
+ *
+ * pxa168 keypad platform specific parameter
+ *
+ * NOTE:
+ * clear_wakeup_event callback is a workaround required to clear the
+ * keypad interrupt. The keypad wake must be cleared in addition to
+ * reading the MI/DI bits in the KPC register.
  */
 struct pxa27x_keypad_platform_data {
 
@@ -52,6 +59,9 @@ struct pxa27x_keypad_platform_data {
 
        /* key debounce interval */
        unsigned int    debounce_interval;
+
+       /* clear wakeup event requirement for pxa168 */
+       void            (*clear_wakeup_event)(void);
 };
 
 extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
index 0732c6c8d511979e354cced2cd6987889702a1e7..ef32686feef9431ab00f42e4a2a0e2d7656af783 100644 (file)
@@ -176,7 +176,7 @@ static inline void __add_pwm(struct pwm_device *pwm)
 
 static int __devinit pwm_probe(struct platform_device *pdev)
 {
-       struct platform_device_id *id = platform_get_device_id(pdev);
+       const struct platform_device_id *id = platform_get_device_id(pdev);
        struct pwm_device *pwm, *secondary = NULL;
        struct resource *r;
        int ret = 0;
index c6a855db2fb6f327bc962b0b3e1913630c9252d6..25960966af7c7f1acf54c168ddc06e36ca97b91c 100644 (file)
@@ -7,7 +7,7 @@
 
 config PLAT_S5P
        bool
-       depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
+       depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
        default y
        select ARM_VIC if !ARCH_S5PV310
        select ARM_GIC if ARCH_S5PV310
@@ -30,7 +30,7 @@ config S5P_EXT_INT
        bool
        help
          Use the external interrupts (other than GPIO interrupts.)
-         Note: Do not choose this for S5P6440.
+         Note: Do not choose this for S5P6440 and S5P6450.
 
 config S5P_DEV_FIMC0
        bool
@@ -46,3 +46,8 @@ config S5P_DEV_FIMC2
        bool
        help
          Compile in platform device definitions for FIMC controller 2
+
+config S5P_DEV_ONENAND
+       bool
+       help
+         Compile in platform device definition for OneNAND controller
index b2e029673950fb028b2a936a2d0bbf7d9ee771e3..f3e917e27da870341a5d7c9d6b0c56b5964f9430 100644 (file)
@@ -24,3 +24,4 @@ obj-$(CONFIG_S5P_EXT_INT)     += irq-eint.o
 obj-$(CONFIG_S5P_DEV_FIMC0)    += dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)    += dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)    += dev-fimc2.o
+obj-$(CONFIG_S5P_DEV_ONENAND)  += dev-onenand.o
index b5e255265f20de4085bac619341f8bb9c1c40fd7..8aaf4e6b60c300760c443aa6fe4548fe165ff3b6 100644 (file)
@@ -74,6 +74,13 @@ struct clk clk_fout_epll = {
        .ctrlbit        = (1 << 31),
 };
 
+/* DPLL clock output */
+struct clk clk_fout_dpll = {
+       .name           = "fout_dpll",
+       .id             = -1,
+       .ctrlbit        = (1 << 31),
+};
+
 /* VPLL clock output */
 struct clk clk_fout_vpll = {
        .name           = "fout_vpll",
@@ -122,6 +129,17 @@ struct clksrc_sources clk_src_epll = {
        .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
 };
 
+/* Possible clock sources for DPLL Mux */
+static struct clk *clk_src_dpll_list[] = {
+       [0] = &clk_fin_dpll,
+       [1] = &clk_fout_dpll,
+};
+
+struct clksrc_sources clk_src_dpll = {
+       .sources        = clk_src_dpll_list,
+       .nr_sources     = ARRAY_SIZE(clk_src_dpll_list),
+};
+
 struct clk clk_vpll = {
        .name           = "vpll",
        .id             = -1,
@@ -145,6 +163,7 @@ static struct clk *s5p_clks[] __initdata = {
        &clk_fout_apll,
        &clk_fout_mpll,
        &clk_fout_epll,
+       &clk_fout_dpll,
        &clk_fout_vpll,
        &clk_arm,
        &clk_vpll,
index b07a078fd28449b80c9171d46f10975a5998b2b9..74f7f5a5446cdaf4bdc9a3212f1dc9679611abfb 100644 (file)
@@ -19,6 +19,7 @@
 #include <plat/cpu.h>
 #include <plat/s5p6440.h>
 #include <plat/s5p6442.h>
+#include <plat/s5p6450.h>
 #include <plat/s5pc100.h>
 #include <plat/s5pv210.h>
 #include <plat/s5pv310.h>
@@ -27,6 +28,7 @@
 
 static const char name_s5p6440[] = "S5P6440";
 static const char name_s5p6442[] = "S5P6442";
+static const char name_s5p6450[] = "S5P6450";
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
 static const char name_s5pv310[] = "S5PV310";
@@ -38,7 +40,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .map_io         = s5p6440_map_io,
                .init_clocks    = s5p6440_init_clocks,
                .init_uarts     = s5p6440_init_uarts,
-               .init           = s5p6440_init,
+               .init           = s5p64x0_init,
                .name           = name_s5p6440,
        }, {
                .idcode         = 0x36442000,
@@ -48,6 +50,14 @@ static struct cpu_table cpu_ids[] __initdata = {
                .init_uarts     = s5p6442_init_uarts,
                .init           = s5p6442_init,
                .name           = name_s5p6442,
+       }, {
+               .idcode         = 0x36450000,
+               .idmask         = 0xffffff00,
+               .map_io         = s5p6450_map_io,
+               .init_clocks    = s5p6450_init_clocks,
+               .init_uarts     = s5p6450_init_uarts,
+               .init           = s5p64x0_init,
+               .name           = name_s5p6450,
        }, {
                .idcode         = 0x43100000,
                .idmask         = 0xfffff000,
@@ -88,33 +98,11 @@ static struct map_desc s5p_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(S5P_PA_SYSCON),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_UART,
-               .pfn            = __phys_to_pfn(S3C_PA_UART),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-#ifdef CONFIG_ARM_VIC
-       }, {
-               .virtual        = (unsigned long)VA_VIC0,
-               .pfn            = __phys_to_pfn(S5P_PA_VIC0),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)VA_VIC1,
-               .pfn            = __phys_to_pfn(S5P_PA_VIC1),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-#endif
        }, {
                .virtual        = (unsigned long)S3C_VA_TIMER,
                .pfn            = __phys_to_pfn(S5P_PA_TIMER),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_GPIO,
-               .pfn            = __phys_to_pfn(S5P_PA_GPIO),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C_VA_WATCHDOG,
                .pfn            = __phys_to_pfn(S3C_PA_WDT),
index d3f1a9b5d2b5a4d01f040ba784a13185629b5938..608770fc1531335967f4e42a4c9355ed8e5f6c87 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -18,7 +19,7 @@
 static struct resource s5p_fimc0_resource[] = {
        [0] = {
                .start  = S5P_PA_FIMC0,
-               .end    = S5P_PA_FIMC0 + SZ_1M - 1,
+               .end    = S5P_PA_FIMC0 + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -28,9 +29,15 @@ static struct resource s5p_fimc0_resource[] = {
        },
 };
 
+static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32);
+
 struct platform_device s5p_device_fimc0 = {
        .name           = "s5p-fimc",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(s5p_fimc0_resource),
        .resource       = s5p_fimc0_resource,
+       .dev            = {
+               .dma_mask               = &s5p_fimc0_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
 };
index 41bd6986d0ad03210cf85c4e32f1f497a29d67f6..76e3a97a87d37c934f95da3ab2187831b9eb6da6 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -18,7 +19,7 @@
 static struct resource s5p_fimc1_resource[] = {
        [0] = {
                .start  = S5P_PA_FIMC1,
-               .end    = S5P_PA_FIMC1 + SZ_1M - 1,
+               .end    = S5P_PA_FIMC1 + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -28,9 +29,15 @@ static struct resource s5p_fimc1_resource[] = {
        },
 };
 
+static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32);
+
 struct platform_device s5p_device_fimc1 = {
        .name           = "s5p-fimc",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(s5p_fimc1_resource),
        .resource       = s5p_fimc1_resource,
+       .dev            = {
+               .dma_mask               = &s5p_fimc1_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
 };
index dfddeda6d4a373445abdabbbe3e59155c61fa84e..24d29816fa2c03711ad0b5a62e2561caabd11e3b 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -18,7 +19,7 @@
 static struct resource s5p_fimc2_resource[] = {
        [0] = {
                .start  = S5P_PA_FIMC2,
-               .end    = S5P_PA_FIMC2 + SZ_1M - 1,
+               .end    = S5P_PA_FIMC2 + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -28,9 +29,15 @@ static struct resource s5p_fimc2_resource[] = {
        },
 };
 
+static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32);
+
 struct platform_device s5p_device_fimc2 = {
        .name           = "s5p-fimc",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(s5p_fimc2_resource),
        .resource       = s5p_fimc2_resource,
+       .dev            = {
+               .dma_mask               = &s5p_fimc2_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
 };
similarity index 59%
rename from arch/arm/mach-s5pv210/dev-onenand.c
rename to arch/arm/plat-s5p/dev-onenand.c
index f8ede33ee82b8e1d0acee891e54d6772a628d650..6db926202caa6adcb193b899e21eb78584c28ff0 100644 (file)
@@ -1,10 +1,12 @@
-/*
- * linux/arch/arm/mach-s5pv210/dev-onenand.c
+/* linux/arch/arm/plat-s5p/dev-onenand.c
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  *  Copyright (c) 2008-2010 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
- * S5PC110 series device definition for OneNAND devices
+ * S5P series device definition for OneNAND devices
  *
  * 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
 #include <mach/irqs.h>
 #include <mach/map.h>
 
-static struct resource s5pc110_onenand_resources[] = {
+static struct resource s5p_onenand_resources[] = {
        [0] = {
-               .start  = S5PC110_PA_ONENAND,
-               .end    = S5PC110_PA_ONENAND + SZ_128K - 1,
+               .start  = S5P_PA_ONENAND,
+               .end    = S5P_PA_ONENAND + SZ_128K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = S5PC110_PA_ONENAND_DMA,
-               .end    = S5PC110_PA_ONENAND_DMA + SZ_8K - 1,
+               .start  = S5P_PA_ONENAND_DMA,
+               .end    = S5P_PA_ONENAND_DMA + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
@@ -37,19 +39,19 @@ static struct resource s5pc110_onenand_resources[] = {
        },
 };
 
-struct platform_device s5pc110_device_onenand = {
+struct platform_device s5p_device_onenand = {
        .name           = "s5pc110-onenand",
        .id             = -1,
-       .num_resources  = ARRAY_SIZE(s5pc110_onenand_resources),
-       .resource       = s5pc110_onenand_resources,
+       .num_resources  = ARRAY_SIZE(s5p_onenand_resources),
+       .resource       = s5p_onenand_resources,
 };
 
-void s5pc110_onenand_set_platdata(struct onenand_platform_data *pdata)
+void s5p_onenand_set_platdata(struct onenand_platform_data *pdata)
 {
        struct onenand_platform_data *pd;
 
        pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
        if (!pd)
                printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-       s5pc110_device_onenand.dev.platform_data = pd;
+       s5p_device_onenand.dev.platform_data = pd;
 }
index a89331ef4ae172b97d6f21aba05fd8cd80c7eb09..6a7342886171fde25d9c531f4e86db6c7ef52f1b 100644 (file)
@@ -119,6 +119,56 @@ static struct resource s5p_uart3_resource[] = {
 #endif
 };
 
+static struct resource s5p_uart4_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+       [0] = {
+               .start  = S5P_PA_UART4,
+               .end    = S5P_PA_UART4 + S5P_SZ_UART,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_S5P_UART_RX4,
+               .end    = IRQ_S5P_UART_RX4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = IRQ_S5P_UART_TX4,
+               .end    = IRQ_S5P_UART_TX4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .start  = IRQ_S5P_UART_ERR4,
+               .end    = IRQ_S5P_UART_ERR4,
+               .flags  = IORESOURCE_IRQ,
+       },
+#endif
+};
+
+static struct resource s5p_uart5_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+       [0] = {
+               .start  = S5P_PA_UART5,
+               .end    = S5P_PA_UART5 + S5P_SZ_UART,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_S5P_UART_RX5,
+               .end    = IRQ_S5P_UART_RX5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = IRQ_S5P_UART_TX5,
+               .end    = IRQ_S5P_UART_TX5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .start  = IRQ_S5P_UART_ERR5,
+               .end    = IRQ_S5P_UART_ERR5,
+               .flags  = IORESOURCE_IRQ,
+       },
+#endif
+};
+
 struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
        [0] = {
                .resources      = s5p_uart0_resource,
@@ -136,4 +186,12 @@ struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
                .resources      = s5p_uart3_resource,
                .nr_resources   = ARRAY_SIZE(s5p_uart3_resource),
        },
+       [4] = {
+               .resources      = s5p_uart4_resource,
+               .nr_resources   = ARRAY_SIZE(s5p_uart4_resource),
+       },
+       [5] = {
+               .resources      = s5p_uart5_resource,
+               .nr_resources   = ARRAY_SIZE(s5p_uart5_resource),
+       },
 };
index 54e9fb9d315e949129b4754b8b99a195a7771aee..c4ff88bf6477d2797b6ba578c768b0edadaba073 100644 (file)
@@ -17,6 +17,7 @@
 #define S5P_VA_GPIO            S3C_ADDR(0x00500000)
 #define S5P_VA_SYSTIMER                S3C_ADDR(0x01200000)
 #define S5P_VA_SROMC           S3C_ADDR(0x01100000)
+#define S5P_VA_SYSRAM          S3C_ADDR(0x01180000)
 
 #define S5P_VA_COMBINER_BASE   S3C_ADDR(0x00600000)
 #define S5P_VA_COMBINER(x)     (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
@@ -29,6 +30,7 @@
 #define S5P_VA_GIC_DIST                S5P_VA_COREPERI(0x1000)
 
 #define S5P_VA_L2CC            S3C_ADDR(0x00900000)
+#define S5P_VA_CMU             S3C_ADDR(0x00920000)
 
 #define S5P_VA_UART(x)         (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 #define S5P_VA_UART0           S5P_VA_UART(0)
index 4e8fe08cb70d96ad13dee8c1288e95f206c4bb17..bf28fadee7ae07c931174fab01d14875e396b316 100644 (file)
@@ -47,6 +47,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
 }
 
 #define PLL46XX_KDIV_MASK      (0xFFFF)
+#define PLL4650C_KDIV_MASK     (0xFFF)
 #define PLL46XX_MDIV_MASK      (0x1FF)
 #define PLL46XX_PDIV_MASK      (0x3F)
 #define PLL46XX_SDIV_MASK      (0x7)
@@ -57,6 +58,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
 enum pll46xx_type_t {
        pll_4600,
        pll_4650,
+       pll_4650c,
 };
 
 static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
@@ -72,6 +74,11 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
        sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
        kdiv = pll_con1 & PLL46XX_KDIV_MASK;
 
+       if (pll_type == pll_4650c)
+               kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+       else
+               kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
        tmp = baseclk;
 
        if (pll_type == pll_4600) {
index 09418b1101fe582a374b4ded78010e36de392d11..17036c898409adafc0756b2064bb77e9f1e8e187 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
  *
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Header file for s5p clock support
  *
@@ -20,6 +20,7 @@
 #define clk_fin_apll clk_ext_xtal_mux
 #define clk_fin_mpll clk_ext_xtal_mux
 #define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
 #define clk_fin_vpll clk_ext_xtal_mux
 #define clk_fin_hpll clk_ext_xtal_mux
 
@@ -30,6 +31,7 @@ extern struct clk s5p_clk_27m;
 extern struct clk clk_fout_apll;
 extern struct clk clk_fout_mpll;
 extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
 extern struct clk clk_fout_vpll;
 extern struct clk clk_arm;
 extern struct clk clk_vpll;
@@ -37,8 +39,8 @@ extern struct clk clk_vpll;
 extern struct clksrc_sources clk_src_apll;
 extern struct clksrc_sources clk_src_mpll;
 extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
 
-extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable);
 extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
 
 #endif /* __ASM_PLAT_S5P_CLOCK_H */
index a4cd75afeb3bf4efcd09dce436e198b341b58a54..528585d2cafcef8a0bae0926fd2318ede7d4a474 100644 (file)
 
  /* Common init code for S5P6440 related SoCs */
 
-extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 extern void s5p6440_register_clocks(void);
 extern void s5p6440_setup_clocks(void);
 
 #ifdef CONFIG_CPU_S5P6440
 
-extern  int s5p6440_init(void);
+extern  int s5p64x0_init(void);
 extern void s5p6440_init_irq(void);
 extern void s5p6440_map_io(void);
 extern void s5p6440_init_clocks(int xtal);
 
-#define s5p6440_init_uarts s5p6440_common_init_uarts
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 #else
 #define s5p6440_init_clocks NULL
 #define s5p6440_init_uarts NULL
 #define s5p6440_map_io NULL
-#define s5p6440_init NULL
+#define s5p64x0_init NULL
 #endif
 
 /* S5P6440 timer */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h
new file mode 100644 (file)
index 0000000..640a41c
--- /dev/null
@@ -0,0 +1,36 @@
+/* arch/arm/plat-s5p/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Header file for s5p6450 cpu support
+ *
+ * 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.
+*/
+
+/* Common init code for S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern  int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
index 04d9521ddc9f0e652d62453a99bbb19fa877c7fa..e8f2be2d67f2cac33961487b47a7880b68f33832 100644 (file)
@@ -435,7 +435,6 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
 static int s3c_adc_resume(struct platform_device *pdev)
 {
        struct adc_device *adc = platform_get_drvdata(pdev);
-       unsigned long flags;
 
        clk_enable(adc->clk);
        enable_irq(adc->irq);
index 90a20512d68d5a40d9fa789b15c24620a0c8f9b3..e8d20b0bc50e11ee43d78f230b811409def1cb87 100644 (file)
@@ -48,6 +48,9 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
+#include <linux/serial_core.h>
+#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
+
 /* clock information */
 
 static LIST_HEAD(clocks);
@@ -65,6 +68,28 @@ static int clk_null_enable(struct clk *clk, int enable)
        return 0;
 }
 
+static int dev_is_s3c_uart(struct device *dev)
+{
+       struct platform_device **pdev = s3c24xx_uart_devs;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
+               if (*pdev && dev == &(*pdev)->dev)
+                       return 1;
+       return 0;
+}
+
+/*
+ * Serial drivers call get_clock() very early, before platform bus
+ * has been set up, this requires a special check to let them get
+ * a proper clock
+ */
+
+static int dev_is_platform_device(struct device *dev)
+{
+       return dev->bus == &platform_bus_type ||
+              (dev->bus == NULL && dev_is_s3c_uart(dev));
+}
+
 /* Clock API calls */
 
 struct clk *clk_get(struct device *dev, const char *id)
@@ -73,7 +98,7 @@ struct clk *clk_get(struct device *dev, const char *id)
        struct clk *clk = ERR_PTR(-ENOENT);
        int idno;
 
-       if (dev == NULL || dev->bus != &platform_bus_type)
+       if (dev == NULL || !dev_is_platform_device(dev))
                idno = -1;
        else
                idno = to_platform_device(dev)->id;
index 57b68a50f45e93aa14852500ace0df1fdc48da8b..e3d41eaed1ffd9feed571cef0af6bf5bf0841bf2 100644 (file)
@@ -273,13 +273,13 @@ s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
        if (!chip)
                return -EINVAL;
 
-       off = chip->chip.base - pin;
+       off = pin - chip->chip.base;
        shift = off * 2;
        reg = chip->base + 0x0C;
 
        drvstr = __raw_readl(reg);
-       drvstr = 0xffff & (0x3 << shift);
        drvstr = drvstr >> shift;
+       drvstr &= 0x3;
 
        return (__force s5p_gpio_drvstr_t)drvstr;
 }
@@ -296,11 +296,12 @@ int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
        if (!chip)
                return -EINVAL;
 
-       off = chip->chip.base - pin;
+       off = pin - chip->chip.base;
        shift = off * 2;
        reg = chip->base + 0x0C;
 
        tmp = __raw_readl(reg);
+       tmp &= ~(0x3 << shift);
        tmp |= drvstr << shift;
 
        __raw_writel(tmp, reg);
index 6412933d6fbb813050b840e1d71e788758b9a9fc..9addb3dfb4bc31d83227acc18bcd654da748d380 100644 (file)
@@ -79,7 +79,7 @@ extern struct sysdev_class s3c2442_sysclass;
 extern struct sysdev_class s3c2443_sysclass;
 extern struct sysdev_class s3c6410_sysclass;
 extern struct sysdev_class s3c64xx_sysclass;
-extern struct sysdev_class s5p6440_sysclass;
+extern struct sysdev_class s5p64x0_sysclass;
 extern struct sysdev_class s5p6442_sysclass;
 extern struct sysdev_class s5pv210_sysclass;
 
index 85f6f23a510f56cd1b9ce5f1f7871f0923b26c11..7d448e13879241c8a62da6f26604ea00ecc1a3d1 100644 (file)
@@ -67,13 +67,15 @@ extern struct platform_device s5pv210_device_spi0;
 extern struct platform_device s5pv210_device_spi1;
 extern struct platform_device s5p6440_device_spi0;
 extern struct platform_device s5p6440_device_spi1;
+extern struct platform_device s5p6450_device_spi0;
+extern struct platform_device s5p6450_device_spi1;
 
 extern struct platform_device s3c_device_hwmon;
 
 extern struct platform_device s3c_device_nand;
 extern struct platform_device s3c_device_onenand;
 extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5pc110_device_onenand;
+extern struct platform_device s5p_device_onenand;
 
 extern struct platform_device s3c_device_usbgadget;
 extern struct platform_device s3c_device_usb_hsotg;
@@ -95,6 +97,9 @@ extern struct platform_device s5p6442_device_spi;
 extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
 
+extern struct platform_device s5p6450_device_iis0;
+extern struct platform_device s5p6450_device_pcm0;
+
 extern struct platform_device s5pc100_device_ac97;
 extern struct platform_device s5pc100_device_pcm0;
 extern struct platform_device s5pc100_device_pcm1;
index db4112c6f2becd7371fc86428c5ca4b50a07bbdd..1c6b92947c5db7e8b955ac3831214bbf556bf2bb 100644 (file)
@@ -143,12 +143,12 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
 /* Define values for the drvstr available for each gpio pin.
  *
  * These values control the value of the output signal driver strength,
- * configurable on most pins on the S5C series.
+ * configurable on most pins on the S5P series.
  */
-#define S5P_GPIO_DRVSTR_LV1    ((__force s5p_gpio_drvstr_t)0x00)
-#define S5P_GPIO_DRVSTR_LV2    ((__force s5p_gpio_drvstr_t)0x01)
-#define S5P_GPIO_DRVSTR_LV3    ((__force s5p_gpio_drvstr_t)0x10)
-#define S5P_GPIO_DRVSTR_LV4    ((__force s5p_gpio_drvstr_t)0x11)
+#define S5P_GPIO_DRVSTR_LV1    ((__force s5p_gpio_drvstr_t)0x0)
+#define S5P_GPIO_DRVSTR_LV2    ((__force s5p_gpio_drvstr_t)0x2)
+#define S5P_GPIO_DRVSTR_LV3    ((__force s5p_gpio_drvstr_t)0x1)
+#define S5P_GPIO_DRVSTR_LV4    ((__force s5p_gpio_drvstr_t)0x3)
 
 /**
  * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin
index 5fe6721b57f7060acd8180522c3d2df41ad8cf62..81074421312068bfc24e5f9329d8d44d60538c8b 100644 (file)
@@ -32,6 +32,12 @@ enum dma_ch {
        DMACH_UART2_TX,
        DMACH_UART3_RX,
        DMACH_UART3_TX,
+       DMACH_UART4_RX,
+       DMACH_UART4_TX,
+       DMACH_UART5_RX,
+       DMACH_UART5_TX,
+       DMACH_USI_RX,
+       DMACH_USI_TX,
        DMACH_IRDA,
        DMACH_I2S0_RX,
        DMACH_I2S0_TX,
@@ -64,6 +70,20 @@ enum dma_ch {
        DMACH_MSM_REQ2,
        DMACH_MSM_REQ1,
        DMACH_MSM_REQ0,
+       DMACH_SLIMBUS0_RX,
+       DMACH_SLIMBUS0_TX,
+       DMACH_SLIMBUS0AUX_RX,
+       DMACH_SLIMBUS0AUX_TX,
+       DMACH_SLIMBUS1_RX,
+       DMACH_SLIMBUS1_TX,
+       DMACH_SLIMBUS2_RX,
+       DMACH_SLIMBUS2_TX,
+       DMACH_SLIMBUS3_RX,
+       DMACH_SLIMBUS3_TX,
+       DMACH_SLIMBUS4_RX,
+       DMACH_SLIMBUS4_TX,
+       DMACH_SLIMBUS5_RX,
+       DMACH_SLIMBUS5_TX,
        /* END Marker, also used to denote a reserved channel */
        DMACH_MAX,
 };
index e5aba8f95b791355f8d01a77347482053099933d..ff1a561b326ee028aa66467e758e12ac03a63b25 100644 (file)
@@ -32,6 +32,8 @@ struct s3c64xx_spi_csinfo {
  * struct s3c64xx_spi_info - SPI Controller defining structure
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
  * @src_clk_name: Platform name of the corresponding clock.
+ * @clk_from_cmu: If the SPI clock/prescalar control block is present
+ *     by the platform's clock-management-unit and not in SPI controller.
  * @num_cs: Number of CS this controller emulates.
  * @cfg_gpio: Configure pins for this SPI controller.
  * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
@@ -41,6 +43,7 @@ struct s3c64xx_spi_csinfo {
 struct s3c64xx_spi_info {
        int src_clk_nr;
        char *src_clk_name;
+       bool clk_from_cmu;
 
        int num_cs;
 
@@ -65,7 +68,7 @@ struct s3c64xx_spi_info {
 extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
-extern void s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
+extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 
 #endif /* __S3C64XX_PLAT_SPI_H */
index 37fa593884ee64d345add30e2ca9738e238e3511..e91270e4f640329ce1424b1ad7c37a89dead7626 100644 (file)
 #include <linux/amba/serial.h>
 #include <mach/spear.h>
 
-               .macro  addruart, rx
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                                 @ MMU enabled?
-               moveq   \rx, #SPEAR_DBG_UART_BASE               @ Physical base
-               movne   \rx, #VA_SPEAR_DBG_UART_BASE            @ Virtual base
+               .macro  addruart, rp, rv
+               mov     \rp, #SPEAR_DBG_UART_BASE               @ Physical base
+               mov     \rv, #VA_SPEAR_DBG_UART_BASE            @ Virtual base
                .endm
 
                .macro  senduart, rd, rx
index 1b9348bf0e4926b542bea6d1bfcc4a9cd2e29440..d3a0985c96817f1dfd9471d7ab2a0f2d13644b48 100644 (file)
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-               .macro  addruart, rx, tmp
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x80000000        @ physical base address
-               addeq   \rx, \rx, #0x00070000
-               movne   \rx, #0xf0000000        @ virtual base
-               addne   \rx, \rx, #0x00070000
+               .macro  addruart, rp, rv
+               mov     \rp,      #0x00070000
+               add     \rv, \rp, #0xf0000000   @ virtual base
+               add     \rp, \rp, #0x80000000   @ physical base
                .endm
 
                .macro  senduart,rd,rx
diff --git a/arch/arm/plat-tcc/Kconfig b/arch/arm/plat-tcc/Kconfig
new file mode 100644 (file)
index 0000000..1bf4995
--- /dev/null
@@ -0,0 +1,20 @@
+if ARCH_TCC_926
+
+menu "Telechips ARM926-based CPUs"
+
+choice
+       prompt "Telechips CPU type:"
+       default ARCH_TCC8K
+
+config ARCH_TCC8K
+       bool TCC8000
+       select USB_ARCH_HAS_OHCI
+       help
+         Support for Telechips TCC8000 systems
+
+endchoice
+
+source "arch/arm/mach-tcc8k/Kconfig"
+
+endmenu
+endif
diff --git a/arch/arm/plat-tcc/Makefile b/arch/arm/plat-tcc/Makefile
new file mode 100644 (file)
index 0000000..eceabc8
--- /dev/null
@@ -0,0 +1,3 @@
+# "Telechips Platform Common Modules"
+
+obj-y := clock.o system.o
diff --git a/arch/arm/plat-tcc/clock.c b/arch/arm/plat-tcc/clock.c
new file mode 100644 (file)
index 0000000..f3ced10
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Clock framework for Telechips SoCs
+ * Based on arch/arm/plat-mxc/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2010 Hans J. Koch, hjk@linutronix.de
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+
+static DEFINE_MUTEX(clocks_mutex);
+
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+
+static void __clk_disable(struct clk *clk)
+{
+       BUG_ON(clk->refcount == 0);
+
+       if (!(--clk->refcount) && clk->disable) {
+               /* Unconditionally disable the clock in hardware */
+               clk->disable(clk);
+               /* recursively disable parents */
+               if (clk->parent)
+                       __clk_disable(clk->parent);
+       }
+}
+
+static int __clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (clk->refcount++ == 0 && clk->enable) {
+               if (clk->parent)
+                       ret = __clk_enable(clk->parent);
+               if (ret)
+                       return ret;
+               else
+                       return clk->enable(clk);
+       }
+
+       return 0;
+}
+
+/* This function increments the reference count on the clock and enables the
+ * clock if not already enabled. The parent clock tree is recursively enabled
+ */
+int clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (!clk)
+               return -EINVAL;
+
+       mutex_lock(&clocks_mutex);
+       ret = __clk_enable(clk);
+       mutex_unlock(&clocks_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+/* This function decrements the reference count on the clock and disables
+ * the clock when reference count is 0. The parent clock tree is
+ * recursively disabled
+ */
+void clk_disable(struct clk *clk)
+{
+       if (!clk)
+               return;
+
+       mutex_lock(&clocks_mutex);
+       __clk_disable(clk);
+       mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+/* Retrieve the *current* clock rate. If the clock itself
+ * does not provide a special calculation routine, ask
+ * its parent and so on, until one is able to return
+ * a valid clock rate
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (!clk)
+               return 0UL;
+
+       if (clk->get_rate)
+               return clk->get_rate(clk);
+
+       return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/* Round the requested clock rate to the nearest supported
+ * rate that is less than or equal to the requested rate.
+ * This is dependent on the clock's current parent.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (!clk)
+               return 0;
+       if (!clk->round_rate)
+               return 0;
+
+       return clk->round_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/* Set the clock to the requested clock rate. The rate must
+ * match a supported rate exactly based on what clk_round_rate returns
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret = -EINVAL;
+
+       if (!clk)
+               return ret;
+       if (!clk->set_rate || !rate)
+               return ret;
+
+       mutex_lock(&clocks_mutex);
+       ret = clk->set_rate(clk, rate);
+       mutex_unlock(&clocks_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/* Set the clock's parent to another clock source */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct clk *old;
+       int ret = -EINVAL;
+
+       if (!clk)
+               return ret;
+       if (!clk->set_parent || !parent)
+               return ret;
+
+       mutex_lock(&clocks_mutex);
+       old = clk->parent;
+       if (clk->refcount)
+               __clk_enable(parent);
+       ret = clk->set_parent(clk, parent);
+       if (ret)
+               old = parent;
+       if (clk->refcount)
+               __clk_disable(old);
+       mutex_unlock(&clocks_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/* Retrieve the clock's parent clock source */
+struct clk *clk_get_parent(struct clk *clk)
+{
+       if (!clk)
+               return NULL;
+
+       return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..04b37a8
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/clock.h b/arch/arm/plat-tcc/include/mach/clock.h
new file mode 100644 (file)
index 0000000..a12f58a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Low level clock header file for Telechips TCC architecture
+ * (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_TCC_CLOCK_H__
+#define __ASM_ARCH_TCC_CLOCK_H__
+
+#ifndef __ASSEMBLY__
+
+struct clk {
+       struct clk *parent;
+       /* id number of a root clock, 0 for normal clocks */
+       int root_id;
+       /* Reference count of clock enable/disable */
+       int refcount;
+       /* Address of associated BCLKCTRx register. Must be set. */
+       void __iomem *bclkctr;
+       /* Bit position for BCLKCTRx. Must be set. */
+       int bclk_shift;
+       /* Address of ACLKxxx register, if any. */
+       void __iomem *aclkreg;
+       /* get the current clock rate (always a fresh value) */
+       unsigned long (*get_rate) (struct clk *);
+       /* Function ptr to set the clock to a new rate. The rate must match a
+          supported rate returned from round_rate. Leave blank if clock is not
+          programmable */
+       int (*set_rate) (struct clk *, unsigned long);
+       /* Function ptr to round the requested clock rate to the nearest
+          supported rate that is less than or equal to the requested rate. */
+       unsigned long (*round_rate) (struct clk *, unsigned long);
+       /* Function ptr to enable the clock. Leave blank if clock can not
+          be gated. */
+       int (*enable) (struct clk *);
+       /* Function ptr to disable the clock. Leave blank if clock can not
+          be gated. */
+       void (*disable) (struct clk *);
+       /* Function ptr to set the parent clock of the clock. */
+       int (*set_parent) (struct clk *, struct clk *);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_ARCH_MXC_CLOCK_H__ */
diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..7662f73
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1994-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * 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.
+ *
+ */
+
+               .macro  addruart, rp, rv
+               moveq   \rp, #0x90000000        @ physical base address
+               movne   \rv, #0xF1000000        @ virtual base
+               orr     \rp, \rp, #0x00007000   @ UART0
+               orr     \rv, \rv, #0x00007000   @ UART0
+               .endm
+
+               .macro  senduart,rd,rx
+               strb    \rd, [\rx, #0x44]
+               .endm
+
+               .macro  waituart,rd,rx
+               .endm
+
+               .macro  busyuart,rd,rx
+1001:
+               ldr \rd, [\rx, #0x14]
+               tst \rd, #0x20
+
+               beq 1001b
+               .endm
diff --git a/arch/arm/plat-tcc/include/mach/entry-macro.S b/arch/arm/plat-tcc/include/mach/entry-macro.S
new file mode 100644 (file)
index 0000000..748f401
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * include/asm-arm/arch-tcc83x/entry-macro.S
+ *
+ * Author : <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: Low-level IRQ helper macros for Telechips-based platforms
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+               ldr     \base, =0xF2003000 @ base address of PIC registers
+
+               @@ read MREQ register of PIC0
+
+               mov     \irqnr, #0
+               ldr     \irqstat, [\base, #0x00000014 ] @ lower 32 interrupts
+               cmp     \irqstat, #0
+               bne     1001f
+
+               @@ read MREQ register of PIC1
+
+               ldr     \irqstat, [\base, #0x00000094]  @ upper 32 interrupts
+               cmp     \irqstat, #0
+               beq     1002f
+               mov     \irqnr, #0x20
+
+1001:
+               movs    \tmp, \irqstat, lsl #16
+               movne   \irqstat, \tmp
+               addeq   \irqnr, \irqnr, #16
+
+               movs    \tmp, \irqstat, lsl #8
+               movne   \irqstat, \tmp
+               addeq   \irqnr, \irqnr, #8
+
+               movs    \tmp, \irqstat, lsl #4
+               movne   \irqstat, \tmp
+               addeq   \irqnr, \irqnr, #4
+
+               movs    \tmp, \irqstat, lsl #2
+               movne   \irqstat, \tmp
+               addeq   \irqnr, \irqnr, #2
+
+               movs    \tmp, \irqstat, lsl #1
+               addeq   \irqnr, \irqnr, #1
+               orrs    \base, \base, #1
+1002:
+               @@ exit here, Z flag unset if IRQ
+
+       .endm
diff --git a/arch/arm/plat-tcc/include/mach/hardware.h b/arch/arm/plat-tcc/include/mach/hardware.h
new file mode 100644 (file)
index 0000000..e70d126
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
+ * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com>
+ *                          and Dirk Behme <dirk.behme@de.bosch.com>
+ * Rewritten by:    <linux@telechips.com>
+ * Description: Hardware definitions for TCC8300 processors and boards
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Modifications for mainline (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Pulic License version 2.
+ */
+
+#ifndef __ASM_ARCH_TCC_HARDWARE_H
+#define __ASM_ARCH_TCC_HARDWARE_H
+
+#include <asm/sizes.h>
+#ifndef __ASSEMBLER__
+#include <asm/types.h>
+#endif
+#include <mach/io.h>
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_BASE                0xfffece00
+#define ARM_CKCTL              (CLKGEN_REG_BASE + 0x0)
+#define ARM_IDLECT1            (CLKGEN_REG_BASE + 0x4)
+#define ARM_IDLECT2            (CLKGEN_REG_BASE + 0x8)
+#define ARM_EWUPCT             (CLKGEN_REG_BASE + 0xC)
+#define ARM_RSTCT1             (CLKGEN_REG_BASE + 0x10)
+#define ARM_RSTCT2             (CLKGEN_REG_BASE + 0x14)
+#define ARM_SYSST              (CLKGEN_REG_BASE + 0x18)
+#define ARM_IDLECT3            (CLKGEN_REG_BASE + 0x24)
+
+/* DPLL control registers */
+#define DPLL_CTL               0xfffecf00
+
+#endif /* __ASM_ARCH_TCC_HARDWARE_H */
diff --git a/arch/arm/plat-tcc/include/mach/io.h b/arch/arm/plat-tcc/include/mach/io.h
new file mode 100644 (file)
index 0000000..3e911d3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * IO definitions for TCC8000 processors and boards
+ *
+ * Copyright (C) 1997-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Public License version 2.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)                        __typesafe_io(a)
+#define __mem_pci(a)           (a)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/irqs.h b/arch/arm/plat-tcc/include/mach/irqs.h
new file mode 100644 (file)
index 0000000..da86389
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * IRQ definitions for TCC8xxx
+ *
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_TCC_IRQS_H
+#define __ASM_ARCH_TCC_IRQS_H
+
+#define NR_IRQS 64
+
+/* PIC0 interrupts */
+#define INT_ADMA1      0
+#define INT_BDMA       1
+#define INT_ADMA0      2
+#define INT_GDMA1      3
+#define INT_I2S0RX     4
+#define INT_I2S0TX     5
+#define INT_TC         6
+#define INT_UART0      7
+#define INT_USBD       8
+#define INT_SPI0TX     9
+#define INT_UDMA       10
+#define INT_LIRQ       11
+#define INT_GDMA2      12
+#define INT_GDMA0      13
+#define INT_TC32       14
+#define INT_LCD                15
+#define INT_ADC                16
+#define INT_I2C                17
+#define INT_RTCP       18
+#define INT_RTCA       19
+#define INT_NFC                20
+#define INT_SD0                21
+#define INT_GSB0       22
+#define INT_PK         23
+#define INT_USBH0      24
+#define INT_USBH1      25
+#define INT_G2D                26
+#define INT_ECC                27
+#define INT_SPI0RX     28
+#define INT_UART1      29
+#define INT_MSCL       30
+#define INT_GSB1       31
+/* PIC1 interrupts */
+#define INT_E0         32
+#define INT_E1         33
+#define INT_E2         34
+#define INT_E3         35
+#define INT_E4         36
+#define INT_E5         37
+#define INT_E6         38
+#define INT_E7         39
+#define INT_UART2      40
+#define INT_UART3      41
+#define INT_SPI1TX     42
+#define INT_SPI1RX     43
+#define INT_GSB2       44
+#define INT_SPDIF      45
+#define INT_CDIF       46
+#define INT_VBON       47
+#define INT_VBOFF      48
+#define INT_SD1                49
+#define INT_UART4      50
+#define INT_GDMA3      51
+#define INT_I2S1RX     52
+#define INT_I2S1TX     53
+#define INT_CAN0       54
+#define INT_CAN1       55
+#define INT_GSB3       56
+#define INT_KRST       57
+#define INT_UNUSED     58
+#define INT_SD0D3      59
+#define INT_SD1D3      60
+#define INT_GPS0       61
+#define INT_GPS1       62
+#define INT_GPS2       63
+
+#endif  /* ASM_ARCH_TCC_IRQS_H */
diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h
new file mode 100644 (file)
index 0000000..cd91ba8
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET            UL(0x20000000)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/system.h b/arch/arm/plat-tcc/include/mach/system.h
new file mode 100644 (file)
index 0000000..909e603
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: LINUX SYSTEM FUNCTIONS for TCC83x
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <linux/clk.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+extern void plat_tcc_reboot(void);
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+       plat_tcc_reboot();
+}
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h
new file mode 100644 (file)
index 0000000..1d94282
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * Telechips TCC8000 register definitions
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPLv2.
+ */
+
+#ifndef TCC8K_REGS_H
+#define TCC8K_REGS_H
+
+#include <linux/types.h>
+
+#define EXT_SDRAM_BASE         0x20000000
+#define INT_SRAM_BASE          0x30000000
+#define INT_SRAM_SIZE          SZ_32K
+#define CS0_BASE               0x40000000
+#define CS1_BASE               0x50000000
+#define CS1_SIZE               SZ_64K
+#define CS2_BASE               0x60000000
+#define CS3_BASE               0x70000000
+#define AHB_PERI_BASE          0x80000000
+#define AHB_PERI_SIZE          SZ_64K
+#define APB0_PERI_BASE         0x90000000
+#define APB0_PERI_SIZE         SZ_128K
+#define APB1_PERI_BASE         0x98000000
+#define APB1_PERI_SIZE         SZ_128K
+#define DATA_TCM_BASE          0xa0000000
+#define DATA_TCM_SIZE          SZ_8K
+#define EXT_MEM_CTRL_BASE      0xf0000000
+#define EXT_MEM_CTRL_SIZE      SZ_4K
+
+#define CS1_BASE_VIRT          (void __iomem *)0xf7000000
+#define AHB_PERI_BASE_VIRT     (void __iomem *)0xf4000000
+#define APB0_PERI_BASE_VIRT    (void __iomem *)0xf1000000
+#define APB1_PERI_BASE_VIRT    (void __iomem *)0xf2000000
+#define EXT_MEM_CTRL_BASE_VIRT (void __iomem *)0xf3000000
+#define INT_SRAM_BASE_VIRT     (void __iomem *)0xf5000000
+#define DATA_TCM_BASE_VIRT     (void __iomem *)0xf6000000
+
+#define __REG(x)     (*((volatile u32 *)(x)))
+
+/* USB Device Controller Registers */
+#define UDC_BASE       (AHB_PERI_BASE_VIRT + 0x8000)
+#define UDC_BASE_PHYS  (AHB_PERI_BASE + 0x8000)
+
+#define UDC_IR_OFFS            0x00
+#define UDC_EIR_OFFS           0x04
+#define UDC_EIER_OFFS          0x08
+#define UDC_FAR_OFFS           0x0c
+#define UDC_FNR_OFFS           0x10
+#define UDC_EDR_OFFS           0x14
+#define UDC_RT_OFFS            0x18
+#define UDC_SSR_OFFS           0x1c
+#define UDC_SCR_OFFS           0x20
+#define UDC_EP0SR_OFFS         0x24
+#define UDC_EP0CR_OFFS         0x28
+
+#define UDC_ESR_OFFS           0x2c
+#define UDC_ECR_OFFS           0x30
+#define UDC_BRCR_OFFS          0x34
+#define UDC_BWCR_OFFS          0x38
+#define UDC_MPR_OFFS           0x3c
+#define UDC_DCR_OFFS           0x40
+#define UDC_DTCR_OFFS          0x44
+#define UDC_DFCR_OFFS          0x48
+#define UDC_DTTCR1_OFFS                0x4c
+#define UDC_DTTCR2_OFFS                0x50
+#define UDC_ESR2_OFFS          0x54
+
+#define UDC_SCR2_OFFS          0x58
+#define UDC_EP0BUF_OFFS                0x60
+#define UDC_EP1BUF_OFFS                0x64
+#define UDC_EP2BUF_OFFS                0x68
+#define UDC_EP3BUF_OFFS                0x6c
+#define UDC_PLICR_OFFS         0xa0
+#define UDC_PCR_OFFS           0xa4
+
+#define UDC_UPCR0_OFFS         0xc8
+#define UDC_UPCR1_OFFS         0xcc
+#define UDC_UPCR2_OFFS         0xd0
+#define UDC_UPCR3_OFFS         0xd4
+
+/* Bits in UDC_EIR */
+#define UDC_EIR_EP0I           (1 << 0)
+#define UDC_EIR_EP1I           (1 << 1)
+#define UDC_EIR_EP2I           (1 << 2)
+#define UDC_EIR_EP3I           (1 << 3)
+#define UDC_EIR_EPI_MASK       0x0f
+
+/* Bits in UDC_EIER */
+#define UDC_EIER_EP0IE         (1 << 0)
+#define UDC_EIER_EP1IE         (1 << 1)
+#define UDC_EIER_EP2IE         (1 << 2)
+#define UDC_EIER_EP3IE         (1 << 3)
+
+/* Bits in UDC_FNR */
+#define UDC_FNR_FN_MASK                0x7ff
+#define UDC_FNR_SM             (1 << 13)
+#define UDC_FNR_FTL            (1 << 14)
+
+/* Bits in UDC_SSR */
+#define UDC_SSR_HFRES          (1 << 0)
+#define UDC_SSR_HFSUSP         (1 << 1)
+#define UDC_SSR_HFRM           (1 << 2)
+#define UDC_SSR_SDE            (1 << 3)
+#define UDC_SSR_HSP            (1 << 4)
+#define UDC_SSR_DM             (1 << 5)
+#define UDC_SSR_DP             (1 << 6)
+#define UDC_SSR_TBM            (1 << 7)
+#define UDC_SSR_VBON           (1 << 8)
+#define UDC_SSR_VBOFF          (1 << 9)
+#define UDC_SSR_EOERR          (1 << 10)
+#define UDC_SSR_DCERR          (1 << 11)
+#define UDC_SSR_TCERR          (1 << 12)
+#define UDC_SSR_BSERR          (1 << 13)
+#define UDC_SSR_TMERR          (1 << 14)
+#define UDC_SSR_BAERR          (1 << 15)
+
+/* Bits in UDC_SCR */
+#define UDC_SCR_HRESE          (1 << 0)
+#define UDC_SCR_HSSPE          (1 << 1)
+#define UDC_SCR_RRDE           (1 << 5)
+#define UDC_SCR_SPDEN          (1 << 6)
+#define UDC_SCR_DIEN           (1 << 12)
+
+/* Bits in UDC_EP0SR */
+#define UDC_EP0SR_RSR          (1 << 0)
+#define UDC_EP0SR_TST          (1 << 1)
+#define UDC_EP0SR_SHT          (1 << 4)
+#define UDC_EP0SR_LWO          (1 << 6)
+
+/* Bits in UDC_EP0CR */
+#define UDC_EP0CR_ESS          (1 << 1)
+
+/* Bits in UDC_ESR */
+#define UDC_ESR_RPS            (1 << 0)
+#define UDC_ESR_TPS            (1 << 1)
+#define UDC_ESR_LWO            (1 << 4)
+#define UDC_ESR_FFS            (1 << 6)
+
+/* Bits in UDC_ECR */
+#define UDC_ECR_ESS            (1 << 1)
+#define UDC_ECR_CDP            (1 << 2)
+
+#define UDC_ECR_FLUSH          (1 << 6)
+#define UDC_ECR_DUEN           (1 << 7)
+
+/* Bits in UDC_UPCR0 */
+#define UDC_UPCR0_VBD          (1 << 1)
+#define UDC_UPCR0_VBDS         (1 << 6)
+#define UDC_UPCR0_RCD_12       (0x0 << 9)
+#define UDC_UPCR0_RCD_24       (0x1 << 9)
+#define UDC_UPCR0_RCD_48       (0x2 << 9)
+#define UDC_UPCR0_RCS_EXT      (0x1 << 11)
+#define UDC_UPCR0_RCS_XTAL     (0x0 << 11)
+
+/* Bits in UDC_UPCR1 */
+#define UDC_UPCR1_CDT(x)       ((x) << 0)
+#define UDC_UPCR1_OTGT(x)      ((x) << 3)
+#define UDC_UPCR1_SQRXT(x)     ((x) << 8)
+#define UDC_UPCR1_TXFSLST(x)   ((x) << 12)
+
+/* Bits in UDC_UPCR2 */
+#define UDC_UPCR2_TP           (1 << 0)
+#define UDC_UPCR2_TXRT(x)      ((x) << 2)
+#define UDC_UPCR2_TXVRT(x)     ((x) << 5)
+#define UDC_UPCR2_OPMODE(x)    ((x) << 9)
+#define UDC_UPCR2_XCVRSEL(x)   ((x) << 12)
+#define UDC_UPCR2_TM           (1 << 14)
+
+/* USB Host Controller registers */
+#define USBH0_BASE     (AHB_PERI_BASE_VIRT + 0xb000)
+#define USBH1_BASE     (AHB_PERI_BASE_VIRT + 0xb800)
+
+#define OHCI_INT_ENABLE_OFFS   0x10
+
+#define RH_DESCRIPTOR_A_OFFS   0x48
+#define RH_DESCRIPTOR_B_OFFS   0x4c
+
+#define USBHTCFG0_OFFS         0x100
+#define USBHHCFG0_OFFS         0x104
+#define USBHHCFG1_OFFS         0x104
+
+/* DMA controller registers */
+#define DMAC0_BASE     (AHB_PERI_BASE + 0x4000)
+#define DMAC1_BASE     (AHB_PERI_BASE + 0xa000)
+#define DMAC2_BASE     (AHB_PERI_BASE + 0x4800)
+#define DMAC3_BASE     (AHB_PERI_BASE + 0xa800)
+
+#define DMAC_CH_OFFSET(ch)     (ch * 0x30)
+
+#define ST_SADR_OFFS           0x00
+#define SPARAM_OFFS            0x04
+#define C_SADR_OFFS            0x0c
+#define ST_DADR_OFFS           0x10
+#define DPARAM_OFFS            0x14
+#define C_DADR_OFFS            0x1c
+#define HCOUNT_OFFS            0x20
+#define CHCTRL_OFFS            0x24
+#define RPTCTRL_OFFS           0x28
+#define EXTREQ_A_OFFS          0x2c
+
+/* Bits in CHCTRL register */
+#define CHCTRL_EN              (1 << 0)
+
+#define CHCTRL_IEN             (1 << 2)
+#define CHCTRL_FLAG            (1 << 3)
+#define CHCTRL_WSIZE8          (0 << 4)
+#define CHCTRL_WSIZE16         (1 << 4)
+#define CHCTRL_WSIZE32         (2 << 4)
+
+#define CHCTRL_BSIZE1          (0 << 6)
+#define CHCTRL_BSIZE2          (1 << 6)
+#define CHCTRL_BSIZE4          (2 << 6)
+#define CHCTRL_BSIZE8          (3 << 6)
+
+#define CHCTRL_TYPE_SINGLE_E   (0 << 8)
+#define CHCTRL_TYPE_HW         (1 << 8)
+#define CHCTRL_TYPE_SW         (2 << 8)
+#define CHCTRL_TYPE_SINGLE_L   (3 << 8)
+
+#define CHCTRL_BST             (1 << 10)
+
+/* Use DMA controller 0, channel 2 for USB */
+#define USB_DMA_BASE           (DMAC0_BASE + DMAC_CH_OFFSET(2))
+
+/* NAND flash controller registers */
+#define NFC_BASE       (AHB_PERI_BASE_VIRT + 0xd000)
+#define NFC_BASE_PHYS  (AHB_PERI_BASE + 0xd000)
+
+#define NFC_CMD_OFFS           0x00
+#define NFC_LADDR_OFFS         0x04
+#define NFC_BADDR_OFFS         0x08
+#define NFC_SADDR_OFFS         0x0c
+#define NFC_WDATA_OFFS         0x10
+#define NFC_LDATA_OFFS         0x20
+#define NFC_SDATA_OFFS         0x40
+#define NFC_CTRL_OFFS          0x50
+#define NFC_PSTART_OFFS                0x54
+#define NFC_RSTART_OFFS                0x58
+#define NFC_DSIZE_OFFS         0x5c
+#define NFC_IREQ_OFFS          0x60
+#define NFC_RST_OFFS           0x64
+#define NFC_CTRL1_OFFS         0x68
+#define NFC_MDATA_OFFS         0x70
+
+#define NFC_WDATA_PHYS_ADDR    (NFC_BASE_PHYS + NFC_WDATA_OFFS)
+
+/* Bits in NFC_CTRL */
+#define NFC_CTRL_BHLD_MASK     (0xf << 0)
+#define NFC_CTRL_BPW_MASK      (0xf << 4)
+#define NFC_CTRL_BSTP_MASK     (0xf << 8)
+#define NFC_CTRL_CADDR_MASK    (0x7 << 12)
+#define NFC_CTRL_CADDR_1       (0x0 << 12)
+#define NFC_CTRL_CADDR_2       (0x1 << 12)
+#define NFC_CTRL_CADDR_3       (0x2 << 12)
+#define NFC_CTRL_CADDR_4       (0x3 << 12)
+#define NFC_CTRL_CADDR_5       (0x4 << 12)
+#define NFC_CTRL_MSK           (1 << 15)
+#define NFC_CTRL_PSIZE256      (0 << 16)
+#define NFC_CTRL_PSIZE512      (1 << 16)
+#define NFC_CTRL_PSIZE1024     (2 << 16)
+#define NFC_CTRL_PSIZE2048     (3 << 16)
+#define NFC_CTRL_PSIZE4096     (4 << 16)
+#define NFC_CTRL_PSIZE_MASK    (7 << 16)
+#define NFC_CTRL_BSIZE1                (0 << 19)
+#define NFC_CTRL_BSIZE2                (1 << 19)
+#define NFC_CTRL_BSIZE4                (2 << 19)
+#define NFC_CTRL_BSIZE8                (3 << 19)
+#define NFC_CTRL_BSIZE_MASK    (3 << 19)
+#define NFC_CTRL_RDY           (1 << 21)
+#define NFC_CTRL_CS0SEL                (1 << 22)
+#define NFC_CTRL_CS1SEL                (1 << 23)
+#define NFC_CTRL_CS2SEL                (1 << 24)
+#define NFC_CTRL_CS3SEL                (1 << 25)
+#define NFC_CTRL_CSMASK                (0xf << 22)
+#define NFC_CTRL_BW            (1 << 26)
+#define NFC_CTRL_FS            (1 << 27)
+#define NFC_CTRL_DEN           (1 << 28)
+#define NFC_CTRL_READ_IEN      (1 << 29)
+#define NFC_CTRL_PROG_IEN      (1 << 30)
+#define NFC_CTRL_RDY_IEN       (1 << 31)
+
+/* Bits in NFC_IREQ */
+#define NFC_IREQ_IRQ0          (1 << 0)
+#define NFC_IREQ_IRQ1          (1 << 1)
+#define NFC_IREQ_IRQ2          (1 << 2)
+
+#define NFC_IREQ_FLAG0         (1 << 4)
+#define NFC_IREQ_FLAG1         (1 << 5)
+#define NFC_IREQ_FLAG2         (1 << 6)
+
+/* MMC controller registers */
+#define MMC0_BASE      (AHB_PERI_BASE_VIRT + 0xe000)
+#define MMC1_BASE      (AHB_PERI_BASE_VIRT + 0xe800)
+
+/* UART base addresses */
+
+#define UART0_BASE     (APB0_PERI_BASE_VIRT + 0x07000)
+#define UART0_BASE_PHYS        (APB0_PERI_BASE + 0x07000)
+#define UART1_BASE     (APB0_PERI_BASE_VIRT + 0x08000)
+#define UART1_BASE_PHYS        (APB0_PERI_BASE + 0x08000)
+#define UART2_BASE     (APB0_PERI_BASE_VIRT + 0x09000)
+#define UART2_BASE_PHYS        (APB0_PERI_BASE + 0x09000)
+#define UART3_BASE     (APB0_PERI_BASE_VIRT + 0x0a000)
+#define UART3_BASE_PHYS        (APB0_PERI_BASE + 0x0a000)
+#define UART4_BASE     (APB0_PERI_BASE_VIRT + 0x15000)
+#define UART4_BASE_PHYS        (APB0_PERI_BASE + 0x15000)
+
+#define UART_BASE      UART0_BASE
+#define UART_BASE_PHYS UART0_BASE_PHYS
+
+/* ECC controller */
+#define ECC_CTR_BASE   (APB0_PERI_BASE_VIRT + 0xd000)
+
+#define ECC_CTRL_OFFS          0x00
+#define ECC_BASE_OFFS          0x04
+#define ECC_MASK_OFFS          0x08
+#define ECC_CLEAR_OFFS         0x0c
+#define ECC4_0_OFFS            0x10
+#define ECC4_1_OFFS            0x14
+
+#define ECC_EADDR0_OFFS                0x50
+
+#define ECC_ERRNUM_OFFS                0x90
+#define ECC_IREQ_OFFS          0x94
+
+/* Bits in ECC_CTRL */
+#define ECC_CTRL_ECC4_DIEN     (1 << 28)
+#define ECC_CTRL_ECC8_DIEN     (1 << 29)
+#define ECC_CTRL_ECC12_DIEN    (1 << 30)
+#define ECC_CTRL_ECC_DISABLE   0x0
+#define ECC_CTRL_ECC_SLC_ENC   0x8
+#define ECC_CTRL_ECC_SLC_DEC   0x9
+#define ECC_CTRL_ECC4_ENC      0xa
+#define ECC_CTRL_ECC4_DEC      0xb
+#define ECC_CTRL_ECC8_ENC      0xc
+#define ECC_CTRL_ECC8_DEC      0xd
+#define ECC_CTRL_ECC12_ENC     0xe
+#define ECC_CTRL_ECC12_DEC     0xf
+
+/* Bits in ECC_IREQ */
+#define ECC_IREQ_E4DI          (1 << 4)
+
+#define ECC_IREQ_E4DF          (1 << 20)
+#define ECC_IREQ_E4EF          (1 << 21)
+
+/* Interrupt controller */
+
+#define PIC0_BASE      (APB1_PERI_BASE_VIRT + 0x3000)
+#define PIC0_BASE_PHYS (APB1_PERI_BASE + 0x3000)
+
+#define PIC0_IEN_OFFS          0x00
+#define PIC0_CREQ_OFFS         0x04
+#define PIC0_IREQ_OFFS         0x08
+#define PIC0_IRQSEL_OFFS       0x0c
+#define PIC0_SRC_OFFS          0x10
+#define PIC0_MREQ_OFFS         0x14
+#define PIC0_TSTREQ_OFFS       0x18
+#define PIC0_POL_OFFS          0x1c
+#define PIC0_IRQ_OFFS          0x20
+#define PIC0_FIQ_OFFS          0x24
+#define PIC0_MIRQ_OFFS         0x28
+#define PIC0_MFIQ_OFFS         0x2c
+#define PIC0_TMODE_OFFS                0x30
+#define PIC0_SYNC_OFFS         0x34
+#define PIC0_WKUP_OFFS         0x38
+#define PIC0_TMODEA_OFFS       0x3c
+#define PIC0_INTOEN_OFFS       0x40
+#define PIC0_MEN0_OFFS         0x44
+#define PIC0_MEN_OFFS          0x48
+
+#define PIC0_IEN               __REG(PIC0_BASE + PIC0_IEN_OFFS)
+#define PIC0_IEN_PHYS          __REG(PIC0_BASE_PHYS + PIC0_IEN_OFFS)
+#define PIC0_CREQ              __REG(PIC0_BASE + PIC0_CREQ_OFFS)
+#define PIC0_CREQ_PHYS         __REG(PIC0_BASE_PHYS + PIC0_CREQ_OFFS)
+#define PIC0_IREQ              __REG(PIC0_BASE + PIC0_IREQ_OFFS)
+#define PIC0_IRQSEL            __REG(PIC0_BASE + PIC0_IRQSEL_OFFS)
+#define PIC0_IRQSEL_PHYS       __REG(PIC0_BASE_PHYS + PIC0_IRQSEL_OFFS)
+#define PIC0_SRC               __REG(PIC0_BASE + PIC0_SRC_OFFS)
+#define PIC0_MREQ              __REG(PIC0_BASE + PIC0_MREQ_OFFS)
+#define PIC0_TSTREQ            __REG(PIC0_BASE + PIC0_TSTREQ_OFFS)
+#define PIC0_POL               __REG(PIC0_BASE + PIC0_POL_OFFS)
+#define PIC0_IRQ               __REG(PIC0_BASE + PIC0_IRQ_OFFS)
+#define PIC0_FIQ               __REG(PIC0_BASE + PIC0_FIQ_OFFS)
+#define PIC0_MIRQ              __REG(PIC0_BASE + PIC0_MIRQ_OFFS)
+#define PIC0_MFIQ              __REG(PIC0_BASE + PIC0_MFIQ_OFFS)
+#define PIC0_TMODE             __REG(PIC0_BASE + PIC0_TMODE_OFFS)
+#define PIC0_TMODE_PHYS                __REG(PIC0_BASE_PHYS + PIC0_TMODE_OFFS)
+#define PIC0_SYNC              __REG(PIC0_BASE + PIC0_SYNC_OFFS)
+#define PIC0_WKUP              __REG(PIC0_BASE + PIC0_WKUP_OFFS)
+#define PIC0_TMODEA            __REG(PIC0_BASE + PIC0_TMODEA_OFFS)
+#define PIC0_INTOEN            __REG(PIC0_BASE + PIC0_INTOEN_OFFS)
+#define PIC0_MEN0              __REG(PIC0_BASE + PIC0_MEN0_OFFS)
+#define PIC0_MEN               __REG(PIC0_BASE + PIC0_MEN_OFFS)
+
+#define PIC1_BASE      (APB1_PERI_BASE_VIRT + 0x3080)
+
+#define PIC1_IEN_OFFS          0x00
+#define PIC1_CREQ_OFFS         0x04
+#define PIC1_IREQ_OFFS         0x08
+#define PIC1_IRQSEL_OFFS       0x0c
+#define PIC1_SRC_OFFS          0x10
+#define PIC1_MREQ_OFFS         0x14
+#define PIC1_TSTREQ_OFFS       0x18
+#define PIC1_POL_OFFS          0x1c
+#define PIC1_IRQ_OFFS          0x20
+#define PIC1_FIQ_OFFS          0x24
+#define PIC1_MIRQ_OFFS         0x28
+#define PIC1_MFIQ_OFFS         0x2c
+#define PIC1_TMODE_OFFS                0x30
+#define PIC1_SYNC_OFFS         0x34
+#define PIC1_WKUP_OFFS         0x38
+#define PIC1_TMODEA_OFFS       0x3c
+#define PIC1_INTOEN_OFFS       0x40
+#define PIC1_MEN1_OFFS         0x44
+#define PIC1_MEN_OFFS          0x48
+
+#define PIC1_IEN       __REG(PIC1_BASE + PIC1_IEN_OFFS)
+#define PIC1_CREQ      __REG(PIC1_BASE + PIC1_CREQ_OFFS)
+#define PIC1_IREQ      __REG(PIC1_BASE + PIC1_IREQ_OFFS)
+#define PIC1_IRQSEL    __REG(PIC1_BASE + PIC1_IRQSEL_OFFS)
+#define PIC1_SRC       __REG(PIC1_BASE + PIC1_SRC_OFFS)
+#define PIC1_MREQ      __REG(PIC1_BASE + PIC1_MREQ_OFFS)
+#define PIC1_TSTREQ    __REG(PIC1_BASE + PIC1_TSTREQ_OFFS)
+#define PIC1_POL       __REG(PIC1_BASE + PIC1_POL_OFFS)
+#define PIC1_IRQ       __REG(PIC1_BASE + PIC1_IRQ_OFFS)
+#define PIC1_FIQ       __REG(PIC1_BASE + PIC1_FIQ_OFFS)
+#define PIC1_MIRQ      __REG(PIC1_BASE + PIC1_MIRQ_OFFS)
+#define PIC1_MFIQ      __REG(PIC1_BASE + PIC1_MFIQ_OFFS)
+#define PIC1_TMODE     __REG(PIC1_BASE + PIC1_TMODE_OFFS)
+#define PIC1_SYNC      __REG(PIC1_BASE + PIC1_SYNC_OFFS)
+#define PIC1_WKUP      __REG(PIC1_BASE + PIC1_WKUP_OFFS)
+#define PIC1_TMODEA    __REG(PIC1_BASE + PIC1_TMODEA_OFFS)
+#define PIC1_INTOEN    __REG(PIC1_BASE + PIC1_INTOEN_OFFS)
+#define PIC1_MEN1      __REG(PIC1_BASE + PIC1_MEN1_OFFS)
+#define PIC1_MEN       __REG(PIC1_BASE + PIC1_MEN_OFFS)
+
+/* Timer registers */
+#define TIMER_BASE             (APB1_PERI_BASE_VIRT + 0x4000)
+#define TIMER_BASE_PHYS                (APB1_PERI_BASE + 0x4000)
+
+#define TWDCFG_OFFS            0x70
+
+#define TC32EN_OFFS            0x80
+#define TC32LDV_OFFS           0x84
+#define TC32CMP0_OFFS          0x88
+#define TC32CMP1_OFFS          0x8c
+#define TC32PCNT_OFFS          0x90
+#define TC32MCNT_OFFS          0x94
+#define TC32IRQ_OFFS           0x98
+
+/* Bits in TC32EN */
+#define TC32EN_PRESCALE_MASK   0x00ffffff
+#define TC32EN_ENABLE          (1 << 24)
+#define TC32EN_LOADZERO                (1 << 25)
+#define TC32EN_STOPMODE                (1 << 26)
+#define TC32EN_LDM0            (1 << 28)
+#define TC32EN_LDM1            (1 << 29)
+
+/* Bits in TC32IRQ */
+#define TC32IRQ_MSTAT_MASK     0x0000001f
+#define TC32IRQ_RSTAT_MASK     (0x1f << 8)
+#define TC32IRQ_IRQEN0         (1 << 16)
+#define TC32IRQ_IRQEN1         (1 << 17)
+#define TC32IRQ_IRQEN2         (1 << 18)
+#define TC32IRQ_IRQEN3         (1 << 19)
+#define TC32IRQ_IRQEN4         (1 << 20)
+#define TC32IRQ_RSYNC          (1 << 30)
+#define TC32IRQ_IRQCLR         (1 << 31)
+
+/* GPIO registers */
+#define GPIOPD_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPD_DAT_OFFS                0x00
+#define GPIOPD_DOE_OFFS                0x04
+#define GPIOPD_FS0_OFFS                0x08
+#define GPIOPD_FS1_OFFS                0x0c
+#define GPIOPD_FS2_OFFS                0x10
+#define GPIOPD_RPU_OFFS                0x30
+#define GPIOPD_RPD_OFFS                0x34
+#define GPIOPD_DV0_OFFS                0x38
+#define GPIOPD_DV1_OFFS                0x3c
+
+#define GPIOPS_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPS_DAT_OFFS                0x40
+#define GPIOPS_DOE_OFFS                0x44
+#define GPIOPS_FS0_OFFS                0x48
+#define GPIOPS_FS1_OFFS                0x4c
+#define GPIOPS_FS2_OFFS                0x50
+#define GPIOPS_FS3_OFFS                0x54
+#define GPIOPS_RPU_OFFS                0x70
+#define GPIOPS_RPD_OFFS                0x74
+#define GPIOPS_DV0_OFFS                0x78
+#define GPIOPS_DV1_OFFS                0x7c
+
+#define GPIOPS_FS1_SDH0_BITS   0x000000ff
+#define GPIOPS_FS1_SDH1_BITS   0x0000ff00
+
+#define GPIOPU_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPU_DAT_OFFS                0x80
+#define GPIOPU_DOE_OFFS                0x84
+#define GPIOPU_FS0_OFFS                0x88
+#define GPIOPU_FS1_OFFS                0x8c
+#define GPIOPU_FS2_OFFS                0x90
+#define GPIOPU_RPU_OFFS                0xb0
+#define GPIOPU_RPD_OFFS                0xb4
+#define GPIOPU_DV0_OFFS                0xb8
+#define GPIOPU_DV1_OFFS                0xbc
+
+#define GPIOPU_FS0_TXD0                (1 << 0)
+#define GPIOPU_FS0_RXD0                (1 << 1)
+#define GPIOPU_FS0_CTS0                (1 << 2)
+#define GPIOPU_FS0_RTS0                (1 << 3)
+#define GPIOPU_FS0_TXD1                (1 << 4)
+#define GPIOPU_FS0_RXD1                (1 << 5)
+#define GPIOPU_FS0_CTS1                (1 << 6)
+#define GPIOPU_FS0_RTS1                (1 << 7)
+#define GPIOPU_FS0_TXD2                (1 << 8)
+#define GPIOPU_FS0_RXD2                (1 << 9)
+#define GPIOPU_FS0_CTS2                (1 << 10)
+#define GPIOPU_FS0_RTS2                (1 << 11)
+#define GPIOPU_FS0_TXD3                (1 << 12)
+#define GPIOPU_FS0_RXD3                (1 << 13)
+#define GPIOPU_FS0_CTS3                (1 << 14)
+#define GPIOPU_FS0_RTS3                (1 << 15)
+#define GPIOPU_FS0_TXD4                (1 << 16)
+#define GPIOPU_FS0_RXD4                (1 << 17)
+#define GPIOPU_FS0_CTS4                (1 << 18)
+#define GPIOPU_FS0_RTS4                (1 << 19)
+
+#define GPIOFC_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFC_DAT_OFFS                0xc0
+#define GPIOFC_DOE_OFFS                0xc4
+#define GPIOFC_FS0_OFFS                0xc8
+#define GPIOFC_FS1_OFFS                0xcc
+#define GPIOFC_FS2_OFFS                0xd0
+#define GPIOFC_FS3_OFFS                0xd4
+#define GPIOFC_RPU_OFFS                0xf0
+#define GPIOFC_RPD_OFFS                0xf4
+#define GPIOFC_DV0_OFFS                0xf8
+#define GPIOFC_DV1_OFFS                0xfc
+
+#define GPIOFD_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFD_DAT_OFFS                0x100
+#define GPIOFD_DOE_OFFS                0x104
+#define GPIOFD_FS0_OFFS                0x108
+#define GPIOFD_FS1_OFFS                0x10c
+#define GPIOFD_FS2_OFFS                0x110
+#define GPIOFD_RPU_OFFS                0x130
+#define GPIOFD_RPD_OFFS                0x134
+#define GPIOFD_DV0_OFFS                0x138
+#define GPIOFD_DV1_OFFS                0x13c
+
+#define GPIOLC_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLC_DAT_OFFS                0x140
+#define GPIOLC_DOE_OFFS                0x144
+#define GPIOLC_FS0_OFFS                0x148
+#define GPIOLC_FS1_OFFS                0x14c
+#define GPIOLC_RPU_OFFS                0x170
+#define GPIOLC_RPD_OFFS                0x174
+#define GPIOLC_DV0_OFFS                0x178
+#define GPIOLC_DV1_OFFS                0x17c
+
+#define GPIOLD_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLD_DAT_OFFS                0x180
+#define GPIOLD_DOE_OFFS                0x184
+#define GPIOLD_FS0_OFFS                0x188
+#define GPIOLD_FS1_OFFS                0x18c
+#define GPIOLD_FS2_OFFS                0x190
+#define GPIOLD_RPU_OFFS                0x1b0
+#define GPIOLD_RPD_OFFS                0x1b4
+#define GPIOLD_DV0_OFFS                0x1b8
+#define GPIOLD_DV1_OFFS                0x1bc
+
+#define GPIOAD_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOAD_DAT_OFFS                0x1c0
+#define GPIOAD_DOE_OFFS                0x1c4
+#define GPIOAD_FS0_OFFS                0x1c8
+#define GPIOAD_RPU_OFFS                0x1f0
+#define GPIOAD_RPD_OFFS                0x1f4
+#define GPIOAD_DV0_OFFS                0x1f8
+#define GPIOAD_DV1_OFFS                0x1fc
+
+#define GPIOXC_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXC_DAT_OFFS                0x200
+#define GPIOXC_DOE_OFFS                0x204
+#define GPIOXC_FS0_OFFS                0x208
+#define GPIOXC_RPU_OFFS                0x230
+#define GPIOXC_RPD_OFFS                0x234
+#define GPIOXC_DV0_OFFS                0x238
+#define GPIOXC_DV1_OFFS                0x23c
+
+#define GPIOXC_FS0             __REG(GPIOXC_BASE + GPIOXC_FS0_OFFS)
+
+#define GPIOXC_FS0_CS0         (1 << 26)
+#define GPIOXC_FS0_CS1         (1 << 27)
+
+#define GPIOXD_BASE            (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXD_DAT_OFFS                0x240
+#define GPIOXD_FS0_OFFS                0x248
+#define GPIOXD_RPU_OFFS                0x270
+#define GPIOXD_RPD_OFFS                0x274
+#define GPIOXD_DV0_OFFS                0x278
+#define GPIOXD_DV1_OFFS                0x27c
+
+#define GPIOPK_BASE            (APB1_PERI_BASE_VIRT + 0x1c000)
+
+#define GPIOPK_RST_OFFS                0x008
+#define GPIOPK_DAT_OFFS                0x100
+#define GPIOPK_DOE_OFFS                0x104
+#define GPIOPK_FS0_OFFS                0x108
+#define GPIOPK_FS1_OFFS                0x10c
+#define GPIOPK_FS2_OFFS                0x110
+#define GPIOPK_IRQST_OFFS      0x210
+#define GPIOPK_IRQEN_OFFS      0x214
+#define GPIOPK_IRQPOL_OFFS     0x218
+#define GPIOPK_IRQTM0_OFFS     0x21c
+#define GPIOPK_IRQTM1_OFFS     0x220
+#define GPIOPK_CTL_OFFS                0x22c
+
+#define PMGPIO_BASE            (APB1_PERI_BASE_VIRT + 0x10000)
+#define BACKUP_RAM_BASE                PMGPIO_BASE
+
+#define PMGPIO_DAT_OFFS                0x800
+#define PMGPIO_DOE_OFFS                0x804
+#define PMGPIO_FS0_OFFS                0x808
+#define PMGPIO_RPU_OFFS                0x810
+#define PMGPIO_RPD_OFFS                0x814
+#define PMGPIO_DV0_OFFS                0x818
+#define PMGPIO_DV1_OFFS                0x81c
+#define PMGPIO_EE0_OFFS                0x820
+#define PMGPIO_EE1_OFFS                0x824
+#define PMGPIO_CTL_OFFS                0x828
+#define PMGPIO_DI_OFFS         0x82c
+#define PMGPIO_STR_OFFS                0x830
+#define PMGPIO_STF_OFFS                0x834
+#define PMGPIO_POL_OFFS                0x838
+#define PMGPIO_APB_OFFS                0x800
+
+/* Clock controller registers */
+#define CKC_BASE       ((void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000))
+
+#define CLKCTRL_OFFS           0x00
+#define PLL0CFG_OFFS           0x04
+#define PLL1CFG_OFFS           0x08
+#define CLKDIVC0_OFFS          0x0c
+
+#define BCLKCTR0_OFFS          0x14
+#define SWRESET0_OFFS          0x18
+
+#define BCLKCTR1_OFFS          0x60
+#define SWRESET1_OFFS          0x64
+#define PWDCTL_OFFS            0x68
+#define PLL2CFG_OFFS           0x6c
+#define CLKDIVC1_OFFS          0x70
+
+#define ACLKREF_OFFS           0x80
+#define ACLKI2C_OFFS           0x84
+#define ACLKSPI0_OFFS          0x88
+#define ACLKSPI1_OFFS          0x8c
+#define ACLKUART0_OFFS         0x90
+#define ACLKUART1_OFFS         0x94
+#define ACLKUART2_OFFS         0x98
+#define ACLKUART3_OFFS         0x9c
+#define ACLKUART4_OFFS         0xa0
+#define ACLKTCT_OFFS           0xa4
+#define ACLKTCX_OFFS           0xa8
+#define ACLKTCZ_OFFS           0xac
+#define ACLKADC_OFFS           0xb0
+#define ACLKDAI0_OFFS          0xb4
+#define ACLKDAI1_OFFS          0xb8
+#define ACLKLCD_OFFS           0xbc
+#define ACLKSPDIF_OFFS         0xc0
+#define ACLKUSBH_OFFS          0xc4
+#define ACLKSDH0_OFFS          0xc8
+#define ACLKSDH1_OFFS          0xcc
+#define ACLKC3DEC_OFFS         0xd0
+#define ACLKEXT_OFFS           0xd4
+#define ACLKCAN0_OFFS          0xd8
+#define ACLKCAN1_OFFS          0xdc
+#define ACLKGSB0_OFFS          0xe0
+#define ACLKGSB1_OFFS          0xe4
+#define ACLKGSB2_OFFS          0xe8
+#define ACLKGSB3_OFFS          0xec
+
+#define PLLxCFG_PD             (1 << 31)
+
+/* CLKCTRL bits */
+#define CLKCTRL_XE             (1 << 31)
+
+/* CLKDIVCx bits */
+#define CLKDIVC0_XTE           (1 << 7)
+#define CLKDIVC0_XE            (1 << 15)
+#define CLKDIVC0_P1E           (1 << 23)
+#define CLKDIVC0_P0E           (1 << 31)
+
+#define CLKDIVC1_P2E           (1 << 7)
+
+/* BCLKCTR0 clock bits */
+#define BCLKCTR0_USBD          (1 << 4)
+#define BCLKCTR0_ECC           (1 << 9)
+#define BCLKCTR0_USBH0         (1 << 11)
+#define BCLKCTR0_NFC           (1 << 16)
+
+/* BCLKCTR1 clock bits */
+#define BCLKCTR1_USBH1         (1 << 20)
+
+/* SWRESET0 bits */
+#define SWRESET0_USBD          (1 << 4)
+#define SWRESET0_USBH0         (1 << 11)
+
+/* SWRESET1 bits */
+#define SWRESET1_USBH1         (1 << 20)
+
+/* System clock sources.
+ * Note: These are the clock sources that serve as parents for
+ * all other clocks. They have no parents themselves.
+ *
+ * These values are used for struct clk->root_id. All clocks
+ * that are not system clock sources have this value set to
+ * CLK_SRC_NOROOT.
+ * The values for system clocks start with CLK_SRC_PLL0 == 0
+ * because this gives us exactly the values needed for the lower
+ * 4 bits of ACLK_* registers. Therefore, CLK_SRC_NOROOT is
+ * defined as -1 to not disturb the order.
+ */
+enum root_clks {
+       CLK_SRC_NOROOT = -1,
+       CLK_SRC_PLL0 = 0,
+       CLK_SRC_PLL1,
+       CLK_SRC_PLL0DIV,
+       CLK_SRC_PLL1DIV,
+       CLK_SRC_XI,
+       CLK_SRC_XIDIV,
+       CLK_SRC_XTI,
+       CLK_SRC_XTIDIV,
+       CLK_SRC_PLL2,
+       CLK_SRC_PLL2DIV,
+       CLK_SRC_PK0,
+       CLK_SRC_PK1,
+       CLK_SRC_PK2,
+       CLK_SRC_PK3,
+       CLK_SRC_PK4,
+       CLK_SRC_48MHZ
+};
+
+#define CLK_SRC_MASK           0xf
+
+/* Bits in ACLK* registers */
+#define ACLK_EN                (1 << 28)
+#define ACLK_SEL_SHIFT         24
+#define ACLK_SEL_MASK          0x0f000000
+#define ACLK_DIV_MASK          0x00000fff
+
+/* System configuration registers */
+
+#define SCFG_BASE              (APB1_PERI_BASE_VIRT + 0x13000)
+
+#define        BMI_OFFS                0x00
+#define AHBCON0_OFFS           0x04
+#define APBPWE_OFFS            0x08
+#define DTCMWAIT_OFFS          0x0c
+#define ECCSEL_OFFS            0x10
+#define AHBCON1_OFFS           0x14
+#define SDHCFG_OFFS            0x18
+#define REMAP_OFFS             0x20
+#define LCDSIAE_OFFS           0x24
+#define XMCCFG_OFFS            0xe0
+#define IMCCFG_OFFS            0xe4
+
+/* Values for ECCSEL */
+#define ECCSEL_EXTMEM          0x0
+#define ECCSEL_DTCM            0x1
+#define ECCSEL_INT_SRAM                0x2
+#define ECCSEL_AHB             0x3
+
+/* Bits in XMCCFG */
+#define XMCCFG_NFCE            (1 << 1)
+#define XMCCFG_FDXD            (1 << 2)
+
+/* External memory controller registers */
+
+#define EMC_BASE               EXT_MEM_CTRL_BASE
+
+#define SDCFG_OFFS             0x00
+#define SDFSM_OFFS             0x04
+#define MCFG_OFFS              0x08
+
+#define CSCFG0_OFFS            0x10
+#define CSCFG1_OFFS            0x14
+#define CSCFG2_OFFS            0x18
+#define CSCFG3_OFFS            0x1c
+
+#define MCFG_SDEN              (1 << 4)
+
+#endif /* TCC8K_REGS_H */
diff --git a/arch/arm/plat-tcc/include/mach/timex.h b/arch/arm/plat-tcc/include/mach/timex.h
new file mode 100644 (file)
index 0000000..057acbe
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * A definition needed by arch core code.
+ *
+ */
+#define CLOCK_TICK_RATE                (HZ * 100000UL)
diff --git a/arch/arm/plat-tcc/include/mach/uncompress.h b/arch/arm/plat-tcc/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..7a3e33a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This file is licensed under the terms of the GPL version 2.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/types.h>
+
+#include <mach/tcc8k-regs.h>
+
+unsigned int system_rev;
+
+#define ID_MASK                        0x7fff
+
+static void putc(int c)
+{
+       u32 *uart_lsr = (u32 *)(UART_BASE_PHYS + (UART_LSR << 2));
+       u32 *uart_tx = (u32 *)(UART_BASE_PHYS + (UART_TX << 2));
+
+       while (!(*uart_lsr & UART_LSR_THRE))
+               barrier();
+       *uart_tx = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/plat-tcc/include/mach/vmalloc.h b/arch/arm/plat-tcc/include/mach/vmalloc.h
new file mode 100644 (file)
index 0000000..99414d9
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ *
+ * Copyright (C) 2000 Russell King.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+#define VMALLOC_END    0xf0000000UL
diff --git a/arch/arm/plat-tcc/system.c b/arch/arm/plat-tcc/system.c
new file mode 100644 (file)
index 0000000..cc208fa
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * System functions for Telechips TCCxxxx SoCs
+ *
+ * Copyright (C) Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#include <linux/io.h>
+
+#include <mach/tcc8k-regs.h>
+
+/* System reboot */
+void plat_tcc_reboot(void)
+{
+       /* Make sure clocks are on */
+       __raw_writel(0xffffffff, CKC_BASE + BCLKCTR0_OFFS);
+
+       /* Enable watchdog reset */
+       __raw_writel(0x49, TIMER_BASE + TWDCFG_OFFS);
+       /* Wait for reset */
+       while(1)
+               ;
+}
index 48cbdcb6bbd4288929f31bef94da3691b160a489..55590a4d87c932984404d1df13ca4c296c9d7117 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Jul 12 21:10:14 2010
+# Last update: Thu Sep 9 22:43:01 2010
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -2622,7 +2622,7 @@ kraken                    MACH_KRAKEN             KRAKEN                  2634
 gw2388                 MACH_GW2388             GW2388                  2635
 jadecpu                        MACH_JADECPU            JADECPU                 2636
 carlisle               MACH_CARLISLE           CARLISLE                2637
-lux_sf9                        MACH_LUX_SFT9           LUX_SFT9                2638
+lux_sf9                        MACH_LUX_SF9            LUX_SF9                 2638
 nemid_tb               MACH_NEMID_TB           NEMID_TB                2639
 terrier                        MACH_TERRIER            TERRIER                 2640
 turbot                 MACH_TURBOT             TURBOT                  2641
@@ -2950,3 +2950,97 @@ davinci_dm365_dvr        MACH_DAVINCI_DM365_DVR  DAVINCI_DM365_DVR       2963
 netviz                 MACH_NETVIZ             NETVIZ                  2964
 flexibity              MACH_FLEXIBITY          FLEXIBITY               2965
 wlan_computer          MACH_WLAN_COMPUTER      WLAN_COMPUTER           2966
+lpc24xx                        MACH_LPC24XX            LPC24XX                 2967
+spica                  MACH_SPICA              SPICA                   2968
+gpsdisplay             MACH_GPSDISPLAY         GPSDISPLAY              2969
+bipnet                 MACH_BIPNET             BIPNET                  2970
+overo_ctu_inertial     MACH_OVERO_CTU_INERTIAL OVERO_CTU_INERTIAL      2971
+davinci_dm355_mmm      MACH_DAVINCI_DM355_MMM  DAVINCI_DM355_MMM       2972
+pc9260_v2              MACH_PC9260_V2          PC9260_V2               2973
+ptx7545                        MACH_PTX7545            PTX7545                 2974
+tm_efdc                        MACH_TM_EFDC            TM_EFDC                 2975
+omap3_waldo1           MACH_OMAP3_WALDO1       OMAP3_WALDO1            2977
+flyer                  MACH_FLYER              FLYER                   2978
+tornado3240            MACH_TORNADO3240        TORNADO3240             2979
+soli_01                        MACH_SOLI_01            SOLI_01                 2980
+omapl138_europalc      MACH_OMAPL138_EUROPALC  OMAPL138_EUROPALC       2981
+helios_v1              MACH_HELIOS_V1          HELIOS_V1               2982
+netspace_lite_v2       MACH_NETSPACE_LITE_V2   NETSPACE_LITE_V2        2983
+ssc                    MACH_SSC                SSC                     2984
+premierwave_en         MACH_PREMIERWAVE_EN     PREMIERWAVE_EN          2985
+wasabi                 MACH_WASABI             WASABI                  2986
+vivow                  MACH_VIVOW              VIVOW                   2987
+mx50_rdp               MACH_MX50_RDP           MX50_RDP                2988
+universal              MACH_UNIVERSAL          UNIVERSAL               2989
+real6410               MACH_REAL6410           REAL6410                2990
+spx_sakura             MACH_SPX_SAKURA         SPX_SAKURA              2991
+ij3k_2440              MACH_IJ3K_2440          IJ3K_2440               2992
+omap3_bc10             MACH_OMAP3_BC10         OMAP3_BC10              2993
+thebe                  MACH_THEBE              THEBE                   2994
+rv082                  MACH_RV082              RV082                   2995
+armlguest              MACH_ARMLGUEST          ARMLGUEST               2996
+tjinc1000              MACH_TJINC1000          TJINC1000               2997
+dockstar               MACH_DOCKSTAR           DOCKSTAR                2998
+ax8008                 MACH_AX8008             AX8008                  2999
+gnet_sgce              MACH_GNET_SGCE          GNET_SGCE               3000
+pxwnas_500_1000                MACH_PXWNAS_500_1000    PXWNAS_500_1000         3001
+ea20                   MACH_EA20               EA20                    3002
+awm2                   MACH_AWM2               AWM2                    3003
+ti8148evm              MACH_TI8148EVM          TI8148EVM               3004
+tegra_seaboard         MACH_TEGRA_SEABOARD     TEGRA_SEABOARD          3005
+linkstation_chlv2      MACH_LINKSTATION_CHLV2  LINKSTATION_CHLV2       3006
+tera_pro2_rack         MACH_TERA_PRO2_RACK     TERA_PRO2_RACK          3007
+rubys                  MACH_RUBYS              RUBYS                   3008
+aquarius               MACH_AQUARIUS           AQUARIUS                3009
+mx53_ard               MACH_MX53_ARD           MX53_ARD                3010
+mx53_smd               MACH_MX53_SMD           MX53_SMD                3011
+lswxl                  MACH_LSWXL              LSWXL                   3012
+dove_avng_v3           MACH_DOVE_AVNG_V3       DOVE_AVNG_V3            3013
+sdi_ess_9263           MACH_SDI_ESS_9263       SDI_ESS_9263            3014
+jocpu550               MACH_JOCPU550           JOCPU550                3015
+msm8x60_rumi3          MACH_MSM8X60_RUMI3      MSM8X60_RUMI3           3016
+msm8x60_ffa            MACH_MSM8X60_FFA        MSM8X60_FFA             3017
+yanomami               MACH_YANOMAMI           YANOMAMI                3018
+gta04                  MACH_GTA04              GTA04                   3019
+cm_a510                        MACH_CM_A510            CM_A510                 3020
+omap3_rfs200           MACH_OMAP3_RFS200       OMAP3_RFS200            3021
+kx33xx                 MACH_KX33XX             KX33XX                  3022
+ptx7510                        MACH_PTX7510            PTX7510                 3023
+top9000                        MACH_TOP9000            TOP9000                 3024
+teenote                        MACH_TEENOTE            TEENOTE                 3025
+ts3                    MACH_TS3                TS3                     3026
+a0                     MACH_A0                 A0                      3027
+fsm9xxx_surf           MACH_FSM9XXX_SURF       FSM9XXX_SURF            3028
+fsm9xxx_ffa            MACH_FSM9XXX_FFA        FSM9XXX_FFA             3029
+frrhwcdma60w           MACH_FRRHWCDMA60W       FRRHWCDMA60W            3030
+remus                  MACH_REMUS              REMUS                   3031
+at91cap7xdk            MACH_AT91CAP7XDK        AT91CAP7XDK             3032
+at91cap7stk            MACH_AT91CAP7STK        AT91CAP7STK             3033
+kt_sbc_sam9_1          MACH_KT_SBC_SAM9_1      KT_SBC_SAM9_1           3034
+oratisrouter           MACH_ORATISROUTER       ORATISROUTER            3035
+armada_xp_db           MACH_ARMADA_XP_DB       ARMADA_XP_DB            3036
+spdm                   MACH_SPDM               SPDM                    3037
+gtib                   MACH_GTIB               GTIB                    3038
+dgm3240                        MACH_DGM3240            DGM3240                 3039
+atlas_i_lpe            MACH_ATLAS_I_LPE        ATLAS_I_LPE             3040
+htcmega                        MACH_HTCMEGA            HTCMEGA                 3041
+tricorder              MACH_TRICORDER          TRICORDER               3042
+tx28                   MACH_TX28               TX28                    3043
+bstbrd                 MACH_BSTBRD             BSTBRD                  3044
+pwb3090                        MACH_PWB3090            PWB3090                 3045
+idea6410               MACH_IDEA6410           IDEA6410                3046
+qbc9263                        MACH_QBC9263            QBC9263                 3047
+borabora               MACH_BORABORA           BORABORA                3048
+valdez                 MACH_VALDEZ             VALDEZ                  3049
+ls9g20                 MACH_LS9G20             LS9G20                  3050
+mios_v1                        MACH_MIOS_V1            MIOS_V1                 3051
+s5pc110_crespo         MACH_S5PC110_CRESPO     S5PC110_CRESPO          3052
+controltek9g20         MACH_CONTROLTEK9G20     CONTROLTEK9G20          3053
+tin307                 MACH_TIN307             TIN307                  3054
+tin510                 MACH_TIN510             TIN510                  3055
+bluecheese             MACH_BLUECHEESE         BLUECHEESE              3057
+tem3x30                        MACH_TEM3X30            TEM3X30                 3058
+harvest_desoto         MACH_HARVEST_DESOTO     HARVEST_DESOTO          3059
+msm8x60_qrdc           MACH_MSM8X60_QRDC       MSM8X60_QRDC            3060
+spear900               MACH_SPEAR900           SPEAR900                3061
+pcontrol_g20           MACH_PCONTROL_G20       PCONTROL_G20            3062
index f51572772e217d5ba9b674ffa2a5d68e5f13ca00..9ac87255a03a335917d994ddaa855f1ba180da79 100644 (file)
@@ -90,6 +90,7 @@ config PLATFORM_AT32AP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_ALLOCATOR
        select HAVE_FB_ATMEL
+       select HAVE_NET_MACB
 
 #
 # CPU types
index 54fbd95cee9b40cc583fa6df49767b2f859a5598..9764a1a1073e933aa1c2d6a73e51483553da2dfa 100644 (file)
@@ -41,6 +41,7 @@ static int fram_mmap(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations fram_fops = {
        .owner                  = THIS_MODULE,
        .mmap                   = fram_mmap,
+       .llseek                 = noop_llseek,
 };
 
 #define FRAM_MINOR     0
index 93570daac38ac47360bc16868be7eb6ada8fbaa8..006e9487372dc2d188672f37e5731b6699f5fdc2 100644 (file)
@@ -8,16 +8,14 @@
 #ifndef __ASM_AVR32_IRQFLAGS_H
 #define __ASM_AVR32_IRQFLAGS_H
 
+#include <linux/types.h>
 #include <asm/sysreg.h>
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
        return sysreg_read(SR);
 }
 
-#define raw_local_save_flags(x)                                        \
-       do { (x) = __raw_local_save_flags(); } while (0)
-
 /*
  * This will restore ALL status register flags, not only the interrupt
  * mask flag.
@@ -25,44 +23,39 @@ static inline unsigned long __raw_local_save_flags(void)
  * The empty asm statement informs the compiler of this fact while
  * also serving as a barrier.
  */
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
        sysreg_write(SR, flags);
        asm volatile("" : : : "memory", "cc");
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
        asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
        asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return (flags & SYSREG_BIT(GM)) != 0;
 }
 
-static inline int raw_irqs_disabled(void)
+static inline bool arch_irqs_disabled(void)
 {
-       unsigned long flags = __raw_local_save_flags();
-
-       return raw_irqs_disabled_flags(flags);
+       return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
-       unsigned long flags = __raw_local_save_flags();
+       unsigned long flags = arch_local_save_flags();
 
-       raw_local_irq_disable();
+       arch_local_irq_disable();
 
        return flags;
 }
 
-#define raw_local_irq_save(flags)                              \
-       do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* __ASM_AVR32_IRQFLAGS_H */
index 98f94d041d9c1dd212a0519efac60def8034b7db..a727f54d64d6e633d58ae2836bbbfae4c82f0017 100644 (file)
@@ -314,10 +314,9 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
        vfree(module->arch.syminfo);
        module->arch.syminfo = NULL;
 
-       return module_bug_finalize(hdr, sechdrs, module);
+       return 0;
 }
 
 void module_arch_cleanup(struct module *module)
 {
-       module_bug_cleanup(module);
 }
index ed4f8c6db0cdd12778ca41d561fa0760a7564dbe..4223cf08ce8359e377a87b4321e09c98863f158d 100644 (file)
 
 #define MIN_SPI_BAUD_VAL       2
 
-#define SPI_READ              0
-#define SPI_WRITE             1
-
-#define SPI_CTRL_OFF            0x0
-#define SPI_FLAG_OFF            0x4
-#define SPI_STAT_OFF            0x8
-#define SPI_TXBUFF_OFF          0xc
-#define SPI_RXBUFF_OFF          0x10
-#define SPI_BAUD_OFF            0x14
-#define SPI_SHAW_OFF            0x18
-
-
 #define BIT_CTL_ENABLE      0x4000
 #define BIT_CTL_OPENDRAIN   0x2000
 #define BIT_CTL_MASTER      0x1000
-#define BIT_CTL_POLAR       0x0800
-#define BIT_CTL_PHASE       0x0400
-#define BIT_CTL_BITORDER    0x0200
+#define BIT_CTL_CPOL        0x0800
+#define BIT_CTL_CPHA        0x0400
+#define BIT_CTL_LSBF        0x0200
 #define BIT_CTL_WORDSIZE    0x0100
-#define BIT_CTL_MISOENABLE  0x0020
+#define BIT_CTL_EMISO       0x0020
+#define BIT_CTL_PSSE        0x0010
+#define BIT_CTL_GM          0x0008
+#define BIT_CTL_SZ          0x0004
 #define BIT_CTL_RXMOD       0x0000
 #define BIT_CTL_TXMOD       0x0001
 #define BIT_CTL_TIMOD_DMA_TX 0x0003
 #define BIT_STU_SENDOVER    0x0001
 #define BIT_STU_RECVFULL    0x0020
 
-#define CFG_SPI_ENABLE      1
-#define CFG_SPI_DISABLE     0
-
-#define CFG_SPI_OUTENABLE   1
-#define CFG_SPI_OUTDISABLE  0
-
-#define CFG_SPI_ACTLOW      1
-#define CFG_SPI_ACTHIGH     0
-
-#define CFG_SPI_PHASESTART  1
-#define CFG_SPI_PHASEMID    0
-
-#define CFG_SPI_MASTER      1
-#define CFG_SPI_SLAVE       0
-
-#define CFG_SPI_SENELAST    0
-#define CFG_SPI_SENDZERO    1
-
-#define CFG_SPI_RCVFLUSH    1
-#define CFG_SPI_RCVDISCARD  0
-
-#define CFG_SPI_LSBFIRST    1
-#define CFG_SPI_MSBFIRST    0
-
-#define CFG_SPI_WORDSIZE16  1
-#define CFG_SPI_WORDSIZE8   0
-
-#define CFG_SPI_MISOENABLE   1
-#define CFG_SPI_MISODISABLE  0
-
-#define CFG_SPI_READ      0x00
-#define CFG_SPI_WRITE     0x01
-#define CFG_SPI_DMAREAD   0x02
-#define CFG_SPI_DMAWRITE  0x03
-
-#define CFG_SPI_CSCLEARALL  0
-#define CFG_SPI_CHIPSEL1    1
-#define CFG_SPI_CHIPSEL2    2
-#define CFG_SPI_CHIPSEL3    3
-#define CFG_SPI_CHIPSEL4    4
-#define CFG_SPI_CHIPSEL5    5
-#define CFG_SPI_CHIPSEL6    6
-#define CFG_SPI_CHIPSEL7    7
-
-#define CFG_SPI_CS1VALUE    1
-#define CFG_SPI_CS2VALUE    2
-#define CFG_SPI_CS3VALUE    3
-#define CFG_SPI_CS4VALUE    4
-#define CFG_SPI_CS5VALUE    5
-#define CFG_SPI_CS6VALUE    6
-#define CFG_SPI_CS7VALUE    7
-
-#define CMD_SPI_SET_BAUDRATE  2
-#define CMD_SPI_GET_SYSTEMCLOCK   25
-#define CMD_SPI_SET_WRITECONTINUOUS     26
+#define MAX_CTRL_CS          8  /* cs in spi controller */
 
 /* device.platform_data for SSP controller devices */
 struct bfin5xx_spi_master {
@@ -120,9 +57,7 @@ struct bfin5xx_spi_chip {
        u16 ctl_reg;
        u8 enable_dma;
        u8 bits_per_word;
-       u8 cs_change_per_word;
        u16 cs_chg_udelay; /* Some devices require 16-bit delays */
-       u32 cs_gpio;
        /* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
        u16 idle_tx_val;
        u8 pio_interrupt; /* Enable spi data irq */
index 9626cf7e4251d7c220534acc7343d4ffc16f3194..d27600c262c2b18427b0d28feed430440cbd6452 100644 (file)
@@ -115,12 +115,6 @@ struct sport_register {
 
 #endif
 
-/* Workaround defBF*.h SPORT MMRs till they get cleansed */
-#undef DTYPE_NORM
-#undef SLEN
-#undef SP_WOFF
-#undef SP_WSIZE
-
 /* SPORT_TCR1 Masks */
 #define TSPEN          0x0001  /* TX enable */
 #define ITCLK          0x0002  /* Internal TX Clock Select */
index d5872cd967ab3e793fd6f6a55e0f296b138444e3..3f7ef4d97791514c9d4eab13d17baffc78efb5f3 100644 (file)
@@ -22,7 +22,9 @@
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
+
 #include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/ext2-atomic.h>
 #include <asm-generic/bitops/minix.h>
@@ -115,7 +117,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
  * of bits set) of a N-bit word
  */
 
-static inline unsigned int hweight32(unsigned int w)
+static inline unsigned int __arch_hweight32(unsigned int w)
 {
        unsigned int res;
 
@@ -125,19 +127,20 @@ static inline unsigned int hweight32(unsigned int w)
        return res;
 }
 
-static inline unsigned int hweight64(__u64 w)
+static inline unsigned int __arch_hweight64(__u64 w)
 {
-       return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
+       return __arch_hweight32((unsigned int)(w >> 32)) +
+              __arch_hweight32((unsigned int)w);
 }
 
-static inline unsigned int hweight16(unsigned int w)
+static inline unsigned int __arch_hweight16(unsigned int w)
 {
-       return hweight32(w & 0xffff);
+       return __arch_hweight32(w & 0xffff);
 }
 
-static inline unsigned int hweight8(unsigned int w)
+static inline unsigned int __arch_hweight8(unsigned int w)
 {
-       return hweight32(w & 0xff);
+       return __arch_hweight32(w & 0xff);
 }
 
 #endif                         /* _BLACKFIN_BITOPS_H */
index d3b40449ca0e20e07efa820272748000ebd35961..40f94a704c0202ace94e99429d7b67cb241d40f1 100644 (file)
@@ -49,7 +49,7 @@
 #define prepare_arch_switch(next)              \
 do {                                           \
        ipipe_schedule_notify(current, next);   \
-       local_irq_disable_hw();                 \
+       hard_local_irq_disable();                       \
 } while (0)
 
 #define task_hijacked(p)                                               \
@@ -57,7 +57,7 @@ do {                                          \
                int __x__ = __ipipe_root_domain_p;                      \
                __clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
                if (__x__)                                              \
-                       local_irq_enable_hw();                          \
+                       hard_local_irq_enable();                                \
                !__x__;                                                 \
        })
 
@@ -167,7 +167,7 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
 #define __ipipe_run_isr(ipd, irq)                                      \
        do {                                                            \
                if (!__ipipe_pipeline_head_p(ipd))                      \
-                       local_irq_enable_hw();                          \
+                       hard_local_irq_enable();                                \
                if (ipd == ipipe_root_domain) {                         \
                        if (unlikely(ipipe_virtual_irq_p(irq))) {       \
                                irq_enter();                            \
@@ -183,7 +183,7 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
                        __ipipe_run_irqtail();                          \
                        __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
                }                                                       \
-               local_irq_disable_hw();                                 \
+               hard_local_irq_disable();                                       \
        } while (0)
 
 #define __ipipe_syscall_watched_p(p, sc)       \
index 813a1af3e865e589f5cf17a822796e79297a884f..41c4d70544ef4811cd23c85f03c68122221f7aae 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_BFIN_IRQFLAGS_H__
 #define __ASM_BFIN_IRQFLAGS_H__
 
+#include <mach/blackfin.h>
+
 #ifdef CONFIG_SMP
 # include <asm/pda.h>
 # include <asm/processor.h>
@@ -31,54 +33,108 @@ static inline unsigned long bfin_cli(void)
        return flags;
 }
 
-#ifdef CONFIG_IPIPE
-
-#include <linux/compiler.h>
-#include <linux/ipipe_base.h>
-#include <linux/ipipe_trace.h>
-
 #ifdef CONFIG_DEBUG_HWERR
 # define bfin_no_irqs 0x3f
 #else
 # define bfin_no_irqs 0x1f
 #endif
 
-#define raw_local_irq_disable()                                \
-       do {                                            \
-               ipipe_check_context(ipipe_root_domain); \
-               __ipipe_stall_root();                   \
-               barrier();                              \
-       } while (0)
+/*****************************************************************************/
+/*
+ * Hard, untraced CPU interrupt flag manipulation and access.
+ */
+static inline void __hard_local_irq_disable(void)
+{
+       bfin_cli();
+}
+
+static inline void __hard_local_irq_enable(void)
+{
+       bfin_sti(bfin_irq_flags);
+}
+
+static inline unsigned long hard_local_save_flags(void)
+{
+       return bfin_read_IMASK();
+}
 
-#define raw_local_irq_enable()                         \
-       do {                                            \
-               barrier();                              \
-               ipipe_check_context(ipipe_root_domain); \
-               __ipipe_unstall_root();                 \
-       } while (0)
+static inline unsigned long __hard_local_irq_save(void)
+{
+       unsigned long flags;
+       flags = bfin_cli();
+#ifdef CONFIG_DEBUG_HWERR
+       bfin_sti(0x3f);
+#endif
+       return flags;
+}
+
+static inline int hard_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & ~0x3f) == 0;
+}
+
+static inline int hard_irqs_disabled(void)
+{
+       unsigned long flags = hard_local_save_flags();
+       return hard_irqs_disabled_flags(flags);
+}
+
+static inline void __hard_local_irq_restore(unsigned long flags)
+{
+       if (!hard_irqs_disabled_flags(flags))
+               __hard_local_irq_enable();
+}
+
+/*****************************************************************************/
+/*
+ * Interrupt pipe handling.
+ */
+#ifdef CONFIG_IPIPE
+
+#include <linux/compiler.h>
+#include <linux/ipipe_base.h>
+#include <linux/ipipe_trace.h>
+
+/*
+ * Interrupt pipe interface to linux/irqflags.h.
+ */
+static inline void arch_local_irq_disable(void)
+{
+       ipipe_check_context(ipipe_root_domain);
+       __ipipe_stall_root();
+       barrier();
+}
 
-#define raw_local_save_flags_ptr(x)                                    \
-       do {                                                            \
-               *(x) = __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; \
-       } while (0)
+static inline void arch_local_irq_enable(void)
+{
+       barrier();
+       ipipe_check_context(ipipe_root_domain);
+       __ipipe_unstall_root();
+}
 
-#define raw_local_save_flags(x)                raw_local_save_flags_ptr(&(x))
+static inline unsigned long arch_local_save_flags(void)
+{
+       return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
+}
 
-#define raw_irqs_disabled_flags(x)     ((x) == bfin_no_irqs)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+       return flags == bfin_no_irqs;
+}
 
-#define raw_local_irq_save_ptr(x)                                      \
-       do {                                                            \
-               *(x) = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; \
-               barrier();                                              \
-       } while (0)
+static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+{
+       x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+       barrier();
+}
 
-#define raw_local_irq_save(x)                          \
-       do {                                            \
-               ipipe_check_context(ipipe_root_domain); \
-               raw_local_irq_save_ptr(&(x));           \
-       } while (0)
+static inline unsigned long arch_local_irq_save(void)
+{
+       ipipe_check_context(ipipe_root_domain);
+       return __hard_local_irq_save();
+}
 
-static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
+static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
 {
        /*
         * Merge virtual and real interrupt mask bits into a single
@@ -87,130 +143,79 @@ static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
        return (real & ~(1 << 31)) | ((virt != 0) << 31);
 }
 
-static inline int raw_demangle_irq_bits(unsigned long *x)
+static inline int arch_demangle_irq_bits(unsigned long *x)
 {
        int virt = (*x & (1 << 31)) != 0;
        *x &= ~(1L << 31);
        return virt;
 }
 
-static inline void local_irq_disable_hw_notrace(void)
+/*
+ * Interface to various arch routines that may be traced.
+ */
+#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
+static inline void hard_local_irq_disable(void)
 {
-       bfin_cli();
+       if (!hard_irqs_disabled()) {
+               __hard_local_irq_disable();
+               ipipe_trace_begin(0x80000000);
+       }
 }
 
-static inline void local_irq_enable_hw_notrace(void)
+static inline void hard_local_irq_enable(void)
 {
-       bfin_sti(bfin_irq_flags);
+       if (hard_irqs_disabled()) {
+               ipipe_trace_end(0x80000000);
+               __hard_local_irq_enable();
+       }
 }
 
-#define local_save_flags_hw(flags)                     \
-       do {                                            \
-               (flags) = bfin_read_IMASK();            \
-       } while (0)
-
-#define irqs_disabled_flags_hw(flags) (((flags) & ~0x3f) == 0)
-
-#define irqs_disabled_hw()                     \
-       ({                                      \
-       unsigned long flags;                    \
-       local_save_flags_hw(flags);             \
-       irqs_disabled_flags_hw(flags);          \
-       })
-
-static inline void local_irq_save_ptr_hw(unsigned long *flags)
+static inline unsigned long hard_local_irq_save(void)
 {
-       *flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
-       bfin_sti(0x3f);
-#endif
+       unsigned long flags = hard_local_save_flags();
+       if (!hard_irqs_disabled_flags(flags)) {
+               __hard_local_irq_disable();
+               ipipe_trace_begin(0x80000001);
+       }
+       return flags;
 }
 
-#define local_irq_save_hw_notrace(flags)               \
-       do {                                            \
-               local_irq_save_ptr_hw(&(flags));        \
-       } while (0)
-
-static inline void local_irq_restore_hw_notrace(unsigned long flags)
+static inline void hard_local_irq_restore(unsigned long flags)
 {
-       if (!irqs_disabled_flags_hw(flags))
-               local_irq_enable_hw_notrace();
+       if (!hard_irqs_disabled_flags(flags)) {
+               ipipe_trace_end(0x80000001);
+               __hard_local_irq_enable();
+       }
 }
 
-#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-# define local_irq_disable_hw()                                \
-       do {                                            \
-               if (!irqs_disabled_hw()) {              \
-                       local_irq_disable_hw_notrace(); \
-                       ipipe_trace_begin(0x80000000);  \
-               }                                       \
-       } while (0)
-# define local_irq_enable_hw()                         \
-       do {                                            \
-               if (irqs_disabled_hw()) {               \
-                       ipipe_trace_end(0x80000000);    \
-                       local_irq_enable_hw_notrace();  \
-               }                                       \
-       } while (0)
-# define local_irq_save_hw(flags)                      \
-       do {                                            \
-               local_save_flags_hw(flags);             \
-               if (!irqs_disabled_flags_hw(flags)) {   \
-                       local_irq_disable_hw_notrace(); \
-                       ipipe_trace_begin(0x80000001);  \
-               }                                       \
-       } while (0)
-# define local_irq_restore_hw(flags)                   \
-       do {                                            \
-               if (!irqs_disabled_flags_hw(flags)) {   \
-                       ipipe_trace_end(0x80000001);    \
-                       local_irq_enable_hw_notrace();  \
-               }                                       \
-       } while (0)
 #else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
-# define local_irq_disable_hw()                local_irq_disable_hw_notrace()
-# define local_irq_enable_hw()         local_irq_enable_hw_notrace()
-# define local_irq_save_hw(flags)      local_irq_save_hw_notrace(flags)
-# define local_irq_restore_hw(flags)   local_irq_restore_hw_notrace(flags)
+# define hard_local_irq_disable()      __hard_local_irq_disable()
+# define hard_local_irq_enable()       __hard_local_irq_enable()
+# define hard_local_irq_save()         __hard_local_irq_save()
+# define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 
 #else /* CONFIG_IPIPE */
 
-static inline void raw_local_irq_disable(void)
-{
-       bfin_cli();
-}
-static inline void raw_local_irq_enable(void)
-{
-       bfin_sti(bfin_irq_flags);
-}
-
-#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0)
-
-#define raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0)
+/*
+ * Direct interface to linux/irqflags.h.
+ */
+#define arch_local_save_flags()                hard_local_save_flags()
+#define arch_local_irq_save(flags)     __hard_local_irq_save()
+#define arch_local_irq_restore(flags)  __hard_local_irq_restore(flags)
+#define arch_local_irq_enable()                __hard_local_irq_enable()
+#define arch_local_irq_disable()       __hard_local_irq_disable()
+#define arch_irqs_disabled_flags(flags)        hard_irqs_disabled_flags(flags)
+#define arch_irqs_disabled()           hard_irqs_disabled()
 
-static inline unsigned long __raw_local_irq_save(void)
-{
-       unsigned long flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
-       bfin_sti(0x3f);
-#endif
-       return flags;
-}
-#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0)
+/*
+ * Interface to various arch routines that may be traced.
+ */
+#define hard_local_irq_save()          __hard_local_irq_save()
+#define hard_local_irq_restore(flags)  __hard_local_irq_restore(flags)
+#define hard_local_irq_enable()                __hard_local_irq_enable()
+#define hard_local_irq_disable()       __hard_local_irq_disable()
 
-#define local_irq_save_hw(flags)       raw_local_irq_save(flags)
-#define local_irq_restore_hw(flags)    raw_local_irq_restore(flags)
-#define local_irq_enable_hw()          raw_local_irq_enable()
-#define local_irq_disable_hw()         raw_local_irq_disable()
-#define irqs_disabled_hw()             irqs_disabled()
 
 #endif /* !CONFIG_IPIPE */
-
-static inline void raw_local_irq_restore(unsigned long flags)
-{
-       if (!raw_irqs_disabled_flags(flags))
-               raw_local_irq_enable();
-}
-
 #endif
index e1a9b4624f919ddae4675b1a8ff122e89944c764..3828c70e7a2ecb2e7ef0651a102de174f8c3ca49 100644 (file)
@@ -97,8 +97,8 @@ static inline void __switch_mm(struct mm_struct *prev_mm, struct mm_struct *next
 }
 
 #ifdef CONFIG_IPIPE
-#define lock_mm_switch(flags)  local_irq_save_hw_cond(flags)
-#define unlock_mm_switch(flags)        local_irq_restore_hw_cond(flags)
+#define lock_mm_switch(flags)  flags = hard_local_irq_save_cond()
+#define unlock_mm_switch(flags)        hard_local_irq_restore_cond(flags)
 #else
 #define lock_mm_switch(flags)  do { (void)(flags); } while (0)
 #define unlock_mm_switch(flags)        do { (void)(flags); } while (0)
@@ -205,9 +205,9 @@ static inline void destroy_context(struct mm_struct *mm)
 }
 
 #define ipipe_mm_switch_protect(flags)         \
-       local_irq_save_hw_cond(flags)
+       flags = hard_local_irq_save_cond()
 
 #define ipipe_mm_switch_unprotect(flags)       \
-       local_irq_restore_hw_cond(flags)
+       hard_local_irq_restore_cond(flags)
 
 #endif
index dde19b1d25f51020cf359aeda42bfede292fd25e..19e2c7c3e63ac41bf62f2e55a4db10d6bf97a13f 100644 (file)
@@ -117,7 +117,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
        unsigned long tmp = 0;
        unsigned long flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        switch (size) {
        case 1:
@@ -139,7 +139,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                         : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
                break;
        }
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        return tmp;
 }
 
index 22886cbdae7aa2b7c615bd800259600bc1148bf6..14fcd254b185a2706bd53c5bad024b4b749273af 100644 (file)
 #define __NR_rt_tgsigqueueinfo 368
 #define __NR_perf_event_open   369
 #define __NR_recvmmsg          370
+#define __NR_fanotify_init     371
+#define __NR_fanotify_mark     372
+#define __NR_prlimit64         373
 
-#define __NR_syscall           371
+#define __NR_syscall           374
 #define NR_syscalls            __NR_syscall
 
 /* Old optional stuff no one actually uses */
index dc07ed08b37f858403f716093d211d0793576b00..ca1c1f9debd68814c996f242ff91546f40e0133e 100644 (file)
@@ -349,13 +349,13 @@ inline void portmux_setup(unsigned short per)
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
-       local_irq_save_hw(flags); \
+       flags = hard_local_irq_save(); \
        if (arg) \
                gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
        else \
                gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
        AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
+       hard_local_irq_restore(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 
@@ -371,14 +371,14 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        if (arg) \
                gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
        else \
                gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
@@ -391,11 +391,11 @@ void set_gpio_toggle(unsigned gpio)
 {
        unsigned long flags;
        if (ANOMALY_05000311 || ANOMALY_05000323)
-               local_irq_save_hw(flags);
+               flags = hard_local_irq_save();
        gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
        if (ANOMALY_05000311 || ANOMALY_05000323) {
                AWA_DUMMY_READ(toggle);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
        }
 }
 EXPORT_SYMBOL(set_gpio_toggle);
@@ -408,11 +408,11 @@ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        gpio_array[gpio_bank(gpio)]->name = arg; \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
 } \
 EXPORT_SYMBOL(set_gpiop_ ## name);
@@ -433,11 +433,11 @@ unsigned short get_gpio_ ## name(unsigned gpio) \
        unsigned long flags; \
        unsigned short ret; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
        return ret; \
 } \
@@ -460,11 +460,11 @@ unsigned short get_gpiop_ ## name(unsigned gpio) \
        unsigned long flags; \
        unsigned short ret; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        ret = (gpio_array[gpio_bank(gpio)]->name); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
        return ret; \
 } \
@@ -525,14 +525,14 @@ int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        if (ctrl)
                reserve(wakeup, gpio);
        else
                unreserve(wakeup, gpio);
 
        set_gpio_maskb(gpio, ctrl);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -690,7 +690,7 @@ int peripheral_request(unsigned short per, const char *label)
 
        BUG_ON(ident >= MAX_RESOURCES);
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /* If a pin can be muxed as either GPIO or peripheral, make
         * sure it is not already a GPIO pin when we request it.
@@ -701,7 +701,7 @@ int peripheral_request(unsigned short per, const char *label)
                printk(KERN_ERR
                       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
                       __func__, ident, get_label(ident));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
 
@@ -730,7 +730,7 @@ int peripheral_request(unsigned short per, const char *label)
                        printk(KERN_ERR
                               "%s: Peripheral %d function %d is already reserved by %s !\n",
                               __func__, ident, P_FUNCT2MUX(per), get_label(ident));
-                       local_irq_restore_hw(flags);
+                       hard_local_irq_restore(flags);
                        return -EBUSY;
                }
        }
@@ -741,7 +741,7 @@ int peripheral_request(unsigned short per, const char *label)
        portmux_setup(per);
        port_setup(ident, PERIPHERAL_USAGE);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        set_label(ident, label);
 
        return 0;
@@ -780,10 +780,10 @@ void peripheral_free(unsigned short per)
        if (!(per & P_DEFINED))
                return;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(peri, ident, 0))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -794,7 +794,7 @@ void peripheral_free(unsigned short per)
 
        set_label(ident, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(peripheral_free);
 
@@ -828,7 +828,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /*
         * Allow that the identical GPIO can
@@ -837,7 +837,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
         */
 
        if (cmp_label(gpio, label) == 0) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return 0;
        }
 
@@ -846,7 +846,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
                        dump_stack();
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(peri, gpio, 1))) {
@@ -855,7 +855,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
@@ -871,7 +871,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
        reserve(gpio, gpio);
        set_label(gpio, label);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        port_setup(gpio, GPIO_USAGE);
 
@@ -888,13 +888,13 @@ void bfin_gpio_free(unsigned gpio)
 
        might_sleep();
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(gpio, gpio, 0))) {
                if (system_state == SYSTEM_BOOTING)
                        dump_stack();
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -902,7 +902,7 @@ void bfin_gpio_free(unsigned gpio)
 
        set_label(gpio, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_gpio_free);
 
@@ -913,7 +913,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
 {
        unsigned long flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /*
         * Allow that the identical GPIO can
@@ -922,19 +922,19 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
         */
 
        if (cmp_label(gpio, label) == 0) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return 0;
        }
 
        if (unlikely(is_reserved(special_gpio, gpio, 1))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
                       gpio, get_label(gpio));
 
                return -EBUSY;
        }
        if (unlikely(is_reserved(peri, gpio, 1))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
@@ -946,7 +946,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
        reserve(peri, gpio);
 
        set_label(gpio, label);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        port_setup(gpio, GPIO_USAGE);
 
        return 0;
@@ -959,18 +959,18 @@ void bfin_special_gpio_free(unsigned gpio)
 
        might_sleep();
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
        unreserve(special_gpio, gpio);
        unreserve(peri, gpio);
        set_label(gpio, "free");
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_special_gpio_free);
 #endif
@@ -983,7 +983,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(is_reserved(peri, gpio, 1))) {
                if (system_state == SYSTEM_BOOTING)
@@ -991,7 +991,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(gpio, gpio, 1)))
@@ -1002,7 +1002,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
        reserve(gpio_irq, gpio);
        set_label(gpio, label);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        port_setup(gpio, GPIO_USAGE);
 
@@ -1016,13 +1016,13 @@ void bfin_gpio_irq_free(unsigned gpio)
        if (check_gpio(gpio) < 0)
                return;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
                if (system_state == SYSTEM_BOOTING)
                        dump_stack();
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -1030,7 +1030,7 @@ void bfin_gpio_irq_free(unsigned gpio)
 
        set_label(gpio, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 static inline void __bfin_gpio_direction_input(unsigned gpio)
@@ -1052,10 +1052,10 @@ int bfin_gpio_direction_input(unsigned gpio)
                return -EINVAL;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        __bfin_gpio_direction_input(gpio);
        AWA_DUMMY_READ(inen);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -1070,9 +1070,9 @@ void bfin_gpio_irq_prepare(unsigned gpio)
        port_setup(gpio, GPIO_USAGE);
 
 #ifdef CONFIG_BF54x
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        __bfin_gpio_direction_input(gpio);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 #endif
 }
 
@@ -1094,7 +1094,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
                return -EINVAL;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
        gpio_set_value(gpio, value);
@@ -1105,7 +1105,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
 #endif
 
        AWA_DUMMY_READ(dir);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -1120,11 +1120,11 @@ int bfin_gpio_get_value(unsigned gpio)
 
        if (unlikely(get_gpio_edge(gpio))) {
                int ret;
-               local_irq_save_hw(flags);
+               flags = hard_local_irq_save();
                set_gpio_edge(gpio, 0);
                ret = get_gpio_data(gpio);
                set_gpio_edge(gpio, 1);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return ret;
        } else
                return get_gpio_data(gpio);
index 87b25b1b30ed6a317b6b57bf98d82de6241648a0..8de92299b3ee1d58df6871822e3a8ff65c0c52f0 100644 (file)
@@ -318,7 +318,7 @@ void flush_switched_cplbs(unsigned int cpu)
 
        nr_cplb_flush[cpu]++;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        _disable_icplb();
        for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
                icplb_tbl[cpu][i].data = 0;
@@ -332,7 +332,7 @@ void flush_switched_cplbs(unsigned int cpu)
                bfin_write32(DCPLB_DATA0 + i * 4, 0);
        }
        _enable_dcplb();
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
 }
 
@@ -348,7 +348,7 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
                return;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        current_rwx_mask[cpu] = masks;
 
        if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
@@ -373,5 +373,5 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
                addr += PAGE_SIZE;
        }
        _enable_dcplb();
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
index 1a496cd71ba2427fb7dffa75cbc331d522b39275..3b1da4aff2a1ed560f2c7041d85ccdf571f4972e 100644 (file)
@@ -219,10 +219,10 @@ int __ipipe_syscall_root(struct pt_regs *regs)
 
        ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (!__ipipe_root_domain_p) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return 1;
        }
 
@@ -230,7 +230,7 @@ int __ipipe_syscall_root(struct pt_regs *regs)
        if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
                __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return -ret;
 }
@@ -239,14 +239,14 @@ unsigned long ipipe_critical_enter(void (*syncfn) (void))
 {
        unsigned long flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        return flags;
 }
 
 void ipipe_critical_exit(unsigned long flags)
 {
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 static void __ipipe_no_irqtail(void)
@@ -279,9 +279,9 @@ int ipipe_trigger_irq(unsigned irq)
                return -EINVAL;
 #endif
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        __ipipe_handle_irq(irq, NULL);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 1;
 }
@@ -293,7 +293,7 @@ asmlinkage void __ipipe_sync_root(void)
 
        BUG_ON(irqs_disabled());
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (irq_tail_hook)
                irq_tail_hook();
@@ -303,7 +303,7 @@ asmlinkage void __ipipe_sync_root(void)
        if (ipipe_root_cpudom_var(irqpend_himask) != 0)
                __ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 void ___ipipe_sync_pipeline(unsigned long syncmask)
@@ -344,10 +344,10 @@ void __ipipe_stall_root(void)
 {
        unsigned long *p, flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        p = &__ipipe_root_status;
        __set_bit(IPIPE_STALL_FLAG, p);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_stall_root);
 
@@ -356,10 +356,10 @@ unsigned long __ipipe_test_and_stall_root(void)
        unsigned long *p, flags;
        int x;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        p = &__ipipe_root_status;
        x = __test_and_set_bit(IPIPE_STALL_FLAG, p);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return x;
 }
@@ -371,10 +371,10 @@ unsigned long __ipipe_test_root(void)
        unsigned long flags;
        int x;
 
-       local_irq_save_hw_smp(flags);
+       flags = hard_local_irq_save_smp();
        p = &__ipipe_root_status;
        x = test_bit(IPIPE_STALL_FLAG, p);
-       local_irq_restore_hw_smp(flags);
+       hard_local_irq_restore_smp(flags);
 
        return x;
 }
@@ -384,10 +384,10 @@ void __ipipe_lock_root(void)
 {
        unsigned long *p, flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        p = &__ipipe_root_status;
        __set_bit(IPIPE_SYNCDEFER_FLAG, p);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_lock_root);
 
@@ -395,9 +395,9 @@ void __ipipe_unlock_root(void)
 {
        unsigned long *p, flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        p = &__ipipe_root_status;
        __clear_bit(IPIPE_SYNCDEFER_FLAG, p);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_unlock_root);
index 9a4b07594389a6f45f390885f8e62a6365356ded..08c0236acf3c5ab903d5e863b17f8290bd4a8e7a 100644 (file)
@@ -88,6 +88,7 @@ static const struct file_operations kgdb_test_proc_fops = {
        .owner = THIS_MODULE,
        .read  = kgdb_test_proc_read,
        .write = kgdb_test_proc_write,
+       .llseek = noop_llseek,
 };
 
 static int __init kgdbtest_init(void)
index 01f98cb964d2654e4d7c235e6db4d647f893696b..c86a3ed5f48fb24d5df1dd5328e2f63290c6ba1d 100644 (file)
@@ -65,11 +65,11 @@ static void default_idle(void)
 #ifdef CONFIG_IPIPE
        ipipe_suspend_domain();
 #endif
-       local_irq_disable_hw();
+       hard_local_irq_disable();
        if (!need_resched())
                idle_with_irq_disabled();
 
-       local_irq_enable_hw();
+       hard_local_irq_enable();
 }
 
 /*
index 59fcdf6b0138532604be9d8de4d1c93260029349..05b550891ce563f72db45d3700c38fde46eecba8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kallsyms.h>
 #include <linux/err.h>
 #include <linux/fs.h>
+#include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/trace.h>
 #include <asm/fixed_code.h>
index e548e9d1d6fac5a91b0824701c349883ec5cdac7..29498e59e71f4e7272fb38296abd8825115c0607 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF52X_H */
index 2bc8f4f980113b6fb0272d2cec839b1d84159ce9..037a51fd8e9382cca213271f289fcde90fc66644 100644 (file)
 #define PH6            0x0040
 #define PH7            0x0080
 
-
-/* *******************  SERIAL PORT MASKS  **************************************/
-/* SPORTx_TCR1 Masks                                                                                                                   */
-#define TSPEN          0x0001          /* Transmit Enable                                                              */
-#define ITCLK          0x0002          /* Internal Transmit Clock Select                               */
-#define DTYPE_NORM     0x0004          /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define TLSBIT         0x0010          /* Transmit Bit Order                                                   */
-#define ITFS           0x0200          /* Internal Transmit Frame Sync Select                  */
-#define TFSR           0x0400          /* Transmit Frame Sync Required Select                  */
-#define DITFS          0x0800          /* Data-Independent Transmit Frame Sync Select  */
-#define LTFS           0x1000          /* Low Transmit Frame Sync Select                               */
-#define LATFS          0x2000          /* Late Transmit Frame Sync Select                              */
-#define TCKFE          0x4000          /* Clock Falling Edge Select                                    */
-
-/* SPORTx_TCR2 Masks and Macro                                                                                                 */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT TX Word Length (2 - 31)                                */
-#define TXSE           0x0100          /* TX Secondary Enable                                                  */
-#define TSFSE          0x0200          /* Transmit Stereo Frame Sync Enable                    */
-#define TRFST          0x0400          /* Left/Right Order (1 = Right Channel 1st)             */
-
-/* SPORTx_RCR1 Masks                                                                                                                   */
-#define RSPEN          0x0001          /* Receive Enable                                                               */
-#define IRCLK          0x0002          /* Internal Receive Clock Select                                */
-#define DTYPE_NORM     0x0004          /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define RLSBIT         0x0010          /* Receive Bit Order                                                    */
-#define IRFS           0x0200          /* Internal Receive Frame Sync Select                   */
-#define RFSR           0x0400          /* Receive Frame Sync Required Select                   */
-#define LRFS           0x1000          /* Low Receive Frame Sync Select                                */
-#define LARFS          0x2000          /* Late Receive Frame Sync Select                               */
-#define RCKFE          0x4000          /* Clock Falling Edge Select                                    */
-
-/* SPORTx_RCR2 Masks                                                                                                                   */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT RX Word Length (2 - 31)                                */
-#define RXSE           0x0100          /* RX Secondary Enable                                                  */
-#define RSFSE          0x0200          /* RX Stereo Frame Sync Enable                                  */
-#define RRFST          0x0400          /* Right-First Data Order                                               */
-
-/* SPORTx_STAT Masks                                                                                                                   */
-#define RXNE           0x0001          /* Receive FIFO Not Empty Status                                */
-#define RUVF           0x0002          /* Sticky Receive Underflow Status                              */
-#define ROVF           0x0004          /* Sticky Receive Overflow Status                               */
-#define TXF                    0x0008          /* Transmit FIFO Full Status                                    */
-#define TUVF           0x0010          /* Sticky Transmit Underflow Status                             */
-#define TOVF           0x0020          /* Sticky Transmit Overflow Status                              */
-#define TXHRE          0x0040          /* Transmit Hold Register Empty                                 */
-
-/* SPORTx_MCMC1 Macros                                                                                                                 */
-#define SP_WOFF(x)     ((x) & 0x3FF)   /* Multichannel Window Offset Field                     */
-
-/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits                                           */
-#define SP_WSIZE(x)    (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1   */
-
-/* SPORTx_MCMC2 Masks                                                                                                                  */
-#define REC_BYPASS     0x0000          /* Bypass Mode (No Clock Recovery)                              */
-#define REC_2FROM4     0x0002          /* Recover 2 MHz Clock from 4 MHz Clock                 */
-#define REC_8FROM16    0x0003          /* Recover 8 MHz Clock from 16 MHz Clock                */
-#define MCDTXPE                0x0004          /* Multichannel DMA Transmit Packing                    */
-#define MCDRXPE                0x0008          /* Multichannel DMA Receive Packing                             */
-#define MCMEN          0x0010          /* Multichannel Frame Mode Enable                               */
-#define FSDR           0x0080          /* Multichannel Frame Sync to Data Relationship */
-#define MFD_0          0x0000          /* Multichannel Frame Delay = 0                                 */
-#define MFD_1          0x1000          /* Multichannel Frame Delay = 1                                 */
-#define MFD_2          0x2000          /* Multichannel Frame Delay = 2                                 */
-#define MFD_3          0x3000          /* Multichannel Frame Delay = 3                                 */
-#define MFD_4          0x4000          /* Multichannel Frame Delay = 4                                 */
-#define MFD_5          0x5000          /* Multichannel Frame Delay = 5                                 */
-#define MFD_6          0x6000          /* Multichannel Frame Delay = 6                                 */
-#define MFD_7          0x7000          /* Multichannel Frame Delay = 7                                 */
-#define MFD_8          0x8000          /* Multichannel Frame Delay = 8                                 */
-#define MFD_9          0x9000          /* Multichannel Frame Delay = 9                                 */
-#define MFD_10         0xA000          /* Multichannel Frame Delay = 10                                */
-#define MFD_11         0xB000          /* Multichannel Frame Delay = 11                                */
-#define MFD_12         0xC000          /* Multichannel Frame Delay = 12                                */
-#define MFD_13         0xD000          /* Multichannel Frame Delay = 13                                */
-#define MFD_14         0xE000          /* Multichannel Frame Delay = 14                                */
-#define MFD_15         0xF000          /* Multichannel Frame Delay = 15                                */
-
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
 /* EBIU_AMGCTL Masks                                                                                                                                   */
 #define AMCKEN                 0x0001          /* Enable CLKOUT                                                                        */
diff --git a/arch/blackfin/mach-bf518/include/mach/pll.h b/arch/blackfin/mach-bf518/include/mach/pll.h
new file mode 100644 (file)
index 0000000..d550298
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index f392af641657d78f5be0294cc162c4c294c4f5d2..645ba5c8077b108672818de20b143054a386aec3 100644 (file)
@@ -145,7 +145,6 @@ static struct mtd_partition partition_info[] = {
 };
 
 static struct bf5xx_nand_platform bf5xx_nand_platform = {
-       .page_size = NFC_PG_SIZE_256,
        .data_width = NFC_NWIDTH_8,
        .partitions = partition_info,
        .nr_partitions = ARRAY_SIZE(partition_info),
index 606eb36b9d6ea2ce31d9d9082d0c8de9ac5512d4..c975fe88eba387738ee1fb2dd838371d69f2a5c0 100644 (file)
@@ -149,7 +149,6 @@ static struct mtd_partition partition_info[] = {
 };
 
 static struct bf5xx_nand_platform bf5xx_nand_platform = {
-       .page_size = NFC_PG_SIZE_256,
        .data_width = NFC_NWIDTH_8,
        .partitions = partition_info,
        .nr_partitions = ARRAY_SIZE(partition_info),
index a05c967a24cfc22046fde2709da087a6c30bfef1..87b41e994ba31d24cce7fdb2528d254a9834e8f6 100644 (file)
@@ -234,7 +234,6 @@ static struct mtd_partition partition_info[] = {
 };
 
 static struct bf5xx_nand_platform bf5xx_nand_platform = {
-       .page_size = NFC_PG_SIZE_256,
        .data_width = NFC_NWIDTH_8,
        .partitions = partition_info,
        .nr_partitions = ARRAY_SIZE(partition_info),
index 12f2ad45314eb3c1bfbdaabc7ae96edc3bbb7ae4..11fb27bc427dfa291b6d3cf017395e8779cfa9c0 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF52X_H */
index 5f97f01fcda61cf14d91f011606a2a4de57563c6..3e000756aacd0bcf3eb5ffd0c3ec78f75f55d857 100644 (file)
 #define PH14   0x4000
 #define PH15   0x8000
 
-
-/* *******************  SERIAL PORT MASKS  **************************************/
-/* SPORTx_TCR1 Masks                                                                                                                   */
-#define TSPEN          0x0001          /* Transmit Enable                                                              */
-#define ITCLK          0x0002          /* Internal Transmit Clock Select                               */
-#define DTYPE_NORM     0x0004          /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define TLSBIT         0x0010          /* Transmit Bit Order                                                   */
-#define ITFS           0x0200          /* Internal Transmit Frame Sync Select                  */
-#define TFSR           0x0400          /* Transmit Frame Sync Required Select                  */
-#define DITFS          0x0800          /* Data-Independent Transmit Frame Sync Select  */
-#define LTFS           0x1000          /* Low Transmit Frame Sync Select                               */
-#define LATFS          0x2000          /* Late Transmit Frame Sync Select                              */
-#define TCKFE          0x4000          /* Clock Falling Edge Select                                    */
-
-/* SPORTx_TCR2 Masks and Macro                                                                                                 */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT TX Word Length (2 - 31)                                */
-#define TXSE           0x0100          /* TX Secondary Enable                                                  */
-#define TSFSE          0x0200          /* Transmit Stereo Frame Sync Enable                    */
-#define TRFST          0x0400          /* Left/Right Order (1 = Right Channel 1st)             */
-
-/* SPORTx_RCR1 Masks                                                                                                                   */
-#define RSPEN          0x0001          /* Receive Enable                                                               */
-#define IRCLK          0x0002          /* Internal Receive Clock Select                                */
-#define DTYPE_NORM     0x0004          /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define RLSBIT         0x0010          /* Receive Bit Order                                                    */
-#define IRFS           0x0200          /* Internal Receive Frame Sync Select                   */
-#define RFSR           0x0400          /* Receive Frame Sync Required Select                   */
-#define LRFS           0x1000          /* Low Receive Frame Sync Select                                */
-#define LARFS          0x2000          /* Late Receive Frame Sync Select                               */
-#define RCKFE          0x4000          /* Clock Falling Edge Select                                    */
-
-/* SPORTx_RCR2 Masks                                                                                                                   */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT RX Word Length (2 - 31)                                */
-#define RXSE           0x0100          /* RX Secondary Enable                                                  */
-#define RSFSE          0x0200          /* RX Stereo Frame Sync Enable                                  */
-#define RRFST          0x0400          /* Right-First Data Order                                               */
-
-/* SPORTx_STAT Masks                                                                                                                   */
-#define RXNE           0x0001          /* Receive FIFO Not Empty Status                                */
-#define RUVF           0x0002          /* Sticky Receive Underflow Status                              */
-#define ROVF           0x0004          /* Sticky Receive Overflow Status                               */
-#define TXF                    0x0008          /* Transmit FIFO Full Status                                    */
-#define TUVF           0x0010          /* Sticky Transmit Underflow Status                             */
-#define TOVF           0x0020          /* Sticky Transmit Overflow Status                              */
-#define TXHRE          0x0040          /* Transmit Hold Register Empty                                 */
-
-/* SPORTx_MCMC1 Macros                                                                                                                 */
-#define SP_WOFF(x)     ((x) & 0x3FF)   /* Multichannel Window Offset Field                     */
-
-/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits                                           */
-#define SP_WSIZE(x)    (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1   */
-
-/* SPORTx_MCMC2 Masks                                                                                                                  */
-#define REC_BYPASS     0x0000          /* Bypass Mode (No Clock Recovery)                              */
-#define REC_2FROM4     0x0002          /* Recover 2 MHz Clock from 4 MHz Clock                 */
-#define REC_8FROM16    0x0003          /* Recover 8 MHz Clock from 16 MHz Clock                */
-#define MCDTXPE                0x0004          /* Multichannel DMA Transmit Packing                    */
-#define MCDRXPE                0x0008          /* Multichannel DMA Receive Packing                             */
-#define MCMEN          0x0010          /* Multichannel Frame Mode Enable                               */
-#define FSDR           0x0080          /* Multichannel Frame Sync to Data Relationship */
-#define MFD_0          0x0000          /* Multichannel Frame Delay = 0                                 */
-#define MFD_1          0x1000          /* Multichannel Frame Delay = 1                                 */
-#define MFD_2          0x2000          /* Multichannel Frame Delay = 2                                 */
-#define MFD_3          0x3000          /* Multichannel Frame Delay = 3                                 */
-#define MFD_4          0x4000          /* Multichannel Frame Delay = 4                                 */
-#define MFD_5          0x5000          /* Multichannel Frame Delay = 5                                 */
-#define MFD_6          0x6000          /* Multichannel Frame Delay = 6                                 */
-#define MFD_7          0x7000          /* Multichannel Frame Delay = 7                                 */
-#define MFD_8          0x8000          /* Multichannel Frame Delay = 8                                 */
-#define MFD_9          0x9000          /* Multichannel Frame Delay = 9                                 */
-#define MFD_10         0xA000          /* Multichannel Frame Delay = 10                                */
-#define MFD_11         0xB000          /* Multichannel Frame Delay = 11                                */
-#define MFD_12         0xC000          /* Multichannel Frame Delay = 12                                */
-#define MFD_13         0xD000          /* Multichannel Frame Delay = 13                                */
-#define MFD_14         0xE000          /* Multichannel Frame Delay = 14                                */
-#define MFD_15         0xF000          /* Multichannel Frame Delay = 15                                */
-
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
 /* EBIU_AMGCTL Masks                                                                                                                                   */
 #define AMCKEN                 0x0001          /* Enable CLKOUT                                                                        */
diff --git a/arch/blackfin/mach-bf527/include/mach/pll.h b/arch/blackfin/mach-bf527/include/mach/pll.h
new file mode 100644 (file)
index 0000000..24f1d7c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index 842b4fa76ea992d31c932eced7876fabdb6083aa..84a06f677dffa056dffc3048586cf7c1c4205959 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
index 7349970db97860f8b0def99b000ed8c36c642cb8..b8474cac6b03f3470b144629d0e2067ef054044b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
index c457eaa60239e4e2281553114302c1001eeabdff..29c219eff2ff4499ff951341b8469f5d7326a63e 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/reboot.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
index feb2392c43ea0ad68e3aa31fd2c40299d4caf0ea..401e524f532168c4e85690694e0f041d91962db7 100644 (file)
@@ -7,11 +7,6 @@
 #ifndef _CDEF_BF532_H
 #define _CDEF_BF532_H
 
-#include <asm/blackfin.h>
-
-/*include all Core registers and bit definitions*/
-#include "defBF532.h"
-
 /*include core specific register pointer definitions*/
 #include <asm/cdef_LPBlackfin.h>
 
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-#if ANOMALY_05000311
-#define BFIN_WRITE_FIO_FLAG(name) \
-static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
-{ \
-       unsigned long flags; \
-       local_irq_save_hw(flags); \
-       bfin_write16(FIO_FLAG_##name, val); \
-       bfin_read_CHIPID(); \
-       local_irq_restore_hw(flags); \
-}
-BFIN_WRITE_FIO_FLAG(D)
-BFIN_WRITE_FIO_FLAG(C)
-BFIN_WRITE_FIO_FLAG(S)
-BFIN_WRITE_FIO_FLAG(T)
-
-#define BFIN_READ_FIO_FLAG(name) \
-static inline u16 bfin_read_FIO_FLAG_##name(void) \
-{ \
-       unsigned long flags; \
-       u16 ret; \
-       local_irq_save_hw(flags); \
-       ret = bfin_read16(FIO_FLAG_##name); \
-       bfin_read_CHIPID(); \
-       local_irq_restore_hw(flags); \
-       return ret; \
-}
-BFIN_READ_FIO_FLAG(D)
-BFIN_READ_FIO_FLAG(C)
-BFIN_READ_FIO_FLAG(S)
-BFIN_READ_FIO_FLAG(T)
-
-#else
-#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
-#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
-#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
-#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
-#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
-#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
-#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
-#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
-#endif
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr = bfin_read32(SIC_IWR);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR, iwr);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr = bfin_read32(SIC_IWR);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR, iwr);
-       local_irq_restore_hw(flags);
-}
-
 #endif                         /* _CDEF_BF532_H */
index e9ff491c095380396706add9fd80ed0789c7b3d4..04acf1ed10f96ccd1cad3d530b7b98610d11c0fe 100644 (file)
 #define IREN_P 0x01
 #define UCEN_P 0x00
 
-/* **********  SERIAL PORT MASKS  ********************** */
-
-/* SPORTx_TCR1 Masks */
-#define TSPEN    0x0001                /* TX enable  */
-#define ITCLK    0x0002                /* Internal TX Clock Select  */
-#define TDTYPE   0x000C                /* TX Data Formatting Select */
-#define DTYPE_NORM     0x0000          /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define TLSBIT   0x0010                /* TX Bit Order */
-#define ITFS     0x0200                /* Internal TX Frame Sync Select  */
-#define TFSR     0x0400                /* TX Frame Sync Required Select  */
-#define DITFS    0x0800                /* Data Independent TX Frame Sync Select  */
-#define LTFS     0x1000                /* Low TX Frame Sync Select  */
-#define LATFS    0x2000                /* Late TX Frame Sync Select  */
-#define TCKFE    0x4000                /* TX Clock Falling Edge Select  */
-
-/* SPORTx_TCR2 Masks */
-#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || \
-    defined(__ADSPBF533__)
-# define SLEN      0x001F      /*TX Word Length  */
-#else
-# define SLEN(x)               ((x)&0x1F)      /* SPORT TX Word Length (2 - 31)                                */
-#endif
-#define TXSE        0x0100     /*TX Secondary Enable */
-#define TSFSE       0x0200     /*TX Stereo Frame Sync Enable */
-#define TRFST       0x0400     /*TX Right-First Data Order  */
-
-/* SPORTx_RCR1 Masks */
-#define RSPEN    0x0001                /* RX enable  */
-#define IRCLK    0x0002                /* Internal RX Clock Select  */
-#define RDTYPE   0x000C                /* RX Data Formatting Select */
-#define DTYPE_NORM     0x0000          /* no companding                                                        */
-#define DTYPE_ULAW     0x0008          /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C          /* Compand Using A-Law                                                  */
-#define RLSBIT   0x0010                /* RX Bit Order */
-#define IRFS     0x0200                /* Internal RX Frame Sync Select  */
-#define RFSR     0x0400                /* RX Frame Sync Required Select  */
-#define LRFS     0x1000                /* Low RX Frame Sync Select  */
-#define LARFS    0x2000                /* Late RX Frame Sync Select  */
-#define RCKFE    0x4000                /* RX Clock Falling Edge Select  */
-
-/* SPORTx_RCR2 Masks */
-/* SLEN defined above */
-#define RXSE        0x0100     /*RX Secondary Enable */
-#define RSFSE       0x0200     /*RX Stereo Frame Sync Enable */
-#define RRFST       0x0400     /*Right-First Data Order  */
-
-/*SPORTx_STAT Masks */
-#define RXNE           0x0001  /*RX FIFO Not Empty Status */
-#define RUVF           0x0002  /*RX Underflow Status */
-#define ROVF           0x0004  /*RX Overflow Status */
-#define TXF            0x0008  /*TX FIFO Full Status */
-#define TUVF           0x0010  /*TX Underflow Status */
-#define TOVF           0x0020  /*TX Overflow Status */
-#define TXHRE          0x0040  /*TX Hold Register Empty */
-
-/*SPORTx_MCMC1 Masks */
-#define SP_WSIZE               0x0000F000      /*Multichannel Window Size Field */
-#define SP_WOFF                0x000003FF      /*Multichannel Window Offset Field */
-/* SPORTx_MCMC1 Macros                                                                                                                 */
-#define SET_SP_WOFF(x) ((x) & 0x3FF)   /* Multichannel Window Offset Field                     */
-/* Only use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits                                               */
-#define SET_SP_WSIZE(x)        (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1   */
-
-/*SPORTx_MCMC2 Masks */
-#define MCCRM          0x00000003      /*Multichannel Clock Recovery Mode */
-#define REC_BYPASS     0x0000          /* Bypass Mode (No Clock Recovery)                              */
-#define REC_2FROM4     0x0002          /* Recover 2 MHz Clock from 4 MHz Clock                 */
-#define REC_8FROM16    0x0003          /* Recover 8 MHz Clock from 16 MHz Clock                */
-#define MCDTXPE                0x00000004      /*Multichannel DMA Transmit Packing */
-#define MCDRXPE                0x00000008      /*Multichannel DMA Receive Packing */
-#define MCMEN          0x00000010      /*Multichannel Frame Mode Enable */
-#define FSDR           0x00000080      /*Multichannel Frame Sync to Data Relationship */
-#define MFD            0x0000F000      /*Multichannel Frame Delay    */
-#define MFD_0          0x0000          /* Multichannel Frame Delay = 0                                 */
-#define MFD_1          0x1000          /* Multichannel Frame Delay = 1                                 */
-#define MFD_2          0x2000          /* Multichannel Frame Delay = 2                                 */
-#define MFD_3          0x3000          /* Multichannel Frame Delay = 3                                 */
-#define MFD_4          0x4000          /* Multichannel Frame Delay = 4                                 */
-#define MFD_5          0x5000          /* Multichannel Frame Delay = 5                                 */
-#define MFD_6          0x6000          /* Multichannel Frame Delay = 6                                 */
-#define MFD_7          0x7000          /* Multichannel Frame Delay = 7                                 */
-#define MFD_8          0x8000          /* Multichannel Frame Delay = 8                                 */
-#define MFD_9          0x9000          /* Multichannel Frame Delay = 9                                 */
-#define MFD_10         0xA000          /* Multichannel Frame Delay = 10                                */
-#define MFD_11         0xB000          /* Multichannel Frame Delay = 11                                */
-#define MFD_12         0xC000          /* Multichannel Frame Delay = 12                                */
-#define MFD_13         0xD000          /* Multichannel Frame Delay = 13                                */
-#define MFD_14         0xE000          /* Multichannel Frame Delay = 14                                */
-#define MFD_15         0xF000          /* Multichannel Frame Delay = 15                                */
-
 /*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 
 /*  PPI_CONTROL Masks         */
diff --git a/arch/blackfin/mach-bf533/include/mach/fio_flag.h b/arch/blackfin/mach-bf533/include/mach/fio_flag.h
new file mode 100644 (file)
index 0000000..d0bfba0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_FIO_FLAG_H
+#define _MACH_FIO_FLAG_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+#if ANOMALY_05000311
+#define BFIN_WRITE_FIO_FLAG(name) \
+static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
+{ \
+       unsigned long flags; \
+       flags = hard_local_irq_save(); \
+       bfin_write16(FIO_FLAG_##name, val); \
+       bfin_read_CHIPID(); \
+       hard_local_irq_restore(flags); \
+}
+BFIN_WRITE_FIO_FLAG(D)
+BFIN_WRITE_FIO_FLAG(C)
+BFIN_WRITE_FIO_FLAG(S)
+BFIN_WRITE_FIO_FLAG(T)
+
+#define BFIN_READ_FIO_FLAG(name) \
+static inline u16 bfin_read_FIO_FLAG_##name(void) \
+{ \
+       unsigned long flags; \
+       u16 ret; \
+       flags = hard_local_irq_save(); \
+       ret = bfin_read16(FIO_FLAG_##name); \
+       bfin_read_CHIPID(); \
+       hard_local_irq_restore(flags); \
+       return ret; \
+}
+BFIN_READ_FIO_FLAG(D)
+BFIN_READ_FIO_FLAG(C)
+BFIN_READ_FIO_FLAG(S)
+BFIN_READ_FIO_FLAG(T)
+
+#else
+#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
+#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
+#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
+#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
+#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
+#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
+#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
+#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
+#endif
+
+#endif /* _MACH_FIO_FLAG_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/pll.h b/arch/blackfin/mach-bf533/include/mach/pll.h
new file mode 100644 (file)
index 0000000..169c106
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index 91825c9bd226e1914acf714d7f6983a8c14a85f0..fbeb35e141357dca5abb489e0ad03dbcef69080c 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr = bfin_read32(SIC_IWR);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR, iwr);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr = bfin_read32(SIC_IWR);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR, iwr);
-       local_irq_restore_hw(flags);
-}
-
 #endif                         /* _CDEF_BF534_H */
index aad61b8873731f5ed6877e189ab61bf4e2a85dfa..6f56907a18c027c903491f52e1c4bcfeaca36f72 100644 (file)
 #define PH14   0x4000
 #define PH15   0x8000
 
-/* *******************  SERIAL PORT MASKS  **************************************/
-/* SPORTx_TCR1 Masks                                                                                                                   */
-#define TSPEN          0x0001  /* Transmit Enable                                                              */
-#define ITCLK          0x0002  /* Internal Transmit Clock Select                               */
-#define DTYPE_NORM     0x0004  /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008  /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C  /* Compand Using A-Law                                                  */
-#define TLSBIT         0x0010  /* Transmit Bit Order                                                   */
-#define ITFS           0x0200  /* Internal Transmit Frame Sync Select                  */
-#define TFSR           0x0400  /* Transmit Frame Sync Required Select                  */
-#define DITFS          0x0800  /* Data-Independent Transmit Frame Sync Select  */
-#define LTFS           0x1000  /* Low Transmit Frame Sync Select                               */
-#define LATFS          0x2000  /* Late Transmit Frame Sync Select                              */
-#define TCKFE          0x4000  /* Clock Falling Edge Select                                    */
-
-/* SPORTx_TCR2 Masks and Macro                                                                                                 */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT TX Word Length (2 - 31)                                */
-#define TXSE           0x0100  /* TX Secondary Enable                                                  */
-#define TSFSE          0x0200  /* Transmit Stereo Frame Sync Enable                    */
-#define TRFST          0x0400  /* Left/Right Order (1 = Right Channel 1st)             */
-
-/* SPORTx_RCR1 Masks                                                                                                                   */
-#define RSPEN          0x0001  /* Receive Enable                                                               */
-#define IRCLK          0x0002  /* Internal Receive Clock Select                                */
-#define DTYPE_NORM     0x0004  /* Data Format Normal                                                   */
-#define DTYPE_ULAW     0x0008  /* Compand Using u-Law                                                  */
-#define DTYPE_ALAW     0x000C  /* Compand Using A-Law                                                  */
-#define RLSBIT         0x0010  /* Receive Bit Order                                                    */
-#define IRFS           0x0200  /* Internal Receive Frame Sync Select                   */
-#define RFSR           0x0400  /* Receive Frame Sync Required Select                   */
-#define LRFS           0x1000  /* Low Receive Frame Sync Select                                */
-#define LARFS          0x2000  /* Late Receive Frame Sync Select                               */
-#define RCKFE          0x4000  /* Clock Falling Edge Select                                    */
-
-/* SPORTx_RCR2 Masks                                                                                                                   */
-#define SLEN(x)                ((x)&0x1F)      /* SPORT RX Word Length (2 - 31)                                */
-#define RXSE           0x0100  /* RX Secondary Enable                                                  */
-#define RSFSE          0x0200  /* RX Stereo Frame Sync Enable                                  */
-#define RRFST          0x0400  /* Right-First Data Order                                               */
-
-/* SPORTx_STAT Masks                                                                                                                   */
-#define RXNE           0x0001  /* Receive FIFO Not Empty Status                                */
-#define RUVF           0x0002  /* Sticky Receive Underflow Status                              */
-#define ROVF           0x0004  /* Sticky Receive Overflow Status                               */
-#define TXF                    0x0008  /* Transmit FIFO Full Status                                    */
-#define TUVF           0x0010  /* Sticky Transmit Underflow Status                             */
-#define TOVF           0x0020  /* Sticky Transmit Overflow Status                              */
-#define TXHRE          0x0040  /* Transmit Hold Register Empty                                 */
-
-/* SPORTx_MCMC1 Macros                                                                                                                 */
-#define SP_WOFF(x)             ((x) & 0x3FF)   /* Multichannel Window Offset Field                     */
-
-/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits                                           */
-#define SP_WSIZE(x)    (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1   */
-
-/* SPORTx_MCMC2 Masks                                                                                                                  */
-#define REC_BYPASS     0x0000  /* Bypass Mode (No Clock Recovery)                              */
-#define REC_2FROM4     0x0002  /* Recover 2 MHz Clock from 4 MHz Clock                 */
-#define REC_8FROM16    0x0003  /* Recover 8 MHz Clock from 16 MHz Clock                */
-#define MCDTXPE                0x0004  /* Multichannel DMA Transmit Packing                    */
-#define MCDRXPE                0x0008  /* Multichannel DMA Receive Packing                             */
-#define MCMEN          0x0010  /* Multichannel Frame Mode Enable                               */
-#define FSDR           0x0080  /* Multichannel Frame Sync to Data Relationship */
-#define MFD_0          0x0000  /* Multichannel Frame Delay = 0                                 */
-#define MFD_1          0x1000  /* Multichannel Frame Delay = 1                                 */
-#define MFD_2          0x2000  /* Multichannel Frame Delay = 2                                 */
-#define MFD_3          0x3000  /* Multichannel Frame Delay = 3                                 */
-#define MFD_4          0x4000  /* Multichannel Frame Delay = 4                                 */
-#define MFD_5          0x5000  /* Multichannel Frame Delay = 5                                 */
-#define MFD_6          0x6000  /* Multichannel Frame Delay = 6                                 */
-#define MFD_7          0x7000  /* Multichannel Frame Delay = 7                                 */
-#define MFD_8          0x8000  /* Multichannel Frame Delay = 8                                 */
-#define MFD_9          0x9000  /* Multichannel Frame Delay = 9                                 */
-#define MFD_10         0xA000  /* Multichannel Frame Delay = 10                                */
-#define MFD_11         0xB000  /* Multichannel Frame Delay = 11                                */
-#define MFD_12         0xC000  /* Multichannel Frame Delay = 12                                */
-#define MFD_13         0xD000  /* Multichannel Frame Delay = 13                                */
-#define MFD_14         0xE000  /* Multichannel Frame Delay = 14                                */
-#define MFD_15         0xF000  /* Multichannel Frame Delay = 15                                */
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
 /* EBIU_AMGCTL Masks                                                                                                                                   */
 #define AMCKEN                 0x0001  /* Enable CLKOUT                                                                        */
diff --git a/arch/blackfin/mach-bf537/include/mach/pll.h b/arch/blackfin/mach-bf537/include/mach/pll.h
new file mode 100644 (file)
index 0000000..169c106
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index 66aa722cf6c89beb302816ab44f039ad35418dd3..085b06b8c0a5512935e91e3899fcfb211320a662 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
 #endif
index b674a1c4aef1efdbe30eb6c1cb5ca76d2bd260f6..fe43062b4975a5548f259a487bc83a8330842797 100644 (file)
 #define        UCEN_P          0x00
 
 
-/* **********  SERIAL PORT MASKS  ********************** */
-/* SPORTx_TCR1 Masks */
-#define        TSPEN           0x0001  /* TX enable  */
-#define        ITCLK           0x0002  /* Internal TX Clock Select  */
-#define        TDTYPE          0x000C  /* TX Data Formatting Select */
-#define        DTYPE_NORM      0x0000          /* Data Format Normal */
-#define        DTYPE_ULAW      0x0008          /* Compand Using u-Law */
-#define        DTYPE_ALAW      0x000C          /* Compand Using A-Law */
-#define        TLSBIT          0x0010  /* TX Bit Order */
-#define        ITFS            0x0200  /* Internal TX Frame Sync Select  */
-#define        TFSR            0x0400  /* TX Frame Sync Required Select  */
-#define        DITFS           0x0800  /* Data Independent TX Frame Sync Select  */
-#define        LTFS            0x1000  /* Low TX Frame Sync Select  */
-#define        LATFS           0x2000  /* Late TX Frame Sync Select  */
-#define        TCKFE           0x4000  /* TX Clock Falling Edge Select */
-/* SPORTx_RCR1 Deprecated Masks                                                                 */
-#define        TULAW           DTYPE_ULAW              /* Compand Using u-Law */
-#define        TALAW           DTYPE_ALAW                      /* Compand Using A-Law */
-
-/* SPORTx_TCR2 Masks */
-#ifdef _MISRA_RULES
-#define        SLEN(x)         ((x)&0x1Fu)     /* SPORT TX Word Length (2 - 31) */
-#else
-#define        SLEN(x)         ((x)&0x1F)      /* SPORT TX Word Length (2 - 31) */
-#endif /* _MISRA_RULES */
-#define        TXSE            0x0100  /*TX Secondary Enable */
-#define        TSFSE           0x0200  /*TX Stereo Frame Sync Enable */
-#define        TRFST           0x0400  /*TX Right-First Data Order  */
-
-/* SPORTx_RCR1 Masks */
-#define        RSPEN           0x0001  /* RX enable  */
-#define        IRCLK           0x0002  /* Internal RX Clock Select  */
-#define        RDTYPE          0x000C  /* RX Data Formatting Select */
-#define        DTYPE_NORM      0x0000          /* no companding */
-#define        DTYPE_ULAW      0x0008          /* Compand Using u-Law */
-#define        DTYPE_ALAW      0x000C          /* Compand Using A-Law */
-#define        RLSBIT          0x0010  /* RX Bit Order */
-#define        IRFS            0x0200  /* Internal RX Frame Sync Select  */
-#define        RFSR            0x0400  /* RX Frame Sync Required Select  */
-#define        LRFS            0x1000  /* Low RX Frame Sync Select  */
-#define        LARFS           0x2000  /* Late RX Frame Sync Select  */
-#define        RCKFE           0x4000  /* RX Clock Falling Edge Select */
-/* SPORTx_RCR1 Deprecated Masks                                                                 */
-#define        RULAW           DTYPE_ULAW              /* Compand Using u-Law */
-#define        RALAW           DTYPE_ALAW                      /* Compand Using A-Law */
-
-/* SPORTx_RCR2 Masks */
-#ifdef _MISRA_RULES
-#define        SLEN(x)         ((x)&0x1Fu)     /* SPORT RX Word Length (2 - 31) */
-#else
-#define        SLEN(x)         ((x)&0x1F)      /* SPORT RX Word Length (2 - 31) */
-#endif /* _MISRA_RULES */
-#define        RXSE            0x0100  /*RX Secondary Enable */
-#define        RSFSE           0x0200  /*RX Stereo Frame Sync Enable */
-#define        RRFST           0x0400  /*Right-First Data Order  */
-
-/*SPORTx_STAT Masks */
-#define        RXNE            0x0001          /*RX FIFO Not Empty Status */
-#define        RUVF            0x0002          /*RX Underflow Status */
-#define        ROVF            0x0004          /*RX Overflow Status */
-#define        TXF                     0x0008          /*TX FIFO Full Status */
-#define        TUVF            0x0010          /*TX Underflow Status */
-#define        TOVF            0x0020          /*TX Overflow Status */
-#define        TXHRE           0x0040          /*TX Hold Register Empty */
-
-/*SPORTx_MCMC1 Masks */
-#define        WOFF                    0x000003FF      /*Multichannel Window Offset Field */
-/* SPORTx_MCMC1        Macros                                                           */
-#ifdef _MISRA_RULES
-#define        SET_WOFF(x)             ((x) & 0x3FFu)  /* Multichannel Window Offset Field */
-/* Only        use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits */
-#define        SET_WSIZE(x)    (((((x)>>0x3)-1u)&0xFu) << 0xC) /* Multichannel Window Size = (x/8)-1 */
-#else
-#define        SET_WOFF(x)             ((x) & 0x3FF)   /* Multichannel Window Offset Field */
-/* Only        use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits */
-#define        SET_WSIZE(x)    (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1 */
-#endif /* _MISRA_RULES */
-
-
-/*SPORTx_MCMC2 Masks */
-#define        MCCRM           0x0003  /*Multichannel Clock Recovery Mode */
-#define        REC_BYPASS      0x0000          /* Bypass Mode (No Clock Recovery) */
-#define        REC_2FROM4      0x0002          /* Recover 2 MHz Clock from 4 MHz Clock */
-#define        REC_8FROM16     0x0003          /* Recover 8 MHz Clock from 16 MHz Clock */
-#define        MCDTXPE         0x0004  /*Multichannel DMA Transmit Packing */
-#define        MCDRXPE         0x0008  /*Multichannel DMA Receive Packing */
-#define        MCMEN           0x0010  /*Multichannel Frame Mode Enable */
-#define        FSDR            0x0080  /*Multichannel Frame Sync to Data Relationship */
-#define        MFD                     0xF000  /*Multichannel Frame Delay    */
-#define        MFD_0           0x0000          /* Multichannel Frame Delay = 0 */
-#define        MFD_1           0x1000          /* Multichannel Frame Delay = 1 */
-#define        MFD_2           0x2000          /* Multichannel Frame Delay = 2 */
-#define        MFD_3           0x3000          /* Multichannel Frame Delay = 3 */
-#define        MFD_4           0x4000          /* Multichannel Frame Delay = 4 */
-#define        MFD_5           0x5000          /* Multichannel Frame Delay = 5 */
-#define        MFD_6           0x6000          /* Multichannel Frame Delay = 6 */
-#define        MFD_7           0x7000          /* Multichannel Frame Delay = 7 */
-#define        MFD_8           0x8000          /* Multichannel Frame Delay = 8 */
-#define        MFD_9           0x9000          /* Multichannel Frame Delay = 9 */
-#define        MFD_10          0xA000          /* Multichannel Frame Delay = 10 */
-#define        MFD_11          0xB000          /* Multichannel Frame Delay = 11 */
-#define        MFD_12          0xC000          /* Multichannel Frame Delay = 12 */
-#define        MFD_13          0xD000          /* Multichannel Frame Delay = 13 */
-#define        MFD_14          0xE000          /* Multichannel Frame Delay = 14 */
-#define        MFD_15          0xF000          /* Multichannel Frame Delay = 15 */
-
-
 /*  *********  PARALLEL        PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 /*  PPI_CONTROL        Masks         */
 #define        PORT_EN         0x0001  /* PPI Port Enable  */
diff --git a/arch/blackfin/mach-bf538/include/mach/pll.h b/arch/blackfin/mach-bf538/include/mach/pll.h
new file mode 100644 (file)
index 0000000..b30bbcd
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index dbb6b1d83f6dc7a2d0dc1861f23d0856a1170bd0..0c38eec9ade11f77f7422dc4dcf42a29e6dc3be0 100644 (file)
@@ -706,7 +706,6 @@ static struct mtd_partition partition_info[] = {
 };
 
 static struct bf5xx_nand_platform bf5xx_nand_platform = {
-       .page_size = NFC_PG_SIZE_256,
        .data_width = NFC_NWIDTH_8,
        .partitions = partition_info,
        .nr_partitions = ARRAY_SIZE(partition_info),
index 6fcfb9187c357bcf1b69f5ae821fec5386f6dc6b..56682a36e42df0bf7be8825c7e4789d315a5de90 100644 (file)
@@ -849,7 +849,6 @@ static struct mtd_partition partition_info[] = {
 };
 
 static struct bf5xx_nand_platform bf5xx_nand_platform = {
-       .page_size = NFC_PG_SIZE_256,
        .data_width = NFC_NWIDTH_8,
        .partitions = partition_info,
        .nr_partitions = ARRAY_SIZE(partition_info),
index ea3ec4ea9e2bc3e699fe8c6b8ece46109e6270e2..0c16067df4f3730913d5d20fc6960e91050d6320 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1, iwr2;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       iwr2 = bfin_read32(SIC_IWR2);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-       bfin_write32(SIC_IWR2, 0);
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       bfin_write32(SIC_IWR2, iwr2);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1, iwr2;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SIC_IWR0);
-       iwr1 = bfin_read32(SIC_IWR1);
-       iwr2 = bfin_read32(SIC_IWR2);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-       bfin_write32(SIC_IWR1, 0);
-       bfin_write32(SIC_IWR2, 0);
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SIC_IWR0, iwr0);
-       bfin_write32(SIC_IWR1, iwr1);
-       bfin_write32(SIC_IWR2, iwr2);
-       local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF54X_H */
 
index 95ff44601fd1e7401ac4955cfe7d0348cd8cb77b..7866197f5485f063229f7e5909d9693251a28d89 100644 (file)
 
 #define                 RCVDATA16  0xffff     /* Receive FIFO 16-Bit Data */
 
-/* Bit masks for SPORTx_TCR1 */
-
-#define                     TCKFE  0x4000     /* Clock Falling Edge Select */
-#define                     LATFS  0x2000     /* Late Transmit Frame Sync */
-#define                      LTFS  0x1000     /* Low Transmit Frame Sync Select */
-#define                     DITFS  0x800      /* Data-Independent Transmit Frame Sync Select */
-#define                      TFSR  0x400      /* Transmit Frame Sync Required Select */
-#define                      ITFS  0x200      /* Internal Transmit Frame Sync Select */
-#define                    TLSBIT  0x10       /* Transmit Bit Order */
-#define                    TDTYPE  0xc        /* Data Formatting Type Select */
-#define                     ITCLK  0x2        /* Internal Transmit Clock Select */
-#define                     TSPEN  0x1        /* Transmit Enable */
-
-/* Bit masks for SPORTx_TCR2 */
-
-#define                     TRFST  0x400      /* Left/Right Order */
-#define                     TSFSE  0x200      /* Transmit Stereo Frame Sync Enable */
-#define                      TXSE  0x100      /* TxSEC Enable */
-#define                    SLEN_T  0x1f       /* SPORT Word Length */
-
-/* Bit masks for SPORTx_RCR1 */
-
-#define                     RCKFE  0x4000     /* Clock Falling Edge Select */
-#define                     LARFS  0x2000     /* Late Receive Frame Sync */
-#define                      LRFS  0x1000     /* Low Receive Frame Sync Select */
-#define                      RFSR  0x400      /* Receive Frame Sync Required Select */
-#define                      IRFS  0x200      /* Internal Receive Frame Sync Select */
-#define                    RLSBIT  0x10       /* Receive Bit Order */
-#define                    RDTYPE  0xc        /* Data Formatting Type Select */
-#define                     IRCLK  0x2        /* Internal Receive Clock Select */
-#define                     RSPEN  0x1        /* Receive Enable */
-
-/* Bit masks for SPORTx_RCR2 */
-
-#define                     RRFST  0x400      /* Left/Right Order */
-#define                     RSFSE  0x200      /* Receive Stereo Frame Sync Enable */
-#define                      RXSE  0x100      /* RxSEC Enable */
-#define                    SLEN_R  0x1f       /* SPORT Word Length */
-
-/* Bit masks for SPORTx_STAT */
-
-#define                     TXHRE  0x40       /* Transmit Hold Register Empty */
-#define                      TOVF  0x20       /* Sticky Transmit Overflow Status */
-#define                      TUVF  0x10       /* Sticky Transmit Underflow Status */
-#define                       TXF  0x8        /* Transmit FIFO Full Status */
-#define                      ROVF  0x4        /* Sticky Receive Overflow Status */
-#define                      RUVF  0x2        /* Sticky Receive Underflow Status */
-#define                      RXNE  0x1        /* Receive FIFO Not Empty Status */
-
-/* Bit masks for SPORTx_MCMC1 */
-
-#define                  SP_WSIZE  0xf000     /* Window Size */
-#define                   SP_WOFF  0x3ff      /* Windows Offset */
-
-/* Bit masks for SPORTx_MCMC2 */
-
-#define                       MFD  0xf000     /* Multi channel Frame Delay */
-#define                      FSDR  0x80       /* Frame Sync to Data Relationship */
-#define                  MCMEN  0x10       /* Multi channel Frame Mode Enable */
-#define                   MCDRXPE  0x8        /* Multi channel DMA Receive Packing */
-#define                   MCDTXPE  0x4        /* Multi channel DMA Transmit Packing */
-#define                     MCCRM  0x3        /* 2X Clock Recovery Mode */
-
-/* Bit masks for SPORTx_CHNL */
-
-#define                  CUR_CHNL  0x3ff      /* Current Channel Indicator */
-
 /* Bit masks for UARTx_LCR */
 
 #if 0
diff --git a/arch/blackfin/mach-bf548/include/mach/pll.h b/arch/blackfin/mach-bf548/include/mach/pll.h
new file mode 100644 (file)
index 0000000..7865a09
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1, iwr2;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       iwr2 = bfin_read32(SIC_IWR2);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+       bfin_write32(SIC_IWR2, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       bfin_write32(SIC_IWR2, iwr2);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1, iwr2;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       iwr2 = bfin_read32(SIC_IWR2);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+       bfin_write32(SIC_IWR2, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       bfin_write32(SIC_IWR2, iwr2);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index deb2271d09a327a5301cb2aeb97498673126f053..c6a4c8f2d37b8b47b12a6c92dbb4e83c96598675 100644 (file)
@@ -51,6 +51,7 @@ coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static const struct file_operations coreb_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = coreb_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice coreb_dev = {
index 81ecdb71c6afe4635f1bf6bdd010c5af8418299f..cc0416a5fa027a79815501dc5905fe945c771d96 100644 (file)
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_PLL_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SICA_IWR0);
-       iwr1 = bfin_read32(SICA_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-       bfin_write32(SICA_IWR1, 0);
-
-       bfin_write16(PLL_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SICA_IWR0, iwr0);
-       bfin_write32(SICA_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-       unsigned long flags, iwr0, iwr1;
-
-       if (val == bfin_read_VR_CTL())
-               return;
-
-       local_irq_save_hw(flags);
-       /* Enable the PLL Wakeup bit in SIC IWR */
-       iwr0 = bfin_read32(SICA_IWR0);
-       iwr1 = bfin_read32(SICA_IWR1);
-       /* Only allow PPL Wakeup) */
-       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-       bfin_write32(SICA_IWR1, 0);
-
-       bfin_write16(VR_CTL, val);
-       SSYNC();
-       asm("IDLE;");
-
-       bfin_write32(SICA_IWR0, iwr0);
-       bfin_write32(SICA_IWR1, iwr1);
-       local_irq_restore_hw(flags);
-}
-
 #endif                         /* _CDEF_BF561_H */
index 4c8e36b7fb33752144d616fe7f406d1b968f8906..2674f0097576d138d2c4f4c1ba8940e103a9e393 100644 (file)
 #define IREN_P 0x01
 #define UCEN_P 0x00
 
-/* **********  SERIAL PORT MASKS  ********************** */
-
-/* SPORTx_TCR1 Masks */
-#define TSPEN    0x0001                /* TX enable  */
-#define ITCLK    0x0002                /* Internal TX Clock Select  */
-#define TDTYPE   0x000C                /* TX Data Formatting Select */
-#define TLSBIT   0x0010                /* TX Bit Order */
-#define ITFS     0x0200                /* Internal TX Frame Sync Select  */
-#define TFSR     0x0400                /* TX Frame Sync Required Select  */
-#define DITFS    0x0800                /* Data Independent TX Frame Sync Select  */
-#define LTFS     0x1000                /* Low TX Frame Sync Select  */
-#define LATFS    0x2000                /* Late TX Frame Sync Select  */
-#define TCKFE    0x4000                /* TX Clock Falling Edge Select  */
-
-/* SPORTx_TCR2 Masks */
-#define SLEN       0x001F      /*TX Word Length  */
-#define TXSE        0x0100     /*TX Secondary Enable */
-#define TSFSE       0x0200     /*TX Stereo Frame Sync Enable */
-#define TRFST       0x0400     /*TX Right-First Data Order  */
-
-/* SPORTx_RCR1 Masks */
-#define RSPEN    0x0001                /* RX enable  */
-#define IRCLK    0x0002                /* Internal RX Clock Select  */
-#define RDTYPE   0x000C                /* RX Data Formatting Select */
-#define RULAW    0x0008                /* u-Law enable  */
-#define RALAW    0x000C                /* A-Law enable  */
-#define RLSBIT   0x0010                /* RX Bit Order */
-#define IRFS     0x0200                /* Internal RX Frame Sync Select  */
-#define RFSR     0x0400                /* RX Frame Sync Required Select  */
-#define LRFS     0x1000                /* Low RX Frame Sync Select  */
-#define LARFS    0x2000                /* Late RX Frame Sync Select  */
-#define RCKFE    0x4000                /* RX Clock Falling Edge Select  */
-
-/* SPORTx_RCR2 Masks */
-#define SLEN       0x001F      /*RX Word Length  */
-#define RXSE        0x0100     /*RX Secondary Enable */
-#define RSFSE       0x0200     /*RX Stereo Frame Sync Enable */
-#define RRFST       0x0400     /*Right-First Data Order  */
-
-/*SPORTx_STAT Masks */
-#define RXNE           0x0001  /*RX FIFO Not Empty Status */
-#define RUVF           0x0002  /*RX Underflow Status */
-#define ROVF           0x0004  /*RX Overflow Status */
-#define TXF            0x0008  /*TX FIFO Full Status */
-#define TUVF           0x0010  /*TX Underflow Status */
-#define TOVF           0x0020  /*TX Overflow Status */
-#define TXHRE          0x0040  /*TX Hold Register Empty */
-
-/*SPORTx_MCMC1 Masks */
-#define SP_WSIZE               0x0000F000      /*Multichannel Window Size Field */
-#define SP_WOFF                0x000003FF      /*Multichannel Window Offset Field */
-
-/*SPORTx_MCMC2 Masks */
-#define MCCRM          0x00000003      /*Multichannel Clock Recovery Mode */
-#define MCDTXPE                0x00000004      /*Multichannel DMA Transmit Packing */
-#define MCDRXPE                0x00000008      /*Multichannel DMA Receive Packing */
-#define MCMEN          0x00000010      /*Multichannel Frame Mode Enable */
-#define FSDR           0x00000080      /*Multichannel Frame Sync to Data Relationship */
-#define MFD            0x0000F000      /*Multichannel Frame Delay    */
-
 /*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 
 /*  PPI_CONTROL Masks         */
diff --git a/arch/blackfin/mach-bf561/include/mach/pll.h b/arch/blackfin/mach-bf561/include/mach/pll.h
new file mode 100644 (file)
index 0000000..f2b1fbd
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SICA_IWR0);
+       iwr1 = bfin_read32(SICA_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       bfin_write32(SICA_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SICA_IWR0, iwr0);
+       bfin_write32(SICA_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       flags = hard_local_irq_save();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SICA_IWR0);
+       iwr1 = bfin_read32(SICA_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       bfin_write32(SICA_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SICA_IWR0, iwr0);
+       bfin_write32(SICA_IWR1, iwr1);
+       hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
index 4391d03dc8455056c6984f6931d3bee246856220..f4cf11d362e1df4f67315a68714cac5faf6b293b 100644 (file)
@@ -134,7 +134,7 @@ static int bfin_target(struct cpufreq_policy *poli,
 
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
                if (cpu == CPUFREQ_CPU) {
-                       local_irq_save_hw(flags);
+                       flags = hard_local_irq_save();
                        plldiv = (bfin_read_PLL_DIV() & SSEL) |
                                                dpm_state_table[index].csel;
                        bfin_write_PLL_DIV(plldiv);
@@ -155,7 +155,7 @@ static int bfin_target(struct cpufreq_policy *poli,
                                loops_per_jiffy = cpufreq_scale(lpj_ref,
                                                lpj_ref_freq, freqs.new);
                        }
-                       local_irq_restore_hw(flags);
+                       hard_local_irq_restore(flags);
                }
                /* TODO: just test case for cycles clock source, remove later */
                cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
index a5847f5d67c7325ae6c53996f02f0b7d348267c3..af1bffa21dc14dccdefca16268da5c737024dfa8 100644 (file)
@@ -1628,6 +1628,9 @@ ENTRY(_sys_call_table)
        .long _sys_rt_tgsigqueueinfo
        .long _sys_perf_event_open
        .long _sys_recvmmsg             /* 370 */
+       .long _sys_fanotify_init
+       .long _sys_fanotify_mark
+       .long _sys_prlimit64
 
        .rept NR_syscalls-(.-_sys_call_table)/4
        .long _sys_ni_syscall
index 1c8c4c7245c3868eb9cfcc62b783bac6a7c90755..eaece5f84e428011d57a8943da8ad603762e9f27 100644 (file)
@@ -132,8 +132,8 @@ static void bfin_ack_noop(unsigned int irq)
 static void bfin_core_mask_irq(unsigned int irq)
 {
        bfin_irq_flags &= ~(1 << irq);
-       if (!irqs_disabled_hw())
-               local_irq_enable_hw();
+       if (!hard_irqs_disabled())
+               hard_local_irq_enable();
 }
 
 static void bfin_core_unmask_irq(unsigned int irq)
@@ -148,8 +148,8 @@ static void bfin_core_unmask_irq(unsigned int irq)
         * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
         * what we need.
         */
-       if (!irqs_disabled_hw())
-               local_irq_enable_hw();
+       if (!hard_irqs_disabled())
+               hard_local_irq_enable();
        return;
 }
 
@@ -158,12 +158,12 @@ static void bfin_internal_mask_irq(unsigned int irq)
        unsigned long flags;
 
 #ifdef CONFIG_BF53x
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
                             ~(1 << SIC_SYSIRQ(irq)));
 #else
        unsigned mask_bank, mask_bit;
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        mask_bank = SIC_SYSIRQ(irq) / 32;
        mask_bit = SIC_SYSIRQ(irq) % 32;
        bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
@@ -173,7 +173,7 @@ static void bfin_internal_mask_irq(unsigned int irq)
                             ~(1 << mask_bit));
 #endif
 #endif
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 #ifdef CONFIG_SMP
@@ -186,12 +186,12 @@ static void bfin_internal_unmask_irq(unsigned int irq)
        unsigned long flags;
 
 #ifdef CONFIG_BF53x
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
                             (1 << SIC_SYSIRQ(irq)));
 #else
        unsigned mask_bank, mask_bit;
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        mask_bank = SIC_SYSIRQ(irq) / 32;
        mask_bit = SIC_SYSIRQ(irq) % 32;
 #ifdef CONFIG_SMP
@@ -207,7 +207,7 @@ static void bfin_internal_unmask_irq(unsigned int irq)
                        (1 << mask_bit));
 #endif
 #endif
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 #ifdef CONFIG_SMP
@@ -264,7 +264,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
        break;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (state) {
                bfin_sic_iwr[bank] |= (1 << bit);
@@ -275,7 +275,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
                vr_wakeup  &= ~wakeup;
        }
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
index 09c1fb410748436d096bc629805295acc086025f..80884b136a0c330b20180921baf58f7584a1401a 100644 (file)
@@ -25,7 +25,7 @@ void bfin_pm_suspend_standby_enter(void)
 {
        unsigned long flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        bfin_pm_standby_setup();
 
 #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -56,7 +56,7 @@ void bfin_pm_suspend_standby_enter(void)
        bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -149,12 +149,12 @@ int bfin_pm_suspend_mem_enter(void)
        wakeup |= GPWE;
 #endif
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        ret = blackfin_dma_suspend();
 
        if (ret) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                kfree(memptr);
                return ret;
        }
@@ -178,7 +178,7 @@ int bfin_pm_suspend_mem_enter(void)
        bfin_gpio_pm_hibernate_restore();
        blackfin_dma_resume();
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        kfree(memptr);
 
        return 0;
index 884275629ef7405dfbbb901e0758fdc75594fd3e..3d655dcc65da89df480c51d25c6b0b7199965053 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/bcd.h>
 #include <linux/capability.h>
 
@@ -34,6 +34,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(ds1302_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* The DS1302 might be connected to different bits on different products. 
@@ -357,9 +358,9 @@ static long rtc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned lon
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ds1302_mutex);
        ret = rtc_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ds1302_mutex);
 
        return ret;
 }
@@ -387,6 +388,7 @@ print_rtc_status(void)
 static const struct file_operations rtc_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = rtc_unlocked_ioctl,
+       .llseek         = noop_llseek,
 }; 
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
index a07b6d25b0c7956eb6e4a6fd36aa070a75a6a140..a276f0811731c8d0b3bb68f30c1bb3173a1c5e75 100644 (file)
@@ -745,6 +745,7 @@ static const struct file_operations gpio_fops = {
        .write          = gpio_write,
        .open           = gpio_open,
        .release        = gpio_release,
+       .llseek         = noop_llseek,
 };
 
 static void ioif_watcher(const unsigned int gpio_in_available,
index 77a94181381981eebebe5760bb9b1ca0c376614e..c413539d4205f929c75382bac787d74893575924 100644 (file)
@@ -617,6 +617,7 @@ static const struct file_operations i2c_fops = {
        .unlocked_ioctl = i2c_ioctl,
        .open           = i2c_open,
        .release        = i2c_release,
+       .llseek         = noop_llseek,
 };
 
 int __init
index 7dcb1f85f42b157c93eaaac921381e8ae163ca84..ea69faba9b6212f00a731652e96966ed1116186c 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -49,6 +48,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -64,6 +64,7 @@ static int voltage_low;
 static const struct file_operations pcf8563_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = pcf8563_unlocked_ioctl,
+       .llseek         = noop_llseek,
 };
 
 unsigned char
@@ -343,9 +344,9 @@ static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pcf8563_mutex);
        return pcf8563_ioctl(filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&pcf8563_mutex);
 
        return ret;
 }
index ee2dd4323daf4ee0c901045748714057c738e64f..399dc1ec8e6fe3c4e1ac5d3bd89bd0537a57a490 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
@@ -149,6 +149,7 @@ struct sync_port {
 };
 
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -250,7 +251,8 @@ static const struct file_operations sync_serial_fops = {
        .poll           = sync_serial_poll,
        .unlocked_ioctl = sync_serial_ioctl,
        .open           = sync_serial_open,
-       .release        = sync_serial_release
+       .release        = sync_serial_release,
+       .llseek         = noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -445,7 +447,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
        int mode;
        int err = -EBUSY;
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
        if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
@@ -626,7 +628,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
        ret = 0;
        
 out:
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
        return ret;
 }
 
@@ -961,9 +963,9 @@ static long sync_serial_ioctl(struct file *file,
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
 
        return ret;
 }
index b07646a30509680b0ad31c3d3c288de7d78107c8..c03bc3bc30c2f581f1dce2a4783fcf570d81ab6c 100644 (file)
@@ -281,7 +281,8 @@ const struct file_operations cryptocop_fops = {
        .owner          = THIS_MODULE,
        .open           = cryptocop_open,
        .release        = cryptocop_release,
-       .unlocked_ioctl = cryptocop_ioctl
+       .unlocked_ioctl = cryptocop_ioctl,
+       .llseek         = noop_llseek,
 };
 
 
@@ -3139,9 +3140,9 @@ cryptocop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        struct inode *inode = file->f_path.dentry->d_inode;
        long ret;
 
-       lock_kernel();
+       mutex_lock(&cryptocop_mutex);
        ret = cryptocop_ioctl_unlocked(inode, filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&cryptocop_mutex);
 
        return ret;
 }
index 5a3e900c9a78df9cf36c8483655a280c2d91699d..ddb23996f11a8ef56183c155b82c20bd17214b48 100644 (file)
@@ -698,6 +698,7 @@ static const struct file_operations i2c_fops = {
        .unlocked_ioctl = i2c_ioctl,
        .open           = i2c_open,
        .release        = i2c_release,
+       .llseek         = noop_llseek,
 };
 
 static int __init i2c_init(void)
index 2dcd27adbad485442f55278119b51e298ddf0687..c845831e222590c7e6289d4fef846ea21305aadf 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -66,6 +66,7 @@ static int dp_cnt;
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -391,7 +392,7 @@ static int gpio_open(struct inode *inode, struct file *filp)
        if (!priv)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        memset(priv, 0, sizeof(*priv));
 
        priv->minor = p;
@@ -414,7 +415,7 @@ static int gpio_open(struct inode *inode, struct file *filp)
                spin_unlock_irq(&gpio_lock);
        }
 
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
        return 0;
 }
 
@@ -667,9 +668,9 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -893,6 +894,7 @@ static const struct file_operations gpio_fops = {
        .write          = gpio_write,
        .open           = gpio_open,
        .release        = gpio_release,
+       .llseek         = noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
index 5ec8a7d4e7d78db9b1eca0a5e5461414f2c71bb8..ee90d2659be76db461cd12043bffe842160420a9 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -64,6 +64,7 @@ static int dp_cnt;
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #if 0
@@ -429,7 +430,7 @@ gpio_open(struct inode *inode, struct file *filp)
        if (!priv)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        memset(priv, 0, sizeof(*priv));
 
        priv->minor = p;
@@ -450,7 +451,7 @@ gpio_open(struct inode *inode, struct file *filp)
        alarmlist = priv;
        spin_unlock_irq(&alarm_lock);
 
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
        return 0;
 }
 
@@ -708,9 +709,9 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -870,6 +871,7 @@ static const struct file_operations gpio_fops = {
        .write          = gpio_write,
        .open           = gpio_open,
        .release        = gpio_release,
+       .llseek         = noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
index bef6eb53b1539b9e6974b1e472aa638187e6ca6c..b6e4fc0aad42e844899b5f213a28262038cbbd2f 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
@@ -45,6 +44,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -60,6 +60,7 @@ static int voltage_low;
 static const struct file_operations pcf8563_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = pcf8563_unlocked_ioctl,
+       .llseek         = noop_llseek,
 };
 
 unsigned char
@@ -339,9 +340,9 @@ static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pcf8563_mutex);
        return pcf8563_ioctl(filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&pcf8563_mutex);
 
        return ret;
 }
index ca248f3adb800e26403d591b9c72c8cae0c200fa..c8637a9195eadb5bb0d8d0f9e3b658923767fbdc 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
@@ -145,6 +145,7 @@ typedef struct sync_port
        spinlock_t lock;
 } sync_port;
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -247,7 +248,8 @@ static const struct file_operations sync_serial_fops = {
        .poll           = sync_serial_poll,
        .unlocked_ioctl = sync_serial_ioctl,
        .open           = sync_serial_open,
-       .release        = sync_serial_release
+       .release        = sync_serial_release,
+       .llseek         = noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -434,7 +436,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
        reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
        reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
        if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
@@ -583,7 +585,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
        port->busy++;
        ret = 0;
 out:
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
        return ret;
 }
 
@@ -966,9 +968,9 @@ static long sync_serial_ioctl(struct file *file,
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
 
        return ret;
 }
diff --git a/arch/cris/include/arch-v10/arch/irqflags.h b/arch/cris/include/arch-v10/arch/irqflags.h
new file mode 100644 (file)
index 0000000..75ef189
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("move $ccr,%0" : "=rm" (flags) : : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("move %0,$ccr" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1 << 5));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
index 4a9cd36c9e16e58b16e0dbb6f8e3a2db31145b86..935fde34aa15782db1fc2dd7c39e4b47c2a96992 100644 (file)
@@ -44,20 +44,4 @@ static inline unsigned long _get_base(char * addr)
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
-/* interrupt control.. */
-#define local_save_flags(x)    __asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
-#define local_irq_restore(x)   __asm__ __volatile__ ("move %0,$ccr" : : "rm" (x) : "memory");
-#define local_irq_disable()    __asm__ __volatile__ ( "di" : : :"memory");
-#define local_irq_enable()     __asm__ __volatile__ ( "ei" : : :"memory");
-
-#define irqs_disabled()                        \
-({                                     \
-       unsigned long flags;            \
-       local_save_flags(flags);        \
-       !(flags & (1<<5));              \
-})
-
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory");
-
 #endif
diff --git a/arch/cris/include/arch-v32/arch/irqflags.h b/arch/cris/include/arch-v32/arch/irqflags.h
new file mode 100644 (file)
index 0000000..041851f
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <arch/ptrace.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("move $ccs,%0" : "=rm" (flags) : : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("move %0,$ccs" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1 << I_CCS_BITNR));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
index 6ca90f1f110acd15aa4ee68171e3047ef7ec6a16..76cea99eaa6012a5e7f6335cf215e74dd1fc860c 100644 (file)
@@ -44,26 +44,4 @@ static inline unsigned long rdsp(void)
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
-/* Used for interrupt control. */
-#define local_save_flags(x) \
-       __asm__ __volatile__ ("move $ccs, %0" : "=rm" (x) : : "memory");
-
-#define local_irq_restore(x) \
-       __asm__ __volatile__ ("move %0, $ccs" : : "rm" (x) : "memory");
-
-#define local_irq_disable()  __asm__ __volatile__ ("di" : : : "memory");
-#define local_irq_enable()   __asm__ __volatile__ ("ei" : : : "memory");
-
-#define irqs_disabled()                \
-({                             \
-       unsigned long flags;    \
-                               \
-       local_save_flags(flags);\
-       !(flags & (1 << I_CCS_BITNR));  \
-})
-
-/* Used for spinlocks, etc. */
-#define local_irq_save(x) \
-       __asm__ __volatile__ ("move $ccs, %0\n\tdi" : "=rm" (x) : : "memory");
-
 #endif /* _ASM_CRIS_ARCH_SYSTEM_H */
diff --git a/arch/cris/include/asm/irqflags.h b/arch/cris/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..943ba5c
--- /dev/null
@@ -0,0 +1 @@
+#include <arch/irqflags.h>
index 8657b084a922e3ff0cb5187130961ada08262cee..ea10592f7d75ccab1a4512b9e4f4f9c79da4cd3d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_CRIS_SYSTEM_H
 #define __ASM_CRIS_SYSTEM_H
 
+#include <linux/irqflags.h>
 #include <arch/system.h>
 
 /* the switch_to macro calls resume, an asm function in entry.S which does the actual
index 195ec5fa0dd2a25f14d612e13f18d174756695b4..b82e08615d1bb81960a9010aeba114f522b80657 100644 (file)
@@ -59,6 +59,7 @@ write_cris_profile(struct file *file, const char __user *buf,
 static const struct file_operations cris_proc_profile_operations = {
        .read           = read_cris_profile,
        .write          = write_cris_profile,
+       .llseek         = default_llseek,
 };
 
 static int __init init_cris_profile(void)
index 16399bd249930c1a9e2e06f7d0da247b288b6d34..0f2417df63230fb90114d96e7cb5f583d48fab34 100644 (file)
@@ -7,6 +7,7 @@ config FRV
        default y
        select HAVE_IDE
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
 
 config ZONE_DMA
diff --git a/arch/frv/include/asm/irqflags.h b/arch/frv/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..82f0b53
--- /dev/null
@@ -0,0 +1,158 @@
+/* FR-V interrupt handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+/*
+ * interrupt flag manipulation
+ * - use virtual interrupt management since touching the PSR is slow
+ *   - ICC2.Z: T if interrupts virtually disabled
+ *   - ICC2.C: F if interrupts really disabled
+ * - if Z==1 upon interrupt:
+ *   - C is set to 0
+ *   - interrupts are really disabled
+ *   - entry.S returns immediately
+ * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
+ *   - if taken, the trap:
+ *     - sets ICC2.C
+ *     - enables interrupts
+ */
+static inline void arch_local_irq_disable(void)
+{
+       /* set Z flag, but don't change the C flag */
+       asm volatile("  andcc   gr0,gr0,gr0,icc2        \n"
+                    :
+                    :
+                    : "memory", "icc2"
+                    );
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       /* clear Z flag and then test the C flag */
+       asm volatile("  oricc   gr0,#1,gr0,icc2         \n"
+                    "  tihi    icc2,gr0,#2             \n"
+                    :
+                    :
+                    : "memory", "icc2"
+                    );
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+
+       asm volatile("movsg ccr,%0"
+                    : "=r"(flags)
+                    :
+                    : "memory");
+
+       /* shift ICC2.Z to bit 0 */
+       flags >>= 26;
+
+       /* make flags 1 if interrupts disabled, 0 otherwise */
+       return flags & 1UL;
+
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       /* load the Z flag by turning 1 if disabled into 0 if disabled
+        * and thus setting the Z flag but not the C flag */
+       asm volatile("  xoricc  %0,#1,gr0,icc2          \n"
+                    /* then trap if Z=0 and C=0 */
+                    "  tihi    icc2,gr0,#2             \n"
+                    :
+                    : "r"(flags)
+                    : "memory", "icc2"
+                    );
+
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * real interrupt flag manipulation
+ */
+#define __arch_local_irq_disable()                     \
+do {                                                   \
+       unsigned long psr;                              \
+       asm volatile("  movsg   psr,%0          \n"     \
+                    "  andi    %0,%2,%0        \n"     \
+                    "  ori     %0,%1,%0        \n"     \
+                    "  movgs   %0,psr          \n"     \
+                    : "=r"(psr)                        \
+                    : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
+                    : "memory");                       \
+} while (0)
+
+#define __arch_local_irq_enable()                      \
+do {                                                   \
+       unsigned long psr;                              \
+       asm volatile("  movsg   psr,%0          \n"     \
+                    "  andi    %0,%1,%0        \n"     \
+                    "  movgs   %0,psr          \n"     \
+                    : "=r"(psr)                        \
+                    : "i" (~PSR_PIL)                   \
+                    : "memory");                       \
+} while (0)
+
+#define __arch_local_save_flags(flags)         \
+do {                                           \
+       typecheck(unsigned long, flags);        \
+       asm("movsg psr,%0"                      \
+           : "=r"(flags)                       \
+           :                                   \
+           : "memory");                        \
+} while (0)
+
+#define        __arch_local_irq_save(flags)                    \
+do {                                                   \
+       unsigned long npsr;                             \
+       typecheck(unsigned long, flags);                \
+       asm volatile("  movsg   psr,%0          \n"     \
+                    "  andi    %0,%3,%1        \n"     \
+                    "  ori     %1,%2,%1        \n"     \
+                    "  movgs   %1,psr          \n"     \
+                    : "=r"(flags), "=r"(npsr)          \
+                    : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
+                    : "memory");                       \
+} while (0)
+
+#define        __arch_local_irq_restore(flags)                 \
+do {                                                   \
+       typecheck(unsigned long, flags);                \
+       asm volatile("  movgs   %0,psr          \n"     \
+                    :                                  \
+                    : "r" (flags)                      \
+                    : "memory");                       \
+} while (0)
+
+#define __arch_irqs_disabled()                 \
+       ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
+
+#endif /* _ASM_IRQFLAGS_H */
index efd22d9077ac3be05e0ce45b4d9cd5fa0f1a83ce..0a6d8d9ca45bdbb6398b2ff2882203743963ea8b 100644 (file)
@@ -36,142 +36,6 @@ do {                                                                        \
        mb();                                                           \
 } while(0)
 
-/*
- * interrupt flag manipulation
- * - use virtual interrupt management since touching the PSR is slow
- *   - ICC2.Z: T if interrupts virtually disabled
- *   - ICC2.C: F if interrupts really disabled
- * - if Z==1 upon interrupt:
- *   - C is set to 0
- *   - interrupts are really disabled
- *   - entry.S returns immediately
- * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
- *   - if taken, the trap:
- *     - sets ICC2.C
- *     - enables interrupts
- */
-#define local_irq_disable()                                    \
-do {                                                           \
-       /* set Z flag, but don't change the C flag */           \
-       asm volatile("  andcc   gr0,gr0,gr0,icc2        \n"     \
-                    :                                          \
-                    :                                          \
-                    : "memory", "icc2"                         \
-                    );                                         \
-} while(0)
-
-#define local_irq_enable()                                     \
-do {                                                           \
-       /* clear Z flag and then test the C flag */             \
-       asm volatile("  oricc   gr0,#1,gr0,icc2         \n"     \
-                    "  tihi    icc2,gr0,#2             \n"     \
-                    :                                          \
-                    :                                          \
-                    : "memory", "icc2"                         \
-                    );                                         \
-} while(0)
-
-#define local_save_flags(flags)                                        \
-do {                                                           \
-       typecheck(unsigned long, flags);                        \
-       asm volatile("movsg ccr,%0"                             \
-                    : "=r"(flags)                              \
-                    :                                          \
-                    : "memory");                               \
-                                                               \
-       /* shift ICC2.Z to bit 0 */                             \
-       flags >>= 26;                                           \
-                                                               \
-       /* make flags 1 if interrupts disabled, 0 otherwise */  \
-       flags &= 1UL;                                           \
-} while(0)
-
-#define irqs_disabled() \
-       ({unsigned long flags; local_save_flags(flags); !!flags; })
-
-#define        local_irq_save(flags)                   \
-do {                                           \
-       typecheck(unsigned long, flags);        \
-       local_save_flags(flags);                \
-       local_irq_disable();                    \
-} while(0)
-
-#define        local_irq_restore(flags)                                        \
-do {                                                                   \
-       typecheck(unsigned long, flags);                                \
-                                                                       \
-       /* load the Z flag by turning 1 if disabled into 0 if disabled  \
-        * and thus setting the Z flag but not the C flag */            \
-       asm volatile("  xoricc  %0,#1,gr0,icc2          \n"             \
-                    /* then test Z=0 and C=0 */                        \
-                    "  tihi    icc2,gr0,#2             \n"             \
-                    :                                                  \
-                    : "r"(flags)                                       \
-                    : "memory", "icc2"                                 \
-                    );                                                 \
-                                                                       \
-} while(0)
-
-/*
- * real interrupt flag manipulation
- */
-#define __local_irq_disable()                          \
-do {                                                   \
-       unsigned long psr;                              \
-       asm volatile("  movsg   psr,%0          \n"     \
-                    "  andi    %0,%2,%0        \n"     \
-                    "  ori     %0,%1,%0        \n"     \
-                    "  movgs   %0,psr          \n"     \
-                    : "=r"(psr)                        \
-                    : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
-                    : "memory");                       \
-} while(0)
-
-#define __local_irq_enable()                           \
-do {                                                   \
-       unsigned long psr;                              \
-       asm volatile("  movsg   psr,%0          \n"     \
-                    "  andi    %0,%1,%0        \n"     \
-                    "  movgs   %0,psr          \n"     \
-                    : "=r"(psr)                        \
-                    : "i" (~PSR_PIL)                   \
-                    : "memory");                       \
-} while(0)
-
-#define __local_save_flags(flags)              \
-do {                                           \
-       typecheck(unsigned long, flags);        \
-       asm("movsg psr,%0"                      \
-           : "=r"(flags)                       \
-           :                                   \
-           : "memory");                        \
-} while(0)
-
-#define        __local_irq_save(flags)                         \
-do {                                                   \
-       unsigned long npsr;                             \
-       typecheck(unsigned long, flags);                \
-       asm volatile("  movsg   psr,%0          \n"     \
-                    "  andi    %0,%3,%1        \n"     \
-                    "  ori     %1,%2,%1        \n"     \
-                    "  movgs   %1,psr          \n"     \
-                    : "=r"(flags), "=r"(npsr)          \
-                    : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
-                    : "memory");                       \
-} while(0)
-
-#define        __local_irq_restore(flags)                      \
-do {                                                   \
-       typecheck(unsigned long, flags);                \
-       asm volatile("  movgs   %0,psr          \n"     \
-                    :                                  \
-                    : "r" (flags)                      \
-                    : "memory");                       \
-} while(0)
-
-#define __irqs_disabled() \
-       ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
-
 /*
  * Force strict CPU ordering.
  */
index 0974c0ecc594817ee9d8067aeba0eee7e3379dbf..bab01298b58ee2873fd7ef85de9230ac7af354f7 100644 (file)
@@ -121,6 +121,9 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
        struct user_context *user = current->thread.user;
        unsigned long tbr, psr;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        tbr = user->i.tbr;
        psr = user->i.psr;
        if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context)))
@@ -250,6 +253,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
        struct sigframe __user *frame;
        int rsig;
 
+       set_fs(USER_DS);
+
        frame = get_sigframe(ka, sizeof(*frame));
 
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -293,22 +298,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
                                   (unsigned long) (frame->retcode + 2));
        }
 
-       /* set up registers for signal handler */
-       __frame->sp   = (unsigned long) frame;
-       __frame->lr   = (unsigned long) &frame->retcode;
-       __frame->gr8  = sig;
-
+       /* Set up registers for the signal handler */
        if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
-               __get_user(__frame->pc, &funcptr->text);
-               __get_user(__frame->gr15, &funcptr->GOT);
+               struct fdpic_func_descriptor desc;
+               if (copy_from_user(&desc, funcptr, sizeof(desc)))
+                       goto give_sigsegv;
+               __frame->pc = desc.text;
+               __frame->gr15 = desc.GOT;
        } else {
                __frame->pc   = (unsigned long) ka->sa.sa_handler;
                __frame->gr15 = 0;
        }
 
-       set_fs(USER_DS);
+       __frame->sp   = (unsigned long) frame;
+       __frame->lr   = (unsigned long) &frame->retcode;
+       __frame->gr8  = sig;
 
        /* the tracer may want to single-step inside the handler */
        if (test_thread_flag(TIF_SINGLESTEP))
@@ -323,7 +329,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
        return 0;
 
 give_sigsegv:
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 
 } /* end setup_frame() */
@@ -338,6 +344,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        struct rt_sigframe __user *frame;
        int rsig;
 
+       set_fs(USER_DS);
+
        frame = get_sigframe(ka, sizeof(*frame));
 
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -392,22 +400,23 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        }
 
        /* Set up registers for signal handler */
-       __frame->sp  = (unsigned long) frame;
-       __frame->lr   = (unsigned long) &frame->retcode;
-       __frame->gr8 = sig;
-       __frame->gr9 = (unsigned long) &frame->info;
-
        if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
-               __get_user(__frame->pc, &funcptr->text);
-               __get_user(__frame->gr15, &funcptr->GOT);
+               struct fdpic_func_descriptor desc;
+               if (copy_from_user(&desc, funcptr, sizeof(desc)))
+                       goto give_sigsegv;
+               __frame->pc = desc.text;
+               __frame->gr15 = desc.GOT;
        } else {
                __frame->pc   = (unsigned long) ka->sa.sa_handler;
                __frame->gr15 = 0;
        }
 
-       set_fs(USER_DS);
+       __frame->sp  = (unsigned long) frame;
+       __frame->lr  = (unsigned long) &frame->retcode;
+       __frame->gr8 = sig;
+       __frame->gr9 = (unsigned long) &frame->info;
 
        /* the tracer may want to single-step inside the handler */
        if (test_thread_flag(TIF_SINGLESTEP))
@@ -422,7 +431,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return 0;
 
 give_sigsegv:
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 
 } /* end setup_rt_frame() */
@@ -437,7 +446,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        int ret;
 
        /* Are we from a system call? */
-       if (in_syscall(__frame)) {
+       if (__frame->syscallno != -1) {
                /* If so, check system call restarting.. */
                switch (__frame->gr8) {
                case -ERESTART_RESTARTBLOCK:
@@ -456,6 +465,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
                        __frame->gr8 = __frame->orig_gr8;
                        __frame->pc -= 4;
                }
+               __frame->syscallno = -1;
        }
 
        /* Set up the stack frame */
@@ -538,10 +548,11 @@ no_signal:
                        break;
 
                case -ERESTART_RESTARTBLOCK:
-                       __frame->gr8 = __NR_restart_syscall;
+                       __frame->gr7 = __NR_restart_syscall;
                        __frame->pc -= 4;
                        break;
                }
+               __frame->syscallno = -1;
        }
 
        /* if there's no signal to deliver, we just put the saved sigmask
index f4709756d0d9da2046c89fb12d5af54aa032492f..4ff2fb1e6b1694848eb688700e8be330a41a9c51 100644 (file)
@@ -5,4 +5,4 @@
 lib-y := \
        __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
        checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
-       outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_event.o
+       outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
index e936804b7508758112b853bfca42f9992ebadb44..984221abb66d3d470483f0f14a7271ef944dce21 100644 (file)
@@ -18,7 +18,8 @@
 
 static __inline__ int atomic_add_return(int i, atomic_t *v)
 {
-       int ret,flags;
+       unsigned long flags;
+       int ret;
        local_irq_save(flags);
        ret = v->counter += i;
        local_irq_restore(flags);
@@ -30,7 +31,8 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
 
 static __inline__ int atomic_sub_return(int i, atomic_t *v)
 {
-       int ret,flags;
+       unsigned long flags;
+       int ret;
        local_irq_save(flags);
        ret = v->counter -= i;
        local_irq_restore(flags);
@@ -42,7 +44,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
 
 static __inline__ int atomic_inc_return(atomic_t *v)
 {
-       int ret,flags;
+       unsigned long flags;
+       int ret;
        local_irq_save(flags);
        v->counter++;
        ret = v->counter;
@@ -64,7 +67,8 @@ static __inline__ int atomic_inc_return(atomic_t *v)
 
 static __inline__ int atomic_dec_return(atomic_t *v)
 {
-       int ret,flags;
+       unsigned long flags;
+       int ret;
        local_irq_save(flags);
        --v->counter;
        ret = v->counter;
@@ -76,7 +80,8 @@ static __inline__ int atomic_dec_return(atomic_t *v)
 
 static __inline__ int atomic_dec_and_test(atomic_t *v)
 {
-       int ret,flags;
+       unsigned long flags;
+       int ret;
        local_irq_save(flags);
        --v->counter;
        ret = v->counter;
diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..9617cd5
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _H8300_IRQFLAGS_H
+#define _H8300_IRQFLAGS_H
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile ("stc ccr,%w0" : "=r" (flags));
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile ("orc  #0x80,ccr" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile ("andc #0x7f,ccr" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & 0x80) == 0x80;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _H8300_IRQFLAGS_H */
index d98d97685f068da986c8639bd29953d94a8ceb8d..2c2382e50d934b23dd28f4a2a6c4e7e01ce06f10 100644 (file)
@@ -2,6 +2,9 @@
 #define _H8300_SYSTEM_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+struct pt_regs;
 
 /*
  * switch_to(n) should switch tasks to task ptr, first checking that
@@ -49,31 +52,8 @@ asmlinkage void resume(void);
   (last) = _last;                                          \
 }
 
-#define __sti() asm volatile ("andc #0x7f,ccr")
-#define __cli() asm volatile ("orc  #0x80,ccr")
-
-#define __save_flags(x) \
-       asm volatile ("stc ccr,%w0":"=r" (x))
-
-#define __restore_flags(x) \
-       asm volatile ("ldc %w0,ccr": :"r" (x))
-
-#define        irqs_disabled()                 \
-({                                     \
-       unsigned char flags;            \
-       __save_flags(flags);            \
-       ((flags & 0x80) == 0x80);       \
-})
-
 #define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
 
-/* For spinlocks etc */
-#define local_irq_disable()    __cli()
-#define local_irq_enable()      __sti()
-#define local_irq_save(x)      ({ __save_flags(x); local_irq_disable(); })
-#define local_irq_restore(x)   __restore_flags(x)
-#define local_save_flags(x)     __save_flags(x)
-
 /*
  * Force strict CPU ordering.
  * Not really required on H8...
@@ -155,6 +135,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 
 #define arch_align_stack(x) (x)
 
-void die(char *str, struct pt_regs *fp, unsigned long err);
+extern void die(const char *str, struct pt_regs *fp, unsigned long err);
 
 #endif /* _H8300_SYSTEM_H */
index 0865e291c20d2948c95edc70f52925121409599d..db4953dc4e1b445adbdd7e004a68890a5c1c07a6 100644 (file)
@@ -112,10 +112,9 @@ int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
 {
-       return module_bug_finalize(hdr, sechdrs, me);
+       return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-       module_bug_cleanup(mod);
 }
index dc1ac0243b78d0532640c55517753cdbdeacc8f0..aaf5e5a48f93167c2513a00e56155b166ee631b8 100644 (file)
@@ -56,8 +56,8 @@ int kernel_execve(const char *filename,
                  const char *const envp[])
 {
        register long res __asm__("er0");
-       register char *const *_c __asm__("er3") = envp;
-       register char *const *_b __asm__("er2") = argv;
+       register const char *const *_c __asm__("er3") = envp;
+       register const char *const *_b __asm__("er2") = argv;
        register const char * _a __asm__("er1") = filename;
        __asm__ __volatile__ ("mov.l %1,er0\n\t"
                        "trapa  #0\n\t"
index 3c0b66bc669eca40ced007cccb5d2ce5d6695904..dfa05bd908b6b22139c388ebbe983721c39b6100 100644 (file)
@@ -96,7 +96,7 @@ static void dump(struct pt_regs *fp)
        printk("\n\n");
 }
 
-void die(char *str, struct pt_regs *fp, unsigned long err)
+void die(const char *str, struct pt_regs *fp, unsigned long err)
 {
        static int diecount;
 
index ba22849ee3ec1c268f201553658a5f5931f38fc3..7c82fa1fc911fe44c7beef2d36af4a0240ce35ab 100644 (file)
@@ -53,6 +53,9 @@ config MMU
        bool
        default y
 
+config ARCH_DMA_ADDR_T_64BIT
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
@@ -62,6 +65,9 @@ config NEED_SG_DMA_LENGTH
 config SWIOTLB
        bool
 
+config STACKTRACE_SUPPORT
+       def_bool y
+
 config GENERIC_LOCKBREAK
        def_bool n
 
@@ -683,8 +689,10 @@ source "lib/Kconfig"
 # Use the generic interrupt handling code in kernel/irq/:
 #
 config GENERIC_HARDIRQS
-       bool
-       default y
+       def_bool y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
 
 config GENERIC_IRQ_PROBE
        bool
index 2bef5261d96dce13c983758a68f0e280041bdaa5..1e8d71ad93ef6ecd57bbfcc918067e6998b443d7 100644 (file)
@@ -149,7 +149,7 @@ static  void receive_chars(struct tty_struct *tty)
                                                ch = ia64_ssc(0, 0, 0, 0,
                                                              SSC_GETCHAR);
                                        while (!ch);
-                                       handle_sysrq(ch, NULL);
+                                       handle_sysrq(ch);
                                }
 #endif
                                seen_esc = 0;
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
deleted file mode 100644 (file)
index f90edc8..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-#ifndef _ASM_IA64_COMPAT_H
-#define _ASM_IA64_COMPAT_H
-/*
- * Architecture specific compatibility types
- */
-#include <linux/types.h>
-
-#define COMPAT_USER_HZ         100
-#define COMPAT_UTS_MACHINE     "i686\0\0\0"
-
-typedef u32            compat_size_t;
-typedef s32            compat_ssize_t;
-typedef s32            compat_time_t;
-typedef s32            compat_clock_t;
-typedef s32            compat_key_t;
-typedef s32            compat_pid_t;
-typedef u16            __compat_uid_t;
-typedef u16            __compat_gid_t;
-typedef u32            __compat_uid32_t;
-typedef u32            __compat_gid32_t;
-typedef u16            compat_mode_t;
-typedef u32            compat_ino_t;
-typedef u16            compat_dev_t;
-typedef s32            compat_off_t;
-typedef s64            compat_loff_t;
-typedef u16            compat_nlink_t;
-typedef u16            compat_ipc_pid_t;
-typedef s32            compat_daddr_t;
-typedef u32            compat_caddr_t;
-typedef __kernel_fsid_t        compat_fsid_t;
-typedef s32            compat_timer_t;
-
-typedef s32            compat_int_t;
-typedef s32            compat_long_t;
-typedef s64 __attribute__((aligned(4))) compat_s64;
-typedef u32            compat_uint_t;
-typedef u32            compat_ulong_t;
-typedef u64 __attribute__((aligned(4))) compat_u64;
-
-struct compat_timespec {
-       compat_time_t   tv_sec;
-       s32             tv_nsec;
-};
-
-struct compat_timeval {
-       compat_time_t   tv_sec;
-       s32             tv_usec;
-};
-
-struct compat_stat {
-       compat_dev_t    st_dev;
-       u16             __pad1;
-       compat_ino_t    st_ino;
-       compat_mode_t   st_mode;
-       compat_nlink_t  st_nlink;
-       __compat_uid_t  st_uid;
-       __compat_gid_t  st_gid;
-       compat_dev_t    st_rdev;
-       u16             __pad2;
-       u32             st_size;
-       u32             st_blksize;
-       u32             st_blocks;
-       u32             st_atime;
-       u32             st_atime_nsec;
-       u32             st_mtime;
-       u32             st_mtime_nsec;
-       u32             st_ctime;
-       u32             st_ctime_nsec;
-       u32             __unused4;
-       u32             __unused5;
-};
-
-struct compat_flock {
-       short           l_type;
-       short           l_whence;
-       compat_off_t    l_start;
-       compat_off_t    l_len;
-       compat_pid_t    l_pid;
-};
-
-#define F_GETLK64      12
-#define F_SETLK64      13
-#define F_SETLKW64     14
-
-/*
- * IA32 uses 4 byte alignment for 64 bit quantities,
- * so we need to pack this structure.
- */
-struct compat_flock64 {
-       short           l_type;
-       short           l_whence;
-       compat_loff_t   l_start;
-       compat_loff_t   l_len;
-       compat_pid_t    l_pid;
-} __attribute__((packed));
-
-struct compat_statfs {
-       int             f_type;
-       int             f_bsize;
-       int             f_blocks;
-       int             f_bfree;
-       int             f_bavail;
-       int             f_files;
-       int             f_ffree;
-       compat_fsid_t   f_fsid;
-       int             f_namelen;      /* SunOS ignores this field. */
-       int             f_frsize;
-       int             f_spare[5];
-};
-
-#define COMPAT_RLIM_OLD_INFINITY       0x7fffffff
-#define COMPAT_RLIM_INFINITY           0xffffffff
-
-typedef u32            compat_old_sigset_t;    /* at least 32 bits */
-
-#define _COMPAT_NSIG           64
-#define _COMPAT_NSIG_BPW       32
-
-typedef u32            compat_sigset_word;
-
-#define COMPAT_OFF_T_MAX       0x7fffffff
-#define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
-
-struct compat_ipc64_perm {
-       compat_key_t key;
-       __compat_uid32_t uid;
-       __compat_gid32_t gid;
-       __compat_uid32_t cuid;
-       __compat_gid32_t cgid;
-       unsigned short mode;
-       unsigned short __pad1;
-       unsigned short seq;
-       unsigned short __pad2;
-       compat_ulong_t unused1;
-       compat_ulong_t unused2;
-};
-
-struct compat_semid64_ds {
-       struct compat_ipc64_perm sem_perm;
-       compat_time_t  sem_otime;
-       compat_ulong_t __unused1;
-       compat_time_t  sem_ctime;
-       compat_ulong_t __unused2;
-       compat_ulong_t sem_nsems;
-       compat_ulong_t __unused3;
-       compat_ulong_t __unused4;
-};
-
-struct compat_msqid64_ds {
-       struct compat_ipc64_perm msg_perm;
-       compat_time_t  msg_stime;
-       compat_ulong_t __unused1;
-       compat_time_t  msg_rtime;
-       compat_ulong_t __unused2;
-       compat_time_t  msg_ctime;
-       compat_ulong_t __unused3;
-       compat_ulong_t msg_cbytes;
-       compat_ulong_t msg_qnum;
-       compat_ulong_t msg_qbytes;
-       compat_pid_t   msg_lspid;
-       compat_pid_t   msg_lrpid;
-       compat_ulong_t __unused4;
-       compat_ulong_t __unused5;
-};
-
-struct compat_shmid64_ds {
-       struct compat_ipc64_perm shm_perm;
-       compat_size_t  shm_segsz;
-       compat_time_t  shm_atime;
-       compat_ulong_t __unused1;
-       compat_time_t  shm_dtime;
-       compat_ulong_t __unused2;
-       compat_time_t  shm_ctime;
-       compat_ulong_t __unused3;
-       compat_pid_t   shm_cpid;
-       compat_pid_t   shm_lpid;
-       compat_ulong_t shm_nattch;
-       compat_ulong_t __unused4;
-       compat_ulong_t __unused5;
-};
-
-/*
- * A pointer passed in from user mode. This should not be used for syscall parameters,
- * just declare them as pointers because the syscall entry code will have appropriately
- * converted them already.
- */
-typedef        u32             compat_uptr_t;
-
-static inline void __user *
-compat_ptr (compat_uptr_t uptr)
-{
-       return (void __user *) (unsigned long) uptr;
-}
-
-static inline compat_uptr_t
-ptr_to_compat(void __user *uptr)
-{
-       return (u32)(unsigned long)uptr;
-}
-
-static __inline__ void __user *
-compat_alloc_user_space (long len)
-{
-       struct pt_regs *regs = task_pt_regs(current);
-       return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
-}
-
-#endif /* _ASM_IA64_COMPAT_H */
index d514cd9edb49f45c9ac5871d407ec7ff65b0927e..8fb7d33a661f9e6de23ec01be699e4300ad4f363 100644 (file)
@@ -6,12 +6,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-#include <asm/processor.h>
-
 /*
  * No irq_cpustat_t for IA-64.  The data is held in the per-CPU data structure.
  */
 
 #define local_softirq_pending()                (local_cpu_data->softirq_pending)
 
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+#include <asm/processor.h>
+
 extern void __iomem *ipi_base_addr;
 
 void ack_bad_irq(unsigned int irq);
diff --git a/arch/ia64/include/asm/iommu_table.h b/arch/ia64/include/asm/iommu_table.h
new file mode 100644 (file)
index 0000000..92c8d36
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_IOMMU_TABLE_H
+#define _ASM_IA64_IOMMU_TABLE_H
+
+#define IOMMU_INIT_POST(_detect)
+
+#endif /* _ASM_IA64_IOMMU_TABLE_H */
diff --git a/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..f82d6be
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * IRQ flags defines.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+#ifndef _ASM_IA64_IRQFLAGS_H
+#define _ASM_IA64_IRQFLAGS_H
+
+#ifdef CONFIG_IA64_DEBUG_IRQ
+extern unsigned long last_cli_ip;
+static inline void arch_maybe_save_ip(unsigned long flags)
+{
+       if (flags & IA64_PSR_I)
+               last_cli_ip = ia64_getreg(_IA64_REG_IP);
+}
+#else
+#define arch_maybe_save_ip(flags) do {} while (0)
+#endif
+
+/*
+ * - clearing psr.i is implicitly serialized (visible by next insn)
+ * - setting psr.i requires data serialization
+ * - we need a stop-bit before reading PSR because we sometimes
+ *   write a floating-point register right before reading the PSR
+ *   and that writes to PSR.mfl
+ */
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       ia64_stop();
+#ifdef CONFIG_PARAVIRT
+       return ia64_get_psr_i();
+#else
+       return ia64_getreg(_IA64_REG_PSR);
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+
+       ia64_stop();
+       ia64_rsm(IA64_PSR_I);
+       arch_maybe_save_ip(flags);
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+       arch_local_irq_save();
+#else
+       ia64_stop();
+       ia64_rsm(IA64_PSR_I);
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       ia64_stop();
+       ia64_ssm(IA64_PSR_I);
+       ia64_srlz_d();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+       unsigned long old_psr = arch_local_save_flags();
+#endif
+       ia64_intrin_local_irq_restore(flags & IA64_PSR_I);
+       arch_maybe_save_ip(old_psr & ~flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & IA64_PSR_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline void arch_safe_halt(void)
+{
+       ia64_pal_halt_light();  /* PAL_HALT_LIGHT */
+}
+
+
+#endif /* _ASM_IA64_IRQFLAGS_H */
index 9f342a574ce8c669310b6857b5b1ac7152f8bae0..6cca30705d50196e767049fcfc7d9768b850d342 100644 (file)
@@ -107,87 +107,11 @@ extern struct ia64_boot_param {
  */
 #define set_mb(var, value)     do { (var) = (value); mb(); } while (0)
 
-#define safe_halt()         ia64_pal_halt_light()    /* PAL_HALT_LIGHT */
-
 /*
  * The group barrier in front of the rsm & ssm are necessary to ensure
  * that none of the previous instructions in the same group are
  * affected by the rsm/ssm.
  */
-/* For spinlocks etc */
-
-/*
- * - clearing psr.i is implicitly serialized (visible by next insn)
- * - setting psr.i requires data serialization
- * - we need a stop-bit before reading PSR because we sometimes
- *   write a floating-point register right before reading the PSR
- *   and that writes to PSR.mfl
- */
-#ifdef CONFIG_PARAVIRT
-#define __local_save_flags()   ia64_get_psr_i()
-#else
-#define __local_save_flags()   ia64_getreg(_IA64_REG_PSR)
-#endif
-
-#define __local_irq_save(x)                    \
-do {                                           \
-       ia64_stop();                            \
-       (x) = __local_save_flags();             \
-       ia64_stop();                            \
-       ia64_rsm(IA64_PSR_I);                   \
-} while (0)
-
-#define __local_irq_disable()                  \
-do {                                           \
-       ia64_stop();                            \
-       ia64_rsm(IA64_PSR_I);                   \
-} while (0)
-
-#define __local_irq_restore(x) ia64_intrin_local_irq_restore((x) & IA64_PSR_I)
-
-#ifdef CONFIG_IA64_DEBUG_IRQ
-
-  extern unsigned long last_cli_ip;
-
-# define __save_ip()           last_cli_ip = ia64_getreg(_IA64_REG_IP)
-
-# define local_irq_save(x)                                     \
-do {                                                           \
-       unsigned long __psr;                                    \
-                                                               \
-       __local_irq_save(__psr);                                \
-       if (__psr & IA64_PSR_I)                                 \
-               __save_ip();                                    \
-       (x) = __psr;                                            \
-} while (0)
-
-# define local_irq_disable()   do { unsigned long __x; local_irq_save(__x); } while (0)
-
-# define local_irq_restore(x)                                  \
-do {                                                           \
-       unsigned long __old_psr, __psr = (x);                   \
-                                                               \
-       local_save_flags(__old_psr);                            \
-       __local_irq_restore(__psr);                             \
-       if ((__old_psr & IA64_PSR_I) && !(__psr & IA64_PSR_I))  \
-               __save_ip();                                    \
-} while (0)
-
-#else /* !CONFIG_IA64_DEBUG_IRQ */
-# define local_irq_save(x)     __local_irq_save(x)
-# define local_irq_disable()   __local_irq_disable()
-# define local_irq_restore(x)  __local_irq_restore(x)
-#endif /* !CONFIG_IA64_DEBUG_IRQ */
-
-#define local_irq_enable()     ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
-#define local_save_flags(flags)        ({ ia64_stop(); (flags) = __local_save_flags(); })
-
-#define irqs_disabled()                                \
-({                                             \
-       unsigned long __ia64_id_flags;          \
-       local_save_flags(__ia64_id_flags);      \
-       (__ia64_id_flags & IA64_PSR_I) == 0;    \
-})
 
 #ifdef __KERNEL__
 
@@ -272,10 +196,6 @@ void cpu_idle_wait(void);
 
 void default_idle(void);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
index db10b1e378b0470ec52828a19e78da43e26d31db..395c2f216dd899ddb6871db79b3f45e4f041d442 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_AUDIT)           += audit.o
 obj-$(CONFIG_PCI_MSI)          += msi_ia64.o
 mca_recovery-y                 += mca_drv.o mca_drv_asm.o
 obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
+obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 
 obj-$(CONFIG_PARAVIRT)         += paravirt.o paravirtentry.o \
                                   paravirt_patch.o
index 71e35864d2e251a48630472071f5c9ae76af39e0..d52f1f78eff2ab01b126cc5ef35e2039400fddaf 100644 (file)
@@ -59,13 +59,13 @@ int __init init_cyclone_clock(void)
                return -ENODEV;
        }
        base = readq(reg);
+       iounmap(reg);
        if(!base){
                printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
                                " value.\n");
                use_cyclone = 0;
                return -ENODEV;
        }
-       iounmap(reg);
 
        /* setup PMCC */
        offset = (base + CYCLONE_PMCC_OFFSET);
index 3567d54f8cee7533ecba41847c5f9957d9481296..331d42bda77ae97f457b13f970aa83c40e11d4b0 100644 (file)
@@ -420,22 +420,31 @@ EX(.fail_efault, ld8 r14=[r33])                   // r14 <- *set
        ;;
 
        RSM_PSR_I(p0, r18, r19)                 // mask interrupt delivery
-       mov ar.ccv=0
        andcm r14=r14,r17                       // filter out SIGKILL & SIGSTOP
+       mov r8=EINVAL                   // default to EINVAL
 
 #ifdef CONFIG_SMP
-       mov r17=1
+       // __ticket_spin_trylock(r31)
+       ld4 r17=[r31]
        ;;
-       cmpxchg4.acq r18=[r31],r17,ar.ccv       // try to acquire the lock
-       mov r8=EINVAL                   // default to EINVAL
+       mov.m ar.ccv=r17
+       extr.u r9=r17,17,15
+       adds r19=1,r17
+       extr.u r18=r17,0,15
+       ;;
+       cmp.eq p6,p7=r9,r18
        ;;
+(p6)   cmpxchg4.acq r9=[r31],r19,ar.ccv
+(p6)   dep.z r20=r19,1,15              // next serving ticket for unlock
+(p7)   br.cond.spnt.many .lock_contention
+       ;;
+       cmp4.eq p0,p7=r9,r17
+       adds r31=2,r31
+(p7)   br.cond.spnt.many .lock_contention
        ld8 r3=[r2]                     // re-read current->blocked now that we hold the lock
-       cmp4.ne p6,p0=r18,r0
-(p6)   br.cond.spnt.many .lock_contention
        ;;
 #else
        ld8 r3=[r2]                     // re-read current->blocked now that we hold the lock
-       mov r8=EINVAL                   // default to EINVAL
 #endif
        add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16
        add r19=IA64_TASK_SIGNAL_OFFSET,r16
@@ -490,7 +499,9 @@ EX(.fail_efault, ld8 r14=[r33])                     // r14 <- *set
 (p6)   br.cond.spnt.few 1b                     // yes -> retry
 
 #ifdef CONFIG_SMP
-       st4.rel [r31]=r0                        // release the lock
+       // __ticket_spin_unlock(r31)
+       st2.rel [r31]=r20
+       mov r20=0                                       // i must not leak kernel bits...
 #endif
        SSM_PSR_I(p0, p9, r31)
        ;;
@@ -512,7 +523,8 @@ EX(.fail_efault, (p15) st8 [r34]=r3)
 
 .sig_pending:
 #ifdef CONFIG_SMP
-       st4.rel [r31]=r0                        // release the lock
+       // __ticket_spin_unlock(r31)
+       st2.rel [r31]=r20                       // release the lock
 #endif
        SSM_PSR_I(p0, p9, r17)
        ;;
index 7ded76658d2da69075bb0c748d73c8159beda9dd..22c38404f539eeb9ab268ca226db94d1e243e860 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#define NR_PREALLOCATE_RTE_ENTRIES \
-       (PAGE_SIZE / sizeof(struct iosapic_rte_info))
-#define RTE_PREALLOCATED       (1)
-
 static DEFINE_SPINLOCK(iosapic_lock);
 
 /*
@@ -136,7 +132,6 @@ struct iosapic_rte_info {
        struct list_head rte_list;      /* RTEs sharing the same vector */
        char            rte_index;      /* IOSAPIC RTE index */
        int             refcnt;         /* reference counter */
-       unsigned int    flags;          /* flags */
        struct iosapic  *iosapic;
 } ____cacheline_aligned;
 
@@ -155,9 +150,6 @@ static struct iosapic_intr_info {
 
 static unsigned char pcat_compat __devinitdata;        /* 8259 compatibility flag */
 
-static int iosapic_kmalloc_ok;
-static LIST_HEAD(free_rte_list);
-
 static inline void
 iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
 {
@@ -394,7 +386,7 @@ iosapic_startup_level_irq (unsigned int irq)
 }
 
 static void
-iosapic_end_level_irq (unsigned int irq)
+iosapic_unmask_level_irq (unsigned int irq)
 {
        ia64_vector vec = irq_to_vector(irq);
        struct iosapic_rte_info *rte;
@@ -404,7 +396,8 @@ iosapic_end_level_irq (unsigned int irq)
        if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
                do_unmask_irq = 1;
                mask_irq(irq);
-       }
+       } else
+               unmask_irq(irq);
 
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
                iosapic_eoi(rte->iosapic->addr, vec);
@@ -427,9 +420,8 @@ static struct irq_chip irq_type_iosapic_level = {
        .enable =       iosapic_enable_level_irq,
        .disable =      iosapic_disable_level_irq,
        .ack =          iosapic_ack_level_irq,
-       .end =          iosapic_end_level_irq,
        .mask =         mask_irq,
-       .unmask =       unmask_irq,
+       .unmask =       iosapic_unmask_level_irq,
        .set_affinity = iosapic_set_affinity
 };
 
@@ -552,37 +544,6 @@ iosapic_reassign_vector (int irq)
        }
 }
 
-static struct iosapic_rte_info * __init_refok iosapic_alloc_rte (void)
-{
-       int i;
-       struct iosapic_rte_info *rte;
-       int preallocated = 0;
-
-       if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
-               rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
-                                   NR_PREALLOCATE_RTE_ENTRIES);
-               for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
-                       list_add(&rte->rte_list, &free_rte_list);
-       }
-
-       if (!list_empty(&free_rte_list)) {
-               rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
-                                rte_list);
-               list_del(&rte->rte_list);
-               preallocated++;
-       } else {
-               rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
-               if (!rte)
-                       return NULL;
-       }
-
-       memset(rte, 0, sizeof(struct iosapic_rte_info));
-       if (preallocated)
-               rte->flags |= RTE_PREALLOCATED;
-
-       return rte;
-}
-
 static inline int irq_is_shared (int irq)
 {
        return (iosapic_intr_info[irq].count > 1);
@@ -615,7 +576,7 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
 
        rte = find_rte(irq, gsi);
        if (!rte) {
-               rte = iosapic_alloc_rte();
+               rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
                if (!rte) {
                        printk(KERN_WARNING "%s: cannot allocate memory\n",
                               __func__);
@@ -658,6 +619,10 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
                               idesc->chip->name, irq_type->name);
                idesc->chip = irq_type;
        }
+       if (trigger == IOSAPIC_EDGE)
+               __set_irq_handler_unlocked(irq, handle_edge_irq);
+       else
+               __set_irq_handler_unlocked(irq, handle_level_irq);
        return 0;
 }
 
@@ -1161,10 +1126,3 @@ map_iosapic_to_node(unsigned int gsi_base, int node)
        return;
 }
 #endif
-
-static int __init iosapic_enable_kmalloc (void)
-{
-       iosapic_kmalloc_ok = 1;
-       return 0;
-}
-core_initcall (iosapic_enable_kmalloc);
index f14c35f9b03a469cc8ef19e84283cf9d7071b90d..9a26015c3e50027d7cb88981881971feb3d88bc0 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/ratelimit.h>
+#include <linux/acpi.h>
 
 #include <asm/delay.h>
 #include <asm/intrinsics.h>
@@ -635,6 +636,7 @@ ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
        desc->chip = &irq_type_ia64_lsapic;
        if (action)
                setup_irq(irq, action);
+       set_irq_handler(irq, handle_percpu_irq);
 }
 
 void __init
@@ -650,6 +652,9 @@ ia64_native_register_ipi(void)
 void __init
 init_IRQ (void)
 {
+#ifdef CONFIG_ACPI
+       acpi_boot_init();
+#endif
        ia64_register_ipi();
        register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
index a0220dc5ff421effdc55e130aad53a6af39ba348..1753f6a30d55e6d66c5e3198a9b271601c89a39e 100644 (file)
@@ -2055,25 +2055,6 @@ ia64_mca_init(void)
 
        IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __func__);
 
-       /*
-        *  Configure the CMCI/P vector and handler. Interrupts for CMC are
-        *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
-        */
-       register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
-       register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
-       ia64_mca_cmc_vector_setup();       /* Setup vector on BSP */
-
-       /* Setup the MCA rendezvous interrupt vector */
-       register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
-
-       /* Setup the MCA wakeup interrupt vector */
-       register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-
-#ifdef CONFIG_ACPI
-       /* Setup the CPEI/P handler */
-       register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-#endif
-
        /* Initialize the areas set aside by the OS to buffer the
         * platform/processor error states for MCA/INIT/CMC
         * handling.
@@ -2103,6 +2084,25 @@ ia64_mca_late_init(void)
        if (!mca_init)
                return 0;
 
+       /*
+        *  Configure the CMCI/P vector and handler. Interrupts for CMC are
+        *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
+        */
+       register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+       register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
+       ia64_mca_cmc_vector_setup();       /* Setup vector on BSP */
+
+       /* Setup the MCA rendezvous interrupt vector */
+       register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
+
+       /* Setup the MCA wakeup interrupt vector */
+       register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
+
+#ifdef CONFIG_ACPI
+       /* Setup the CPEI/P handler */
+       register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+#endif
+
        register_hotcpu_notifier(&mca_cpu_notifier);
 
        /* Setup the CMCI/P vector and handler */
index 4a746ea838ff37b423f92f31a8eecc8207f6217a..00b19a416eab5b1fc6db10bb366c37c048f8c7c2 100644 (file)
@@ -104,8 +104,8 @@ static int ia64_msi_retrigger_irq(unsigned int irq)
  */
 static struct irq_chip ia64_msi_chip = {
        .name           = "PCI-MSI",
-       .mask           = mask_msi_irq,
-       .unmask         = unmask_msi_irq,
+       .irq_mask       = mask_msi_irq,
+       .irq_unmask     = unmask_msi_irq,
        .ack            = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = ia64_set_msi_irq_affinity,
@@ -160,8 +160,8 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 
 static struct irq_chip dmar_msi_type = {
        .name = "DMAR_MSI",
-       .unmask = dmar_msi_unmask,
-       .mask = dmar_msi_mask,
+       .irq_unmask = dmar_msi_unmask,
+       .irq_mask = dmar_msi_mask,
        .ack = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
        .set_affinity = dmar_msi_set_affinity,
index fdf6f9d013e5b3f8b5ed3145543ca9ac34b8180a..77597e5ea60aca9429f29c26ec7973bf89a19683 100644 (file)
@@ -434,7 +434,7 @@ register_info(char *page)
        unsigned long phys_stacked;
        pal_hints_u_t hints;
        unsigned long iregs, dregs;
-       char *info_type[]={
+       static const char * const info_type[] = {
                "Implemented AR(s)",
                "AR(s) with read side-effects",
                "Implemented CR(s)",
index cce050e85c73558040fe7c4970e3beb69d7ee2a1..6b1852f7f972b80fcccc06ba0214acc321cd84e5 100644 (file)
@@ -1573,7 +1573,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
                return -EINVAL;
        }
 
-       ctx = (pfm_context_t *)filp->private_data;
+       ctx = filp->private_data;
        if (ctx == NULL) {
                printk(KERN_ERR "perfmon: pfm_read: NULL ctx [%d]\n", task_pid_nr(current));
                return -EINVAL;
@@ -1673,7 +1673,7 @@ pfm_poll(struct file *filp, poll_table * wait)
                return 0;
        }
 
-       ctx = (pfm_context_t *)filp->private_data;
+       ctx = filp->private_data;
        if (ctx == NULL) {
                printk(KERN_ERR "perfmon: pfm_poll: NULL ctx [%d]\n", task_pid_nr(current));
                return 0;
@@ -1733,7 +1733,7 @@ pfm_fasync(int fd, struct file *filp, int on)
                return -EBADF;
        }
 
-       ctx = (pfm_context_t *)filp->private_data;
+       ctx = filp->private_data;
        if (ctx == NULL) {
                printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", task_pid_nr(current));
                return -EBADF;
@@ -1841,7 +1841,7 @@ pfm_flush(struct file *filp, fl_owner_t id)
                return -EBADF;
        }
 
-       ctx = (pfm_context_t *)filp->private_data;
+       ctx = filp->private_data;
        if (ctx == NULL) {
                printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", task_pid_nr(current));
                return -EBADF;
@@ -1984,7 +1984,7 @@ pfm_close(struct inode *inode, struct file *filp)
                return -EBADF;
        }
        
-       ctx = (pfm_context_t *)filp->private_data;
+       ctx = filp->private_data;
        if (ctx == NULL) {
                printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", task_pid_nr(current));
                return -EBADF;
@@ -4907,7 +4907,7 @@ restart_args:
                goto error_args;
        }
 
-       ctx = (pfm_context_t *)file->private_data;
+       ctx = file->private_data;
        if (unlikely(ctx == NULL)) {
                DPRINT(("no context for fd %d\n", fd));
                goto error_args;
index aa8b5fa1a8dec906c19b7ce99d6f721f60bb025b..79802e540e538d52defaea3f3a4cea903d9b0cce 100644 (file)
@@ -354,6 +354,7 @@ retry:
 static const struct file_operations salinfo_event_fops = {
        .open  = salinfo_event_open,
        .read  = salinfo_event_read,
+       .llseek = noop_llseek,
 };
 
 static int
@@ -571,6 +572,7 @@ static const struct file_operations salinfo_data_fops = {
        .release = salinfo_log_release,
        .read    = salinfo_log_read,
        .write   = salinfo_log_write,
+       .llseek  = default_llseek,
 };
 
 static int __cpuinit
@@ -642,7 +644,7 @@ salinfo_init(void)
        for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
                data = salinfo_data + i;
                data->type = i;
-               init_MUTEX(&data->mutex);
+               sema_init(&data->mutex, 1);
                dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
                if (!dir)
                        continue;
index 8fb958abf8d008e95259f209d4caf7e53420b009..911cf974970008c6e01a92c36c2d1233ece62f8a 100644 (file)
@@ -594,10 +594,6 @@ setup_arch (char **cmdline_p)
        cpu_init();     /* initialize the bootstrap CPU */
        mmu_context_init();     /* initialize context_id bitmap */
 
-#ifdef CONFIG_ACPI
-       acpi_boot_init();
-#endif
-
        paravirt_banner();
        paravirt_arch_setup_console(cmdline_p);
 
diff --git a/arch/ia64/kernel/stacktrace.c b/arch/ia64/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..5af2783
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * arch/ia64/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+
+static void
+ia64_do_save_stack(struct unw_frame_info *info, void *arg)
+{
+       struct stack_trace *trace = arg;
+       unsigned long ip;
+       int skip = trace->skip;
+
+       trace->nr_entries = 0;
+       do {
+               unw_get_ip(info, &ip);
+               if (ip == 0)
+                       break;
+               if (skip == 0) {
+                       trace->entries[trace->nr_entries++] = ip;
+                       if (trace->nr_entries == trace->max_entries)
+                               break;
+               } else
+                       skip--;
+       } while (unw_unwind(info) >= 0);
+}
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+       unw_init_running(ia64_do_save_stack, trace);
+}
+EXPORT_SYMBOL(save_stack_trace);
index b6c0e63a0bf61535386fff325adaf5f3e40e2932..fed6afa2e8a9014e65229e51e64fa4b1c13cc284 100644 (file)
@@ -1204,10 +1204,10 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#      define hashmagic        0x9e3779b97f4a7c16UL    /* based on (sqrt(5)/2-1)*2^64 */
+       /* magic number = ((sqrt(5)-1)/2)*2^64 */
+       static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL;
 
-       return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
-#undef hashmagic
+       return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE);
 }
 
 static inline long
@@ -1531,7 +1531,7 @@ build_script (struct unw_frame_info *info)
        struct unw_labeled_state *ls, *next;
        unsigned long ip = info->ip;
        struct unw_state_record sr;
-       struct unw_table *table;
+       struct unw_table *table, *prev;
        struct unw_reg_info *r;
        struct unw_insn insn;
        u8 *dp, *desc_end;
@@ -1560,11 +1560,26 @@ build_script (struct unw_frame_info *info)
 
        STAT(parse_start = ia64_get_itc());
 
+       prev = NULL;
        for (table = unw.tables; table; table = table->next) {
                if (ip >= table->start && ip < table->end) {
+                       /*
+                        * Leave the kernel unwind table at the very front,
+                        * lest moving it breaks some assumption elsewhere.
+                        * Otherwise, move the matching table to the second
+                        * position in the list so that traversals can benefit
+                        * from commonality in backtrace paths.
+                        */
+                       if (prev && prev != unw.tables) {
+                               /* unw is safe - we're already spinlocked */
+                               prev->next = table->next;
+                               table->next = unw.tables->next;
+                               unw.tables->next = table;
+                       }
                        e = lookup(table, ip - table->segment_base);
                        break;
                }
+               prev = table;
        }
        if (!e) {
                /* no info, return default unwinder (leaf proc, no mem stack, no saved regs)  */
index 0c72dd4638314523eeb8a71b6204826fc9777303..a5e500f02853003604979a9b1c8c7fe1f25e0b4c 100644 (file)
@@ -228,8 +228,8 @@ static int sn_msi_retrigger_irq(unsigned int irq)
 
 static struct irq_chip sn_msi_chip = {
        .name           = "PCI-MSI",
-       .mask           = mask_msi_irq,
-       .unmask         = unmask_msi_irq,
+       .irq_mask       = mask_msi_irq,
+       .irq_unmask     = unmask_msi_irq,
        .ack            = sn_ack_msi_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = sn_set_msi_irq_affinity,
index fa1eceed0d23addfffb6674061a7ca6504317446..30862c0358cd7a3644f9dd204e203bb2d7efa239 100644 (file)
@@ -860,6 +860,7 @@ error:
 
 static const struct file_operations sn_hwperf_fops = {
        .unlocked_ioctl = sn_hwperf_ioctl,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice sn_hwperf_dev = {
index 8adc6a14272abb990a104017eba40bf88aa2ebd0..3e8d350fdf39bf6bcdfaf314dd0cd5c9b0a0c4a9 100644 (file)
@@ -1136,7 +1136,6 @@ __initconst = {
 static void __init
 xen_patch_branch(unsigned long tag, unsigned long type)
 {
-       const unsigned long nelem =
-               sizeof(xen_branch_target) / sizeof(xen_branch_target[0]);
-       __paravirt_patch_apply_branch(tag, type, xen_branch_target, nelem);
+       __paravirt_patch_apply_branch(tag, type, xen_branch_target,
+                                       ARRAY_SIZE(xen_branch_target));
 }
index 2f85412ef7302a0aedaf1b5e26f63719c69dc033..b8da7d0574d20635f489315ea8caf957d063be08 100644 (file)
@@ -82,9 +82,9 @@ typedef elf_fpreg_t elf_fpregset_t;
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS      ELFCLASS32
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN__)
 #define ELF_DATA       ELFDATA2LSB
-#elif defined(__BIG_ENDIAN)
+#elif defined(__BIG_ENDIAN__)
 #define ELF_DATA       ELFDATA2MSB
 #else
 #error no endian defined
diff --git a/arch/m32r/include/asm/irqflags.h b/arch/m32r/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..1f92d29
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#ifndef _ASM_M32R_IRQFLAGS_H
+#define _ASM_M32R_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("mvfc %0,psw" : "=r"(flags));
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+       asm volatile (
+               "clrpsw #0x40 -> nop"
+               : : : "memory");
+#else
+       unsigned long tmpreg0, tmpreg1;
+       asm volatile (
+               "ld24   %0, #0  ; Use 32-bit insn.                      \n\t"
+               "mvfc   %1, psw ; No interrupt can be accepted here.    \n\t"
+               "mvtc   %0, psw                                         \n\t"
+               "and3   %0, %1, #0xffbf                                 \n\t"
+               "mvtc   %0, psw                                         \n\t"
+               : "=&r" (tmpreg0), "=&r" (tmpreg1)
+               :
+               : "cbit", "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+       asm volatile (
+               "setpsw #0x40 -> nop"
+               : : : "memory");
+#else
+       unsigned long tmpreg;
+       asm volatile (
+               "mvfc   %0, psw;                \n\t"
+               "or3    %0, %0, #0x0040;        \n\t"
+               "mvtc   %0, psw;                \n\t"
+               : "=&r" (tmpreg)
+               :
+               : "cbit", "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
+       asm volatile (
+               "mvfc   %0, psw;        \n\t"
+               "clrpsw #0x40 -> nop;   \n\t"
+               : "=r" (flags)
+               :
+               : "memory");
+#else
+       unsigned long tmpreg;
+       asm volatile (
+               "ld24   %1, #0          \n\t"
+               "mvfc   %0, psw         \n\t"
+               "mvtc   %1, psw         \n\t"
+               "and3   %1, %0, #0xffbf \n\t"
+               "mvtc   %1, psw         \n\t"
+               : "=r" (flags), "=&r" (tmpreg)
+               :
+               : "cbit", "memory");
+#endif
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("mvtc %0,psw"
+                    :
+                    : "r" (flags)
+                    : "cbit", "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & 0x40);
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _ASM_M32R_IRQFLAGS_H */
index 9c1acb2b1a928984c8f62ce4a5cd91a25329dc21..b2eeb0de1c8d337a6d7ab5abef363b4797ab7e9a 100644 (file)
@@ -157,7 +157,6 @@ typedef struct sigaltstack {
 #undef __HAVE_ARCH_SIG_BITOPS
 
 struct pt_regs;
-extern int do_signal(struct pt_regs *regs, sigset_t *oldset);
 
 #define ptrace_signal_deliver(regs, cookie)    do { } while (0)
 
index c980f5ba8de7dc01a2c34e7f64e42b84d0b6a744..13c46794ccb1aa3954b837ce7b652966730aa62e 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <asm/assembler.h>
 
 #ifdef __KERNEL__
        ); \
 } while(0)
 
-/* Interrupt Control */
-#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
-#define local_irq_enable() \
-       __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
-#define local_irq_disable() \
-       __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
-#else  /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-static inline void local_irq_enable(void)
-{
-       unsigned long tmpreg;
-       __asm__ __volatile__(
-               "mvfc   %0, psw;                \n\t"
-               "or3    %0, %0, #0x0040;        \n\t"
-               "mvtc   %0, psw;                \n\t"
-       : "=&r" (tmpreg) : : "cbit", "memory");
-}
-
-static inline void local_irq_disable(void)
-{
-       unsigned long tmpreg0, tmpreg1;
-       __asm__ __volatile__(
-               "ld24   %0, #0  ; Use 32-bit insn. \n\t"
-               "mvfc   %1, psw ; No interrupt can be accepted here. \n\t"
-               "mvtc   %0, psw \n\t"
-               "and3   %0, %1, #0xffbf \n\t"
-               "mvtc   %0, psw \n\t"
-       : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
-}
-#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define local_save_flags(x) \
-       __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
-
-#define local_irq_restore(x) \
-       __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
-               : "r" (x) : "cbit", "memory")
-
-#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
-#define local_irq_save(x)                              \
-       __asm__ __volatile__(                           \
-               "mvfc   %0, psw;                \n\t"   \
-               "clrpsw #0x40 -> nop;           \n\t"   \
-               : "=r" (x) : /* no input */ : "memory")
-#else  /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-#define local_irq_save(x)                              \
-       ({                                              \
-               unsigned long tmpreg;                   \
-               __asm__ __volatile__(                   \
-                       "ld24   %1, #0 \n\t"            \
-                       "mvfc   %0, psw \n\t"           \
-                       "mvtc   %1, psw \n\t"           \
-                       "and3   %1, %0, #0xffbf \n\t"   \
-                       "mvtc   %1, psw \n\t"           \
-                       : "=r" (x), "=&r" (tmpreg)      \
-                       : : "cbit", "memory");          \
-       })
-#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define irqs_disabled()                                        \
-       ({                                              \
-               unsigned long flags;                    \
-               local_save_flags(flags);                \
-               !(flags & 0x40);                        \
-       })
-
 #define nop()  __asm__ __volatile__ ("nop" : : )
 
 #define xchg(ptr, x)                                                   \
index 76125777483ccda07d9d31d55c2f8f3b3201ea05..c70545689da83ef2ffaef987b2c3374fadca04fc 100644 (file)
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 #define __IGNORE_lchown
 #define __IGNORE_setuid
diff --git a/arch/m32r/kernel/.gitignore b/arch/m32r/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index 403869833b98fe6c95fd360d80cd762f3a5008e2..225412bc227e690bcb313743dd16f58fca5c4115 100644 (file)
@@ -235,10 +235,9 @@ work_resched:
 work_notifysig:                                ; deal with pending signals and
                                        ; notify-resume requests
        mv      r0, sp                  ; arg1 : struct pt_regs *regs
-       ldi     r1, #0                  ; arg2 : sigset_t *oldset
-       mv      r2, r9                  ; arg3 : __u32 thread_info_flags
+       mv      r1, r9                  ; arg2 : __u32 thread_info_flags
        bl      do_notify_resume
-       bra     restore_all
+       bra     resume_userspace
 
        ; perform syscall exit tracing
        ALIGN
index 3c71f776872c51842a7959a911182b3c4afa3353..7db26f1f082d097f24ffa51da083694e05f47a5a 100644 (file)
@@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p, void *v)
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
 
                for (action=action->next; action; action = action->next)
index e555091eb97cbcf8bbe261851be3b72e90e6075e..0021ade4cba8c86bf1d2fd348b283d8cac591955 100644 (file)
@@ -592,16 +592,17 @@ void user_enable_single_step(struct task_struct *child)
 
        if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
            != sizeof(insn))
-               break;
+               return -EIO;
 
        compute_next_pc(insn, pc, &next_pc, child);
        if (next_pc & 0x80000000)
-               break;
+               return -EIO;
 
        if (embed_debug_trap(child, next_pc))
-               break;
+               return -EIO;
 
        invalidate_cache();
+       return 0;
 }
 
 void user_disable_single_step(struct task_struct *child)
index 144b0f124fc72f08b20f93336f96da81327fe61c..a08697f0886d7988b012fa727c777d8bbed7b3fb 100644 (file)
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-int do_signal(struct pt_regs *, sigset_t *);
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-                 unsigned long r2, unsigned long r3, unsigned long r4,
-                 unsigned long r5, unsigned long r6, struct pt_regs *regs)
-{
-       sigset_t newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
-}
-
 asmlinkage int
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                unsigned long r2, unsigned long r3, unsigned long r4,
@@ -218,7 +189,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        return (void __user *)((sp - frame_size) & -8ul);
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame;
@@ -275,22 +246,34 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                current->comm, current->pid, frame, regs->pc);
 #endif
 
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
+}
+
+static int prev_insn(struct pt_regs *regs)
+{
+       u16 inst;
+       if (get_user(inst, (u16 __user *)(regs->bpc - 2)))
+               return -EFAULT;
+       if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
+               regs->bpc -= 2;
+       else
+               regs->bpc -= 4;
+       regs->syscall_nr = -1;
+       return 0;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              sigset_t *oldset, struct pt_regs *regs)
 {
-       unsigned short inst;
-
        /* Are we from a system call? */
        if (regs->syscall_nr >= 0) {
                /* If so, check system call restarting.. */
@@ -308,16 +291,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                        /* fallthrough */
                        case -ERESTARTNOINTR:
                                regs->r0 = regs->orig_r0;
-                               inst = *(unsigned short *)(regs->bpc - 2);
-                               if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
-                                       regs->bpc -= 2;
-                               else
-                                       regs->bpc -= 4;
+                               if (prev_insn(regs) < 0)
+                                       return -EFAULT;
                }
        }
 
        /* Set up the stack frame */
-       setup_rt_frame(sig, ka, info, oldset, regs);
+       if (setup_rt_frame(sig, ka, info, oldset, regs))
+               return -EFAULT;
 
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -325,6 +306,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                sigaddset(&current->blocked,sig);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
+       return 0;
 }
 
 /*
@@ -332,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       unsigned short inst;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -346,12 +328,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
        if (try_to_freeze()) 
                goto no_signal;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -363,8 +347,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                 */
 
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &ka, &info, oldset, regs);
-               return 1;
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+               return;
        }
 
  no_signal:
@@ -375,31 +361,24 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                    regs->r0 == -ERESTARTSYS ||
                    regs->r0 == -ERESTARTNOINTR) {
                        regs->r0 = regs->orig_r0;
-                       inst = *(unsigned short *)(regs->bpc - 2);
-                       if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
-                               regs->bpc -= 2;
-                       else
-                               regs->bpc -= 4;
-               }
-               if (regs->r0 == -ERESTART_RESTARTBLOCK){
+                       prev_insn(regs);
+               } else if (regs->r0 == -ERESTART_RESTARTBLOCK){
                        regs->r0 = regs->orig_r0;
                        regs->r7 = __NR_restart_syscall;
-                       inst = *(unsigned short *)(regs->bpc - 2);
-                       if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
-                               regs->bpc -= 2;
-                       else
-                               regs->bpc -= 4;
+                       prev_insn(regs);
                }
        }
-       return 0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
 }
 
 /*
  * notification of userspace execution resumption
  * - triggered by current->work.notify_resume
  */
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
-                     __u32 thread_info_flags)
+void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
 {
        /* Pending single-step? */
        if (thread_info_flags & _TIF_SINGLESTEP)
@@ -407,7 +386,7 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
 
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal(regs,oldset);
+               do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
index 922fdfdadeaa220830d52a99f97a1cbe22e7ebd1..402a59d7219b6f368b38b4c9425ed79fa4279539 100644 (file)
@@ -65,7 +65,7 @@ static void shutdown_m32104ut_irq(unsigned int irq)
 
 static struct irq_chip m32104ut_irq_type =
 {
-       .typename = "M32104UT-IRQ",
+       .name = "M32104UT-IRQ",
        .startup = startup_m32104ut_irq,
        .shutdown = shutdown_m32104ut_irq,
        .enable = enable_m32104ut_irq,
index 9c1bc7487c1e652ff6bd9cb77ea79c5cdb989caf..80b1a026795aec2b8c8dae642143b4f5424538da 100644 (file)
@@ -71,7 +71,7 @@ static void shutdown_m32700ut_irq(unsigned int irq)
 
 static struct irq_chip m32700ut_irq_type =
 {
-       .typename = "M32700UT-IRQ",
+       .name = "M32700UT-IRQ",
        .startup = startup_m32700ut_irq,
        .shutdown = shutdown_m32700ut_irq,
        .enable = enable_m32700ut_irq,
@@ -148,7 +148,7 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-       .typename = "M32700UT-PLD-IRQ",
+       .name = "M32700UT-PLD-IRQ",
        .startup = startup_m32700ut_pld_irq,
        .shutdown = shutdown_m32700ut_pld_irq,
        .enable = enable_m32700ut_pld_irq,
@@ -217,7 +217,7 @@ static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
 
 static struct irq_chip m32700ut_lanpld_irq_type =
 {
-       .typename = "M32700UT-PLD-LAN-IRQ",
+       .name = "M32700UT-PLD-LAN-IRQ",
        .startup = startup_m32700ut_lanpld_irq,
        .shutdown = shutdown_m32700ut_lanpld_irq,
        .enable = enable_m32700ut_lanpld_irq,
@@ -286,7 +286,7 @@ static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
 
 static struct irq_chip m32700ut_lcdpld_irq_type =
 {
-       .typename = "M32700UT-PLD-LCD-IRQ",
+       .name = "M32700UT-PLD-LCD-IRQ",
        .startup = startup_m32700ut_lcdpld_irq,
        .shutdown = shutdown_m32700ut_lcdpld_irq,
        .enable = enable_m32700ut_lcdpld_irq,
index fb4b17799b66fd090b04f4d02364044f5558123d..ea00c84d6b1b2bb665bf0e88cf8ed885b2f96385 100644 (file)
@@ -65,7 +65,7 @@ static void shutdown_mappi_irq(unsigned int irq)
 
 static struct irq_chip mappi_irq_type =
 {
-       .typename = "MAPPI-IRQ",
+       .name = "MAPPI-IRQ",
        .startup = startup_mappi_irq,
        .shutdown = shutdown_mappi_irq,
        .enable = enable_mappi_irq,
index 6a65eda0a056c67ef039a34cc5d0326251be14d5..c049376d0270064869450bb56948a4edd57c068e 100644 (file)
@@ -72,7 +72,7 @@ static void shutdown_mappi2_irq(unsigned int irq)
 
 static struct irq_chip mappi2_irq_type =
 {
-       .typename = "MAPPI2-IRQ",
+       .name = "MAPPI2-IRQ",
        .startup = startup_mappi2_irq,
        .shutdown = shutdown_mappi2_irq,
        .enable = enable_mappi2_irq,
index 9c337aeac94b7db1a1d3d0f9307ef2116e15c687..882de25c6e8cc7d8f6bc9a55ef9a4c422fefcab2 100644 (file)
@@ -72,7 +72,7 @@ static void shutdown_mappi3_irq(unsigned int irq)
 
 static struct irq_chip mappi3_irq_type =
 {
-       .typename = "MAPPI3-IRQ",
+       .name = "MAPPI3-IRQ",
        .startup = startup_mappi3_irq,
        .shutdown = shutdown_mappi3_irq,
        .enable = enable_mappi3_irq,
index ed865741c38df1c6d9702e94bb17f033fdcca5c2..d11d93bf74f52bd4b14baea3e6fc3da16d83b271 100644 (file)
@@ -63,7 +63,7 @@ static void shutdown_oaks32r_irq(unsigned int irq)
 
 static struct irq_chip oaks32r_irq_type =
 {
-       .typename = "OAKS32R-IRQ",
+       .name = "OAKS32R-IRQ",
        .startup = startup_oaks32r_irq,
        .shutdown = shutdown_oaks32r_irq,
        .enable = enable_oaks32r_irq,
index 80d68065701963dff6107f6377bb7fc1c3416707..5f3402a2fbafe3c67cd549ac9c7335ff27aa3e1a 100644 (file)
@@ -72,7 +72,7 @@ static void shutdown_opsput_irq(unsigned int irq)
 
 static struct irq_chip opsput_irq_type =
 {
-       .typename = "OPSPUT-IRQ",
+       .name = "OPSPUT-IRQ",
        .startup = startup_opsput_irq,
        .shutdown = shutdown_opsput_irq,
        .enable = enable_opsput_irq,
@@ -149,7 +149,7 @@ static void shutdown_opsput_pld_irq(unsigned int irq)
 
 static struct irq_chip opsput_pld_irq_type =
 {
-       .typename = "OPSPUT-PLD-IRQ",
+       .name = "OPSPUT-PLD-IRQ",
        .startup = startup_opsput_pld_irq,
        .shutdown = shutdown_opsput_pld_irq,
        .enable = enable_opsput_pld_irq,
@@ -218,7 +218,7 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq)
 
 static struct irq_chip opsput_lanpld_irq_type =
 {
-       .typename = "OPSPUT-PLD-LAN-IRQ",
+       .name = "OPSPUT-PLD-LAN-IRQ",
        .startup = startup_opsput_lanpld_irq,
        .shutdown = shutdown_opsput_lanpld_irq,
        .enable = enable_opsput_lanpld_irq,
index 757302660af84f2f09ffbb0e48fcf946ab27cd45..1beac7a51ed432ea386610b8b1bbe3132e04d6b7 100644 (file)
@@ -63,7 +63,7 @@ static void shutdown_mappi_irq(unsigned int irq)
 
 static struct irq_chip mappi_irq_type =
 {
-       .typename = "M32700-IRQ",
+       .name = "M32700-IRQ",
        .startup = startup_mappi_irq,
        .shutdown = shutdown_mappi_irq,
        .enable = enable_mappi_irq,
@@ -136,7 +136,7 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-       .typename = "USRV-PLD-IRQ",
+       .name = "USRV-PLD-IRQ",
        .startup = startup_m32700ut_pld_irq,
        .shutdown = shutdown_m32700ut_pld_irq,
        .enable = enable_m32700ut_pld_irq,
index cb8617bb194ba638eed418f27aff8fa61a9e1591..1c4d4c7bf4d4a478c938635fbc698c3c0596d6a1 100644 (file)
@@ -155,6 +155,7 @@ static const struct file_operations rtc_fops = {
        .unlocked_ioctl = rtc_ioctl,
        .open           = rtc_open,
        .release        = rtc_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice rtc_dev = {
index 907ed03d792f04bbf8b1aff2f07afa8534d2e237..80e41492aa2a0750018620d73c1387a36bbe265a 100644 (file)
@@ -28,7 +28,7 @@
  *                     M68K              COLDFIRE
  */
 
-#define ALLOWINT 0xf8ff
+#define ALLOWINT (~0x700)
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/m68k/include/asm/irqflags.h b/arch/m68k/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..4a5b284
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef _M68K_IRQFLAGS_H
+#define _M68K_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <asm/thread_info.h>
+#include <asm/entry.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile ("movew %%sr,%0" : "=d" (flags) : : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_COLDFIRE
+       asm volatile (
+               "move   %/sr,%%d0       \n\t"
+               "ori.l  #0x0700,%%d0    \n\t"
+               "move   %%d0,%/sr       \n"
+               : /* no outputs */
+               :
+               : "cc", "%d0", "memory");
+#else
+       asm volatile ("oriw  #0x0700,%%sr" : : : "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if defined(CONFIG_COLDFIRE)
+       asm volatile (
+               "move   %/sr,%%d0       \n\t"
+               "andi.l #0xf8ff,%%d0    \n\t"
+               "move   %%d0,%/sr       \n"
+               : /* no outputs */
+               :
+               : "cc", "%d0", "memory");
+#else
+# if defined(CONFIG_MMU)
+       if (MACH_IS_Q40 || !hardirq_count())
+# endif
+               asm volatile (
+                       "andiw %0,%%sr"
+                       :
+                       : "i" (ALLOWINT)
+                       : "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile ("movew %0,%%sr" : : "d" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & ~ALLOWINT) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _M68K_IRQFLAGS_H */
index dbb6515ffd5b21f3d4a9e1544d7f6544ea604742..12053c44cccfe38d06ca1b556da85f1720f227dd 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/linkage.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
 
@@ -62,30 +63,6 @@ asmlinkage void resume(void);
 #define smp_wmb()      barrier()
 #define smp_read_barrier_depends()     ((void)0)
 
-/* interrupt control.. */
-#if 0
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#else
-#include <linux/hardirq.h>
-#define local_irq_enable() ({                                                  \
-       if (MACH_IS_Q40 || !hardirq_count())                                    \
-               asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");    \
-})
-#endif
-#define local_irq_disable() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-static inline int irqs_disabled(void)
-{
-       unsigned long flags;
-       local_save_flags(flags);
-       return flags & ~ALLOWINT;
-}
-
-/* For spinlocks etc */
-#define local_irq_save(x)      ({ local_save_flags(x); local_irq_disable(); })
-
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 struct __xchg_dummy { unsigned long a[100]; };
index 3c0718d74398b3b7ce0b29bfb66b3f1895474db8..20126c09794e5f59d7b58a94fcb07eb9a8e2d6f9 100644 (file)
@@ -2,6 +2,7 @@
 #define _M68KNOMMU_SYSTEM_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
 
@@ -46,54 +47,6 @@ asmlinkage void resume(void);
   (last) = _last;                                              \
 }
 
-#ifdef CONFIG_COLDFIRE
-#define local_irq_enable() __asm__ __volatile__ (              \
-       "move %/sr,%%d0\n\t"                                    \
-       "andi.l #0xf8ff,%%d0\n\t"                               \
-       "move %%d0,%/sr\n"                                      \
-       : /* no outputs */                                      \
-       :                                                       \
-        : "cc", "%d0", "memory")
-#define local_irq_disable() __asm__ __volatile__ (             \
-       "move %/sr,%%d0\n\t"                                    \
-       "ori.l #0x0700,%%d0\n\t"                                \
-       "move %%d0,%/sr\n"                                      \
-       : /* no outputs */                                      \
-       :                                                       \
-       : "cc", "%d0", "memory")
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ (               \
-       "movew %%sr,%0\n\t"                                     \
-       "movew #0x0700,%%d0\n\t"                                \
-       "or.l  %0,%%d0\n\t"                                     \
-       "movew %%d0,%/sr"                                       \
-       : "=d" (x)                                              \
-       :                                                       \
-       : "cc", "%d0", "memory")
-#else
-
-/* portable version */ /* FIXME - see entry.h*/
-#define ALLOWINT 0xf8ff
-
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#define local_irq_disable() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
-#endif
-
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-/* For spinlocks etc */
-#ifndef local_irq_save
-#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
-#endif
-
-#define        irqs_disabled()                 \
-({                                     \
-       unsigned long flags;            \
-       local_save_flags(flags);        \
-       ((flags & 0x0700) == 0x0700);   \
-})
-
 #define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
 
 /*
@@ -206,12 +159,4 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 #define arch_align_stack(x) (x)
 
 
-static inline int irqs_disabled_flags(unsigned long flags)
-{
-       if (flags & 0x0700)
-               return 0;
-       else
-               return 1;
-}
-
 #endif /* _M68KNOMMU_SYSTEM_H */
index 60b15d0aa07290bfd2494423ecc4c331c33c3032..b43b36beafe37aed63baf7714a92ba55a7cf2f1c 100644 (file)
 #define __NR_set_thread_area   334
 #define __NR_atomic_cmpxchg_32 335
 #define __NR_atomic_barrier    336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
 
 #ifdef __KERNEL__
 
-#define NR_syscalls            337
+#define NR_syscalls            340
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 2391bdff09962e7a51d36c7842290ea90932ca54..6360c437dcf51c5491e192151b95ce6c1a6923a2 100644 (file)
@@ -765,4 +765,7 @@ sys_call_table:
        .long sys_set_thread_area
        .long sys_atomic_cmpxchg_32     /* 335 */
        .long sys_atomic_barrier
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
 
index 8f0640847ad2bf7bf99d0a184ed10ce8272a84f8..05285d08e54767a71a814773c23a506386f9626a 100644 (file)
@@ -162,7 +162,7 @@ static void mac_init_asc( void )
 void mac_mksound( unsigned int freq, unsigned int length )
 {
        __u32 cfreq = ( freq << 5 ) / 468;
-       __u32 flags;
+       unsigned long flags;
        int i;
 
        if ( mac_special_bell == NULL )
@@ -224,7 +224,7 @@ static void mac_nosound( unsigned long ignored )
  */
 static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
 {
-       __u32 flags;
+       unsigned long flags;
 
        /* if the bell is already ringing, ring longer */
        if ( mac_bell_duration > 0 )
@@ -271,7 +271,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig
 static void mac_quadra_ring_bell( unsigned long ignored )
 {
        int     i, count = mac_asc_samplespersec / HZ;
-       __u32 flags;
+       unsigned long flags;
 
        /*
         * we neither want a sound buffer overflow nor underflow, so we need to match
index 11ac6f63967a24ac134e406d253400f3ff496bb0..39c79ebcd18a9dc52614844d925f1a9f6df3ed61 100644 (file)
@@ -144,6 +144,7 @@ static const struct file_operations rtc_fops = {
        .unlocked_ioctl = rtc_ioctl,
        .open           = rtc_open,
        .release        = rtc_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice rtc_dev=
index 9a8876f715d81d73214c97079d2a601460fe6234..24335022fa2c74893b695d041b330c4810680087 100644 (file)
@@ -74,8 +74,6 @@ int main(void)
 
        DEFINE(PT_PTRACED, PT_PTRACED);
 
-       DEFINE(THREAD_SIZE, THREAD_SIZE);
-
        /* Offsets in thread_info structure */
        DEFINE(TI_TASK, offsetof(struct thread_info, task));
        DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
index b30b3eb197a5d2c157d6e96f8d60de45395d4a21..79b1ed198c070dd40dbb3cf4f03dd6f24b79cb71 100644 (file)
@@ -355,6 +355,9 @@ ENTRY(sys_call_table)
        .long sys_set_thread_area
        .long sys_atomic_cmpxchg_32     /* 335 */
        .long sys_atomic_barrier
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
 
        .rept NR_syscalls-(.-sys_call_table)/4
                .long sys_ni_syscall
index a91b2713451da0e5290a3889e1bcebbb530c0e4b..ef332136f96dababcbba1e574d2143847f7b368c 100644 (file)
@@ -150,6 +150,8 @@ SECTIONS {
                _sdata = . ;
                DATA_DATA
                CACHELINE_ALIGNED_DATA(32)
+               PAGE_ALIGNED_DATA(PAGE_SIZE)
+               *(.data..shared_aligned)
                INIT_TASK_DATA(THREAD_SIZE)
                _edata = . ;
        } > DATA
index 4b91aa24eb00a6ec95510cfd88b210f99b8dcc05..0b2d7c7adf793324c0c0f193b6e3022bd2e6882c 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/coldfire.h>
 #include <asm/mcfcache.h>
 #include <asm/mcfsim.h>
+#include <asm/thread_info.h>
 
 /*****************************************************************************/
 
index 2c38c6d801769be469348fa80f4ef3283aab44e2..5fd31905775d691cb6d4e4fffbb0eeb91ad40013 100644 (file)
 #ifndef _ASM_MICROBLAZE_IRQFLAGS_H
 #define _ASM_MICROBLAZE_IRQFLAGS_H
 
-#include <linux/irqflags.h>
+#include <linux/types.h>
 #include <asm/registers.h>
 
-# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-
-# define raw_local_irq_save(flags)                     \
-       do {                                            \
-               asm volatile (" msrclr %0, %1;          \
-                               nop;"                   \
-                               : "=r"(flags)           \
-                               : "i"(MSR_IE)           \
-                               : "memory");            \
-       } while (0)
-
-# define raw_local_irq_disable()                       \
-       do {                                            \
-               asm volatile (" msrclr r0, %0;          \
-                               nop;"                   \
-                               :                       \
-                               : "i"(MSR_IE)           \
-                               : "memory");            \
-       } while (0)
-
-# define raw_local_irq_enable()                                \
-       do {                                            \
-               asm volatile (" msrset  r0, %0;         \
-                               nop;"                   \
-                               :                       \
-                               : "i"(MSR_IE)           \
-                               : "memory");            \
-       } while (0)
-
-# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
-
-# define raw_local_irq_save(flags)                             \
-       do {                                                    \
-               register unsigned tmp;                          \
-               asm volatile (" mfs     %0, rmsr;               \
-                               nop;                            \
-                               andi    %1, %0, %2;             \
-                               mts     rmsr, %1;               \
-                               nop;"                           \
-                               : "=r"(flags), "=r" (tmp)       \
-                               : "i"(~MSR_IE)                  \
-                               : "memory");                    \
-       } while (0)
-
-# define raw_local_irq_disable()                               \
-       do {                                                    \
-               register unsigned tmp;                          \
-               asm volatile (" mfs     %0, rmsr;               \
-                               nop;                            \
-                               andi    %0, %0, %1;             \
-                               mts     rmsr, %0;               \
-                               nop;"                   \
-                               : "=r"(tmp)                     \
-                               : "i"(~MSR_IE)                  \
-                               : "memory");                    \
-       } while (0)
-
-# define raw_local_irq_enable()                                        \
-       do {                                                    \
-               register unsigned tmp;                          \
-               asm volatile (" mfs     %0, rmsr;               \
-                               nop;                            \
-                               ori     %0, %0, %1;             \
-                               mts     rmsr, %0;               \
-                               nop;"                           \
-                               : "=r"(tmp)                     \
-                               : "i"(MSR_IE)                   \
-                               : "memory");                    \
-       } while (0)
-
-# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
-
-#define raw_local_irq_restore(flags)                           \
-       do {                                                    \
-               asm volatile (" mts     rmsr, %0;               \
-                               nop;"                           \
-                               :                               \
-                               : "r"(flags)                    \
-                               : "memory");                    \
-       } while (0)
-
-static inline unsigned long get_msr(void)
+#ifdef CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       asm volatile("  msrclr %0, %1   \n"
+                    "  nop             \n"
+                    : "=r"(flags)
+                    : "i"(MSR_IE)
+                    : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       /* this uses r0 without declaring it - is that correct? */
+       asm volatile("  msrclr r0, %0   \n"
+                    "  nop             \n"
+                    :
+                    : "i"(MSR_IE)
+                    : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       /* this uses r0 without declaring it - is that correct? */
+       asm volatile("  msrset  r0, %0  \n"
+                    "  nop             \n"
+                    :
+                    : "i"(MSR_IE)
+                    : "memory");
+}
+
+#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags, tmp;
+       asm volatile (" mfs     %0, rmsr        \n"
+                     " nop                     \n"
+                     " andi    %1, %0, %2      \n"
+                     " mts     rmsr, %1        \n"
+                     " nop                     \n"
+                     : "=r"(flags), "=r"(tmp)
+                     : "i"(~MSR_IE)
+                     : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       unsigned long tmp;
+       asm volatile("  mfs     %0, rmsr        \n"
+                    "  nop                     \n"
+                    "  andi    %0, %0, %1      \n"
+                    "  mts     rmsr, %0        \n"
+                    "  nop                     \n"
+                    : "=r"(tmp)
+                    : "i"(~MSR_IE)
+                    : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       unsigned long tmp;
+       asm volatile("  mfs     %0, rmsr        \n"
+                    "  nop                     \n"
+                    "  ori     %0, %0, %1      \n"
+                    "  mts     rmsr, %0        \n"
+                    "  nop                     \n"
+                    : "=r"(tmp)
+                    : "i"(MSR_IE)
+                    : "memory");
+}
+
+#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
-       asm volatile (" mfs     %0, rmsr;       \
-                       nop;"                   \
-                       : "=r"(flags)           \
-                       :                       \
-                       : "memory");            \
+       asm volatile("  mfs     %0, rmsr        \n"
+                    "  nop                     \n"
+                    : "=r"(flags)
+                    :
+                    : "memory");
        return flags;
 }
 
-#define raw_local_save_flags(flags)    ((flags) = get_msr())
-#define raw_irqs_disabled()            ((get_msr() & MSR_IE) == 0)
-#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0)
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("  mts     rmsr, %0        \n"
+                    "  nop                     \n"
+                    :
+                    : "r"(flags)
+                    : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & MSR_IE) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
index f9c2fa331d2ad92e675aad399befb989cc575fbc..20a8e257c77f3c2abadf04c8c87aad2347de4ee6 100644 (file)
@@ -9,9 +9,6 @@
 #ifndef _ASM_MICROBLAZE_MEMBLOCK_H
 #define _ASM_MICROBLAZE_MEMBLOCK_H
 
-/* MEMBLOCK limit is OFF */
-#define MEMBLOCK_REAL_LIMIT    0xFFFFFFFF
-
 #endif /* _ASM_MICROBLAZE_MEMBLOCK_H */
 
 
index 65eb00419d19dc8ac69e98cc2755b9cbc841d405..c8437866d3b75f3bde5d7c5fad00f9d624e9d58e 100644 (file)
@@ -70,16 +70,16 @@ static void __init paging_init(void)
 
 void __init setup_memory(void)
 {
-       int i;
        unsigned long map_size;
+       struct memblock_region *reg;
+
 #ifndef CONFIG_MMU
        u32 kernel_align_start, kernel_align_size;
 
        /* Find main memory where is the kernel */
-       for (i = 0; i < memblock.memory.cnt; i++) {
-               memory_start = (u32) memblock.memory.region[i].base;
-               memory_end = (u32) memblock.memory.region[i].base
-                               + (u32) memblock.memory.region[i].size;
+       for_each_memblock(memory, reg) {
+               memory_start = (u32)reg->base;
+               memory_end = (u32) reg->base + reg->size;
                if ((memory_start <= (u32)_text) &&
                                        ((u32)_text <= memory_end)) {
                        memory_size = memory_end - memory_start;
@@ -142,12 +142,10 @@ void __init setup_memory(void)
        free_bootmem(memory_start, memory_size);
 
        /* reserve allocate blocks */
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               pr_debug("reserved %d - 0x%08x-0x%08x\n", i,
-                       (u32) memblock.reserved.region[i].base,
-                       (u32) memblock_size_bytes(&memblock.reserved, i));
-               reserve_bootmem(memblock.reserved.region[i].base,
-                       memblock_size_bytes(&memblock.reserved, i) - 1, BOOTMEM_DEFAULT);
+       for_each_memblock(reserved, reg) {
+               pr_debug("reserved - 0x%08x-0x%08x\n",
+                        (u32) reg->base, (u32) reg->size);
+               reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
        }
 #ifdef CONFIG_MMU
        init_bootmem_done = 1;
@@ -230,7 +228,7 @@ static void mm_cmdline_setup(void)
                if (maxmem && memory_size > maxmem) {
                        memory_size = maxmem;
                        memory_end = memory_start + memory_size;
-                       memblock.memory.region[0].size = memory_size;
+                       memblock.memory.regions[0].size = memory_size;
                }
        }
 }
@@ -273,14 +271,14 @@ asmlinkage void __init mmu_init(void)
                machine_restart(NULL);
        }
 
-       if ((u32) memblock.memory.region[0].size < 0x1000000) {
+       if ((u32) memblock.memory.regions[0].size < 0x1000000) {
                printk(KERN_EMERG "Memory must be greater than 16MB\n");
                machine_restart(NULL);
        }
        /* Find main memory where the kernel is */
-       memory_start = (u32) memblock.memory.region[0].base;
-       memory_end = (u32) memblock.memory.region[0].base +
-                               (u32) memblock.memory.region[0].size;
+       memory_start = (u32) memblock.memory.regions[0].base;
+       memory_end = (u32) memblock.memory.regions[0].base +
+                               (u32) memblock.memory.regions[0].size;
        memory_size = memory_end - memory_start;
 
        mm_cmdline_setup(); /* FIXME parse args from command line - not used */
index e322d65f33a41e0085e5d352410ca0b5c3f37e26..7dd65cfae83759562e43ab20bb03be071ae56ce5 100644 (file)
@@ -7,6 +7,10 @@ subdir-ccflags-y := -Werror
 include arch/mips/Kbuild.platforms
 obj-y := $(platform-y)
 
+# make clean traverses $(obj-) without having included .config, so
+# everything ends up here
+obj- := $(platform-)
+
 # mips object files
 # The object files are linked as core-y files would be linked
 
index 3ad59dde485209bce858c425e4fc8a2f64b04c09..4c9f402295dd3d9b11548ab47d26853761df62f1 100644 (file)
@@ -13,6 +13,7 @@ config MIPS
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select RTC_LIB if !MACH_LOONGSON
+       select GENERIC_ATOMIC64 if !64BIT
 
 mainmenu "Linux/MIPS Kernel Configuration"
 
@@ -880,11 +881,15 @@ config NO_IOPORT
 config GENERIC_ISA_DMA
        bool
        select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
+       select ISA_DMA_API
 
 config GENERIC_ISA_DMA_SUPPORT_BROKEN
        bool
        select GENERIC_ISA_DMA
 
+config ISA_DMA_API
+       bool
+
 config GENERIC_GPIO
        bool
 
@@ -1646,8 +1651,16 @@ config MIPS_MT_SMP
        select SYS_SUPPORTS_SMP
        select SMP_UP
        help
-         This is a kernel model which is also known a VSMP or lately
-         has been marketesed into SMVP.
+         This is a kernel model which is known a VSMP but lately has been
+         marketesed into SMVP.
+         Virtual SMP uses the processor's VPEs  to implement virtual
+         processors. In currently available configuration of the 34K processor
+         this allows for a dual processor. Both processors will share the same
+         primary caches; each will obtain the half of the TLB for it's own
+         exclusive use. For a layman this model can be described as similar to
+         what Intel calls Hyperthreading.
+
+         For further information see http://www.linux-mips.org/wiki/34K#VSMP
 
 config MIPS_MT_SMTC
        bool "SMTC: Use all TCs on all VPEs for SMP"
@@ -1664,6 +1677,14 @@ config MIPS_MT_SMTC
        help
          This is a kernel model which is known a SMTC or lately has been
          marketesed into SMVP.
+         is presenting the available TC's of the core as processors to Linux.
+         On currently available 34K processors this means a Linux system will
+         see up to 5 processors. The implementation of the SMTC kernel differs
+         significantly from VSMP and cannot efficiently coexist in the same
+         kernel binary so the choice between VSMP and SMTC is a compile time
+         decision.
+
+         For further information see http://www.linux-mips.org/wiki/34K#SMTC
 
 endchoice
 
index c29511b11d44fd6732b0dd153d009dbd7051555d..5340210596297fa54c8723e866aebaeb8c20269e 100644 (file)
@@ -43,7 +43,7 @@ int prom_argc;
 char **prom_argv;
 char **prom_envp;
 
-void prom_init_cmdline(void)
+void __init prom_init_cmdline(void)
 {
        int i;
 
@@ -104,7 +104,7 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
        }
 }
 
-int prom_get_ethernet_addr(char *ethernet_addr)
+int __init prom_get_ethernet_addr(char *ethernet_addr)
 {
        char *ethaddr_str;
 
@@ -123,7 +123,6 @@ int prom_get_ethernet_addr(char *ethernet_addr)
 
        return 0;
 }
-EXPORT_SYMBOL(prom_get_ethernet_addr);
 
 void __init prom_free_prom_memory(void)
 {
index 3bc4fd2155d70303a439f2004a6407ec92888b6e..c52af8821da071f5fe49117ddb6f7f2652756c00 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 #include <asm/mach-db1x00/bcsr.h>
index c781556c44e46cea3c51a84d149e1b3d68f6c8b8..4ec2642c568fb18ce58c6eb277f58b7fb55772d9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
index a0c5cd18c192a4aef91634b58ca851576cd2b4c6..3be87f2422f0357ddd16411c4fa0d406dc21cbe1 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <bcm63xx_cpu.h>
index ed9bb709c9a3816a4738d0ceef91db8c8de20cd4..5042d51b0512a087b02b85853aad2d2b38d9d7d6 100644 (file)
@@ -59,7 +59,7 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
 hostprogs-y := calc_vmlinuz_load_addr
 
 VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
-               $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS))
+               $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
 
 vmlinuzobjs-y += $(obj)/piggy.o
 
@@ -105,4 +105,4 @@ OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec
 vmlinuz.srec: vmlinuz
        $(call cmd,objcopy)
 
-clean-files := $(objtree)/vmlinuz.*
+clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec}
index 094c17e38e163ab691b71bef78710f73848c7645..47323ca452dcbde751536c58c9f613dd1d9d51c8 100644 (file)
@@ -83,3 +83,7 @@ config ARCH_SPARSEMEM_ENABLE
        def_bool y
        select SPARSEMEM_STATIC
        depends on CPU_CAVIUM_OCTEON
+
+config CAVIUM_OCTEON_HELPER
+       def_bool y
+       depends on OCTEON_ETHERNET || PCI
index c664c8cc2b42cb8970b9f57531a03e2998075566..a5b427909b5cac04d28c4da1b099342ee72df4ce 100644 (file)
@@ -41,7 +41,7 @@ static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
        return NOTIFY_OK;               /* Let default notifier send signals */
 }
 
-static int cnmips_cu2_setup(void)
+static int __init cnmips_cu2_setup(void)
 {
        return cu2_notifier(cnmips_cu2_call, 0);
 }
index 2fd66db6939e0f981c338015127c69788d960843..7f41c5be2190ddca03fc92a00e8f21bd735414f5 100644 (file)
@@ -11,4 +11,4 @@
 
 obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
 
-obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o
+obj-$(CONFIG_CAVIUM_OCTEON_HELPER) += cvmx-helper-errata.o cvmx-helper-jtag.o
index 638adab028428002186bb83c589b553a0c40545b..12dbf533b77dc2da263c4e0bfe9e4c2fa86c51d8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/tty.h>
+#include <linux/irq.h>
 
 #include <asm/time.h>
 
index 3adbcbd95db1efd4dbb18fba91bc978153079d7f..cf55a6f4e720c4e831733ceab40d820fa136a2c8 100644 (file)
@@ -1,7 +1,7 @@
 #
 # DECstation family
 #
-platform-$(CONFIG_MACH_DECSTATION)     = dec/
+platform-$(CONFIG_MACH_DECSTATION)     += dec/
 cflags-$(CONFIG_MACH_DECSTATION)       += \
                        -I$(srctree)/arch/mips/include/asm/mach-dec
 libs-$(CONFIG_MACH_DECSTATION)         += arch/mips/dec/prom/
index bd5431e1f4085fbfbcd2dfadc5097395828a4fae..fa45e924be05b9e40cf9d23b5a6a866034dfb8f3 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/pm.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
index c63c56bfd18461b558e0cba7380d6297fc47115e..47d87da379f947c8a578f2a2b84e7da804f559a8 100644 (file)
@@ -782,6 +782,10 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
  */
 #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
 
+#else /* !CONFIG_64BIT */
+
+#include <asm-generic/atomic64.h>
+
 #endif /* CONFIG_64BIT */
 
 /*
index 613f6912dfc1d024b2aa6b28fb4215ba8b251552..dbc51065df5b3fe53611ff15e9cc259188ff0dbc 100644 (file)
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = (struct pt_regs *)
                ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
index 2cb2f0c2c4f89342ae5256a79d8082f01af4d319..3532e2c5f098ae46a4a79f7455cd004d699dd4a9 100644 (file)
@@ -24,7 +24,7 @@ extern int cu2_notifier_call_chain(unsigned long val, void *v);
 
 #define cu2_notifier(fn, pri)                                          \
 ({                                                                     \
-       static struct notifier_block fn##_nb __cpuinitdata = {          \
+       static struct notifier_block fn##_nb = {                        \
                .notifier_call = fn,                                    \
                .priority = pri                                         \
        };                                                              \
index e482fe90fe8850609ed05f79d4caa9423e31031a..75eddedcfc3ee31a5ba500089fb92215311f51eb 100644 (file)
@@ -56,6 +56,7 @@
  */
 
 #ifdef CONFIG_32BIT
+#include <linux/types.h>
 
 struct flock {
        short   l_type;
index 9b9436a4d816bfe7f26a1eb8a7e7cb677507c388..86548da650e765f79db345f4d3964a5d0eb6c0fe 100644 (file)
@@ -321,6 +321,7 @@ struct gic_intrmask_regs {
  */
 struct gic_intr_map {
        unsigned int cpunum;    /* Directed to this CPU */
+#define GIC_UNUSED             0xdead                  /* Dummy data */
        unsigned int pin;       /* Directed to this Pin */
        unsigned int polarity;  /* Polarity : +/-       */
        unsigned int trigtype;  /* Trigger  : Edge/Levl */
index 701ec0ba8fa9cdd596369b9de3825b284bae1ec9..9ef3b0d178962e92cf4ac27efc77f564b50667df 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/hazards.h>
 
 __asm__(
-       "       .macro  raw_local_irq_enable                            \n"
+       "       .macro  arch_local_irq_enable                           \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
@@ -40,7 +40,7 @@ __asm__(
 
 extern void smtc_ipi_replay(void);
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
        /*
@@ -50,7 +50,7 @@ static inline void raw_local_irq_enable(void)
        smtc_ipi_replay();
 #endif
        __asm__ __volatile__(
-               "raw_local_irq_enable"
+               "arch_local_irq_enable"
                : /* no outputs */
                : /* no inputs */
                : "memory");
@@ -76,7 +76,7 @@ static inline void raw_local_irq_enable(void)
  * Workaround: mask EXL bit of the result or place a nop before mfc0.
  */
 __asm__(
-       "       .macro  raw_local_irq_disable\n"
+       "       .macro  arch_local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -97,17 +97,17 @@ __asm__(
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
        __asm__ __volatile__(
-               "raw_local_irq_disable"
+               "arch_local_irq_disable"
                : /* no outputs */
                : /* no inputs */
                : "memory");
 }
 
 __asm__(
-       "       .macro  raw_local_save_flags flags                      \n"
+       "       .macro  arch_local_save_flags flags                     \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -118,13 +118,15 @@ __asm__(
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-#define raw_local_save_flags(x)                                                \
-__asm__ __volatile__(                                                  \
-       "raw_local_save_flags %0"                                       \
-       : "=r" (x))
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_save_flags %0" : "=r" (flags));
+       return flags;
+}
 
 __asm__(
-       "       .macro  raw_local_irq_save result                       \n"
+       "       .macro  arch_local_irq_save result                      \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
@@ -148,15 +150,18 @@ __asm__(
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-#define raw_local_irq_save(x)                                          \
-__asm__ __volatile__(                                                  \
-       "raw_local_irq_save\t%0"                                        \
-       : "=r" (x)                                                      \
-       : /* no inputs */                                               \
-       : "memory")
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_irq_save\t%0"
+                    : "=r" (flags)
+                    : /* no inputs */
+                    : "memory");
+       return flags;
+}
 
 __asm__(
-       "       .macro  raw_local_irq_restore flags                     \n"
+       "       .macro  arch_local_irq_restore flags                    \n"
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
@@ -196,7 +201,7 @@ __asm__(
        "       .endm                                                   \n");
 
 
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
@@ -211,24 +216,24 @@ static inline void raw_local_irq_restore(unsigned long flags)
 #endif
 
        __asm__ __volatile__(
-               "raw_local_irq_restore\t%0"
+               "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
                : "0" (flags)
                : "memory");
 }
 
-static inline void __raw_local_irq_restore(unsigned long flags)
+static inline void __arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
        __asm__ __volatile__(
-               "raw_local_irq_restore\t%0"
+               "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
                : "0" (flags)
                : "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
        /*
index cb6985f24303668e661c0373b39e0f08a5d898f5..1e29b9dd1d7395752d401fca112b2f1f528357c8 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/io.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 /* loongson internal northbridge initialization */
 extern void bonito_irq_init(void);
index b74caf65482b2e068b86d2763daa81733bc45503..ff9a8b86cb9363c1fb458546c56550fc35a7a3ab 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef __ASM_MACH_TX49XX_KMALLOC_H
 #define __ASM_MACH_TX49XX_KMALLOC_H
 
-#define ARCH_KMALLOC_MINALIGN  L1_CACHE_BYTES
+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
 
 #endif /* __ASM_MACH_TX49XX_KMALLOC_H */
index cea872fc6f5c0d1ae92f00f920f7f991c8b9b806..d11aa02a956a57ca41ff890dbe16bbdd0145db53 100644 (file)
@@ -88,9 +88,6 @@
 
 #define GIC_EXT_INTR(x)                x
 
-/* Dummy data */
-#define X                      0xdead
-
 /* External Interrupts used for IPI */
 #define GIC_IPI_EXT_INTR_RESCHED_VPE0  16
 #define GIC_IPI_EXT_INTR_CALLFNC_VPE0  17
index a16beafcea91dd091f0b491ea572b5902e272a3d..e59cd1ac09c2f82eb8c91af1bdb0b6a520513d89 100644 (file)
@@ -150,6 +150,20 @@ typedef struct { unsigned long pgprot; } pgprot_t;
     ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 #endif
 #define __va(x)                ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+
+/*
+ * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad
+ * (lmo) rsp. 8431fd094d625b94d364fe393076ccef88e6ce18 (kernel.org).  The
+ * discussion can be found in lkml posting
+ * <a2ebde260608230500o3407b108hc03debb9da6e62c@mail.gmail.com> which is
+ * archived at http://lists.linuxcoding.com/kernel/2006-q3/msg17360.html
+ *
+ * It is unclear if the misscompilations mentioned in
+ * http://lkml.org/lkml/2010/8/8/138 also affect MIPS so we keep this one
+ * until GCC 3.x has been retired before we can apply
+ * https://patchwork.linux-mips.org/patch/1541/
+ */
+
 #define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
 
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
index 96e28f18dad11fbc0dabf41e4fbaf25f1302f3b0..1ca64b4d33d96844da375d3df443246f781e564a 100644 (file)
@@ -88,6 +88,7 @@ typedef struct siginfo {
 #ifdef __ARCH_SI_TRAPNO
                        int _trapno;    /* TRAP # which caused the signal */
 #endif
+                       short _addr_lsb;
                } _sigfault;
 
                /* SIGPOLL, SIGXFSZ (To do ...)  */
index 2376f2e06e470a264eeff5115dc692c80e9f37c3..70df9c0d3c5be20e2d7b646460276a44374fc077 100644 (file)
@@ -146,7 +146,8 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_LOAD_WATCH                (1<<TIF_LOAD_WATCH)
 
 /* work to do on interrupt/exception return */
-#define _TIF_WORK_MASK         (0x0000ffef & ~_TIF_SECCOMP)
+#define _TIF_WORK_MASK         (0x0000ffef &                           \
+                                       ~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT))
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (0x8000ffff & ~_TIF_SECCOMP)
 
index baa318a59c97f8c2791842df809c1218796c7492..550725b881d5edec666a5b32bbe1200164ac7fd8 100644 (file)
 #define __NR_perf_event_open           (__NR_Linux + 333)
 #define __NR_accept4                   (__NR_Linux + 334)
 #define __NR_recvmmsg                  (__NR_Linux + 335)
+#define __NR_fanotify_init             (__NR_Linux + 336)
+#define __NR_fanotify_mark             (__NR_Linux + 337)
+#define __NR_prlimit64                 (__NR_Linux + 338)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            335
+#define __NR_Linux_syscalls            338
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                335
+#define __NR_O32_Linux_syscalls                338
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_perf_event_open           (__NR_Linux + 292)
 #define __NR_accept4                   (__NR_Linux + 293)
 #define __NR_recvmmsg                  (__NR_Linux + 294)
+#define __NR_fanotify_init             (__NR_Linux + 295)
+#define __NR_fanotify_mark             (__NR_Linux + 296)
+#define __NR_prlimit64                 (__NR_Linux + 297)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            294
+#define __NR_Linux_syscalls            297
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         294
+#define __NR_64_Linux_syscalls         297
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_accept4                   (__NR_Linux + 297)
 #define __NR_recvmmsg                  (__NR_Linux + 298)
 #define __NR_getdents64                        (__NR_Linux + 299)
+#define __NR_fanotify_init             (__NR_Linux + 300)
+#define __NR_fanotify_mark             (__NR_Linux + 301)
+#define __NR_prlimit64                 (__NR_Linux + 302)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            299
+#define __NR_Linux_syscalls            302
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                299
+#define __NR_N32_Linux_syscalls                302
 
 #ifdef __KERNEL__
 
index ee18028efe9222ba4c4c9fa54fa37296d3800055..35b3e2f0af04899ee159d59129203e445cfb6e49 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/i8253.h>
index 6a97230e3d05ee4a53478c2a4625c51d92b26bd2..ba91be9c21ef405f65e0ae87fafe92a66ac8b06f 100644 (file)
@@ -1,3 +1,3 @@
-core-$(CONFIG_MACH_JZ4740)     += arch/mips/jz4740/
+platform-$(CONFIG_MACH_JZ4740) += jz4740/
 cflags-$(CONFIG_MACH_JZ4740)   += -I$(srctree)/arch/mips/include/asm/mach-jz4740
 load-$(CONFIG_MACH_JZ4740)     += 0xffffffff80010000
index 0176ed015c895644bc72fc30bc661c2ad555b515..32103cc2a2576877592d91050b86c8944a2479d9 100644 (file)
@@ -40,7 +40,6 @@ int __compute_return_epc(struct pt_regs *regs)
                return -EFAULT;
        }
 
-       regs->regs[0] = 0;
        switch (insn.i_format.opcode) {
        /*
         * jr and jalr are in r_format format.
index bfea327c636c1e635089f19846f14303d7d5911b..36c3898b76dbb01182184744fec80056c1132cd8 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/addrspace.h>
 #include <asm/io.h>
index 00a4da277cbbef1b94b6d0f767973fb19d3c676c..939157e397b940fd811d348997840c9dc34a0a0b 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
+#include <linux/irq.h>
 
 #include <asm/time.h>
 
index 392ef3756c56e0692d46e38cf5647b4f24bac951..339f3639b90e463d41931b7b127c3173e74297af 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/gt64120.h>
 #include <asm/time.h>
index 2a4d50ff5e2c17e8ad56e86593e48b70f29ee4df..2f4d7a99bcc2fcc91b3838599b0b0c3d4fb1c432 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
index da78eeaea6e81a5d6fc7516ed4dcb04195d143a2..590c54f28a81772f961b2513fef1147d4d581f62 100644 (file)
@@ -17,6 +17,7 @@
  */
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
 
index b102e4f1630eaa8e021b4c61b0b959f646f2bb81..2e72d30b2f05a9b2b0d1a40dd90699c658925d5b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
index 218ee6bda9353822e010b5ba8d521b96a05991b9..0b7377361e22fa8b3d76afc335344c35613cac59 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/time.h>
 #include <asm/txx9tmr.h>
 
index 94794062a1777814c03428b27576796fe3f2a7a7..2392a7a296d41d4585fc406948ed58d4f83443f9 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/delay.h>
 #include <asm/i8253.h>
index 27799113332cfa9c952d7402164201c3acf057c3..c58176cc796baa0c03d6d86597ab5252478f4e65 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
+#include <linux/irq.h>
 
 #include <asm/i8259.h>
 #include <asm/io.h>
index b181f2f0ea8e71709f331c8ee32a7f6792999106..1774271af848b7cca4dc2ab2da0578c7f38a6e13 100644 (file)
@@ -3,12 +3,11 @@
 #include <linux/bitmap.h>
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/gic.h>
 #include <asm/gcmpregs.h>
-#include <asm/mips-boards/maltaint.h>
-#include <asm/irq.h>
 #include <linux/hardirq.h>
 #include <asm-generic/bitops/find.h>
 
@@ -131,7 +130,7 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        int             i;
 
        irq -= _irqbase;
-       pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
+       pr_debug("%s(%d) called\n", __func__, irq);
        cpumask_and(&tmp, cpumask, cpu_online_mask);
        if (cpus_empty(tmp))
                return -1;
@@ -222,7 +221,7 @@ static void __init gic_basic_init(int numintrs, int numvpes,
        /* Setup specifics */
        for (i = 0; i < mapsize; i++) {
                cpu = intrmap[i].cpunum;
-               if (cpu == X)
+               if (cpu == GIC_UNUSED)
                        continue;
                if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
                        continue;
index fb50cc78b28b45cf36ffddb8fa4add2a734d5fa1..9731e8b47862f221124b8ed84df2a66a8c704cd5 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 
 #include <asm/irq_cpu.h>
index b47e4615ec126980ca5cb457a67bd7244b2135f5..b7e4025b58a83d940080154b3edb76f3807c9e09 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
index 55c8a3ca507b2800fab0406d81d0844c660a7c04..0262abe09121954b47e40a2b0b4c6f21ff1feb37 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
index 9b78029bea7026f237a337f981f0dd98c90661b5..95a96f69172d6d111a492e120c2af18adc364196 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <linux/irq.h>
 #include <asm/txx9irq.h>
 
 struct txx9_irc_reg {
index 1f4e2fa64140ee8204aed74ecf82eba7bab056be..f4546e97c60db111215495f924aa567595c39581 100644 (file)
@@ -283,7 +283,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
        struct pt_regs *regs = args->regs;
        int trap = (regs->cp0_cause & 0x7c) >> 2;
 
-       /* Userpace events, ignore. */
+       /* Userspace events, ignore. */
        if (user_mode(regs))
                return NOTIFY_DONE;
 
index 80e2ba694babcd0d70bd8266a6be941996e2a8a8..29811f043399588604da9bbc00efd9f0997aa530 100644 (file)
@@ -251,7 +251,7 @@ void sp_work_handle_request(void)
                memset(&tz, 0, sizeof(tz));
                if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
                                             (int)&tz, 0, 0)) == 0)
-               ret.retval = tv.tv_sec;
+                       ret.retval = tv.tv_sec;
                break;
 
        case MTSP_SYSCALL_EXIT:
index c2dab140dc98fb1588259063699c7ba09b6f8ed7..6343b4a5b8350cb3a93edea5d75f3154cde48343 100644 (file)
@@ -341,3 +341,10 @@ asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
 {
        return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
 }
+
+SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
+               u64, a3, u64, a4, int, dfd, const char  __user *, pathname)
+{
+       return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4),
+                                dfd, pathname);
+}
index 2340f11dc29cc8de689593c8b49315b613a6aae8..9a526ba6f25766f3ab6b58bc70b7f792c4011ff9 100644 (file)
@@ -103,7 +103,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
        if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
                goto out_unlock;
 
-       retval = security_task_setscheduler(p, 0, NULL);
+       retval = security_task_setscheduler(p)
        if (retval)
                goto out_unlock;
 
index c51b95ff86443e2fcb1eed618afe0861fd781eef..c8777333e19833667fe882110fe40d954fee5eeb 100644 (file)
@@ -536,7 +536,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
        /* do the secure computing check first */
        if (!entryexit)
-               secure_computing(regs->regs[0]);
+               secure_computing(regs->regs[2]);
 
        if (unlikely(current->audit_context) && entryexit)
                audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
@@ -565,7 +565,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 
 out:
        if (unlikely(current->audit_context) && !entryexit)
-               audit_syscall_entry(audit_arch(), regs->regs[0],
+               audit_syscall_entry(audit_arch(), regs->regs[2],
                                    regs->regs[4], regs->regs[5],
                                    regs->regs[6], regs->regs[7]);
 }
index 26f9b9ab19cc66b020486be6cef3e21cfe347126..557ef72472e08f082e19f068f7d131b93ab9856e 100644 (file)
@@ -468,7 +468,8 @@ static const struct file_operations rtlx_fops = {
        .release = file_release,
        .write =   file_write,
        .read =    file_read,
-       .poll =    file_poll
+       .poll =    file_poll,
+       .llseek =  noop_llseek,
 };
 
 static struct irqaction rtlx_irq = {
index 17202bbe843f91172534dd30e41e8a9542e0d762..fbaabad0e6e28466aa1098d4f50c516d520b0c7d 100644 (file)
@@ -63,9 +63,9 @@ stack_done:
        sw      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       lw      t1, PT_R2(sp)           # syscall number
        negu    v0                      # error
-       sw      v0, PT_R0(sp)           # set flag for syscall
-                                       # restarting
+       sw      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sw      v0, PT_R2(sp)           # result
 
 o32_syscall_exit:
@@ -104,9 +104,9 @@ syscall_trace_entry:
        sw      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       lw      t1, PT_R2(sp)           # syscall number
        negu    v0                      # error
-       sw      v0, PT_R0(sp)           # set flag for syscall
-                                       # restarting
+       sw      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sw      v0, PT_R2(sp)           # result
 
        j       syscall_exit
@@ -169,8 +169,7 @@ stackargs:
         * We probably should handle this case a bit more drastic.
         */
 bad_stack:
-       negu    v0                              # error
-       sw      v0, PT_R0(sp)
+       li      v0, EFAULT
        sw      v0, PT_R2(sp)
        li      t0, 1                           # set error flag
        sw      t0, PT_R7(sp)
@@ -583,7 +582,10 @@ einval:    li      v0, -ENOSYS
        sys     sys_rt_tgsigqueueinfo   4
        sys     sys_perf_event_open     5
        sys     sys_accept4             4
-       sys     sys_recvmmsg            5
+       sys     sys_recvmmsg            5       /* 4335 */
+       sys     sys_fanotify_init       2
+       sys     sys_fanotify_mark       6
+       sys     sys_prlimit64           4
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index a8a6c596eb0405bab886e8dfff6ffeb8097d7fc6..3f4179283207b1cc21e7fc14d9fea4da0c38bb28 100644 (file)
@@ -66,9 +66,9 @@ NESTED(handle_sys64, PT_SIZE, sp)
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # set flag for syscall
-                                       # restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
 n64_syscall_exit:
@@ -109,8 +109,9 @@ syscall_trace_entry:
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # set flag for syscall restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
        j       syscall_exit
@@ -416,9 +417,12 @@ sys_call_table:
        PTR     sys_pipe2
        PTR     sys_inotify_init1
        PTR     sys_preadv
-       PTR     sys_pwritev                     /* 5390 */
+       PTR     sys_pwritev                     /* 5290 */
        PTR     sys_rt_tgsigqueueinfo
        PTR     sys_perf_event_open
        PTR     sys_accept4
-       PTR     sys_recvmmsg
+       PTR     sys_recvmmsg
+       PTR     sys_fanotify_init               /* 5295 */
+       PTR     sys_fanotify_mark
+       PTR     sys_prlimit64
        .size   sys_call_table,.-sys_call_table
index a3d66137731ac24386972c82426a4679d9ff9be3..f08ece6d8acc7f3aa78ecbca23f801ae76727f6a 100644 (file)
@@ -65,8 +65,9 @@ NESTED(handle_sysn32, PT_SIZE, sp)
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # set flag for syscall restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
        local_irq_disable               # make sure need_resched and
@@ -106,8 +107,9 @@ n32_syscall_trace_entry:
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # set flag for syscall restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
        j       syscall_exit
@@ -320,10 +322,10 @@ EXPORT(sysn32_call_table)
        PTR     sys_cacheflush
        PTR     sys_cachectl
        PTR     sys_sysmips
-       PTR     sys_io_setup                    /* 6200 */
+       PTR     compat_sys_io_setup                     /* 6200 */
        PTR     sys_io_destroy
-       PTR     sys_io_getevents
-       PTR     sys_io_submit
+       PTR     compat_sys_io_getevents
+       PTR     compat_sys_io_submit
        PTR     sys_io_cancel
        PTR     sys_exit_group                  /* 6205 */
        PTR     sys_lookup_dcookie
@@ -419,5 +421,8 @@ EXPORT(sysn32_call_table)
        PTR     sys_perf_event_open
        PTR     sys_accept4
        PTR     compat_sys_recvmmsg
-       PTR     sys_getdents
+       PTR     sys_getdents64
+       PTR     sys_fanotify_init               /* 6300 */
+       PTR     sys_fanotify_mark
+       PTR     sys_prlimit64
        .size   sysn32_call_table,.-sysn32_call_table
index 813689ef23847c6a2db230ebd6dcae60e0ff79f6..78d768a3e19da78fc986e9170f73b240ee98c1c2 100644 (file)
@@ -93,8 +93,9 @@ NESTED(handle_sys, PT_SIZE, sp)
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # flag for syscall restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
 o32_syscall_exit:
@@ -142,8 +143,9 @@ trace_a_syscall:
        sd      t0, PT_R7(sp)           # set error flag
        beqz    t0, 1f
 
+       ld      t1, PT_R2(sp)           # syscall number
        dnegu   v0                      # error
-       sd      v0, PT_R0(sp)           # set flag for syscall restarting
+       sd      t1, PT_R0(sp)           # save it for syscall restarting
 1:     sd      v0, PT_R2(sp)           # result
 
        j       syscall_exit
@@ -154,8 +156,7 @@ trace_a_syscall:
         * The stackpointer for a call with more than 4 arguments is bad.
         */
 bad_stack:
-       dnegu   v0                      # error
-       sd      v0, PT_R0(sp)
+       li      v0, EFAULT
        sd      v0, PT_R2(sp)
        li      t0, 1                   # set error flag
        sd      t0, PT_R7(sp)
@@ -444,10 +445,10 @@ sys_call_table:
        PTR     compat_sys_futex
        PTR     compat_sys_sched_setaffinity
        PTR     compat_sys_sched_getaffinity    /* 4240 */
-       PTR     sys_io_setup
+       PTR     compat_sys_io_setup
        PTR     sys_io_destroy
-       PTR     sys_io_getevents
-       PTR     sys_io_submit
+       PTR     compat_sys_io_getevents
+       PTR     compat_sys_io_submit
        PTR     sys_io_cancel                   /* 4245 */
        PTR     sys_exit_group
        PTR     sys32_lookup_dcookie
@@ -538,5 +539,8 @@ sys_call_table:
        PTR     compat_sys_rt_tgsigqueueinfo
        PTR     sys_perf_event_open
        PTR     sys_accept4
-       PTR     compat_sys_recvmmsg
+       PTR     compat_sys_recvmmsg             /* 4335 */
+       PTR     sys_fanotify_init
+       PTR     sys_32_fanotify_mark
+       PTR     sys_prlimit64
        .size   sys_call_table,.-sys_call_table
index 2099d5a4c4b78224f85ee5f9b175907be3d8f15c..5922342bca3991d4b7ab4a9d6f8483fb3e416779 100644 (file)
@@ -390,7 +390,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
        struct rt_sigframe __user *frame;
        sigset_t set;
-       stack_t st;
        int sig;
 
        frame = (struct rt_sigframe __user *) regs.regs[29];
@@ -411,11 +410,9 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        else if (sig)
                force_sig(sig, current);
 
-       if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
-               goto badframe;
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
-       do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+       do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]);
 
        /*
         * Don't let your children do this ...
@@ -550,23 +547,26 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        struct mips_abi *abi = current->thread.abi;
        void *vdso = current->mm->context.vdso;
 
-       switch(regs->regs[0]) {
-       case ERESTART_RESTARTBLOCK:
-       case ERESTARTNOHAND:
-               regs->regs[2] = EINTR;
-               break;
-       case ERESTARTSYS:
-               if (!(ka->sa.sa_flags & SA_RESTART)) {
+       if (regs->regs[0]) {
+               switch(regs->regs[2]) {
+               case ERESTART_RESTARTBLOCK:
+               case ERESTARTNOHAND:
                        regs->regs[2] = EINTR;
                        break;
+               case ERESTARTSYS:
+                       if (!(ka->sa.sa_flags & SA_RESTART)) {
+                               regs->regs[2] = EINTR;
+                               break;
+                       }
+               /* fallthrough */
+               case ERESTARTNOINTR:
+                       regs->regs[7] = regs->regs[26];
+                       regs->regs[2] = regs->regs[0];
+                       regs->cp0_epc -= 4;
                }
-       /* fallthrough */
-       case ERESTARTNOINTR:            /* Userland will reload $v0.  */
-               regs->regs[7] = regs->regs[26];
-               regs->cp0_epc -= 8;
-       }
 
-       regs->regs[0] = 0;              /* Don't deal with this again.  */
+               regs->regs[0] = 0;              /* Don't deal with this again.  */
+       }
 
        if (sig_uses_siginfo(ka))
                ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
@@ -575,6 +575,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
                ret = abi->setup_frame(vdso + abi->signal_return_offset,
                                       ka, regs, sig, oldset);
 
+       if (ret)
+               return ret;
+
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -622,17 +625,13 @@ static void do_signal(struct pt_regs *regs)
                return;
        }
 
-       /*
-        * Who's code doesn't conform to the restartable syscall convention
-        * dies here!!!  The li instruction, a single machine instruction,
-        * must directly be followed by the syscall instruction.
-        */
        if (regs->regs[0]) {
                if (regs->regs[2] == ERESTARTNOHAND ||
                    regs->regs[2] == ERESTARTSYS ||
                    regs->regs[2] == ERESTARTNOINTR) {
+                       regs->regs[2] = regs->regs[0];
                        regs->regs[7] = regs->regs[26];
-                       regs->cp0_epc -= 8;
+                       regs->cp0_epc -= 4;
                }
                if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
                        regs->regs[2] = current->thread.abi->restart;
index 2c5df818c65ae0395768264f1192059b792aaf02..ee24d814d5b91bb474ff3ff114e49f86618cdeae 100644 (file)
@@ -109,6 +109,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
        struct rt_sigframe_n32 __user *frame;
+       mm_segment_t old_fs;
        sigset_t set;
        stack_t st;
        s32 sp;
@@ -143,7 +144,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
        do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+       set_fs(old_fs);
+
 
        /*
         * Don't let your children do this ...
index cfeb2c1558967a540df6be261478df57c73a440f..39c08254b0f16f7d36e1b73344cb75c52ed9619f 100644 (file)
@@ -1038,7 +1038,7 @@ void deferred_smtc_ipi(void)
                 * but it's more efficient, given that we're already
                 * running down the IPI queue.
                 */
-               __raw_local_irq_restore(flags);
+               __arch_local_irq_restore(flags);
        }
 }
 
@@ -1190,7 +1190,7 @@ void smtc_ipi_replay(void)
                /*
                 ** But use a raw restore here to avoid recursion.
                 */
-               __raw_local_irq_restore(flags);
+               __arch_local_irq_restore(flags);
 
                if (pipi) {
                        self_ipi(pipi);
index 03ec0019032bc50ebbc9435cdec3c71eeaa9ac70..d053bf4759e417071760634656083151358ef23c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/kprobes.h>
 #include <linux/notifier.h>
 #include <linux/kdb.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -51,7 +52,6 @@
 #include <asm/mmu_context.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
-#include <asm/irq.h>
 #include <asm/uasm.h>
 
 extern void check_wait(void);
index 69b039ca8d8337e60ecead9e32fbe7bd64659a64..33d5a5ce4a29d56037a38abb346a99e0212c16c2 100644 (file)
@@ -109,8 +109,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
        unsigned long value;
        unsigned int res;
 
-       regs->regs[0] = 0;
-
        /*
         * This load never faults.
         */
index 2bd2151c586a9c219e3eb1a574f65f0105589774..3eb3cde2f66160c0b4f5aeee889dc9adbfedf823 100644 (file)
@@ -1192,7 +1192,8 @@ static const struct file_operations vpe_fops = {
        .owner = THIS_MODULE,
        .open = vpe_open,
        .release = vpe_release,
-       .write = vpe_write
+       .write = vpe_write,
+       .llseek = noop_llseek,
 };
 
 /* module wrapper entry points */
index 7ba890860d98cb3916c84f369e3fef0200b07f2b..469d4019f795bd072b0aa4ba109d075b5377f55c 100644 (file)
@@ -44,27 +44,39 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev)
 
 static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
 {
+       gfp_t dma_flag;
+
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
 
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ISA
        if (dev == NULL)
-               gfp |= __GFP_DMA;
-       else if (dev->coherent_dma_mask < DMA_BIT_MASK(24))
-               gfp |= __GFP_DMA;
+               dma_flag = __GFP_DMA;
        else
 #endif
-#ifdef CONFIG_ZONE_DMA32
+#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
             if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
-               gfp |= __GFP_DMA32;
+                       dma_flag = __GFP_DMA;
+       else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+                       dma_flag = __GFP_DMA32;
+       else
+#endif
+#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
+            if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+               dma_flag = __GFP_DMA32;
+       else
+#endif
+#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
+            if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+               dma_flag = __GFP_DMA;
        else
 #endif
-               ;
+               dma_flag = 0;
 
        /* Don't invoke OOM killer */
        gfp |= __GFP_NORETRY;
 
-       return gfp;
+       return gfp | dma_flag;
 }
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
index 1ef75cd80a0d819827f5057549fdd2622442a752..274af3be1442b42fa41d3cb960b598ddcbf5b8c2 100644 (file)
@@ -30,7 +30,7 @@
 #define tc_lsize       32
 
 extern unsigned long icache_way_size, dcache_way_size;
-unsigned long tcache_size;
+static unsigned long tcache_size;
 
 #include <asm/r4kcache.h>
 
index 15949b0be811f9718af9e2896d4bd9e947c84897..b79b24afe3a2fc67ab6687a082e44d45bf219242 100644 (file)
@@ -385,6 +385,8 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
  */
 
 #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
+#define X GIC_UNUSED
+
 static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
        { X, X,            X,           X,              0 },
        { X, X,            X,           X,              0 },
@@ -404,6 +406,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
        { X, X,            X,           X,              0 },
        /* The remainder of this table is initialised by fill_ipi_map */
 };
+#undef X
 
 /*
  * GCMP needs to be detected before any SMP initialisation
index 72e32a7715beff770347237d6944472184853cf4..4c35301720e76c04aad4eade1d88310c107ba6fd 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/serial_8250.h>
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
index 31c15019659544a55f81f2675abf25f7a085640e..6a3bdb5ffa8074e5ba3e978d6989115857e17e5b 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/addrspace.h>
 #include <asm/txx9irq.h>
index 5989e747527f2e4e67f591b93a1f4eb2f16652f3..a1e7e6d80c8c718e9b532e5ccb8ff0e7bac9e164 100644 (file)
@@ -17,6 +17,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/txx9/pci.h>
 #include <asm/txx9/tx4927pcic.h>
 
index 71f7d27b0d4cccf28dba3777b0a8848de53f82c4..f31218e17d3c1437f4f8ef15a7d1855ddc6a32fb 100644 (file)
@@ -118,7 +118,7 @@ static int __init rc32434_pcibridge_init(void)
        if (!((pcicvalue == PCIM_H_EA) ||
              (pcicvalue == PCIM_H_IA_FIX) ||
              (pcicvalue == PCIM_H_IA_RR))) {
-               pr_err(KERN_ERR "PCI init error!!!\n");
+               pr_err("PCI init error!!!\n");
                /* Not in Host Mode, return ERROR */
                return -1;
        }
index 94c9c2c9fbc1d650897ac14eec91d68377c8ac5e..07e71ff2433f642428462d405c0f843d3928fd6b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
+#include <linux/irq.h>
 
 #include <asm/system.h>
 
index fadd8744a6bccfbf25283369608c66b16afeab04..e7a12ff304b9475c0db2e6097989c510b288a3c4 100644 (file)
  */
 #include <linux/kernel.h>
 
+#include <asm/processor.h>
 #include <asm/reboot.h>
 #include <glb.h>
 
 void pnx8550_machine_restart(char *command)
 {
-       char head[] = "************* Machine restart *************";
-       char foot[] = "*******************************************";
-
-       printk("\n\n");
-       printk("%s\n", head);
-       if (command != NULL)
-               printk("* %s\n", command);
-       printk("%s\n", foot);
-
        PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
 }
 
 void pnx8550_machine_halt(void)
 {
-       printk("*** Machine halt. (Not implemented) ***\n");
-}
-
-void pnx8550_machine_power_off(void)
-{
-       printk("*** Machine power off.  (Not implemented) ***\n");
+       while (1) {
+               if (cpu_wait)
+                       cpu_wait();
+       }
 }
index 64246c9c875c51d09e5c3861ca0e6f1096d50ac5..43cb3945fdbfffb8b355789e237a9b27df21abef 100644 (file)
@@ -44,7 +44,6 @@
 extern void __init board_setup(void);
 extern void pnx8550_machine_restart(char *);
 extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
 extern char *prom_getcmdline(void);
@@ -100,7 +99,7 @@ void __init plat_mem_setup(void)
 
         _machine_restart = pnx8550_machine_restart;
         _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
+        pm_power_off = pnx8550_machine_halt;
 
        /* Clear the Global 2 Register, PCI Inta Output Enable Registers
           Bit 1:Enable DAC Powerdown
index b54d24499b062d31fc5e04cd8f18f0a417532043..e5538243415576d121b1400aceadc726c6a7fec8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
index 00ed19f0bdb56e4a9045ba7e2f7388562978d6a4..70482540b3dbc7edf469be8e14beb7e37a1f5f68 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
+#include <linux/irq.h>
 
 #include <asm/serial.h>
 #include <asm/mach-rc32434/rb.h>
index d4ed7a9156f59d847985909de7fe64f788664921..ca35b730d1892e2e425fa74bce388b7a95c3401b 100644 (file)
@@ -545,6 +545,7 @@ static const struct file_operations sbprof_tb_fops = {
        .unlocked_ioctl = sbprof_tb_ioctl,
        .compat_ioctl   = sbprof_tb_ioctl,
        .mmap           = NULL,
+       .llseek         = default_llseek,
 };
 
 static struct class *tb_class;
index e6980892834aae7a00865172e2303c67732bc86b..bbe7187879fa9bb5c493f215ba1ef8f8f81cc695 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 
index 51e62bbaa23bb2440fa671fc22fe57930690aea6..8c92c73bc717db178bcdbce74788f30fe1b193b5 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
index f4699d35858b70820f638d053dac36be73f4da5c..dc9874553becbf62abc5dce1135e9a7444f43d88 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
index 90c558f7c0fa91b18df793a903cf8296fffc12fa..0e6f42c2bbc86c69117bd90bef5c22456f8c01ac 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
index f3b60e671207bea19676fd1c0cca9a4a38180ccb..c76151b56568ee241e345fe779d3454df0179add 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/clockchips.h>
index ad2870def8f1f7e1697205cfe2094f6a988ab7e8..e1828e8bcaefedd4449cb0b96806c50708b343ed 100644 (file)
@@ -25,6 +25,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9/tx4927.h>
 
index 025ae11359a8183cadd81f1418127b45b215c395..a6e6e805097a80be53edf7501f2ead464ae8f023 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9/tx4938.h>
 
index 013213a8706b61d7c2f7d806b0b98ffb3637fdb3..3886ad77cbadd21a1ed1a97ffea7482ea083d88a 100644 (file)
@@ -19,6 +19,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/types.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9irq.h>
index 575d219b80014fea3e74cfef9865769251b79635..812816c456620f86fce6ba670d2f6352df7f9b6d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/leds.h>
 #include <linux/sysdev.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
index 6ec626c9473fd4014a5c31919347d51aed407810..0a7f8e3b9fd796b7fe384d39772aef124231f40e 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/mipsregs.h>
index 9c14ebb26cb4caf63f7448b02b83ad4e435f2332..c4b54d20efd3c67fc279ef8d6cfbe2099bc0b62a 100644 (file)
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/generic.h>
index 7d21befb8932c5ba36df028cb74b1c66e61c652d..67a73a8065ec800e00ebb753f612195434f5189b 100644 (file)
@@ -64,6 +64,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/generic.h>
 #include <asm/txx9/rbtx4938.h>
index 500cc0a908e6b8876e529c161d2cf1eee6f18f69..57fa740a72056b65ecd0f08e55fb23fe434083e7 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/rbtx4939.h>
 
index bef06872f012d6ecb055aafeae92d9ed6f962135..0975eb72d385e189af3f26895eeb689ab3d950c3 100644 (file)
@@ -19,6 +19,7 @@
  */
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/system.h>
index 54eae56108fb94db06a5add150e8baad4ef5dbfe..bbd45d2559d63b4b1c23da18bdbc0ceb8dc655a9 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/irq.h>
 
 #include <asm/cpu.h>
 #include <asm/vr41xx/siu.h>
index 444b9f918fdf8f2d5dec64b9827d8d746bb1ade1..7c2a2f7f8dc143889b74605d2741f5707ad330e4 100644 (file)
@@ -8,7 +8,6 @@ mainmenu "Linux Kernel Configuration"
 config MN10300
        def_bool y
        select HAVE_OPROFILE
-       select HAVE_ARCH_TRACEHOOK
 
 config AM33
        def_bool y
index ff80e86b9bd2d2305d34a731685d94fe5d3f3491..ce83c74b3fd714abf68fca4a4d2beef024545c83 100644 (file)
@@ -101,7 +101,7 @@ config GDBSTUB_DEBUG_BREAKPOINT
 
 choice
        prompt "GDB stub port"
-       default GDBSTUB_TTYSM0
+       default GDBSTUB_ON_TTYSM0
        depends on GDBSTUB
        help
          Select the serial port used for GDB-stub.
index f49ac49e09adc079adaabdd9893258ae9b795b7f..3f50e966107641f21f346a38e50cca97d2eda24b 100644 (file)
@@ -229,9 +229,9 @@ int ffs(int x)
 #include <asm-generic/bitops/hweight.h>
 
 #define ext2_set_bit_atomic(lock, nr, addr) \
-       test_and_set_bit((nr) ^ 0x18, (addr))
+       test_and_set_bit((nr), (addr))
 #define ext2_clear_bit_atomic(lock, nr, addr) \
-       test_and_clear_bit((nr) ^ 0x18, (addr))
+       test_and_clear_bit((nr), (addr))
 
 #include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/minix-le.h>
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..5e529a1
--- /dev/null
@@ -0,0 +1,123 @@
+/* MN10300 IRQ flag handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/cpu-regs.h>
+
+/*
+ * interrupt control
+ * - "disabled": run in IM1/2
+ *   - level 0 - GDB stub
+ *   - level 1 - virtual serial DMA (if present)
+ *   - level 5 - normal interrupt priority
+ *   - level 6 - timer interrupt
+ * - "enabled":  run in IM7
+ */
+#ifdef CONFIG_MN10300_TTYSM
+#define MN10300_CLI_LEVEL      EPSW_IM_2
+#else
+#define MN10300_CLI_LEVEL      EPSW_IM_1
+#endif
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+
+       asm volatile("mov epsw,%0" : "=d"(flags));
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile(
+               "       and %0,epsw     \n"
+               "       or %1,epsw      \n"
+               "       nop             \n"
+               "       nop             \n"
+               "       nop             \n"
+               :
+               : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
+               : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+
+       flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+/*
+ * we make sure arch_irq_enable() doesn't cause priority inversion
+ */
+extern unsigned long __mn10300_irq_enabled_epsw;
+
+static inline void arch_local_irq_enable(void)
+{
+       unsigned long tmp;
+
+       asm volatile(
+               "       mov     epsw,%0         \n"
+               "       and     %1,%0           \n"
+               "       or      %2,%0           \n"
+               "       mov     %0,epsw         \n"
+               : "=&d"(tmp)
+               : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
+               : "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile(
+               "       mov %0,epsw     \n"
+               "       nop             \n"
+               "       nop             \n"
+               "       nop             \n"
+               :
+               : "d"(flags)
+               : "memory", "cc");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & EPSW_IM) <= MN10300_CLI_LEVEL;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * Hook to save power by halting the CPU
+ * - called from the idle loop
+ * - must reenable interrupts (which takes three instruction cycles to complete)
+ */
+static inline void arch_safe_halt(void)
+{
+       asm volatile(
+               "       or      %0,epsw \n"
+               "       nop             \n"
+               "       nop             \n"
+               "       bset    %2,(%1) \n"
+               :
+               : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
+               : "cc");
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_IRQFLAGS_H */
index 7e891fce2370028acea4a56497aafa74c443c0be..1865d72a86ff7cc6823a7be07dbbb0f3907e2518 100644 (file)
@@ -78,7 +78,7 @@ typedef unsigned long sigset_t;
 
 /* These should not be considered constants from userland.  */
 #define SIGRTMIN       32
-#define SIGRTMAX       (_NSIG-1)
+#define SIGRTMAX       _NSIG
 
 /*
  * SA_FLAGS values:
index 3636c054dcd526202a3028c389c8515a450ffa98..9f7c7e17c01ee7d8560a568dd4f2d98636c7f130 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 struct task_struct;
 struct thread_struct;
@@ -79,114 +80,6 @@ do {                                                                        \
 #define read_barrier_depends()         do {} while (0)
 #define smp_read_barrier_depends()     do {} while (0)
 
-/*****************************************************************************/
-/*
- * interrupt control
- * - "disabled": run in IM1/2
- *   - level 0 - GDB stub
- *   - level 1 - virtual serial DMA (if present)
- *   - level 5 - normal interrupt priority
- *   - level 6 - timer interrupt
- * - "enabled":  run in IM7
- */
-#ifdef CONFIG_MN10300_TTYSM
-#define MN10300_CLI_LEVEL      EPSW_IM_2
-#else
-#define MN10300_CLI_LEVEL      EPSW_IM_1
-#endif
-
-#define local_save_flags(x)                    \
-do {                                           \
-       typecheck(unsigned long, x);            \
-       asm volatile(                           \
-               "       mov epsw,%0     \n"     \
-               : "=d"(x)                       \
-               );                              \
-} while (0)
-
-#define local_irq_disable()                                            \
-do {                                                                   \
-       asm volatile(                                                   \
-               "       and %0,epsw     \n"                             \
-               "       or %1,epsw      \n"                             \
-               "       nop             \n"                             \
-               "       nop             \n"                             \
-               "       nop             \n"                             \
-               :                                                       \
-               : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)       \
-               );                                                      \
-} while (0)
-
-#define local_irq_save(x)                      \
-do {                                           \
-       local_save_flags(x);                    \
-       local_irq_disable();                    \
-} while (0)
-
-/*
- * we make sure local_irq_enable() doesn't cause priority inversion
- */
-#ifndef __ASSEMBLY__
-
-extern unsigned long __mn10300_irq_enabled_epsw;
-
-#endif
-
-#define local_irq_enable()                                             \
-do {                                                                   \
-       unsigned long tmp;                                              \
-                                                                       \
-       asm volatile(                                                   \
-               "       mov     epsw,%0         \n"                     \
-               "       and     %1,%0           \n"                     \
-               "       or      %2,%0           \n"                     \
-               "       mov     %0,epsw         \n"                     \
-               : "=&d"(tmp)                                            \
-               : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)        \
-               : "cc"                                                  \
-               );                                                      \
-} while (0)
-
-#define local_irq_restore(x)                   \
-do {                                           \
-       typecheck(unsigned long, x);            \
-       asm volatile(                           \
-               "       mov %0,epsw     \n"     \
-               "       nop             \n"     \
-               "       nop             \n"     \
-               "       nop             \n"     \
-               :                               \
-               : "d"(x)                        \
-               : "memory", "cc"                \
-               );                              \
-} while (0)
-
-#define irqs_disabled()                                \
-({                                             \
-       unsigned long flags;                    \
-       local_save_flags(flags);                \
-       (flags & EPSW_IM) <= MN10300_CLI_LEVEL; \
-})
-
-/* hook to save power by halting the CPU
- * - called from the idle loop
- * - must reenable interrupts (which takes three instruction cycles to complete)
- */
-#define safe_halt()                                                    \
-do {                                                                   \
-       asm volatile("  or      %0,epsw \n"                             \
-                    "  nop             \n"                             \
-                    "  nop             \n"                             \
-                    "  bset    %2,(%1) \n"                             \
-                    :                                                  \
-                    : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)\
-                    : "cc"                                             \
-                    );                                                 \
-} while (0)
-
-#define STI    or EPSW_IE|EPSW_IM,epsw
-#define CLI    and ~EPSW_IM,epsw; or EPSW_IE|MN10300_CLI_LEVEL,epsw; nop; nop; nop
-
 /*****************************************************************************/
 /*
  * MN10300 doesn't actually have an exchange instruction
index d9ed5a15c547f8800f16080e6699c1ad131d5d2c..3d394b4eefba1e5a90f14c22997b1ccbbcb3fc5e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/linkage.h>
 #include <asm/smp.h>
 #include <asm/system.h>
+#include <asm/irqflags.h>
 #include <asm/thread_info.h>
 #include <asm/intctl-regs.h>
 #include <asm/busctl-regs.h>
index 9d49073e827a26429335b54cc51cff3304433ac7..db509dd80565b9e91c2b661c08c5fd64bc52e8d4 100644 (file)
@@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = {
        ._intr          = &SC0ICR,
        ._rxb           = &SC0RXB,
        ._txb           = &SC0TXB,
-       .rx_name        = "ttySM0/Rx",
-       .tx_name        = "ttySM0/Tx",
+       .rx_name        = "ttySM0:Rx",
+       .tx_name        = "ttySM0:Tx",
 #ifdef CONFIG_MN10300_TTYSM0_TIMER8
-       .tm_name        = "ttySM0/Timer8",
+       .tm_name        = "ttySM0:Timer8",
        ._tmxmd         = &TM8MD,
        ._tmxbr         = &TM8BR,
        ._tmicr         = &TM8ICR,
        .tm_irq         = TM8IRQ,
        .div_timer      = MNSCx_DIV_TIMER_16BIT,
 #else /* CONFIG_MN10300_TTYSM0_TIMER2 */
-       .tm_name        = "ttySM0/Timer2",
+       .tm_name        = "ttySM0:Timer2",
        ._tmxmd         = &TM2MD,
        ._tmxbr         = (volatile u16 *) &TM2BR,
        ._tmicr         = &TM2ICR,
@@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = {
        ._intr          = &SC1ICR,
        ._rxb           = &SC1RXB,
        ._txb           = &SC1TXB,
-       .rx_name        = "ttySM1/Rx",
-       .tx_name        = "ttySM1/Tx",
+       .rx_name        = "ttySM1:Rx",
+       .tx_name        = "ttySM1:Tx",
 #ifdef CONFIG_MN10300_TTYSM1_TIMER9
-       .tm_name        = "ttySM1/Timer9",
+       .tm_name        = "ttySM1:Timer9",
        ._tmxmd         = &TM9MD,
        ._tmxbr         = &TM9BR,
        ._tmicr         = &TM9ICR,
        .tm_irq         = TM9IRQ,
        .div_timer      = MNSCx_DIV_TIMER_16BIT,
 #else /* CONFIG_MN10300_TTYSM1_TIMER3 */
-       .tm_name        = "ttySM1/Timer3",
+       .tm_name        = "ttySM1:Timer3",
        ._tmxmd         = &TM3MD,
        ._tmxbr         = (volatile u16 *) &TM3BR,
        ._tmicr         = &TM3ICR,
@@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = {
        .uart.lock      =
        __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
        .name           = "ttySM2",
-       .rx_name        = "ttySM2/Rx",
-       .tx_name        = "ttySM2/Tx",
-       .tm_name        = "ttySM2/Timer10",
+       .rx_name        = "ttySM2:Rx",
+       .tx_name        = "ttySM2:Tx",
+       .tm_name        = "ttySM2:Timer10",
        ._iobase        = &SC2CTR,
        ._control       = &SC2CTR,
        ._status        = &SC2STR,
index 6aea7fd76993b931f31f2dda76e72aecc1e31b4d..196a111e2e2937b134217356991c0ca2f68bda05 100644 (file)
@@ -206,7 +206,7 @@ int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
 {
-       return module_bug_finalize(hdr, sechdrs, me);
+       return 0;
 }
 
 /*
@@ -214,5 +214,4 @@ int module_finalize(const Elf_Ehdr *hdr,
  */
 void module_arch_cleanup(struct module *mod)
 {
-       module_bug_cleanup(mod);
 }
index 717db14c2cc32d8905a45e6cfae4bf2a00d38abd..d4de05ab786464cd585e7f1f0e6ed1652ad3de1c 100644 (file)
@@ -65,10 +65,10 @@ asmlinkage long sys_sigaction(int sig,
                old_sigset_t mask;
                if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        return -EFAULT;
-               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-               __get_user(mask, &act->sa_mask);
                siginitset(&new_ka.sa.sa_mask, mask);
        }
 
@@ -77,10 +77,10 @@ asmlinkage long sys_sigaction(int sig,
        if (!ret && oact) {
                if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        return -EFAULT;
-               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
        }
 
        return ret;
@@ -102,6 +102,9 @@ static int restore_sigcontext(struct pt_regs *regs,
 {
        unsigned int err = 0;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (is_using_fpu(current))
                fpu_kill_state(current);
 
@@ -330,8 +333,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        regs->d0 = sig;
        regs->d1 = (unsigned long) &frame->sc;
 
-       set_fs(USER_DS);
-
        /* the tracer may want to single-step inside the handler */
        if (test_thread_flag(TIF_SINGLESTEP))
                ptrace_notify(SIGTRAP);
@@ -345,7 +346,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        return 0;
 
 give_sigsegv:
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 }
 
@@ -413,8 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->d0 = sig;
        regs->d1 = (long) &frame->info;
 
-       set_fs(USER_DS);
-
        /* the tracer may want to single-step inside the handler */
        if (test_thread_flag(TIF_SINGLESTEP))
                ptrace_notify(SIGTRAP);
@@ -428,10 +427,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return 0;
 
 give_sigsegv:
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 }
 
+static inline void stepback(struct pt_regs *regs)
+{
+       regs->pc -= 2;
+       regs->orig_d0 = -1;
+}
+
 /*
  * handle the actual delivery of a signal to userspace
  */
@@ -459,7 +464,7 @@ static int handle_signal(int sig,
                        /* fallthrough */
                case -ERESTARTNOINTR:
                        regs->d0 = regs->orig_d0;
-                       regs->pc -= 2;
+                       stepback(regs);
                }
        }
 
@@ -527,12 +532,12 @@ static void do_signal(struct pt_regs *regs)
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
                        regs->d0 = regs->orig_d0;
-                       regs->pc -= 2;
+                       stepback(regs);
                        break;
 
                case -ERESTART_RESTARTBLOCK:
                        regs->d0 = __NR_restart_syscall;
-                       regs->pc -= 2;
+                       stepback(regs);
                        break;
                }
        }
index 28b9d983db0cb280c07dcd76921d695892e11c48..1557277fbc5c03962c56f39b7d1a5687bdea80bd 100644 (file)
@@ -2,13 +2,11 @@
 # Makefile for the MN10300-specific memory management code
 #
 
+cacheflush-y   := cache.o cache-mn10300.o
+cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o
+
+cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
+
 obj-y := \
        init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
-       misalignment.o dma-alloc.o
-
-ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
-obj-y  += cache.o cache-mn10300.o
-ifeq ($(CONFIG_MN10300_CACHE_WBACK),y)
-obj-y  += cache-flush-mn10300.o
-endif
-endif
+       misalignment.o dma-alloc.o $(cacheflush-y)
similarity index 53%
rename from arch/frv/lib/perf_event.c
rename to arch/mn10300/mm/cache-disabled.c
index 9ac5acfd2e9101016140be7360713366b2ffc16f..f669ea42aba638472a9552103dfd66e978d12009 100644 (file)
@@ -1,6 +1,6 @@
-/* Performance event handling
+/* Handle the cache being disabled
  *
- * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -8,12 +8,14 @@
  * as published by the Free Software Foundation; either version
  * 2 of the Licence, or (at your option) any later version.
  */
-
-#include <linux/perf_event.h>
+#include <linux/mm.h>
 
 /*
- * mark the performance event as pending
+ * allow userspace to flush the instruction cache
  */
-void set_perf_event_pending(void)
+asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
 {
+       if (end < start)
+               return -EINVAL;
+       return 0;
 }
index 1b76719ec1c37b1686a648cd07f8c5e7baaf9ce1..9261217e8d2c5741bb500b829bbd7663859b5541 100644 (file)
@@ -54,13 +54,30 @@ EXPORT_SYMBOL(flush_icache_page);
 void flush_icache_range(unsigned long start, unsigned long end)
 {
 #ifdef CONFIG_MN10300_CACHE_WBACK
-       unsigned long addr, size, off;
+       unsigned long addr, size, base, off;
        struct page *page;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *ppte, pte;
 
+       if (end > 0x80000000UL) {
+               /* addresses above 0xa0000000 do not go through the cache */
+               if (end > 0xa0000000UL) {
+                       end = 0xa0000000UL;
+                       if (start >= end)
+                               return;
+               }
+
+               /* kernel addresses between 0x80000000 and 0x9fffffff do not
+                * require page tables, so we just map such addresses directly */
+               base = (start >= 0x80000000UL) ? start : 0x80000000UL;
+               mn10300_dcache_flush_range(base, end);
+               if (base == start)
+                       goto invalidate;
+               end = base;
+       }
+
        for (; start < end; start += size) {
                /* work out how much of the page to flush */
                off = start & (PAGE_SIZE - 1);
@@ -104,6 +121,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
        }
 #endif
 
+invalidate:
        mn10300_icache_inv();
 }
 EXPORT_SYMBOL(flush_icache_range);
index 4e34880bea03b889dcbcaea5865d576045bf1707..159acb02cfd4c16dcd1e91f9268b8d9dc6e74463 100644 (file)
@@ -25,7 +25,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
        unsigned long addr;
        void *ret;
 
-       printk("dma_alloc_coherent(%s,%zu,,%x)\n", dev_name(dev), size, gfp);
+       pr_debug("dma_alloc_coherent(%s,%zu,%x)\n",
+                dev ? dev_name(dev) : "?", size, gfp);
 
        if (0xbe000000 - pci_sram_allocated >= size) {
                size = (size + 255) & ~255;
index 907417d187e15039bb4bb6d96075cd950a045dbd..79a04a9394d5ad33b768d79ce1c2230b24e1c9bb 100644 (file)
@@ -16,6 +16,7 @@ config PARISC
        select RTC_DRV_GENERIC
        select INIT_ALL_POSSIBLE
        select BUG
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select GENERIC_ATOMIC64 if !64BIT
        help
index 02b77baa5da69f04729013cd9b6402ffc2dc3c39..efa0b60c63fe683f22629ddd540ed036495cd896 100644 (file)
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-static __inline__ void __user *compat_alloc_user_space(long len)
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = &current->thread.regs;
        return (void __user *)regs->gr[30];
diff --git a/arch/parisc/include/asm/irqflags.h b/arch/parisc/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..34f9cb9
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __PARISC_IRQFLAGS_H
+#define __PARISC_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <asm/psw.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("ssm 0, %0" : "=r" (flags) : : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       asm volatile("rsm %1,%0" : "=r" (flags) : "i" (PSW_I) : "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("mtsm %0" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & PSW_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __PARISC_IRQFLAGS_H */
index cc146427d8f9acf2219aa14813d76e52835bb83f..1e0fd8ba6c033e5f277afc02075fc7de57b1adc6 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_PARISC_PERF_EVENT_H
 #define __ASM_PARISC_PERF_EVENT_H
 
-/* parisc only supports software events through this interface. */
-static inline void set_perf_event_pending(void) { }
+/* Empty, just to avoid compiling error */
 
 #endif /* __ASM_PARISC_PERF_EVENT_H */
index 2ab4af58ecb9ca20cf13751868c917fe09b36a7b..b19e63a8e8484413b5df79d82e3f3a7905e41a0f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PARISC_SYSTEM_H
 #define __PARISC_SYSTEM_H
 
-#include <asm/psw.h>
+#include <linux/irqflags.h>
 
 /* The program status word as bitfields.  */
 struct pa_psw {
@@ -48,23 +48,6 @@ extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *
        (last) = _switch_to(prev, next);                        \
 } while(0)
 
-/* interrupt control */
-#define local_save_flags(x)    __asm__ __volatile__("ssm 0, %0" : "=r" (x) : : "memory")
-#define local_irq_disable()    __asm__ __volatile__("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-#define local_irq_enable()     __asm__ __volatile__("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-
-#define local_irq_save(x) \
-       __asm__ __volatile__("rsm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" )
-#define local_irq_restore(x) \
-       __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory" )
-
-#define irqs_disabled()                        \
-({                                     \
-       unsigned long flags;            \
-       local_save_flags(flags);        \
-       (flags & PSW_I) == 0;           \
-})
-
 #define mfctl(reg)     ({              \
        unsigned long cr;               \
        __asm__ __volatile__(           \
index 159a2b81e90c630db82eb9834c2096df7eb66896..6e81bb596e5b476e598e4a7309e4aba80ba0a322 100644 (file)
@@ -941,11 +941,10 @@ int module_finalize(const Elf_Ehdr *hdr,
        nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
        DEBUGP("NEW num_symtab %lu\n", nsyms);
        symhdr->sh_size = nsyms * sizeof(Elf_Sym);
-       return module_bug_finalize(hdr, sechdrs, me);
+       return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
        deregister_unwind_table(mod);
-       module_bug_cleanup(mod);
 }
index f9f6783e4bdd207f3266970e6fbb422bdf6b1f08..ba0c053e25ae9d66cf536ab87ce1cca9eef53dbf 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
@@ -261,16 +260,13 @@ printk("Preparing to start counters\n");
  */
 static int perf_open(struct inode *inode, struct file *file)
 {
-       lock_kernel();
        spin_lock(&perf_lock);
        if (perf_enabled) {
                spin_unlock(&perf_lock);
-               unlock_kernel();
                return -EBUSY;
        }
        perf_enabled = 1;
        spin_unlock(&perf_lock);
-       unlock_kernel();
 
        return 0;
 }
index 631e5a0fb6abcf2e124f0dfc6d1ed95d9b9f4566..4b1e521d966f0facaf7d1b70be55ebaf83df3954 100644 (file)
@@ -138,6 +138,7 @@ config PPC
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS if PPC64
        select GENERIC_ATOMIC64 if PPC32
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
index e3ea151c95975a9434995dd7e2da3f6033d6c912..b7212b619c52377ddeb471cf8e32f6080522cafa 100644 (file)
@@ -164,7 +164,7 @@ drivers-$(CONFIG_OPROFILE)  += arch/powerpc/oprofile/
 all: zImage
 
 # With make 3.82 we cannot mix normal and wildcard targets
-BOOT_TARGETS1 := zImage zImage.initrd uImaged
+BOOT_TARGETS1 := zImage zImage.initrd uImage
 BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
 
 PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
index b1e5611b2ab1d639edd67346ca50f88d625b9629..349b5530d2c4c31394cdb03080f4491fcbe047ed 100644 (file)
@@ -20,7 +20,7 @@
 #include <string.h>
 
 /* CHRP note section */
-char arch[] = "PowerPC";
+static const char arch[] = "PowerPC";
 
 #define N_DESCR        6
 unsigned int descr[N_DESCR] = {
@@ -33,7 +33,7 @@ unsigned int descr[N_DESCR] = {
 };
 
 /* RPA note section */
-char rpaname[] = "IBM,RPA-Client-Config";
+static const char rpaname[] = "IBM,RPA-Client-Config";
 
 /*
  * Note: setting ignore_my_client_config *should* mean that OF ignores
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
new file mode 100644 (file)
index 0000000..9bb3d72
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Device Tree for Bluestone (APM821xx) board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Tirumala R Marri <tmarri@apm.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.
+ *
+ * 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
+ *
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       model = "apm,bluestone";
+       compatible = "apm,bluestone";
+       dcr-parent = <&{/cpus/cpu@0}>;
+
+       aliases {
+               ethernet0 = &EMAC0;
+               serial0 = &UART0;
+               serial1 = &UART1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       model = "PowerPC,apm821xx";
+                       reg = <0x00000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+                       timebase-frequency = <0>; /* Filled in by U-Boot */
+                       i-cache-line-size = <32>;
+                       d-cache-line-size = <32>;
+                       i-cache-size = <32768>;
+                       d-cache-size = <32768>;
+                       dcr-controller;
+                       dcr-access-method = "native";
+                       next-level-cache = <&L2C0>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+       };
+
+       UIC0: interrupt-controller0 {
+               compatible = "ibm,uic";
+               interrupt-controller;
+               cell-index = <0>;
+               dcr-reg = <0x0c0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+       };
+
+       UIC1: interrupt-controller1 {
+               compatible = "ibm,uic";
+               interrupt-controller;
+               cell-index = <1>;
+               dcr-reg = <0x0d0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC2: interrupt-controller2 {
+               compatible = "ibm,uic";
+               interrupt-controller;
+               cell-index = <2>;
+               dcr-reg = <0x0e0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC3: interrupt-controller3 {
+               compatible = "ibm,uic";
+               interrupt-controller;
+               cell-index = <3>;
+               dcr-reg = <0x0f0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       SDR0: sdr {
+               compatible = "ibm,sdr-apm821xx";
+               dcr-reg = <0x00e 0x002>;
+       };
+
+       CPR0: cpr {
+               compatible = "ibm,cpr-apm821xx";
+               dcr-reg = <0x00c 0x002>;
+       };
+
+       plb {
+               compatible = "ibm,plb4";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges;
+               clock-frequency = <0>; /* Filled in by U-Boot */
+
+               SDRAM0: sdram {
+                       compatible = "ibm,sdram-apm821xx";
+                       dcr-reg = <0x010 0x002>;
+               };
+
+               MAL0: mcmal {
+                       compatible = "ibm,mcmal2";
+                       descriptor-memory = "ocm";
+                       dcr-reg = <0x180 0x062>;
+                       num-tx-chans = <1>;
+                       num-rx-chans = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-parent = <&UIC2>;
+                       interrupts = <  /*TXEOB*/ 0x6 0x4
+                                       /*RXEOB*/ 0x7 0x4
+                                       /*SERR*/  0x3 0x4
+                                       /*TXDE*/  0x4 0x4
+                                       /*RXDE*/  0x5 0x4
+               };
+
+               POB0: opb {
+                       compatible = "ibm,opb";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+
+                       EBC0: ebc {
+                               compatible = "ibm,ebc";
+                               dcr-reg = <0x012 0x002>;
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               /* ranges property is supplied by U-Boot */
+                               ranges = < 0x00000003 0x00000000 0xe0000000 0x8000000>;
+                               interrupts = <0x6 0x4>;
+                               interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "amd,s29gl512n", "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0x00000000 0x00000000 0x00400000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0x00000000 0x00180000>;
+                                       };
+                                       partition@180000 {
+                                               label = "env";
+                                               reg = <0x00180000 0x00020000>;
+                                       };
+                                       partition@1a0000 {
+                                               label = "u-boot";
+                                               reg = <0x001a0000 0x00060000>;
+                                       };
+                               };
+                       }
+
+                       UART0: serial@ef600300 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <0xef600300 0x00000008>;
+                               virtual-reg = <0xef600300>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               current-speed = <0>; /* Filled in by U-Boot */
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <0x1 0x4>;
+                       };
+
+                       IIC0: i2c@ef600700 {
+                               compatible = "ibm,iic";
+                               reg = <0xef600700 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x2 0x4>;
+                       };
+
+                       IIC1: i2c@ef600800 {
+                               compatible = "ibm,iic";
+                               reg = <0xef600800 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x3 0x4>;
+                       };
+
+                       RGMII0: emac-rgmii@ef601500 {
+                               compatible = "ibm,rgmii";
+                               reg = <0xef601500 0x00000008>;
+                               has-mdio;
+                       };
+
+                       TAH0: emac-tah@ef601350 {
+                               compatible = "ibm,tah";
+                               reg = <0xef601350 0x00000030>;
+                       };
+
+                       EMAC0: ethernet@ef600c00 {
+                               device_type = "network";
+                               compatible = "ibm,emac4sync";
+                               interrupt-parent = <&EMAC0>;
+                               interrupts = <0x0 0x1>;
+                               #interrupt-cells = <1>;
+                               #address-cells = <0>;
+                               #size-cells = <0>;
+                               interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+                                                /*Wake*/   0x1 &UIC2 0x14 0x4>;
+                               reg = <0xef600c00 0x000000c4>;
+                               local-mac-address = [000000000000]; /* Filled in by U-Boot */
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <0>;
+                               mal-rx-channel = <0>;
+                               cell-index = <0>;
+                               max-frame-size = <9000>;
+                               rx-fifo-size = <16384>;
+                               tx-fifo-size = <2048>;
+                               phy-mode = "rgmii";
+                               phy-map = <0x00000000>;
+                               rgmii-device = <&RGMII0>;
+                               rgmii-channel = <0>;
+                               tah-device = <&TAH0>;
+                               tah-channel = <0>;
+                               has-inverted-stacr-oc;
+                               has-new-stacr-staopc;
+                       };
+               };
+
+       };
+};
index 5806ef0b860b5adcf8342e472c744f40cbf8821a..a30370396250ae2d524cac63e987bc5a80f7199b 100644 (file)
                        interrupts = <0x1e 4>;
                };
 
+               SATA0: sata@bffd1000 {
+                       compatible = "amcc,sata-460ex";
+                       reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
+                       interrupt-parent = <&UIC3>;
+                       interrupts = <0x0 0x4       /* SATA */
+                                     0x5 0x4>;     /* AHBDMA */
+               };
+
                POB0: opb {
                        compatible = "ibm,opb-460ex", "ibm,opb";
                        #address-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
new file mode 100644 (file)
index 0000000..05a76cc
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * mpc8308_p1m Device Tree Source
+ *
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.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.
+ */
+
+/dts-v1/;
+
+/ {
+       compatible = "denx,mpc8308_p1m";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8308@0 {
+                       device_type = "cpu";
+                       reg = <0x0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <16384>;
+                       i-cache-size = <16384>;
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x08000000>;  // 128MB at 0
+       };
+
+       localbus@e0005000 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc8315-elbc", "fsl,elbc", "simple-bus";
+               reg = <0xe0005000 0x1000>;
+               interrupts = <77 0x8>;
+               interrupt-parent = <&ipic>;
+
+               ranges = <0x0 0x0 0xfc000000 0x04000000
+                         0x1 0x0 0xfbff0000 0x00008000
+                         0x2 0x0 0xfbff8000 0x00008000>;
+
+               flash@0,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x0 0x0 0x4000000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+
+                       u-boot@0 {
+                               reg = <0x0 0x60000>;
+                               read-only;
+                       };
+                       env@60000 {
+                               reg = <0x60000 0x20000>;
+                       };
+                       env1@80000 {
+                               reg = <0x80000 0x20000>;
+                       };
+                       kernel@a0000 {
+                               reg = <0xa0000 0x200000>;
+                       };
+                       dtb@2a0000 {
+                               reg = <0x2a0000 0x20000>;
+                       };
+                       ramdisk@2c0000 {
+                               reg = <0x2c0000 0x640000>;
+                       };
+                       user@700000 {
+                               reg = <0x700000 0x3900000>;
+                       };
+               };
+
+               can@1,0 {
+                       compatible = "nxp,sja1000";
+                       reg = <0x1 0x0 0x80>;
+                       interrupts = <18 0x8>;
+                       interrups-parent = <&ipic>;
+               };
+
+               cpld@2,0 {
+                       compatible = "denx,mpc8308_p1m-cpld";
+                       reg = <0x2 0x0 0x8>;
+                       interrupts = <48 0x8>;
+                       interrups-parent = <&ipic>;
+               };
+       };
+
+       immr@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "fsl,mpc8308-immr", "simple-bus";
+               ranges = <0 0xe0000000 0x00100000>;
+               reg = <0xe0000000 0x00000200>;
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3000 0x100>;
+                       interrupts = <14 0x8>;
+                       interrupt-parent = <&ipic>;
+                       dfsrr;
+                       fram@50 {
+                               compatible = "ramtron,24c64";
+                               reg = <0x50>;
+                       };
+               };
+
+               i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3100 0x100>;
+                       interrupts = <15 0x8>;
+                       interrupt-parent = <&ipic>;
+                       dfsrr;
+                       pwm@28 {
+                               compatible = "maxim,ds1050";
+                               reg = <0x28>;
+                       };
+                       sensor@48 {
+                               compatible = "maxim,max6625";
+                               reg = <0x48>;
+                       };
+                       sensor@49 {
+                               compatible = "maxim,max6625";
+                               reg = <0x49>;
+                       };
+                       sensor@4b {
+                               compatible = "maxim,max6625";
+                               reg = <0x4b>;
+                       };
+               };
+
+               usb@23000 {
+                       compatible = "fsl-usb2-dr";
+                       reg = <0x23000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupt-parent = <&ipic>;
+                       interrupts = <38 0x8>;
+                       dr_mode = "peripheral";
+                       phy_type = "ulpi";
+               };
+
+               enet0: ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x24000 0x1000>;
+
+                       cell-index = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x24000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <32 0x8 33 0x8 34 0x8>;
+                       interrupt-parent = <&ipic>;
+                       phy-handle = < &phy1 >;
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-mdio";
+                               reg = <0x520 0x20>;
+                               phy1: ethernet-phy@1 {
+                                       interrupt-parent = <&ipic>;
+                                       interrupts = <17 0x8>;
+                                       reg = <0x1>;
+                                       device_type = "ethernet-phy";
+                               };
+                               phy2: ethernet-phy@2 {
+                                       interrupt-parent = <&ipic>;
+                                       interrupts = <19 0x8>;
+                                       reg = <0x2>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
+               };
+
+               enet1: ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <1>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x25000 0x1000>;
+                       ranges = <0x0 0x25000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <35 0x8 36 0x8 37 0x8>;
+                       interrupt-parent = <&ipic>;
+                       phy-handle = < &phy2 >;
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+                               tbi1: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
+               };
+
+               serial0: serial@4500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4500 0x100>;
+                       clock-frequency = <133333333>;
+                       interrupts = <9 0x8>;
+                       interrupt-parent = <&ipic>;
+               };
+
+               serial1: serial@4600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4600 0x100>;
+                       clock-frequency = <133333333>;
+                       interrupts = <10 0x8>;
+                       interrupt-parent = <&ipic>;
+               };
+
+               gpio@c00 {
+                       #gpio-cells = <2>;
+                       compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
+                       reg = <0xc00 0x18>;
+                       interrupts = <74 0x8>;
+                       interrupt-parent = <&ipic>;
+                       gpio-controller;
+               };
+
+               timer@500 {
+                       compatible = "fsl,mpc8308-gtm", "fsl,gtm";
+                       reg = <0x500 0x100>;
+                       interrupts = <90 8 78 8 84 8 72 8>;
+                       interrupt-parent = <&ipic>;
+                       clock-frequency = <133333333>;
+               };
+
+               /* IPIC
+                * interrupts cell = <intr #, sense>
+                * sense values match linux IORESOURCE_IRQ_* defines:
+                * sense == 8: Level, low assertion
+                * sense == 2: Edge, high-to-low change
+                */
+               ipic: interrupt-controller@700 {
+                       compatible = "fsl,ipic";
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <0x700 0x100>;
+                       device_type = "ipic";
+               };
+
+               ipic-msi@7c0 {
+                       compatible = "fsl,ipic-msi";
+                       reg = <0x7c0 0x40>;
+                       msi-available-ranges = <0x0 0x100>;
+                       interrupts = < 0x43 0x8
+                                       0x4  0x8
+                                       0x51 0x8
+                                       0x52 0x8
+                                       0x56 0x8
+                                       0x57 0x8
+                                       0x58 0x8
+                                       0x59 0x8 >;
+                       interrupt-parent = < &ipic >;
+               };
+
+       };
+
+       pci0: pcie@e0009000 {
+               #address-cells = <3>;
+               #size-cells = <2>;
+               #interrupt-cells = <1>;
+               device_type = "pci";
+               compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie";
+               reg = <0xe0009000 0x00001000
+                       0xb0000000 0x01000000>;
+               ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
+               bus-range = <0 0>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &ipic 1 8>;
+               interrupts = <0x1 0x8>;
+               interrupt-parent = <&ipic>;
+               clock-frequency = <0>;
+
+               pcie@0 {
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       reg = <0 0 0 0 0>;
+                       ranges = <0x02000000 0 0xa0000000
+                                 0x02000000 0 0xa0000000
+                                 0 0x10000000
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00800000>;
+               };
+       };
+};
index 815cebb2e3e593641feae4101fde07d419641110..a75c10eed2690ba1d9c7084683517c9cd2a418d3 100644 (file)
                        };
                };
 
+               spi@7000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc8536-espi";
+                       reg = <0x7000 0x1000>;
+                       interrupts = <59 0x2>;
+                       interrupt-parent = <&mpic>;
+                       fsl,espi-num-chipselects = <4>;
+
+                       flash@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,s25sl12801";
+                               reg = <0>;
+                               spi-max-frequency = <40000000>;
+                               partition@u-boot {
+                                       label = "u-boot";
+                                       reg = <0x00000000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@kernel {
+                                       label = "kernel";
+                                       reg = <0x00100000 0x00500000>;
+                                       read-only;
+                               };
+                               partition@dtb {
+                                       label = "dtb";
+                                       reg = <0x00600000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@fs {
+                                       label = "file system";
+                                       reg = <0x00700000 0x00900000>;
+                               };
+                       };
+                       flash@1 {
+                               compatible = "spansion,s25sl12801";
+                               reg = <1>;
+                               spi-max-frequency = <40000000>;
+                       };
+                       flash@2 {
+                               compatible = "spansion,s25sl12801";
+                               reg = <2>;
+                               spi-max-frequency = <40000000>;
+                       };
+                       flash@3 {
+                               compatible = "spansion,s25sl12801";
+                               reg = <3>;
+                               spi-max-frequency = <40000000>;
+                       };
+               };
+
                dma@21300 {
                        #address-cells = <1>;
                        #size-cells = <1>;
index 8bcb10b9267744593b0a95b824f7b205f70030eb..2bbecbb4cbf9a3388749128d751503ce41595aa7 100644 (file)
                                label = "reserved-nand";
                        };
                };
+
+               board-control@3,0 {
+                       compatible = "fsl,p1022ds-pixis";
+                       reg = <3 0 0x30>;
+                       interrupt-parent = <&mpic>;
+                       /*
+                        * IRQ8 is generated if the "EVENT" switch is pressed
+                        * and PX_CTL[EVESEL] is set to 00.
+                        */
+                       interrupts = <8 8>;
+               };
        };
 
        soc@fffe00000 {
index 2f0de24e3822577631169c765f8ac17510144b70..5b7fc29dd6cf6a0aeb81501fc658b7d4e7cd1d04 100644 (file)
                };
 
                spi@110000 {
-                       cell-index = <0>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       compatible = "fsl,espi";
+                       compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
                        reg = <0x110000 0x1000>;
                        interrupts = <53 0x2>;
                        interrupt-parent = <&mpic>;
-                       espi,num-ss-bits = <4>;
-                       mode = "cpu";
+                       fsl,espi-num-chipselects = <4>;
 
-                       fsl_m25p80@0 {
+                       flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "fsl,espi-flash";
+                               compatible = "spansion,s25sl12801";
                                reg = <0>;
-                               linux,modalias = "fsl_m25p80";
                                spi-max-frequency = <40000000>; /* input clock */
                                partition@u-boot {
                                        label = "u-boot";
diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig
new file mode 100644 (file)
index 0000000..ac65b48
--- /dev/null
@@ -0,0 +1,68 @@
+CONFIG_44x=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BLUESTONE=y
+# CONFIG_EBONY is not set
+# CONFIG_KVM_GUEST is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IBM_IIC=y
+CONFIG_SENSORS_AD7414=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS=y
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig
new file mode 100644 (file)
index 0000000..94d120e
--- /dev/null
@@ -0,0 +1,84 @@
+CONFIG_PPC64=y
+CONFIG_PPC_BOOK3E_64=y
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P5020_DS=y
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BINFMT_MISC=m
+CONFIG_SPARSE_IRQ=y
+# CONFIG_PCI is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_EEPROM_LEGACY=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_LIBCRC32C=m
+CONFIG_FRAME_WARN=1024
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TALITOS=y
index cd446fba3faedc2c044575948dd21ea61161ae8c..2fa05f7be4cb9977f273eee5979a24c366353eae 100644 (file)
@@ -12,6 +12,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_BAMBOO=y
+CONFIG_BLUESTONE=y
 CONFIG_SAM440EP=y
 CONFIG_SEQUOIA=y
 CONFIG_TAISHAN=y
@@ -97,14 +98,17 @@ CONFIG_USB_STORAGE=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=m
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=m
 CONFIG_UBIFS_FS_XATTR=y
+CONFIG_LOGFS=m
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
@@ -116,11 +120,8 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_VIRTUALIZATION=y
index 04ae0740b6d0fde0147861746e262825e5903d4f..7bd1763877babeb272b7e3b6a962330de7f6d91e 100644 (file)
@@ -18,6 +18,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_P5020_DS=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -256,7 +257,6 @@ CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=m
@@ -290,7 +290,6 @@ CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_POSIX_ACL=y
-CONFIG_INOTIFY=y
 CONFIG_AUTOFS4_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_UDF_FS=m
@@ -384,7 +383,6 @@ CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_KHAZAD=m
index 7cdf358337cf246c21634650af8495086750361a..ce0c28495f9a0416450a33a4ceee4b3a33be45c2 100644 (file)
@@ -52,12 +52,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
 extern __wsum csum_partial_copy_generic(const void *src, void *dst,
                                              int len, __wsum sum,
                                              int *src_err, int *dst_err);
+
+#ifdef __powerpc64__
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
+                                     int len, __wsum sum, int *err_ptr);
+#define HAVE_CSUM_COPY_USER
+extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
+                                   int len, __wsum sum, int *err_ptr);
+#else
 /*
  * the same as csum_partial, but copies from src to dst while it
  * checksums.
  */
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
         csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
+#endif
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
         csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
index 396d21a800587f0c8a740714a3277a743d2618cc..2296112e247befe8050526420f6fa8db2a42d693 100644 (file)
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = current->thread.regs;
        unsigned long usp = regs->gpr[1];
@@ -143,7 +143,7 @@ static inline void __user *compat_alloc_user_space(long len)
         * We cant access below the stack pointer in the 32bit ABI and
         * can access 288 bytes in the 64bit ABI
         */
-       if (!(test_thread_flag(TIF_32BIT)))
+       if (!is_32bit_task())
                usp -= 288;
 
        return (void __user *) (usp - len);
@@ -213,7 +213,7 @@ struct compat_shmid64_ds {
 
 static inline int is_compat_task(void)
 {
-       return test_thread_flag(TIF_32BIT);
+       return is_32bit_task();
 }
 
 #endif /* __KERNEL__ */
index 3a40a992e5941ea73628aca26f12a30cd0d387d0..f3a1fdd9cf08b67ede4102dab01b8a353c3c826f 100644 (file)
@@ -198,6 +198,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_CP_USE_DCBTZ           LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_UNALIGNED_LD_STD       LONG_ASM_CONST(0x0080000000000000)
 #define CPU_FTR_ASYM_SMT               LONG_ASM_CONST(0x0100000000000000)
+#define CPU_FTR_STCX_CHECKS_ADDRESS    LONG_ASM_CONST(0x0200000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -392,28 +393,31 @@ extern const char *powerpc_base_platform;
            CPU_FTR_MMCRA | CPU_FTR_CTRL)
 #define CPU_FTRS_POWER4        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ)
+           CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
+           CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_PPC970        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
-           CPU_FTR_CP_USE_DCBTZ)
+           CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER5        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-           CPU_FTR_PURR)
+           CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-           CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD)
+           CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
+           CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-           CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT)
+           CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
+           CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_CELL  (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
index 8c9c6ad2004ea1f47ce3e5009da4bf9245131327..6d2416a857096be9548964987af7f701a5fe15c2 100644 (file)
@@ -127,19 +127,7 @@ static inline int dma_supported(struct device *dev, u64 mask)
        return dma_ops->dma_supported(dev, mask);
 }
 
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-       struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
-       if (unlikely(dma_ops == NULL))
-               return -EIO;
-       if (dma_ops->set_dma_mask != NULL)
-               return dma_ops->set_dma_mask(dev, dma_mask);
-       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-               return -EIO;
-       *dev->dma_mask = dma_mask;
-       return 0;
-}
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
                                       dma_addr_t *dma_handle, gfp_t flag)
index c376eda153139673bc879e8b5489470db7a00e99..2b917c69ed15683bc4d761a5c5b6a5d7304718af 100644 (file)
@@ -250,7 +250,7 @@ do {                                                                \
  * the 64bit ABI has never had these issues dont enable the workaround
  * even if we have an executable stack.
  */
-# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \
                (exec_stk == EXSTACK_DEFAULT) : 0)
 #else 
 # define SET_PERSONALITY(ex) \
index 57c4000719959cd4409d109f13d5cb723e70e95c..7778d6f0c878a614a4bda84c52f2a77d02012a07 100644 (file)
        li      r10,0;                                                     \
        ld      r11,exception_marker@toc(r2);                              \
        std     r10,RESULT(r1);         /* clear regs->result           */ \
-       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */
+       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */ \
+       ACCOUNT_STOLEN_TIME
 
 /*
  * Exception vectors.
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
new file mode 100644 (file)
index 0000000..2af2bdc
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Cache SRAM handling for QorIQ platform
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+#define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+
+#include <asm/rheap.h>
+#include <linux/spinlock.h>
+
+/*
+ * Cache-SRAM
+ */
+
+struct mpc85xx_cache_sram {
+       phys_addr_t base_phys;
+       void *base_virt;
+       unsigned int size;
+       rh_info_t *rh;
+       spinlock_t lock;
+};
+
+extern void mpc85xx_cache_sram_free(void *ptr);
+extern void *mpc85xx_cache_sram_alloc(unsigned int size,
+                                 phys_addr_t *phys, unsigned int align);
+
+#endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */
index a67aeed17d405fbc37e3a44a860c67a3a1dd9fcf..debc5ed96d6e087a2e241e47421f537a13bf1feb 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
 #define __ARCH_POWERPC_ASM_FSLDMA_H__
 
+#include <linux/slab.h>
 #include <linux/dmaengine.h>
 
 /*
index bd100fcf40d0c1263e81e5d737e2ec6cfc32b025..ff08b70b36d4befb36139fadbe0cec54829096e8 100644 (file)
@@ -16,42 +16,57 @@ extern void timer_interrupt(struct pt_regs *);
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 
-static inline unsigned long local_get_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
 
-       __asm__ __volatile__("lbz %0,%1(13)"
-       : "=r" (flags)
-       : "i" (offsetof(struct paca_struct, soft_enabled)));
+       asm volatile(
+               "lbz %0,%1(13)"
+               : "=r" (flags)
+               : "i" (offsetof(struct paca_struct, soft_enabled)));
 
        return flags;
 }
 
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_disable(void)
 {
        unsigned long flags, zero;
 
-       __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)"
-       : "=r" (flags), "=&r" (zero)
-       : "i" (offsetof(struct paca_struct, soft_enabled))
-       : "memory");
+       asm volatile(
+               "li %1,0; lbz %0,%2(13); stb %1,%2(13)"
+               : "=r" (flags), "=&r" (zero)
+               : "i" (offsetof(struct paca_struct, soft_enabled))
+               : "memory");
 
        return flags;
 }
 
-extern void raw_local_irq_restore(unsigned long);
+extern void arch_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define raw_local_irq_enable()         raw_local_irq_restore(1)
-#define raw_local_save_flags(flags)    ((flags) = local_get_flags())
-#define raw_local_irq_save(flags)      ((flags) = raw_local_irq_disable())
+static inline void arch_local_irq_enable(void)
+{
+       arch_local_irq_restore(1);
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       return arch_local_irq_disable();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return flags == 0;
+}
 
-#define raw_irqs_disabled()            (local_get_flags() == 0)
-#define raw_irqs_disabled_flags(flags) ((flags) == 0)
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable()    __asm__ __volatile__("wrteei 1": : :"memory");
-#define __hard_irq_disable()   __asm__ __volatile__("wrteei 0": : :"memory");
+#define __hard_irq_enable()    asm volatile("wrteei 1" : : : "memory");
+#define __hard_irq_disable()   asm volatile("wrteei 0" : : : "memory");
 #else
 #define __hard_irq_enable()    __mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()   __mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -64,64 +79,66 @@ extern void iseries_handle_interrupts(void);
                get_paca()->hard_enabled = 0;   \
        } while(0)
 
-#else
+#else /* CONFIG_PPC64 */
 
-#if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)  mtmsr(x)
-#define raw_local_irq_restore(flags)   __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       return mfmsr();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#if defined(CONFIG_BOOKE)
+       asm volatile("wrtee %0" : : "r" (flags) : "memory");
 #else
-#define SET_MSR_EE(x)  mtmsr(x)
-#define raw_local_irq_restore(flags)   mtmsr(flags)
+       mtmsr(flags);
 #endif
+}
 
-static inline void raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_save(void)
 {
+       unsigned long flags = arch_local_save_flags();
 #ifdef CONFIG_BOOKE
-       __asm__ __volatile__("wrteei 0": : :"memory");
+       asm volatile("wrteei 0" : : : "memory");
 #else
-       unsigned long msr;
-
-       msr = mfmsr();
-       SET_MSR_EE(msr & ~MSR_EE);
+       SET_MSR_EE(flags & ~MSR_EE);
 #endif
+       return flags;
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
-       __asm__ __volatile__("wrteei 1": : :"memory");
+       asm volatile("wrteei 0" : : : "memory");
 #else
-       unsigned long msr;
-
-       msr = mfmsr();
-       SET_MSR_EE(msr | MSR_EE);
+       arch_local_irq_save();
 #endif
 }
 
-static inline void raw_local_irq_save_ptr(unsigned long *flags)
+static inline void arch_local_irq_enable(void)
 {
-       unsigned long msr;
-       msr = mfmsr();
-       *flags = msr;
 #ifdef CONFIG_BOOKE
-       __asm__ __volatile__("wrteei 0": : :"memory");
+       asm volatile("wrteei 1" : : : "memory");
 #else
-       SET_MSR_EE(msr & ~MSR_EE);
+       unsigned long msr = mfmsr();
+       SET_MSR_EE(msr | MSR_EE);
 #endif
 }
 
-#define raw_local_save_flags(flags)    ((flags) = mfmsr())
-#define raw_local_irq_save(flags)      raw_local_irq_save_ptr(&flags)
-#define raw_irqs_disabled()            ((mfmsr() & MSR_EE) == 0)
-#define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0)
-
-#define hard_irq_disable()             raw_local_irq_disable()
-
-static inline int irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return (flags & MSR_EE) == 0;
 }
 
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#define hard_irq_disable()             arch_local_irq_disable()
+
 #endif /* CONFIG_PPC64 */
 
 /*
index 5f68ecfdf516bf85d2094396363849647dae9ebd..b85d8ddbb6668b77aed280e750e971c9619f5df0 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifndef __ASSEMBLY__
 /*
- * Get definitions for raw_local_save_flags(x), etc.
+ * Get definitions for arch_local_save_flags(x), etc.
  */
 #include <asm/hw_irq.h>
 
index 076327f2eff777b2cdbd4e15de8336ce7b03faa6..f54408d995b5b9df718f818f4fdf16d37c796517 100644 (file)
@@ -91,6 +91,7 @@ extern void machine_kexec_simple(struct kimage *image);
 extern void crash_kexec_secondary(struct pt_regs *regs);
 extern int overlaps_crashkernel(unsigned long start, unsigned long size);
 extern void reserve_crashkernel(void);
+extern void machine_kexec_mask_interrupts(void);
 
 #else /* !CONFIG_KEXEC */
 static inline int kexec_sr_activated(int cpu) { return 0; }
index c3d4f0518a67c2f89b4c42e3d1b81e20dea0c059..92daae13249245e31783b31756b3b88608f9cf68 100644 (file)
@@ -82,7 +82,7 @@ FPD_THREE_IN(fmadd)
 FPD_THREE_IN(fnmsub)
 FPD_THREE_IN(fnmadd)
 
-extern void kvm_cvt_fd(u32 *from, u64 *to, u64 *fpscr);
-extern void kvm_cvt_df(u64 *from, u32 *to, u64 *fpscr);
+extern void kvm_cvt_fd(u32 *from, u64 *to);
+extern void kvm_cvt_df(u64 *from, u32 *to);
 
 #endif
index 14b592dfb4e824f691a71c248e2f60c6827dcf0e..7f5e0fefebb0f14d5a8456ef8098a16107f70208 100644 (file)
@@ -153,6 +153,8 @@ struct lppaca {
 
 extern struct lppaca lppaca[];
 
+#define lppaca_of(cpu) (*paca[cpu].lppaca_ptr)
+
 /*
  * SLB shadow buffer structure as defined in the PAPR.  The save_area
  * contains adjacent ESID and VSID pairs for each shadowed SLB.  The
@@ -170,6 +172,33 @@ struct slb_shadow {
 
 extern struct slb_shadow slb_shadow[];
 
+/*
+ * Layout of entries in the hypervisor's dispatch trace log buffer.
+ */
+struct dtl_entry {
+       u8      dispatch_reason;
+       u8      preempt_reason;
+       u16     processor_id;
+       u32     enqueue_to_dispatch_time;
+       u32     ready_to_enqueue_time;
+       u32     waiting_to_ready_time;
+       u64     timebase;
+       u64     fault_addr;
+       u64     srr0;
+       u64     srr1;
+};
+
+#define DISPATCH_LOG_BYTES     4096    /* bytes per cpu */
+#define N_DISPATCH_LOG         (DISPATCH_LOG_BYTES / sizeof(struct dtl_entry))
+
+/*
+ * When CONFIG_VIRT_CPU_ACCOUNTING = y, the cpu accounting code controls
+ * reading from the dispatch trace log.  If other code wants to consume
+ * DTL entries, it can set this pointer to a function that will get
+ * called once for each DTL entry that gets processed.
+ */
+extern void (*dtl_consumer)(struct dtl_entry *entry, u64 index);
+
 #endif /* CONFIG_PPC_BOOK3S */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_LPPACA_H */
index adc8e6cdf33914bef9fd07fc69f60ab9730959ea..d045b0145537d47c5201c891f47079b93d4d8681 100644 (file)
@@ -102,6 +102,9 @@ struct machdep_calls {
        void            (*pci_dma_dev_setup)(struct pci_dev *dev);
        void            (*pci_dma_bus_setup)(struct pci_bus *bus);
 
+       /* Platform set_dma_mask override */
+       int             (*dma_set_mask)(struct device *dev, u64 dma_mask);
+
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
        void            (*init_early)(void);
index 3c29728b56b1df4ef2fc6b2c5396717af6daa2a8..43efc345065e968246fc07638503e7fb5ba8911f 100644 (file)
@@ -5,11 +5,4 @@
 
 #define MEMBLOCK_DBG(fmt...) udbg_printf(fmt)
 
-#ifdef CONFIG_PPC32
-extern phys_addr_t lowmem_end_addr;
-#define MEMBLOCK_REAL_LIMIT    lowmem_end_addr
-#else
-#define MEMBLOCK_REAL_LIMIT    0
-#endif
-
 #endif /* _ASM_POWERPC_MEMBLOCK_H */
index 87a1d787c5b626cf3747eb915be383f605b11179..8eaed81ea642663d7aae026ae899a667022302b1 100644 (file)
 
 #define MAS7_RPN               0xFFFFFFFF
 
+/* Bit definitions for MMUCFG */
+#define MMUCFG_MAVN    0x00000003      /* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1 0x00000000      /* v1.0 */
+#define MMUCFG_MAVN_V2 0x00000001      /* v2.0 */
+#define MMUCFG_NTLBS   0x0000000c      /* Number of TLBs */
+#define MMUCFG_PIDSIZE 0x000007c0      /* PID Reg Size */
+#define MMUCFG_TWC     0x00008000      /* TLB Write Conditional (v2.0) */
+#define MMUCFG_LRAT    0x00010000      /* LRAT Supported (v2.0) */
+#define MMUCFG_RASIZE  0x00fe0000      /* Real Addr Size */
+#define MMUCFG_LPIDSIZE        0x0f000000      /* LPID Reg Size */
+
 /* Bit definitions for MMUCSR0 */
 #define MMUCSR0_TLB1FI 0x00000002      /* TLB1 Flash invalidate */
 #define MMUCSR0_TLB0FI 0x00000004      /* TLB0 Flash invalidate */
 #define TLBnCFG_GTWE           0x00010000      /* Guest can write */
 #define TLBnCFG_IND            0x00020000      /* IND entries supported */
 #define TLBnCFG_PT             0x00040000      /* Can load from page table */
+#define TLBnCFG_MINSIZE                0x00f00000      /* Minimum Page Size (v1.0) */
+#define TLBnCFG_MINSIZE_SHIFT  20
+#define TLBnCFG_MAXSIZE                0x000f0000      /* Maximum Page Size (v1.0) */
+#define TLBnCFG_MAXSIZE_SHIFT  16
 #define TLBnCFG_ASSOC          0xff000000      /* Associativity */
 
 /* TLBnPS encoding */
index 0e398cfee2c82826b6abad1eb8ece6330df6b0b4..acac35d5b382da579cd53061c089a88a7758bb2f 100644 (file)
@@ -433,7 +433,7 @@ typedef struct {
  * with.  However gcc is not clever enough to compute the
  * modulus (2^n-1) without a second multiply.
  */
-#define vsid_scrample(protovsid, size) \
+#define vsid_scramble(protovsid, size) \
        ((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size))
 
 #else /* 1 */
index 7ebf42ed84a2aef049946757b2a4c6afe81501c7..bb40a06d3b7701d418b750a24b16a22385570bba 100644 (file)
@@ -2,6 +2,8 @@
 #define _ASM_POWERPC_MMU_H_
 #ifdef __KERNEL__
 
+#include <linux/types.h>
+
 #include <asm/asm-compat.h>
 #include <asm/feature-fixups.h>
 
@@ -82,6 +84,16 @@ extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
 extern void early_init_mmu(void);
 extern void early_init_mmu_secondary(void);
 
+extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                                      phys_addr_t first_memblock_size);
+
+#ifdef CONFIG_PPC64
+/* This is our real memory area size on ppc64 server, on embedded, we
+ * make it match the size our of bolted TLB area
+ */
+extern u64 ppc64_rma_size;
+#endif /* CONFIG_PPC64 */
+
 #endif /* !__ASSEMBLY__ */
 
 /* The kernel use the constants below to index in the page sizes array.
index 1ff6662f7faf28ffce6577ac40f0a237f2b866e8..ec57540cd7af639b6d111f01bc2ae1f8d98c1a46 100644 (file)
@@ -85,6 +85,8 @@ struct paca_struct {
        u8 kexec_state;         /* set when kexec down has irqs off */
 #ifdef CONFIG_PPC_STD_MMU_64
        struct slb_shadow *slb_shadow_ptr;
+       struct dtl_entry *dispatch_log;
+       struct dtl_entry *dispatch_log_end;
 
        /*
         * Now, starting in cacheline 2, the exception save areas
@@ -129,13 +131,19 @@ struct paca_struct {
        u8 soft_enabled;                /* irq soft-enable flag */
        u8 hard_enabled;                /* set if irqs are enabled in MSR */
        u8 io_sync;                     /* writel() needs spin_unlock sync */
-       u8 perf_event_pending;          /* PM interrupt while soft-disabled */
+       u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
 
        /* Stuff for accurate time accounting */
        u64 user_time;                  /* accumulated usermode TB ticks */
        u64 system_time;                /* accumulated system TB ticks */
-       u64 startpurr;                  /* PURR/TB value snapshot */
+       u64 user_time_scaled;           /* accumulated usermode SPURR ticks */
+       u64 starttime;                  /* TB value snapshot */
+       u64 starttime_user;             /* TB value on exit to usermode */
        u64 startspurr;                 /* SPURR value snapshot */
+       u64 utime_sspurr;               /* ->user_time when ->startspurr set */
+       u64 stolen_time;                /* TB ticks taken by hypervisor */
+       u64 dtl_ridx;                   /* read index in dispatch log */
+       struct dtl_entry *dtl_curr;     /* pointer corresponding to dtl_ridx */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
        /* We use this to store guest state in */
index 358ff14ea25ed2d917f442576dba3ac841a1f9b5..932f88dcf6fa175616ca5dae4f3315e684120dbe 100644 (file)
@@ -163,7 +163,7 @@ do {                                                \
 #endif /* !CONFIG_HUGETLB_PAGE */
 
 #define VM_DATA_DEFAULT_FLAGS \
-       (test_thread_flag(TIF_32BIT) ? \
+       (is_32bit_task() ? \
         VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
 
 /*
@@ -179,7 +179,7 @@ do {                                                \
                                         VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #define VM_STACK_DEFAULT_FLAGS \
-       (test_thread_flag(TIF_32BIT) ? \
+       (is_32bit_task() ? \
         VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
 
 #include <asm-generic/getorder.h>
index 42fdff0e4b329a266b6398893fda81bd80de0b8d..43268f15004e8082148cc1a57de8766fdad75c7d 100644 (file)
@@ -28,8 +28,8 @@ extern void find_and_init_phbs(void);
 extern struct pci_dev *isa_bridge_pcidev;      /* may be NULL if no ISA bus */
 
 /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
-#define BUID_HI(buid) ((buid) >> 32)
-#define BUID_LO(buid) ((buid) & 0xffffffff)
+#define BUID_HI(buid) upper_32_bits(buid)
+#define BUID_LO(buid) lower_32_bits(buid)
 
 /* PCI device_node operations */
 struct device_node;
index 498fe09263d3e7df23ca37b848996339ff50b23c..98210067c1ccbac17f449946a4a5b42023cea1f2 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/asm-compat.h>
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
+#include <asm/firmware.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 #define ACCOUNT_CPU_USER_ENTRY(ra, rb)
 #define ACCOUNT_CPU_USER_EXIT(ra, rb)
+#define ACCOUNT_STOLEN_TIME
 #else
 #define ACCOUNT_CPU_USER_ENTRY(ra, rb)                                 \
        beq     2f;                     /* if from kernel mode */       \
-BEGIN_FTR_SECTION;                                                     \
-       mfspr   ra,SPRN_PURR;           /* get processor util. reg */   \
-END_FTR_SECTION_IFSET(CPU_FTR_PURR);                                   \
-BEGIN_FTR_SECTION;                                                     \
-       MFTB(ra);                       /* or get TB if no PURR */      \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);                                   \
-       ld      rb,PACA_STARTPURR(r13);                                 \
-       std     ra,PACA_STARTPURR(r13);                                 \
+       MFTB(ra);                       /* get timebase */              \
+       ld      rb,PACA_STARTTIME_USER(r13);                            \
+       std     ra,PACA_STARTTIME(r13);                                 \
        subf    rb,rb,ra;               /* subtract start value */      \
        ld      ra,PACA_USER_TIME(r13);                                 \
        add     ra,ra,rb;               /* add on to user time */       \
@@ -44,19 +41,34 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR);                                        \
 2:
 
 #define ACCOUNT_CPU_USER_EXIT(ra, rb)                                  \
-BEGIN_FTR_SECTION;                                                     \
-       mfspr   ra,SPRN_PURR;           /* get processor util. reg */   \
-END_FTR_SECTION_IFSET(CPU_FTR_PURR);                                   \
-BEGIN_FTR_SECTION;                                                     \
-       MFTB(ra);                       /* or get TB if no PURR */      \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);                                   \
-       ld      rb,PACA_STARTPURR(r13);                                 \
-       std     ra,PACA_STARTPURR(r13);                                 \
+       MFTB(ra);                       /* get timebase */              \
+       ld      rb,PACA_STARTTIME(r13);                                 \
+       std     ra,PACA_STARTTIME_USER(r13);                            \
        subf    rb,rb,ra;               /* subtract start value */      \
        ld      ra,PACA_SYSTEM_TIME(r13);                               \
-       add     ra,ra,rb;               /* add on to user time */       \
-       std     ra,PACA_SYSTEM_TIME(r13);
-#endif
+       add     ra,ra,rb;               /* add on to system time */     \
+       std     ra,PACA_SYSTEM_TIME(r13)
+
+#ifdef CONFIG_PPC_SPLPAR
+#define ACCOUNT_STOLEN_TIME                                            \
+BEGIN_FW_FTR_SECTION;                                                  \
+       beq     33f;                                                    \
+       /* from user - see if there are any DTL entries to process */   \
+       ld      r10,PACALPPACAPTR(r13); /* get ptr to VPA */            \
+       ld      r11,PACA_DTL_RIDX(r13); /* get log read index */        \
+       ld      r10,LPPACA_DTLIDX(r10); /* get log write index */       \
+       cmpd    cr1,r11,r10;                                            \
+       beq+    cr1,33f;                                                \
+       bl      .accumulate_stolen_time;                                \
+33:                                                                    \
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+
+#else  /* CONFIG_PPC_SPLPAR */
+#define ACCOUNT_STOLEN_TIME
+
+#endif /* CONFIG_PPC_SPLPAR */
+
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
 
 /*
  * Macros for storing registers into and loading registers from
index 19c05b0f74bedb30ea4beddaba9ff005b3d6f2e1..4c14187ba02d24ab65c361023bedf93fff24a30f 100644 (file)
@@ -118,7 +118,7 @@ extern struct task_struct *last_task_used_spe;
 #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
 #define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
 
-#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)) ? \
+#define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \
                TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
 #endif
 
@@ -128,7 +128,7 @@ extern struct task_struct *last_task_used_spe;
 #define STACK_TOP_USER64 TASK_SIZE_USER64
 #define STACK_TOP_USER32 TASK_SIZE_USER32
 
-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+#define STACK_TOP (is_32bit_task() ? \
                   STACK_TOP_USER32 : STACK_TOP_USER64)
 
 #define STACK_TOP_MAX STACK_TOP_USER64
index f2b370180a09772546e2f9fccef588d53660ff88..76bb195e4f24d0e89db09665297dd68ec83ccb37 100644 (file)
@@ -171,6 +171,13 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
 /* Make modules code happy. We don't set RO yet */
 #define PAGE_KERNEL_EXEC       PAGE_KERNEL_X
 
+/*
+ * Don't just check for any non zero bits in __PAGE_USER, since for book3e
+ * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
+ * _PAGE_USER.  Need to explictly match _PAGE_BAP_UR bit in that case too.
+ */
+#define pte_user(val)          ((val & _PAGE_USER) == _PAGE_USER)
+
 /* Advertise special mapping type for AGP */
 #define PAGE_AGP               (PAGE_KERNEL_NC)
 #define HAVE_PAGE_AGP
index d8be016d2ede49e750ad68c478203afe7b45f9a7..ff0005eec7dd0d3d3c54946bcbf51cdfdf8bb569 100644 (file)
 #ifdef CONFIG_PPC64
 
 extern void ppc64_runlatch_on(void);
-extern void ppc64_runlatch_off(void);
+extern void __ppc64_runlatch_off(void);
+
+#define ppc64_runlatch_off()                                   \
+       do {                                                    \
+               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
+                   test_thread_flag(TIF_RUNLATCH))             \
+                       __ppc64_runlatch_off();                 \
+       } while (0)
 
 extern unsigned long scom970_read(unsigned int address);
 extern void scom970_write(unsigned int address, unsigned long value);
index 3d35f8ae377e1b446cc8db98c0ee971f218f24cc..9a1193e30f26ce0e6545cf67c440336723ac7185 100644 (file)
@@ -187,6 +187,7 @@ extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_ibm_suspend_me(struct rtas_args *);
 
 struct rtc_time;
 extern unsigned long rtas_get_boot_time(void);
index 24cd9281ec3726a55c95a7a9f8d076c76b97e2b8..8447d89fbe72639a6a0ce2db68694554bd7c61e8 100644 (file)
 /*
  * the semaphore definition
  */
-struct rw_semaphore {
-       /* XXX this should be able to be an atomic_t  -- paulus */
-       signed int              count;
-#define RWSEM_UNLOCKED_VALUE           0x00000000
-#define RWSEM_ACTIVE_BIAS              0x00000001
-#define RWSEM_ACTIVE_MASK              0x0000ffff
-#define RWSEM_WAITING_BIAS             (-0x00010000)
+#ifdef CONFIG_PPC64
+# define RWSEM_ACTIVE_MASK             0xffffffffL
+#else
+# define RWSEM_ACTIVE_MASK             0x0000ffffL
+#endif
+
+#define RWSEM_UNLOCKED_VALUE           0x00000000L
+#define RWSEM_ACTIVE_BIAS              0x00000001L
+#define RWSEM_WAITING_BIAS             (-RWSEM_ACTIVE_MASK-1)
 #define RWSEM_ACTIVE_READ_BIAS         RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+struct rw_semaphore {
+       long                    count;
        spinlock_t              wait_lock;
        struct list_head        wait_list;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -43,9 +48,13 @@ struct rw_semaphore {
 # define __RWSEM_DEP_MAP_INIT(lockname)
 #endif
 
-#define __RWSEM_INITIALIZER(name) \
-       { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-         LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
+#define __RWSEM_INITIALIZER(name)                              \
+{                                                              \
+       RWSEM_UNLOCKED_VALUE,                                   \
+       __SPIN_LOCK_UNLOCKED((name).wait_lock),                 \
+       LIST_HEAD_INIT((name).wait_list)                        \
+       __RWSEM_DEP_MAP_INIT(name)                              \
+}
 
 #define DECLARE_RWSEM(name)            \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -70,13 +79,13 @@ extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
  */
 static inline void __down_read(struct rw_semaphore *sem)
 {
-       if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0))
+       if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0))
                rwsem_down_read_failed(sem);
 }
 
 static inline int __down_read_trylock(struct rw_semaphore *sem)
 {
-       int tmp;
+       long tmp;
 
        while ((tmp = sem->count) >= 0) {
                if (tmp == cmpxchg(&sem->count, tmp,
@@ -92,10 +101,10 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
  */
 static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
-       int tmp;
+       long tmp;
 
-       tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
-                               (atomic_t *)(&sem->count));
+       tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+                                    (atomic_long_t *)&sem->count);
        if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
                rwsem_down_write_failed(sem);
 }
@@ -107,7 +116,7 @@ static inline void __down_write(struct rw_semaphore *sem)
 
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
-       int tmp;
+       long tmp;
 
        tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
                      RWSEM_ACTIVE_WRITE_BIAS);
@@ -119,9 +128,9 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
  */
 static inline void __up_read(struct rw_semaphore *sem)
 {
-       int tmp;
+       long tmp;
 
-       tmp = atomic_dec_return((atomic_t *)(&sem->count));
+       tmp = atomic_long_dec_return((atomic_long_t *)&sem->count);
        if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
                rwsem_wake(sem);
 }
@@ -131,17 +140,17 @@ static inline void __up_read(struct rw_semaphore *sem)
  */
 static inline void __up_write(struct rw_semaphore *sem)
 {
-       if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
-                             (atomic_t *)(&sem->count)) < 0))
+       if (unlikely(atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+                                (atomic_long_t *)&sem->count) < 0))
                rwsem_wake(sem);
 }
 
 /*
  * implement atomic add functionality
  */
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
 {
-       atomic_add(delta, (atomic_t *)(&sem->count));
+       atomic_long_add(delta, (atomic_long_t *)&sem->count);
 }
 
 /*
@@ -149,9 +158,10 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  */
 static inline void __downgrade_write(struct rw_semaphore *sem)
 {
-       int tmp;
+       long tmp;
 
-       tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+       tmp = atomic_long_add_return(-RWSEM_WAITING_BIAS,
+                                    (atomic_long_t *)&sem->count);
        if (tmp < 0)
                rwsem_downgrade_wake(sem);
 }
@@ -159,14 +169,14 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
 /*
  * implement exchange and add functionality
  */
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-       return atomic_add_return(delta, (atomic_t *)(&sem->count));
+       return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
 static inline int rwsem_is_locked(struct rw_semaphore *sem)
 {
-       return (sem->count != 0);
+       return sem->count != 0;
 }
 
 #endif /* __KERNEL__ */
index a5ee345b6a5cc27134bb42742641048aeba48eb6..aa0f1ebb4aaf0e85a22124b42987ec335cc57d1c 100644 (file)
@@ -326,3 +326,25 @@ SYSCALL_SPU(perf_event_open)
 COMPAT_SYS_SPU(preadv)
 COMPAT_SYS_SPU(pwritev)
 COMPAT_SYS(rt_tgsigqueueinfo)
+SYSCALL(fanotify_init)
+COMPAT_SYS(fanotify_mark)
+SYSCALL_SPU(prlimit64)
+SYSCALL_SPU(socket)
+SYSCALL_SPU(bind)
+SYSCALL_SPU(connect)
+SYSCALL_SPU(listen)
+SYSCALL_SPU(accept)
+SYSCALL_SPU(getsockname)
+SYSCALL_SPU(getpeername)
+SYSCALL_SPU(socketpair)
+SYSCALL_SPU(send)
+SYSCALL_SPU(sendto)
+COMPAT_SYS_SPU(recv)
+COMPAT_SYS_SPU(recvfrom)
+SYSCALL_SPU(shutdown)
+COMPAT_SYS_SPU(setsockopt)
+COMPAT_SYS_SPU(getsockopt)
+COMPAT_SYS_SPU(sendmsg)
+COMPAT_SYS_SPU(recvmsg)
+COMPAT_SYS_SPU(recvmmsg)
+SYSCALL_SPU(accept4)
index 6c294acac848145d868d9f936c5df5ca879b1920..5e474ddd227382350fc82ae0e2ca80352d1fd070 100644 (file)
@@ -154,8 +154,8 @@ extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
 extern int fix_alignment(struct pt_regs *);
-extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
-extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+extern void cvt_fd(float *from, double *to);
+extern void cvt_df(double *from, float *to);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
@@ -542,10 +542,6 @@ extern void reloc_got2(unsigned long);
 
 #define PTRRELOC(x)    ((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 extern struct dentry *powerpc_debugfs_root;
 
 #endif /* __KERNEL__ */
index dc779dfcf25813a4502bf767e6bd6cd2f6c3a5bb..fe6f7c2c9c6889600bd0ec00fab55ed6b7daf1f6 100644 (file)
@@ -34,7 +34,6 @@ extern void to_tm(int tim, struct rtc_time * tm);
 extern void GregorianDay(struct rtc_time *tm);
 
 extern void generic_calibrate_decr(void);
-extern void snapshot_timebase(void);
 
 extern void set_dec_cpu6(unsigned int val);
 
@@ -212,12 +211,8 @@ struct cpu_usage {
 DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
 
 #if defined(CONFIG_VIRT_CPU_ACCOUNTING)
-extern void calculate_steal_time(void);
-extern void snapshot_timebases(void);
 #define account_process_vtime(tsk)             account_process_tick(tsk, 0)
 #else
-#define calculate_steal_time()                 do { } while (0)
-#define snapshot_timebases()                   do { } while (0)
 #define account_process_vtime(tsk)             do { } while (0)
 #endif
 
index f0a10266e7f7b0245180661ae3dc0de2cd92390e..6151937657f69c0a3ee9f201befc74f297c57bce 100644 (file)
 #define __NR_preadv            320
 #define __NR_pwritev           321
 #define __NR_rt_tgsigqueueinfo 322
+#define __NR_fanotify_init     323
+#define __NR_fanotify_mark     324
+#define __NR_prlimit64         325
+#define __NR_socket            326
+#define __NR_bind              327
+#define __NR_connect           328
+#define __NR_listen            329
+#define __NR_accept            330
+#define __NR_getsockname       331
+#define __NR_getpeername       332
+#define __NR_socketpair                333
+#define __NR_send              334
+#define __NR_sendto            335
+#define __NR_recv              336
+#define __NR_recvfrom          337
+#define __NR_shutdown          338
+#define __NR_setsockopt                339
+#define __NR_getsockopt                340
+#define __NR_sendmsg           341
+#define __NR_recvmsg           342
+#define __NR_recvmmsg          343
+#define __NR_accept4           344
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls          323
+#define __NR_syscalls          345
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 1dda70129141d04656c65c3af27389491c5c9261..4ed076a4db2453001468eeb9bc662aa9cf7def73 100644 (file)
@@ -55,7 +55,9 @@ obj-$(CONFIG_IBMVIO)          += vio.o
 obj-$(CONFIG_IBMEBUS)           += ibmebus.o
 obj-$(CONFIG_GENERIC_TBSYNC)   += smp-tbsync.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+ifeq ($(CONFIG_PPC32),y)
 obj-$(CONFIG_E500)             += idle_e500.o
+endif
 obj-$(CONFIG_6xx)              += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)              += tau_6xx.o
 obj-$(CONFIG_HIBERNATION)      += swsusp.o suspend.o
@@ -67,7 +69,7 @@ endif
 obj64-$(CONFIG_HIBERNATION)    += swsusp_asm64.o
 obj-$(CONFIG_MODULES)          += module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)              += cpu_setup_44x.o
-obj-$(CONFIG_FSL_BOOKE)                += cpu_setup_fsl_booke.o dbell.o
+obj-$(CONFIG_PPC_FSL_BOOK3E)   += cpu_setup_fsl_booke.o dbell.o
 obj-$(CONFIG_PPC_BOOK3E_64)    += dbell.o
 
 extra-y                                := head_$(CONFIG_WORD_SIZE).o
index b876e989220b02fbb3314e5ac56043717a42ffcb..8184ee97e484e9b86dcb8c0d0f226e88066796d4 100644 (file)
@@ -889,7 +889,7 @@ int fix_alignment(struct pt_regs *regs)
 #ifdef CONFIG_PPC_FPU
                        preempt_disable();
                        enable_kernel_fp();
-                       cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+                       cvt_df(&data.dd, (float *)&data.v[4]);
                        preempt_enable();
 #else
                        return 0;
@@ -933,7 +933,7 @@ int fix_alignment(struct pt_regs *regs)
 #ifdef CONFIG_PPC_FPU
                preempt_disable();
                enable_kernel_fp();
-               cvt_fd((float *)&data.v[4], &data.dd, &current->thread);
+               cvt_fd((float *)&data.v[4], &data.dd);
                preempt_enable();
 #else
                return 0;
index 1c0607ddccc09e7b3c34dc19695ebdfbbff6295b..c3e01945ad4f6f8493c37cc13b7d5298176f4a98 100644 (file)
@@ -61,7 +61,7 @@
 #endif
 #endif
 
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
 #include "../mm/mmu_decl.h"
 #endif
 
@@ -181,17 +181,19 @@ int main(void)
               offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
        DEFINE(SLBSHADOW_STACKESID,
               offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
+       DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
        DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
        DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
        DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
        DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
-       DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
+       DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
+       DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
 #endif /* CONFIG_PPC_STD_MMU_64 */
        DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
        DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
        DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
-       DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
-       DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
+       DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
+       DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
        DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
        DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
        DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
@@ -468,7 +470,7 @@ int main(void)
        DEFINE(PGD_T_LOG2, PGD_T_LOG2);
        DEFINE(PTE_T_LOG2, PTE_T_LOG2);
 #endif
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_FSL_BOOK3E
        DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
        DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
        DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
index 7d606f89a8396311c5019fc65ba7fa66f6d720b3..e32b4a9a2c2282c2554e854965f7f8b784ffe3eb 100644 (file)
@@ -35,6 +35,7 @@ _GLOBAL(__setup_cpu_440grx)
 _GLOBAL(__setup_cpu_460ex)
 _GLOBAL(__setup_cpu_460gt)
 _GLOBAL(__setup_cpu_460sx)
+_GLOBAL(__setup_cpu_apm821xx)
        mflr    r4
        bl      __init_fpu_44x
        bl      __fixup_440A_mcheck
index 0adb50ad8031220afc2aa3d9ec66b88da5be801e..894e64fa481e94ca51b8c02419310a017ac2adf0 100644 (file)
@@ -51,6 +51,7 @@ _GLOBAL(__e500_dcache_setup)
        isync
        blr
 
+#ifdef CONFIG_PPC32
 _GLOBAL(__setup_cpu_e200)
        /* enable dedicated debug exception handling resources (Debug APU) */
        mfspr   r3,SPRN_HID0
@@ -72,3 +73,17 @@ _GLOBAL(__setup_cpu_e500mc)
        bl      __setup_e500mc_ivors
        mtlr    r4
        blr
+#endif
+/* Right now, restore and setup are the same thing */
+_GLOBAL(__restore_cpu_e5500)
+_GLOBAL(__setup_cpu_e5500)
+       mflr    r4
+       bl      __e500_icache_setup
+       bl      __e500_dcache_setup
+#ifdef CONFIG_PPC_BOOK3E_64
+       bl      .__setup_base_ivors
+#else
+       bl      __setup_e500mc_ivors
+#endif
+       mtlr    r4
+       blr
index 65e2b4e10f97cfb0fa068571c8ec6ac41c59029f..96a908f1cd876ac1d4456e884da8c3cdd5c4e7c8 100644 (file)
@@ -48,6 +48,7 @@ extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec);
+extern void __setup_cpu_apm821xx(unsigned long offset, struct cpu_spec *spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -66,6 +67,10 @@ extern void __restore_cpu_ppc970(void);
 extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power7(void);
 #endif /* CONFIG_PPC64 */
+#if defined(CONFIG_E500)
+extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_e5500(void);
+#endif /* CONFIG_E500 */
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
  * ones as well...
@@ -1805,6 +1810,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .machine_check          = machine_check_440A,
                .platform               = "ppc440",
        },
+       { /* 464 in APM821xx */
+               .pvr_mask               = 0xffffff00,
+               .pvr_value              = 0x12C41C80,
+               .cpu_name               = "APM821XX",
+               .cpu_features           = CPU_FTRS_44X,
+               .cpu_user_features      = COMMON_USER_BOOKE |
+                       PPC_FEATURE_HAS_FPU,
+               .mmu_features           = MMU_FTR_TYPE_44x,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .cpu_setup              = __setup_cpu_apm821xx,
+               .machine_check          = machine_check_440A,
+               .platform               = "ppc440",
+       },
        { /* 476 core */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x11a50000,
@@ -1826,7 +1845,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_features           = CPU_FTRS_47X,
                .cpu_user_features      = COMMON_USER_BOOKE |
                        PPC_FEATURE_HAS_FPU,
-               .cpu_user_features      = COMMON_USER_BOOKE,
                .mmu_features           = MMU_FTR_TYPE_47x |
                        MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
                .icache_bsize           = 32,
@@ -1892,7 +1910,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .platform               = "ppc5554",
        }
 #endif /* CONFIG_E200 */
+#endif /* CONFIG_PPC32 */
 #ifdef CONFIG_E500
+#ifdef CONFIG_PPC32
        {       /* e500 */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x80200000,
@@ -1947,6 +1967,26 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce500mc",
        },
+#endif /* CONFIG_PPC32 */
+       {       /* e5500 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x80240000,
+               .cpu_name               = "e5500",
+               .cpu_features           = CPU_FTRS_E500MC,
+               .cpu_user_features      = COMMON_USER_BOOKE,
+               .mmu_features           = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
+                       MMU_FTR_USE_TLBILX,
+               .icache_bsize           = 64,
+               .dcache_bsize           = 64,
+               .num_pmcs               = 4,
+               .oprofile_cpu_type      = "ppc/e500mc",
+               .oprofile_type          = PPC_OPROFILE_FSL_EMB,
+               .cpu_setup              = __setup_cpu_e5500,
+               .cpu_restore            = __restore_cpu_e5500,
+               .machine_check          = machine_check_e500mc,
+               .platform               = "ppce5500",
+       },
+#ifdef CONFIG_PPC32
        {       /* default match */
                .pvr_mask               = 0x00000000,
                .pvr_value              = 0x00000000,
@@ -1961,8 +2001,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .machine_check          = machine_check_e500,
                .platform               = "powerpc",
        }
-#endif /* CONFIG_E500 */
 #endif /* CONFIG_PPC32 */
+#endif /* CONFIG_E500 */
 
 #ifdef CONFIG_PPC_BOOK3E_64
        {       /* This is a default entry to get going, to be replaced by
index 417f7b05a9cebc6e10acfaf41eec88d17a2f7e89..832c8c4db2541225ad007f5592b60ec8fe14776d 100644 (file)
@@ -402,18 +402,19 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
         */
        hard_irq_disable();
 
-       for_each_irq(i) {
-               struct irq_desc *desc = irq_to_desc(i);
-
-               if (!desc || !desc->chip || !desc->chip->eoi)
-                       continue;
+       /*
+        * Make a note of crashing cpu. Will be used in machine_kexec
+        * such that another IPI will not be sent.
+        */
+       crashing_cpu = smp_processor_id();
+       crash_save_cpu(regs, crashing_cpu);
+       crash_kexec_prepare_cpus(crashing_cpu);
+       cpu_set(crashing_cpu, cpus_in_crash);
+#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
+       crash_kexec_wait_realmode(crashing_cpu);
+#endif
 
-               if (desc->status & IRQ_INPROGRESS)
-                       desc->chip->eoi(i);
-
-               if (!(desc->status & IRQ_DISABLED))
-                       desc->chip->shutdown(i);
-       }
+       machine_kexec_mask_interrupts();
 
        /*
         * Call registered shutdown routines savely.  Swap out
@@ -438,18 +439,8 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
        crash_shutdown_cpu = -1;
        __debugger_fault_handler = old_handler;
 
-       /*
-        * Make a note of crashing cpu. Will be used in machine_kexec
-        * such that another IPI will not be sent.
-        */
-       crashing_cpu = smp_processor_id();
-       crash_save_cpu(regs, crashing_cpu);
-       crash_kexec_prepare_cpus(crashing_cpu);
-       cpu_set(crashing_cpu, cpus_in_crash);
        crash_kexec_stop_spus();
-#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
-       crash_kexec_wait_realmode(crashing_cpu);
-#endif
+
        if (ppc_md.kexec_cpu_down)
                ppc_md.kexec_cpu_down(1, 0);
 }
index 37771a51811915665e7279f0ec0089e20cfcf51b..6e54a0fd31aa2485591b565bb9e0a8e121835fb7 100644 (file)
@@ -74,16 +74,17 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
        struct iommu_table *tbl = get_iommu_table_base(dev);
 
-       if (!tbl || tbl->it_offset > mask) {
-               printk(KERN_INFO
-                      "Warning: IOMMU offset too big for device mask\n");
-               if (tbl)
-                       printk(KERN_INFO
-                              "mask: 0x%08llx, table offset: 0x%08lx\n",
-                               mask, tbl->it_offset);
-               else
-                       printk(KERN_INFO "mask: 0x%08llx, table unavailable\n",
-                               mask);
+       if (!tbl) {
+               dev_info(dev, "Warning: IOMMU dma not supported: mask 0x%08llx"
+                       ", table unavailable\n", mask);
+               return 0;
+       }
+
+       if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) {
+               dev_info(dev, "Warning: IOMMU window too big for device mask\n");
+               dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n",
+                               mask, (tbl->it_offset + tbl->it_size) <<
+                               IOMMU_PAGE_SHIFT);
                return 0;
        } else
                return 1;
index 84d6367ec0030c6611782902321d39871b9fe278..cf02cad62d9a78ecaae14161d7deb6cd78bdf768 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/memblock.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
+#include <asm/machdep.h>
 
 /*
  * Generic direct DMA implementation
@@ -89,7 +90,7 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
        /* Could be improved so platforms can set the limit in case
         * they have limited DMA windows
         */
-       return mask >= (memblock_end_of_DRAM() - 1);
+       return mask >= get_dma_offset(dev) + (memblock_end_of_DRAM() - 1);
 #else
        return 1;
 #endif
@@ -154,6 +155,23 @@ EXPORT_SYMBOL(dma_direct_ops);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (ppc_md.dma_set_mask)
+               return ppc_md.dma_set_mask(dev, dma_mask);
+       if (unlikely(dma_ops == NULL))
+               return -EIO;
+       if (dma_ops->set_dma_mask != NULL)
+               return dma_ops->set_dma_mask(dev, dma_mask);
+       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+               return -EIO;
+       *dev->dma_mask = dma_mask;
+       return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
index 42e9d908914a0e47117cfe7f3dcc5fe50d215d98..d82878c4daa677c416cf116924b4d34e58d501d3 100644 (file)
@@ -97,6 +97,24 @@ system_call_common:
        addi    r9,r1,STACK_FRAME_OVERHEAD
        ld      r11,exception_marker@toc(r2)
        std     r11,-16(r9)             /* "regshere" marker */
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+BEGIN_FW_FTR_SECTION
+       beq     33f
+       /* if from user, see if there are any DTL entries to process */
+       ld      r10,PACALPPACAPTR(r13)  /* get ptr to VPA */
+       ld      r11,PACA_DTL_RIDX(r13)  /* get log read index */
+       ld      r10,LPPACA_DTLIDX(r10)  /* get log write index */
+       cmpd    cr1,r11,r10
+       beq+    cr1,33f
+       bl      .accumulate_stolen_time
+       REST_GPR(0,r1)
+       REST_4GPRS(3,r1)
+       REST_2GPRS(7,r1)
+       addi    r9,r1,STACK_FRAME_OVERHEAD
+33:
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
+
 #ifdef CONFIG_TRACE_IRQFLAGS
        bl      .trace_hardirqs_on
        REST_GPR(0,r1)
@@ -202,7 +220,9 @@ syscall_exit:
        bge-    syscall_error
 syscall_error_cont:
        ld      r7,_NIP(r1)
+BEGIN_FTR_SECTION
        stdcx.  r0,0,r1                 /* to clear the reservation */
+END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
        andi.   r6,r8,MSR_PR
        ld      r4,_LINK(r1)
        /*
@@ -419,6 +439,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        sync
 #endif /* CONFIG_SMP */
 
+       /*
+        * If we optimise away the clear of the reservation in system
+        * calls because we know the CPU tracks the address of the
+        * reservation, then we need to clear it here to cover the
+        * case that the kernel context switch path has no larx
+        * instructions.
+        */
+BEGIN_FTR_SECTION
+       ldarx   r6,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
+
        addi    r6,r4,-THREAD   /* Convert THREAD to 'current' */
        std     r6,PACACURRENT(r13)     /* Set new 'current' */
 
@@ -576,7 +607,16 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
        andi.   r0,r3,MSR_RI
        beq-    unrecov_restore
 
+       /*
+        * Clear the reservation. If we know the CPU tracks the address of
+        * the reservation then we can potentially save some cycles and use
+        * a larx. On POWER6 and POWER7 this is significantly faster.
+        */
+BEGIN_FTR_SECTION
        stdcx.  r0,0,r1         /* to clear the reservation */
+FTR_SECTION_ELSE
+       ldarx   r4,0,r1
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
 
        /*
         * Clear RI before restoring r13.  If we are returning to
index f53029a01554ca3ce86a9e1983b048335f7383f0..39b0c48872d23b337f07c00bb0299e284a8f9ab5 100644 (file)
@@ -818,12 +818,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
        /*
         * hash_page couldn't handle it, set soft interrupt enable back
-        * to what it was before the trap.  Note that .raw_local_irq_restore
+        * to what it was before the trap.  Note that .arch_local_irq_restore
         * handles any interrupts pending at this point.
         */
        ld      r3,SOFTE(r1)
        TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
-       bl      .raw_local_irq_restore
+       bl      .arch_local_irq_restore
        b       11f
 
 /* We have a data breakpoint exception - handle it */
index fc8f5b14019c515ba870868b7789799ca9efd1a0..e86c040ae5857056a2538fe535864e96d2ce3579 100644 (file)
@@ -163,24 +163,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 /*
  * These are used in the alignment trap handler when emulating
  * single-precision loads and stores.
- * We restore and save the fpscr so the task gets the same result
- * and exceptions as if the cpu had performed the load or store.
  */
 
 _GLOBAL(cvt_fd)
-       lfd     0,THREAD_FPSCR(r5)      /* load up fpscr value */
-       MTFSF_L(0)
        lfs     0,0(r3)
        stfd    0,0(r4)
-       mffs    0
-       stfd    0,THREAD_FPSCR(r5)      /* save new fpscr value */
        blr
 
 _GLOBAL(cvt_df)
-       lfd     0,THREAD_FPSCR(r5)      /* load up fpscr value */
-       MTFSF_L(0)
        lfd     0,0(r3)
        stfs    0,0(r4)
-       mffs    0
-       stfd    0,THREAD_FPSCR(r5)      /* save new fpscr value */
        blr
index a90625f9b48517bdca205774dc71a962ec698d91..8278e8bad5a01ebad1de83e5623047cd3899364e 100644 (file)
@@ -923,11 +923,7 @@ initial_mmu:
        mtspr   SPRN_PID,r0
        sync
 
-       /* Configure and load two entries into TLB slots 62 and 63.
-        * In case we are pinning TLBs, these are reserved in by the
-        * other TLB functions.  If not reserving, then it doesn't
-        * matter where they are loaded.
-        */
+       /* Configure and load one entry into TLB slots 63 */
        clrrwi  r4,r4,10                /* Mask off the real page number */
        ori     r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
 
index 5ab484ef06a720770f72d9883340a045a180f520..562305b40a8e7c669adc95cc3cfc5edaca87e5e5 100644 (file)
@@ -113,6 +113,10 @@ _ENTRY(_start);
        stw     r5, 0(r4)       /* Save abatron_pteptrs at a fixed location */
        stw     r6, 0(r5)
 
+       /* Clear the Machine Check Syndrome Register */
+       li      r0,0
+       mtspr   SPRN_MCSR,r0
+
        /* Let's move on */
        lis     r4,start_kernel@h
        ori     r4,r4,start_kernel@l
index 844a44b6447254889a10c35c2acf877981a4f16e..c571cd3c14532db29777c07977582e736be5a9aa 100644 (file)
@@ -572,15 +572,21 @@ __secondary_start:
        /* Set thread priority to MEDIUM */
        HMT_MEDIUM
 
-       /* Do early setup for that CPU (stab, slb, hash table pointer) */
-       bl      .early_setup_secondary
-
        /* Initialize the kernel stack.  Just a repeat for iSeries.      */
        LOAD_REG_ADDR(r3, current_set)
        sldi    r28,r24,3               /* get current_set[cpu#]         */
-       ldx     r1,r3,r28
-       addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
-       std     r1,PACAKSAVE(r13)
+       ldx     r14,r3,r28
+       addi    r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD
+       std     r14,PACAKSAVE(r13)
+
+       /* Do early setup for that CPU (stab, slb, hash table pointer) */
+       bl      .early_setup_secondary
+
+       /*
+        * setup the new stack pointer, but *don't* use this until
+        * translation is on.
+        */
+       mr      r1, r14
 
        /* Clear backchain so we get nice backtraces */
        li      r7,0
index 4faeba247854c038078ef4362836d50b37f4f44a..529b817f473b13de52bea2ac0ae33e859e9e27c4 100644 (file)
@@ -152,8 +152,11 @@ _ENTRY(__early_start)
        /* Check to see if we're the second processor, and jump
         * to the secondary_start code if so
         */
-       mfspr   r24,SPRN_PIR
-       cmpwi   r24,0
+       lis     r24, boot_cpuid@h
+       ori     r24, r24, boot_cpuid@l
+       lwz     r24, 0(r24)
+       cmpwi   r24, -1
+       mfspr   r24,SPRN_PIR
        bne     __secondary_start
 #endif
 
@@ -175,6 +178,9 @@ _ENTRY(__early_start)
        li      r0,0
        stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
 
+       rlwinm  r22,r1,0,0,31-THREAD_SHIFT      /* current thread_info */
+       stw     r24, TI_CPU(r22)
+
        bl      early_init
 
 #ifdef CONFIG_RELOCATABLE
index 049dda60e4750296e7b890e752e6420d0d1fb769..39a2baa6ad58aec28a3c1d0782753569bbb51f6e 100644 (file)
@@ -94,9 +94,9 @@ void cpu_idle(void)
                HMT_medium();
                ppc64_runlatch_on();
                tick_nohz_restart_sched_tick();
+               preempt_enable_no_resched();
                if (cpu_should_die())
                        cpu_die();
-               preempt_enable_no_resched();
                schedule();
                preempt_disable();
        }
index d3ce67cf03be35855394905009d6a39729f7ac92..ce557f6f00fcf2817c38ad8821a2e7fc8c8394a4 100644 (file)
@@ -67,6 +67,7 @@
 #include <asm/machdep.h>
 #include <asm/udbg.h>
 #include <asm/dbell.h>
+#include <asm/smp.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
@@ -115,7 +116,7 @@ static inline notrace void set_soft_enabled(unsigned long enable)
        : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-notrace void raw_local_irq_restore(unsigned long en)
+notrace void arch_local_irq_restore(unsigned long en)
 {
        /*
         * get_paca()->soft_enabled = en;
@@ -191,7 +192,7 @@ notrace void raw_local_irq_restore(unsigned long en)
 
        __hard_irq_enable();
 }
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 #endif /* CONFIG_PPC64 */
 
 static int show_other_interrupts(struct seq_file *p, int prec)
@@ -446,22 +447,23 @@ struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly;
 void exc_lvl_ctx_init(void)
 {
        struct thread_info *tp;
-       int i;
+       int i, hw_cpu;
 
        for_each_possible_cpu(i) {
-               memset((void *)critirq_ctx[i], 0, THREAD_SIZE);
-               tp = critirq_ctx[i];
+               hw_cpu = get_hard_smp_processor_id(i);
+               memset((void *)critirq_ctx[hw_cpu], 0, THREAD_SIZE);
+               tp = critirq_ctx[hw_cpu];
                tp->cpu = i;
                tp->preempt_count = 0;
 
 #ifdef CONFIG_BOOKE
-               memset((void *)dbgirq_ctx[i], 0, THREAD_SIZE);
-               tp = dbgirq_ctx[i];
+               memset((void *)dbgirq_ctx[hw_cpu], 0, THREAD_SIZE);
+               tp = dbgirq_ctx[hw_cpu];
                tp->cpu = i;
                tp->preempt_count = 0;
 
-               memset((void *)mcheckirq_ctx[i], 0, THREAD_SIZE);
-               tp = mcheckirq_ctx[i];
+               memset((void *)mcheckirq_ctx[hw_cpu], 0, THREAD_SIZE);
+               tp = mcheckirq_ctx[hw_cpu];
                tp->cpu = i;
                tp->preempt_count = HARDIRQ_OFFSET;
 #endif
@@ -585,8 +587,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
                         * this will be fixed once slab is made available early
                         * instead of the current cruft
                         */
-                       if (mem_init_done)
+                       if (mem_init_done) {
+                               of_node_put(host->of_node);
                                kfree(host);
+                       }
                        return NULL;
                }
                irq_map[0].host = host;
@@ -1141,7 +1145,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
        unsigned long flags;
        struct irq_desc *desc;
        const char *p;
-       char none[] = "none";
+       static const char none[] = "none";
        int i;
 
        seq_printf(m, "%-5s  %-7s  %-15s  %s\n", "virq", "hwirq",
index 50362b6ef6e93d8752ffda779ffaee429e2a054a..16468362ad579c5581d59f10feb8595336291eab 100644 (file)
@@ -56,7 +56,7 @@ static unsigned long get_purr(void)
 
        for_each_possible_cpu(cpu) {
                if (firmware_has_feature(FW_FEATURE_ISERIES))
-                       sum_purr += lppaca[cpu].emulated_time_base;
+                       sum_purr += lppaca_of(cpu).emulated_time_base;
                else {
                        struct cpu_usage *cu;
 
@@ -263,7 +263,7 @@ static void parse_ppp_data(struct seq_file *m)
                   ppp_data.active_system_procs);
 
        /* pool related entries are apropriate for shared configs */
-       if (lppaca[0].shared_proc) {
+       if (lppaca_of(0).shared_proc) {
                unsigned long pool_idle_time, pool_procs;
 
                seq_printf(m, "pool=%d\n", ppp_data.pool_num);
@@ -460,8 +460,8 @@ static void pseries_cmo_data(struct seq_file *m)
                return;
 
        for_each_possible_cpu(cpu) {
-               cmo_faults += lppaca[cpu].cmo_faults;
-               cmo_fault_time += lppaca[cpu].cmo_fault_time;
+               cmo_faults += lppaca_of(cpu).cmo_faults;
+               cmo_fault_time += lppaca_of(cpu).cmo_fault_time;
        }
 
        seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
@@ -479,8 +479,8 @@ static void splpar_dispatch_data(struct seq_file *m)
        unsigned long dispatch_dispersions = 0;
 
        for_each_possible_cpu(cpu) {
-               dispatches += lppaca[cpu].yield_count;
-               dispatch_dispersions += lppaca[cpu].dispersion_count;
+               dispatches += lppaca_of(cpu).yield_count;
+               dispatch_dispersions += lppaca_of(cpu).dispersion_count;
        }
 
        seq_printf(m, "dispatches=%lu\n", dispatches);
@@ -545,7 +545,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        seq_printf(m, "partition_potential_processors=%d\n",
                   partition_potential_processors);
 
-       seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
+       seq_printf(m, "shared_processor_mode=%d\n", lppaca_of(0).shared_proc);
 
        seq_printf(m, "slb_size=%d\n", mmu_slb_size);
 
@@ -780,6 +780,7 @@ static const struct file_operations lparcfg_fops = {
        .write          = lparcfg_write,
        .open           = lparcfg_open,
        .release        = single_release,
+       .llseek         = seq_lseek,
 };
 
 static int __init lparcfg_init(void)
index dd6c141f166261b7970c42023f8b96a0ccf3085f..df7e20c191cda3190c1396bc60921bd8c8df003f 100644 (file)
 #include <linux/threads.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
+#include <linux/irq.h>
+
 #include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
 
+void machine_kexec_mask_interrupts(void) {
+       unsigned int i;
+
+       for_each_irq(i) {
+               struct irq_desc *desc = irq_to_desc(i);
+
+               if (!desc || !desc->chip)
+                       continue;
+
+               if (desc->chip->eoi &&
+                   desc->status & IRQ_INPROGRESS)
+                       desc->chip->eoi(i);
+
+               if (desc->chip->mask)
+                       desc->chip->mask(i);
+
+               if (desc->chip->disable &&
+                   !(desc->status & IRQ_DISABLED))
+                       desc->chip->disable(i);
+       }
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
        if (ppc_md.machine_crash_shutdown)
index ae63a964b858049f63a47e446e96bb54295a6c0c..e63f2e7d2efb029fca417c344ecee0d9e96daf88 100644 (file)
@@ -39,6 +39,10 @@ void default_machine_kexec(struct kimage *image)
        /* Interrupts aren't acceptable while we reboot */
        local_irq_disable();
 
+       /* mask each interrupt so we are in a more sane state for the
+        * kexec kernel */
+       machine_kexec_mask_interrupts();
+
        page_list = image->head;
 
        /* we need both effective and real address here */
index 6bbd7a604d243c9f8f9f906d683a9a20df2f9a43..a7a570dcdd571c8fb861562e549dbf094147fb32 100644 (file)
@@ -810,6 +810,9 @@ relocate_new_kernel:
        isync
        sync
 
+       mfspr   r3, SPRN_PIR /* current core we are running on */
+       mr      r4, r5 /* load physical address of chunk called */
+
        /* jump to the entry point, usually the setup routine */
        mtlr    r5
        blrl
index 477c663e014043a5c08fbaf51e82853005391344..49cee9df225be8bfc6b06a429ee9243d10484439 100644 (file)
@@ -63,11 +63,6 @@ int module_finalize(const Elf_Ehdr *hdr,
                const Elf_Shdr *sechdrs, struct module *me)
 {
        const Elf_Shdr *sect;
-       int err;
-
-       err = module_bug_finalize(hdr, sechdrs, me);
-       if (err)
-               return err;
 
        /* Apply feature fixups */
        sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -101,5 +96,4 @@ int module_finalize(const Elf_Ehdr *hdr,
 
 void module_arch_cleanup(struct module *mod)
 {
-       module_bug_cleanup(mod);
 }
index d0a26f1770fe0492320e3fe4187cb20b741fd56e..ebf9846f3c3b30b7cf2d61d48a8a96c37b702c1c 100644 (file)
@@ -26,6 +26,20 @@ extern unsigned long __toc_start;
 
 #ifdef CONFIG_PPC_BOOK3S
 
+/*
+ * We only have to have statically allocated lppaca structs on
+ * legacy iSeries, which supports at most 64 cpus.
+ */
+#ifdef CONFIG_PPC_ISERIES
+#if NR_CPUS < 64
+#define NR_LPPACAS     NR_CPUS
+#else
+#define NR_LPPACAS     64
+#endif
+#else /* not iSeries */
+#define NR_LPPACAS     1
+#endif
+
 /*
  * The structure which the hypervisor knows about - this structure
  * should not cross a page boundary.  The vpa_init/register_vpa call
@@ -36,7 +50,7 @@ extern unsigned long __toc_start;
  * will suffice to ensure that it doesn't cross a page boundary.
  */
 struct lppaca lppaca[] = {
-       [0 ... (NR_CPUS-1)] = {
+       [0 ... (NR_LPPACAS-1)] = {
                .desc = 0xd397d781,     /* "LpPa" */
                .size = sizeof(struct lppaca),
                .dyn_proc_status = 2,
@@ -49,6 +63,54 @@ struct lppaca lppaca[] = {
        },
 };
 
+static struct lppaca *extra_lppacas;
+static long __initdata lppaca_size;
+
+static void allocate_lppacas(int nr_cpus, unsigned long limit)
+{
+       if (nr_cpus <= NR_LPPACAS)
+               return;
+
+       lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) *
+                                (nr_cpus - NR_LPPACAS));
+       extra_lppacas = __va(memblock_alloc_base(lppaca_size,
+                                                PAGE_SIZE, limit));
+}
+
+static struct lppaca *new_lppaca(int cpu)
+{
+       struct lppaca *lp;
+
+       if (cpu < NR_LPPACAS)
+               return &lppaca[cpu];
+
+       lp = extra_lppacas + (cpu - NR_LPPACAS);
+       *lp = lppaca[0];
+
+       return lp;
+}
+
+static void free_lppacas(void)
+{
+       long new_size = 0, nr;
+
+       if (!lppaca_size)
+               return;
+       nr = num_possible_cpus() - NR_LPPACAS;
+       if (nr > 0)
+               new_size = PAGE_ALIGN(nr * sizeof(struct lppaca));
+       if (new_size >= lppaca_size)
+               return;
+
+       memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size);
+       lppaca_size = new_size;
+}
+
+#else
+
+static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { }
+static inline void free_lppacas(void) { }
+
 #endif /* CONFIG_PPC_BOOK3S */
 
 #ifdef CONFIG_PPC_STD_MMU_64
@@ -88,7 +150,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
        unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
 
 #ifdef CONFIG_PPC_BOOK3S
-       new_paca->lppaca_ptr = &lppaca[cpu];
+       new_paca->lppaca_ptr = new_lppaca(cpu);
 #else
        new_paca->kernel_pgd = swapper_pg_dir;
 #endif
@@ -127,7 +189,7 @@ void __init allocate_pacas(void)
         * the first segment. On iSeries they must be within the area mapped
         * by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
         */
-       limit = min(0x10000000ULL, memblock.rmo_size);
+       limit = min(0x10000000ULL, ppc64_rma_size);
        if (firmware_has_feature(FW_FEATURE_ISERIES))
                limit = min(limit, HvPagesToMap * HVPAGESIZE);
 
@@ -144,6 +206,8 @@ void __init allocate_pacas(void)
        printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n",
                paca_size, nr_cpus, paca);
 
+       allocate_lppacas(nr_cpus, limit);
+
        /* Can't use for_each_*_cpu, as they aren't functional yet */
        for (cpu = 0; cpu < nr_cpus; cpu++)
                initialise_paca(&paca[cpu], cpu);
@@ -164,4 +228,6 @@ void __init free_unused_pacas(void)
                paca_size - new_size);
 
        paca_size = new_size;
+
+       free_lppacas();
 }
index 9021c4ad4bbd3ebdcda00af9de8bf59e6bfacc83..10a44e68ef11eca50957467569b052fd796d6936 100644 (file)
@@ -1090,8 +1090,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                 bus->number, bus->self ? pci_name(bus->self) : "PHB");
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               struct dev_archdata *sd = &dev->dev.archdata;
-
                /* Cardbus can call us to add new devices to a bus, so ignore
                 * those who are already fully discovered
                 */
@@ -1107,7 +1105,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
 
                /* Hook up default DMA ops */
-               sd->dma_ops = pci_dma_ops;
+               set_dma_ops(&dev->dev, pci_dma_ops);
                set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
 
                /* Additional platform DMA/iommu setup */
index 6ddb795f83e8e9ccd62e713d997599baee77122a..e751506323b4509bf04abefb266a6435173a307f 100644 (file)
@@ -336,7 +336,7 @@ static void __devinit __of_scan_bus(struct device_node *node,
                if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
                    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
                        struct device_node *child = pci_device_to_OF_node(dev);
-                       if (dev)
+                       if (child)
                                of_scan_pci_bridge(child, dev);
                }
        }
index 95ad9dad298e9d4773117b0406bc4a3378d77e5e..d05ae4204bbf3d3ddcc84266476b736a6790715c 100644 (file)
 #include "ppc32.h"
 #endif
 
-/*
- * Store another value in a callchain_entry.
- */
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-       unsigned int nr = entry->nr;
-
-       if (nr < PERF_MAX_STACK_DEPTH) {
-               entry->ip[nr] = ip;
-               entry->nr = nr + 1;
-       }
-}
 
 /*
  * Is sp valid as the address of the next kernel stack frame after prev_sp?
@@ -58,8 +46,8 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp)
        return 0;
 }
 
-static void perf_callchain_kernel(struct pt_regs *regs,
-                                 struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        unsigned long sp, next_sp;
        unsigned long next_ip;
@@ -69,8 +57,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
 
        lr = regs->link;
        sp = regs->gpr[1];
-       callchain_store(entry, PERF_CONTEXT_KERNEL);
-       callchain_store(entry, regs->nip);
+       perf_callchain_store(entry, regs->nip);
 
        if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
                return;
@@ -89,7 +76,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
                        next_ip = regs->nip;
                        lr = regs->link;
                        level = 0;
-                       callchain_store(entry, PERF_CONTEXT_KERNEL);
+                       perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
 
                } else {
                        if (level == 0)
@@ -111,7 +98,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
                        ++level;
                }
 
-               callchain_store(entry, next_ip);
+               perf_callchain_store(entry, next_ip);
                if (!valid_next_sp(next_sp, sp))
                        return;
                sp = next_sp;
@@ -233,8 +220,8 @@ static int sane_signal_64_frame(unsigned long sp)
                puc == (unsigned long) &sf->uc;
 }
 
-static void perf_callchain_user_64(struct pt_regs *regs,
-                                  struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+                                  struct pt_regs *regs)
 {
        unsigned long sp, next_sp;
        unsigned long next_ip;
@@ -246,8 +233,7 @@ static void perf_callchain_user_64(struct pt_regs *regs,
        next_ip = regs->nip;
        lr = regs->link;
        sp = regs->gpr[1];
-       callchain_store(entry, PERF_CONTEXT_USER);
-       callchain_store(entry, next_ip);
+       perf_callchain_store(entry, next_ip);
 
        for (;;) {
                fp = (unsigned long __user *) sp;
@@ -276,14 +262,14 @@ static void perf_callchain_user_64(struct pt_regs *regs,
                            read_user_stack_64(&uregs[PT_R1], &sp))
                                return;
                        level = 0;
-                       callchain_store(entry, PERF_CONTEXT_USER);
-                       callchain_store(entry, next_ip);
+                       perf_callchain_store(entry, PERF_CONTEXT_USER);
+                       perf_callchain_store(entry, next_ip);
                        continue;
                }
 
                if (level == 0)
                        next_ip = lr;
-               callchain_store(entry, next_ip);
+               perf_callchain_store(entry, next_ip);
                ++level;
                sp = next_sp;
        }
@@ -315,8 +301,8 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
        return __get_user_inatomic(*ret, ptr);
 }
 
-static inline void perf_callchain_user_64(struct pt_regs *regs,
-                                         struct perf_callchain_entry *entry)
+static inline void perf_callchain_user_64(struct perf_callchain_entry *entry,
+                                         struct pt_regs *regs)
 {
 }
 
@@ -435,8 +421,8 @@ static unsigned int __user *signal_frame_32_regs(unsigned int sp,
        return mctx->mc_gregs;
 }
 
-static void perf_callchain_user_32(struct pt_regs *regs,
-                                  struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+                                  struct pt_regs *regs)
 {
        unsigned int sp, next_sp;
        unsigned int next_ip;
@@ -447,8 +433,7 @@ static void perf_callchain_user_32(struct pt_regs *regs,
        next_ip = regs->nip;
        lr = regs->link;
        sp = regs->gpr[1];
-       callchain_store(entry, PERF_CONTEXT_USER);
-       callchain_store(entry, next_ip);
+       perf_callchain_store(entry, next_ip);
 
        while (entry->nr < PERF_MAX_STACK_DEPTH) {
                fp = (unsigned int __user *) (unsigned long) sp;
@@ -470,45 +455,24 @@ static void perf_callchain_user_32(struct pt_regs *regs,
                            read_user_stack_32(&uregs[PT_R1], &sp))
                                return;
                        level = 0;
-                       callchain_store(entry, PERF_CONTEXT_USER);
-                       callchain_store(entry, next_ip);
+                       perf_callchain_store(entry, PERF_CONTEXT_USER);
+                       perf_callchain_store(entry, next_ip);
                        continue;
                }
 
                if (level == 0)
                        next_ip = lr;
-               callchain_store(entry, next_ip);
+               perf_callchain_store(entry, next_ip);
                ++level;
                sp = next_sp;
        }
 }
 
-/*
- * Since we can't get PMU interrupts inside a PMU interrupt handler,
- * we don't need separate irq and nmi entries here.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-       struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain);
-
-       entry->nr = 0;
-
-       if (!user_mode(regs)) {
-               perf_callchain_kernel(regs, entry);
-               if (current->mm)
-                       regs = task_pt_regs(current);
-               else
-                       regs = NULL;
-       }
-
-       if (regs) {
-               if (current_is_64bit())
-                       perf_callchain_user_64(regs, entry);
-               else
-                       perf_callchain_user_32(regs, entry);
-       }
-
-       return entry;
+       if (current_is_64bit())
+               perf_callchain_user_64(entry, regs);
+       else
+               perf_callchain_user_32(entry, regs);
 }
index d301a30445e09a49cec4a3d4dcf2ea01529934b3..3129c855933c2a3857b0c4b3321b259b851279b8 100644 (file)
@@ -402,6 +402,9 @@ static void power_pmu_read(struct perf_event *event)
 {
        s64 val, delta, prev;
 
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
        if (!event->hw.idx)
                return;
        /*
@@ -517,7 +520,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, unsigned long mmcr0)
  * Disable all events to prevent PMU interrupts and to allow
  * events to be added or removed.
  */
-void hw_perf_disable(void)
+static void power_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw;
        unsigned long flags;
@@ -565,7 +568,7 @@ void hw_perf_disable(void)
  * If we were previously disabled and events were added, then
  * put the new config on the PMU.
  */
-void hw_perf_enable(void)
+static void power_pmu_enable(struct pmu *pmu)
 {
        struct perf_event *event;
        struct cpu_hw_events *cpuhw;
@@ -672,6 +675,8 @@ void hw_perf_enable(void)
                }
                local64_set(&event->hw.prev_count, val);
                event->hw.idx = idx;
+               if (event->hw.state & PERF_HES_STOPPED)
+                       val = 0;
                write_pmc(idx, val);
                perf_event_update_userpage(event);
        }
@@ -727,7 +732,7 @@ static int collect_events(struct perf_event *group, int max_count,
  * re-enable the PMU in order to get hw_perf_enable to do the
  * actual work of reconfiguring the PMU.
  */
-static int power_pmu_enable(struct perf_event *event)
+static int power_pmu_add(struct perf_event *event, int ef_flags)
 {
        struct cpu_hw_events *cpuhw;
        unsigned long flags;
@@ -735,7 +740,7 @@ static int power_pmu_enable(struct perf_event *event)
        int ret = -EAGAIN;
 
        local_irq_save(flags);
-       perf_disable();
+       perf_pmu_disable(event->pmu);
 
        /*
         * Add the event to the list (if there is room)
@@ -749,6 +754,9 @@ static int power_pmu_enable(struct perf_event *event)
        cpuhw->events[n0] = event->hw.config;
        cpuhw->flags[n0] = event->hw.event_base;
 
+       if (!(ef_flags & PERF_EF_START))
+               event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
        /*
         * If group events scheduling transaction was started,
         * skip the schedulability test here, it will be peformed
@@ -769,7 +777,7 @@ nocheck:
 
        ret = 0;
  out:
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
        return ret;
 }
@@ -777,14 +785,14 @@ nocheck:
 /*
  * Remove a event from the PMU.
  */
-static void power_pmu_disable(struct perf_event *event)
+static void power_pmu_del(struct perf_event *event, int ef_flags)
 {
        struct cpu_hw_events *cpuhw;
        long i;
        unsigned long flags;
 
        local_irq_save(flags);
-       perf_disable();
+       perf_pmu_disable(event->pmu);
 
        power_pmu_read(event);
 
@@ -821,34 +829,60 @@ static void power_pmu_disable(struct perf_event *event)
                cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE);
        }
 
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
 /*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
+ * POWER-PMU does not support disabling individual counters, hence
+ * program their cycle counter to their max value and ignore the interrupts.
  */
-static void power_pmu_unthrottle(struct perf_event *event)
+
+static void power_pmu_start(struct perf_event *event, int ef_flags)
+{
+       unsigned long flags;
+       s64 left;
+
+       if (!event->hw.idx || !event->hw.sample_period)
+               return;
+
+       if (!(event->hw.state & PERF_HES_STOPPED))
+               return;
+
+       if (ef_flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+       local_irq_save(flags);
+       perf_pmu_disable(event->pmu);
+
+       event->hw.state = 0;
+       left = local64_read(&event->hw.period_left);
+       write_pmc(event->hw.idx, left);
+
+       perf_event_update_userpage(event);
+       perf_pmu_enable(event->pmu);
+       local_irq_restore(flags);
+}
+
+static void power_pmu_stop(struct perf_event *event, int ef_flags)
 {
-       s64 val, left;
        unsigned long flags;
 
        if (!event->hw.idx || !event->hw.sample_period)
                return;
+
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
        local_irq_save(flags);
-       perf_disable();
+       perf_pmu_disable(event->pmu);
+
        power_pmu_read(event);
-       left = event->hw.sample_period;
-       event->hw.last_period = left;
-       val = 0;
-       if (left < 0x80000000L)
-               val = 0x80000000L - left;
-       write_pmc(event->hw.idx, val);
-       local64_set(&event->hw.prev_count, val);
-       local64_set(&event->hw.period_left, left);
+       event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+       write_pmc(event->hw.idx, 0);
+
        perf_event_update_userpage(event);
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
@@ -857,10 +891,11 @@ static void power_pmu_unthrottle(struct perf_event *event)
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-void power_pmu_start_txn(const struct pmu *pmu)
+void power_pmu_start_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
+       perf_pmu_disable(pmu);
        cpuhw->group_flag |= PERF_EVENT_TXN;
        cpuhw->n_txn_start = cpuhw->n_events;
 }
@@ -870,11 +905,12 @@ void power_pmu_start_txn(const struct pmu *pmu)
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-void power_pmu_cancel_txn(const struct pmu *pmu)
+void power_pmu_cancel_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
        cpuhw->group_flag &= ~PERF_EVENT_TXN;
+       perf_pmu_enable(pmu);
 }
 
 /*
@@ -882,7 +918,7 @@ void power_pmu_cancel_txn(const struct pmu *pmu)
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-int power_pmu_commit_txn(const struct pmu *pmu)
+int power_pmu_commit_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw;
        long i, n;
@@ -901,19 +937,10 @@ int power_pmu_commit_txn(const struct pmu *pmu)
                cpuhw->event[i]->hw.config = cpuhw->events[i];
 
        cpuhw->group_flag &= ~PERF_EVENT_TXN;
+       perf_pmu_enable(pmu);
        return 0;
 }
 
-struct pmu power_pmu = {
-       .enable         = power_pmu_enable,
-       .disable        = power_pmu_disable,
-       .read           = power_pmu_read,
-       .unthrottle     = power_pmu_unthrottle,
-       .start_txn      = power_pmu_start_txn,
-       .cancel_txn     = power_pmu_cancel_txn,
-       .commit_txn     = power_pmu_commit_txn,
-};
-
 /*
  * Return 1 if we might be able to put event on a limited PMC,
  * or 0 if not.
@@ -1014,7 +1041,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
        return 0;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int power_pmu_event_init(struct perf_event *event)
 {
        u64 ev;
        unsigned long flags;
@@ -1026,25 +1053,27 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        struct cpu_hw_events *cpuhw;
 
        if (!ppmu)
-               return ERR_PTR(-ENXIO);
+               return -ENOENT;
+
        switch (event->attr.type) {
        case PERF_TYPE_HARDWARE:
                ev = event->attr.config;
                if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
-                       return ERR_PTR(-EOPNOTSUPP);
+                       return -EOPNOTSUPP;
                ev = ppmu->generic_events[ev];
                break;
        case PERF_TYPE_HW_CACHE:
                err = hw_perf_cache_event(event->attr.config, &ev);
                if (err)
-                       return ERR_PTR(err);
+                       return err;
                break;
        case PERF_TYPE_RAW:
                ev = event->attr.config;
                break;
        default:
-               return ERR_PTR(-EINVAL);
+               return -ENOENT;
        }
+
        event->hw.config_base = ev;
        event->hw.idx = 0;
 
@@ -1063,7 +1092,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
         * XXX we should check if the task is an idle task.
         */
        flags = 0;
-       if (event->ctx->task)
+       if (event->attach_state & PERF_ATTACH_TASK)
                flags |= PPMU_ONLY_COUNT_RUN;
 
        /*
@@ -1081,7 +1110,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
                         */
                        ev = normal_pmc_alternative(ev, flags);
                        if (!ev)
-                               return ERR_PTR(-EINVAL);
+                               return -EINVAL;
                }
        }
 
@@ -1095,19 +1124,19 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
                n = collect_events(event->group_leader, ppmu->n_counter - 1,
                                   ctrs, events, cflags);
                if (n < 0)
-                       return ERR_PTR(-EINVAL);
+                       return -EINVAL;
        }
        events[n] = ev;
        ctrs[n] = event;
        cflags[n] = flags;
        if (check_excludes(ctrs, cflags, n, 1))
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        cpuhw = &get_cpu_var(cpu_hw_events);
        err = power_check_constraints(cpuhw, events, cflags, n + 1);
        put_cpu_var(cpu_hw_events);
        if (err)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        event->hw.config = events[n];
        event->hw.event_base = cflags[n];
@@ -1132,11 +1161,23 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        }
        event->destroy = hw_perf_event_destroy;
 
-       if (err)
-               return ERR_PTR(err);
-       return &power_pmu;
+       return err;
 }
 
+struct pmu power_pmu = {
+       .pmu_enable     = power_pmu_enable,
+       .pmu_disable    = power_pmu_disable,
+       .event_init     = power_pmu_event_init,
+       .add            = power_pmu_add,
+       .del            = power_pmu_del,
+       .start          = power_pmu_start,
+       .stop           = power_pmu_stop,
+       .read           = power_pmu_read,
+       .start_txn      = power_pmu_start_txn,
+       .cancel_txn     = power_pmu_cancel_txn,
+       .commit_txn     = power_pmu_commit_txn,
+};
+
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -1149,6 +1190,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
        s64 prev, delta, left;
        int record = 0;
 
+       if (event->hw.state & PERF_HES_STOPPED) {
+               write_pmc(event->hw.idx, 0);
+               return;
+       }
+
        /* we don't have to worry about interrupts here */
        prev = local64_read(&event->hw.prev_count);
        delta = (val - prev) & 0xfffffffful;
@@ -1171,6 +1217,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                        val = 0x80000000LL - left;
        }
 
+       write_pmc(event->hw.idx, val);
+       local64_set(&event->hw.prev_count, val);
+       local64_set(&event->hw.period_left, left);
+       perf_event_update_userpage(event);
+
        /*
         * Finally record data if requested.
         */
@@ -1183,23 +1234,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                if (event->attr.sample_type & PERF_SAMPLE_ADDR)
                        perf_get_data_addr(regs, &data.addr);
 
-               if (perf_event_overflow(event, nmi, &data, regs)) {
-                       /*
-                        * Interrupts are coming too fast - throttle them
-                        * by setting the event to 0, so it will be
-                        * at least 2^30 cycles until the next interrupt
-                        * (assuming each event counts at most 2 counts
-                        * per cycle).
-                        */
-                       val = 0;
-                       left = ~0ULL >> 1;
-               }
+               if (perf_event_overflow(event, nmi, &data, regs))
+                       power_pmu_stop(event, 0);
        }
-
-       write_pmc(event->hw.idx, val);
-       local64_set(&event->hw.prev_count, val);
-       local64_set(&event->hw.period_left, left);
-       perf_event_update_userpage(event);
 }
 
 /*
@@ -1342,6 +1379,7 @@ int register_power_pmu(struct power_pmu *pmu)
                freeze_events_kernel = MMCR0_FCHV;
 #endif /* CONFIG_PPC64 */
 
+       perf_pmu_register(&power_pmu);
        perf_cpu_notifier(power_pmu_notifier);
 
        return 0;
index 1ba45471ae436617e1ecbf3654a5064ef15d1af7..7ecca59ddf77fe20bd46b470d9392cdd16fd5ba9 100644 (file)
@@ -156,6 +156,9 @@ static void fsl_emb_pmu_read(struct perf_event *event)
 {
        s64 val, delta, prev;
 
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
        /*
         * Performance monitor interrupts come even when interrupts
         * are soft-disabled, as long as interrupts are hard-enabled.
@@ -177,7 +180,7 @@ static void fsl_emb_pmu_read(struct perf_event *event)
  * Disable all events to prevent PMU interrupts and to allow
  * events to be added or removed.
  */
-void hw_perf_disable(void)
+static void fsl_emb_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw;
        unsigned long flags;
@@ -216,7 +219,7 @@ void hw_perf_disable(void)
  * If we were previously disabled and events were added, then
  * put the new config on the PMU.
  */
-void hw_perf_enable(void)
+static void fsl_emb_pmu_enable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw;
        unsigned long flags;
@@ -262,8 +265,8 @@ static int collect_events(struct perf_event *group, int max_count,
        return n;
 }
 
-/* perf must be disabled, context locked on entry */
-static int fsl_emb_pmu_enable(struct perf_event *event)
+/* context locked on entry */
+static int fsl_emb_pmu_add(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuhw;
        int ret = -EAGAIN;
@@ -271,6 +274,7 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
        u64 val;
        int i;
 
+       perf_pmu_disable(event->pmu);
        cpuhw = &get_cpu_var(cpu_hw_events);
 
        if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
@@ -301,6 +305,12 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
                        val = 0x80000000L - left;
        }
        local64_set(&event->hw.prev_count, val);
+
+       if (!(flags & PERF_EF_START)) {
+               event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+               val = 0;
+       }
+
        write_pmc(i, val);
        perf_event_update_userpage(event);
 
@@ -310,15 +320,17 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
        ret = 0;
  out:
        put_cpu_var(cpu_hw_events);
+       perf_pmu_enable(event->pmu);
        return ret;
 }
 
-/* perf must be disabled, context locked on entry */
-static void fsl_emb_pmu_disable(struct perf_event *event)
+/* context locked on entry */
+static void fsl_emb_pmu_del(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuhw;
        int i = event->hw.idx;
 
+       perf_pmu_disable(event->pmu);
        if (i < 0)
                goto out;
 
@@ -346,44 +358,57 @@ static void fsl_emb_pmu_disable(struct perf_event *event)
        cpuhw->n_events--;
 
  out:
+       perf_pmu_enable(event->pmu);
        put_cpu_var(cpu_hw_events);
 }
 
-/*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
- *
- * Context is locked on entry, but perf is not disabled.
- */
-static void fsl_emb_pmu_unthrottle(struct perf_event *event)
+static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags)
 {
-       s64 val, left;
        unsigned long flags;
+       s64 left;
 
        if (event->hw.idx < 0 || !event->hw.sample_period)
                return;
+
+       if (!(event->hw.state & PERF_HES_STOPPED))
+               return;
+
+       if (ef_flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
        local_irq_save(flags);
-       perf_disable();
-       fsl_emb_pmu_read(event);
-       left = event->hw.sample_period;
-       event->hw.last_period = left;
-       val = 0;
-       if (left < 0x80000000L)
-               val = 0x80000000L - left;
-       write_pmc(event->hw.idx, val);
-       local64_set(&event->hw.prev_count, val);
-       local64_set(&event->hw.period_left, left);
+       perf_pmu_disable(event->pmu);
+
+       event->hw.state = 0;
+       left = local64_read(&event->hw.period_left);
+       write_pmc(event->hw.idx, left);
+
        perf_event_update_userpage(event);
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
-static struct pmu fsl_emb_pmu = {
-       .enable         = fsl_emb_pmu_enable,
-       .disable        = fsl_emb_pmu_disable,
-       .read           = fsl_emb_pmu_read,
-       .unthrottle     = fsl_emb_pmu_unthrottle,
-};
+static void fsl_emb_pmu_stop(struct perf_event *event, int ef_flags)
+{
+       unsigned long flags;
+
+       if (event->hw.idx < 0 || !event->hw.sample_period)
+               return;
+
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
+       local_irq_save(flags);
+       perf_pmu_disable(event->pmu);
+
+       fsl_emb_pmu_read(event);
+       event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+       write_pmc(event->hw.idx, 0);
+
+       perf_event_update_userpage(event);
+       perf_pmu_enable(event->pmu);
+       local_irq_restore(flags);
+}
 
 /*
  * Release the PMU if this is the last perf_event.
@@ -428,7 +453,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
        return 0;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int fsl_emb_pmu_event_init(struct perf_event *event)
 {
        u64 ev;
        struct perf_event *events[MAX_HWEVENTS];
@@ -441,14 +466,14 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        case PERF_TYPE_HARDWARE:
                ev = event->attr.config;
                if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
-                       return ERR_PTR(-EOPNOTSUPP);
+                       return -EOPNOTSUPP;
                ev = ppmu->generic_events[ev];
                break;
 
        case PERF_TYPE_HW_CACHE:
                err = hw_perf_cache_event(event->attr.config, &ev);
                if (err)
-                       return ERR_PTR(err);
+                       return err;
                break;
 
        case PERF_TYPE_RAW:
@@ -456,12 +481,12 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
                break;
 
        default:
-               return ERR_PTR(-EINVAL);
+               return -ENOENT;
        }
 
        event->hw.config = ppmu->xlate_event(ev);
        if (!(event->hw.config & FSL_EMB_EVENT_VALID))
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        /*
         * If this is in a group, check if it can go on with all the
@@ -473,7 +498,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
                n = collect_events(event->group_leader,
                                   ppmu->n_counter - 1, events);
                if (n < 0)
-                       return ERR_PTR(-EINVAL);
+                       return -EINVAL;
        }
 
        if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
@@ -484,7 +509,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
                }
 
                if (num_restricted >= ppmu->n_restricted)
-                       return ERR_PTR(-EINVAL);
+                       return -EINVAL;
        }
 
        event->hw.idx = -1;
@@ -497,7 +522,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        if (event->attr.exclude_kernel)
                event->hw.config_base |= PMLCA_FCS;
        if (event->attr.exclude_idle)
-               return ERR_PTR(-ENOTSUPP);
+               return -ENOTSUPP;
 
        event->hw.last_period = event->hw.sample_period;
        local64_set(&event->hw.period_left, event->hw.last_period);
@@ -523,11 +548,20 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        }
        event->destroy = hw_perf_event_destroy;
 
-       if (err)
-               return ERR_PTR(err);
-       return &fsl_emb_pmu;
+       return err;
 }
 
+static struct pmu fsl_emb_pmu = {
+       .pmu_enable     = fsl_emb_pmu_enable,
+       .pmu_disable    = fsl_emb_pmu_disable,
+       .event_init     = fsl_emb_pmu_event_init,
+       .add            = fsl_emb_pmu_add,
+       .del            = fsl_emb_pmu_del,
+       .start          = fsl_emb_pmu_start,
+       .stop           = fsl_emb_pmu_stop,
+       .read           = fsl_emb_pmu_read,
+};
+
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -540,6 +574,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
        s64 prev, delta, left;
        int record = 0;
 
+       if (event->hw.state & PERF_HES_STOPPED) {
+               write_pmc(event->hw.idx, 0);
+               return;
+       }
+
        /* we don't have to worry about interrupts here */
        prev = local64_read(&event->hw.prev_count);
        delta = (val - prev) & 0xfffffffful;
@@ -562,6 +601,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                        val = 0x80000000LL - left;
        }
 
+       write_pmc(event->hw.idx, val);
+       local64_set(&event->hw.prev_count, val);
+       local64_set(&event->hw.period_left, left);
+       perf_event_update_userpage(event);
+
        /*
         * Finally record data if requested.
         */
@@ -571,23 +615,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                perf_sample_data_init(&data, 0);
                data.period = event->hw.last_period;
 
-               if (perf_event_overflow(event, nmi, &data, regs)) {
-                       /*
-                        * Interrupts are coming too fast - throttle them
-                        * by setting the event to 0, so it will be
-                        * at least 2^30 cycles until the next interrupt
-                        * (assuming each event counts at most 2 counts
-                        * per cycle).
-                        */
-                       val = 0;
-                       left = ~0ULL >> 1;
-               }
+               if (perf_event_overflow(event, nmi, &data, regs))
+                       fsl_emb_pmu_stop(event, 0);
        }
-
-       write_pmc(event->hw.idx, val);
-       local64_set(&event->hw.prev_count, val);
-       local64_set(&event->hw.period_left, left);
-       perf_event_update_userpage(event);
 }
 
 static void perf_event_interrupt(struct pt_regs *regs)
@@ -651,5 +681,7 @@ int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu)
        pr_info("%s performance monitor hardware support registered\n",
                pmu->name);
 
+       perf_pmu_register(&fsl_emb_pmu);
+
        return 0;
 }
index 8eff48e20dba8ae056f9f4469642a5cdc453aefc..3fee685de4df49e01a3a85ff069f3d409354c924 100644 (file)
@@ -169,9 +169,11 @@ static int p970_marked_instr_event(u64 event)
        switch (unit) {
        case PM_VPU:
                mask = 0x4c;            /* byte 0 bits 2,3,6 */
+               break;
        case PM_LSU0:
                /* byte 2 bits 0,2,3,4,6; all of byte 1 */
                mask = 0x085dff00;
+               break;
        case PM_LSU1L:
                mask = 0x50 << 24;      /* byte 3 bits 4,6 */
                break;
index 91356ffda2ca3230e930245a0db1cc58cca323a0..84906d3fc8607befb6e2abca027480f12120d17d 100644 (file)
@@ -517,7 +517,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
        account_system_vtime(current);
        account_process_vtime(current);
-       calculate_steal_time();
 
        /*
         * We can't take a PMU exception inside _switch() since there is a
@@ -728,7 +727,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                p->thread.regs = childregs;
                if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_PPC64
-                       if (!test_thread_flag(TIF_32BIT))
+                       if (!is_32bit_task())
                                childregs->gpr[13] = childregs->gpr[6];
                        else
 #endif
@@ -823,7 +822,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
        regs->nip = start;
        regs->msr = MSR_USER;
 #else
-       if (!test_thread_flag(TIF_32BIT)) {
+       if (!is_32bit_task()) {
                unsigned long entry, toc;
 
                /* start is a relocated pointer to the function descriptor for
@@ -995,7 +994,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp,
        if (usp == 0)
                usp = regs->gpr[1];     /* stack pointer for child */
 #ifdef CONFIG_PPC64
-       if (test_thread_flag(TIF_32BIT)) {
+       if (is_32bit_task()) {
                parent_tidp = TRUNC_PTR(parent_tidp);
                child_tidp = TRUNC_PTR(child_tidp);
        }
@@ -1199,19 +1198,17 @@ void ppc64_runlatch_on(void)
        }
 }
 
-void ppc64_runlatch_off(void)
+void __ppc64_runlatch_off(void)
 {
        unsigned long ctrl;
 
-       if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
-               HMT_medium();
+       HMT_medium();
 
-               clear_thread_flag(TIF_RUNLATCH);
+       clear_thread_flag(TIF_RUNLATCH);
 
-               ctrl = mfspr(SPRN_CTRLF);
-               ctrl &= ~CTRL_RUNLATCH;
-               mtspr(SPRN_CTRLT, ctrl);
-       }
+       ctrl = mfspr(SPRN_CTRLF);
+       ctrl &= ~CTRL_RUNLATCH;
+       mtspr(SPRN_CTRLT, ctrl);
 }
 #endif
 
@@ -1300,14 +1297,3 @@ unsigned long randomize_et_dyn(unsigned long base)
 
        return ret;
 }
-
-#ifdef CONFIG_SMP
-int arch_sd_sibling_asym_packing(void)
-{
-       if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
-               printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
-               return SD_ASYM_PACKING;
-       }
-       return 0;
-}
-#endif
index fed9bf6187d1a514e88677b144c5ad1273be8505..c3c6a88575441a5d68c75705a1ac68e0d130a5f7 100644 (file)
@@ -66,6 +66,7 @@
 int __initdata iommu_is_off;
 int __initdata iommu_force_on;
 unsigned long tce_alloc_start, tce_alloc_end;
+u64 ppc64_rma_size;
 #endif
 
 static int __init early_parse_mem(char *p)
@@ -98,7 +99,7 @@ static void __init move_device_tree(void)
 
        if ((memory_limit && (start + size) > memory_limit) ||
                        overlaps_crashkernel(start, size)) {
-               p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size));
+               p = __va(memblock_alloc(size, PAGE_SIZE));
                memcpy(p, initial_boot_params, size);
                initial_boot_params = (struct boot_param_header *)p;
                DBG("Moved device tree to 0x%p\n", p);
@@ -492,7 +493,7 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node,
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
-#if defined(CONFIG_PPC64)
+#ifdef CONFIG_PPC64
        if (iommu_is_off) {
                if (base >= 0x80000000ul)
                        return;
@@ -501,9 +502,13 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
        }
 #endif
 
-       memblock_add(base, size);
-
+       /* First MEMBLOCK added, do some special initializations */
+       if (memstart_addr == ~(phys_addr_t)0)
+               setup_initial_memory_limit(base, size);
        memstart_addr = min((u64)memstart_addr, base);
+
+       /* Add the chunk to the MEMBLOCK list */
+       memblock_add(base, size);
 }
 
 u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -655,7 +660,6 @@ static void __init phyp_dump_reserve_mem(void)
 static inline void __init phyp_dump_reserve_mem(void) {}
 #endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
 
-
 void __init early_init_devtree(void *params)
 {
        phys_addr_t limit;
@@ -683,6 +687,7 @@ void __init early_init_devtree(void *params)
 
        /* Scan memory nodes and rebuild MEMBLOCKs */
        memblock_init();
+
        of_scan_flat_dt(early_init_dt_scan_root, NULL);
        of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
 
index 11f3cd9c832f6c25fc97b4666fda60eeaaf8e1bd..286d9783d93f3ed2806036e14b5b6690d159865a 100644 (file)
@@ -1681,7 +1681,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 
        if (unlikely(current->audit_context)) {
 #ifdef CONFIG_PPC64
-               if (!test_thread_flag(TIF_32BIT))
+               if (!is_32bit_task())
                        audit_syscall_entry(AUDIT_ARCH_PPC64,
                                            regs->gpr[0],
                                            regs->gpr[3], regs->gpr[4],
index 41048de3c6c396d84826e68a12edc639f86b0587..8fe8bc61c10a5543a2cd1553fbe613a096054586 100644 (file)
@@ -805,7 +805,7 @@ static void rtas_percpu_suspend_me(void *info)
        __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
 }
 
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
 {
        long state;
        long rc;
@@ -855,7 +855,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
        return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
 {
        return -ENOSYS;
 }
@@ -969,7 +969,7 @@ void __init rtas_initialize(void)
         */
 #ifdef CONFIG_PPC64
        if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
-               rtas_region = min(memblock.rmo_size, RTAS_INSTANTIATE_MAX);
+               rtas_region = min(ppc64_rma_size, RTAS_INSTANTIATE_MAX);
                ibm_suspend_me_token = rtas_token("ibm,suspend-me");
        }
 #endif
index 67a84d8f118d665ff78d965752ab08dc3152760e..2b442e6c21e62b47409a35959e30d95b330e9f0f 100644 (file)
@@ -716,6 +716,7 @@ static const struct file_operations rtas_flash_operations = {
        .write          = rtas_flash_write,
        .open           = rtas_excl_open,
        .release        = rtas_flash_release,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations manage_flash_operations = {
@@ -724,6 +725,7 @@ static const struct file_operations manage_flash_operations = {
        .write          = manage_flash_write,
        .open           = rtas_excl_open,
        .release        = rtas_excl_release,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations validate_flash_operations = {
@@ -732,6 +734,7 @@ static const struct file_operations validate_flash_operations = {
        .write          = validate_flash_write,
        .open           = rtas_excl_open,
        .release        = validate_flash_release,
+       .llseek         = default_llseek,
 };
 
 static int __init rtas_flash_init(void)
index 638883e23e3a32b5fd9ea30885cd63122a117f97..0438f819fe6b1adf10a16c42f6b32b8b2c75d059 100644 (file)
@@ -354,6 +354,7 @@ static const struct file_operations proc_rtas_log_operations = {
        .poll =         rtas_log_poll,
        .open =         rtas_log_open,
        .release =      rtas_log_release,
+       .llseek =       noop_llseek,
 };
 
 static int enable_surveillance(int timeout)
index a10ffc85ada77cfa802f371725a8d1b86bc7475b..1d2fbc905303401c50bbd410da0118338cb05eb7 100644 (file)
@@ -46,7 +46,7 @@
 
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
-int boot_cpuid;
+int boot_cpuid = -1;
 EXPORT_SYMBOL_GPL(boot_cpuid);
 int boot_cpuid_phys;
 
@@ -246,7 +246,7 @@ static void __init irqstack_early_init(void)
        unsigned int i;
 
        /* interrupt stacks must be in lowmem, we get that for free on ppc32
-        * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
+        * as the memblock is limited to lowmem by default */
        for_each_possible_cpu(i) {
                softirq_ctx[i] = (struct thread_info *)
                        __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
@@ -258,17 +258,18 @@ static void __init irqstack_early_init(void)
 #if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
 static void __init exc_lvl_early_init(void)
 {
-       unsigned int i;
+       unsigned int i, hw_cpu;
 
        /* interrupt stacks must be in lowmem, we get that for free on ppc32
         * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
        for_each_possible_cpu(i) {
-               critirq_ctx[i] = (struct thread_info *)
+               hw_cpu = get_hard_smp_processor_id(i);
+               critirq_ctx[hw_cpu] = (struct thread_info *)
                        __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
 #ifdef CONFIG_BOOKE
-               dbgirq_ctx[i] = (struct thread_info *)
+               dbgirq_ctx[hw_cpu] = (struct thread_info *)
                        __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
-               mcheckirq_ctx[i] = (struct thread_info *)
+               mcheckirq_ctx[hw_cpu] = (struct thread_info *)
                        __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
 #endif
        }
index 1bee4b68fa452ed4c3894785fdfc8ff80276a6e5..2a178b0ebcdf8ea33ed67c8a4516b7ec0f1d9f26 100644 (file)
@@ -95,7 +95,7 @@ int ucache_bsize;
 
 #ifdef CONFIG_SMP
 
-static int smt_enabled_cmdline;
+static char *smt_enabled_cmdline;
 
 /* Look for ibm,smt-enabled OF option */
 static void check_smt_enabled(void)
@@ -103,37 +103,46 @@ static void check_smt_enabled(void)
        struct device_node *dn;
        const char *smt_option;
 
-       /* Allow the command line to overrule the OF option */
-       if (smt_enabled_cmdline)
-               return;
-
-       dn = of_find_node_by_path("/options");
-
-       if (dn) {
-               smt_option = of_get_property(dn, "ibm,smt-enabled", NULL);
+       /* Default to enabling all threads */
+       smt_enabled_at_boot = threads_per_core;
 
-                if (smt_option) {
-                       if (!strcmp(smt_option, "on"))
-                               smt_enabled_at_boot = 1;
-                       else if (!strcmp(smt_option, "off"))
-                               smt_enabled_at_boot = 0;
-                }
-        }
+       /* Allow the command line to overrule the OF option */
+       if (smt_enabled_cmdline) {
+               if (!strcmp(smt_enabled_cmdline, "on"))
+                       smt_enabled_at_boot = threads_per_core;
+               else if (!strcmp(smt_enabled_cmdline, "off"))
+                       smt_enabled_at_boot = 0;
+               else {
+                       long smt;
+                       int rc;
+
+                       rc = strict_strtol(smt_enabled_cmdline, 10, &smt);
+                       if (!rc)
+                               smt_enabled_at_boot =
+                                       min(threads_per_core, (int)smt);
+               }
+       } else {
+               dn = of_find_node_by_path("/options");
+               if (dn) {
+                       smt_option = of_get_property(dn, "ibm,smt-enabled",
+                                                    NULL);
+
+                       if (smt_option) {
+                               if (!strcmp(smt_option, "on"))
+                                       smt_enabled_at_boot = threads_per_core;
+                               else if (!strcmp(smt_option, "off"))
+                                       smt_enabled_at_boot = 0;
+                       }
+
+                       of_node_put(dn);
+               }
+       }
 }
 
 /* Look for smt-enabled= cmdline option */
 static int __init early_smt_enabled(char *p)
 {
-       smt_enabled_cmdline = 1;
-
-       if (!p)
-               return 0;
-
-       if (!strcmp(p, "on") || !strcmp(p, "1"))
-               smt_enabled_at_boot = 1;
-       else if (!strcmp(p, "off") || !strcmp(p, "0"))
-               smt_enabled_at_boot = 0;
-
+       smt_enabled_cmdline = p;
        return 0;
 }
 early_param("smt-enabled", early_smt_enabled);
@@ -380,8 +389,8 @@ void __init setup_system(void)
         */
        xmon_setup();
 
-       check_smt_enabled();
        smp_setup_cpu_maps();
+       check_smt_enabled();
 
 #ifdef CONFIG_SMP
        /* Release secondary cpus out of their spinloops at 0x60 now that
@@ -477,7 +486,7 @@ static void __init emergency_stack_init(void)
         * bringup, we need to get at them in real mode. This means they
         * must also be within the RMO region.
         */
-       limit = min(slb0_limit(), memblock.rmo_size);
+       limit = min(slb0_limit(), ppc64_rma_size);
 
        for_each_possible_cpu(i) {
                unsigned long sp;
index 7109f5b1baa87bd63e36aa18910c7d0bdfa40b12..2300426e531a096239b0620f9ec29f71e70b6daf 100644 (file)
@@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
                        ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
                        sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
                }
+               regs->trap = 0;
                return 0;               /* no signals delivered */
        }
 
@@ -164,6 +165,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
                ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
        }
 
+       regs->trap = 0;
        if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked, &current->blocked,
index 266610119f664970c66b72832ebb571eb842b1bc..b96a3a010c26859ab93f8cca5ec74cd4905dd16b 100644 (file)
@@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs,
        if (!sig)
                save_r2 = (unsigned int)regs->gpr[2];
        err = restore_general_regs(regs, sr);
+       regs->trap = 0;
        err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
        if (!sig)
                regs->gpr[2] = (unsigned long) save_r2;
@@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
        regs->nip = (unsigned long) ka->sa.sa_handler;
        /* enter the signal handler in big-endian mode */
        regs->msr &= ~MSR_LE;
-       regs->trap = 0;
        return 1;
 
 badframe:
@@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        regs->nip = (unsigned long) ka->sa.sa_handler;
        /* enter the signal handler in big-endian mode */
        regs->msr &= ~MSR_LE;
-       regs->trap = 0;
 
        return 1;
 
index 2fe6fc64b614ef9d1b935a472487eaf161967fd9..27c4a4584f805b83fbcf09c5478e7ec9fa7f5e7c 100644 (file)
@@ -178,7 +178,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
        err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]);
        err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]);
        /* skip SOFTE */
-       err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]);
+       regs->trap = 0;
        err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]);
        err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]);
        err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]);
index a61b3ddd7bb3c0cd8fb3a3ec79d91005a7e4294d..68034bbf2e4f0affdeaa991a56b75482b6c3d615 100644 (file)
@@ -427,11 +427,11 @@ int __cpuinit __cpu_up(unsigned int cpu)
 #endif
 
        if (!cpu_callin_map[cpu]) {
-               printk("Processor %u is stuck.\n", cpu);
+               printk(KERN_ERR "Processor %u is stuck.\n", cpu);
                return -ENOENT;
        }
 
-       printk("Processor %u found.\n", cpu);
+       DBG("Processor %u found.\n", cpu);
 
        if (smp_ops->give_timebase)
                smp_ops->give_timebase();
@@ -508,9 +508,6 @@ int __devinit start_secondary(void *unused)
        if (smp_ops->take_timebase)
                smp_ops->take_timebase();
 
-       if (system_state > SYSTEM_BOOTING)
-               snapshot_timebase();
-
        secondary_cpu_time_init();
 
        ipi_call_lock();
@@ -575,11 +572,18 @@ void __init smp_cpus_done(unsigned int max_cpus)
 
        free_cpumask_var(old_mask);
 
-       snapshot_timebases();
-
        dump_numa_cpu_topology();
 }
 
+int arch_sd_sibling_asym_packing(void)
+{
+       if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
+               printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+               return SD_ASYM_PACKING;
+       }
+       return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 int __cpu_disable(void)
 {
index 20fd701a686adfeffc10e718c078f074eab92eaa..b1b6043a56c44f6b07537e8eb4a0aa720400e296 100644 (file)
@@ -616,3 +616,11 @@ asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
 
        return sys_sync_file_range(fd, offset, nbytes, flags);
 }
+
+asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags,
+                                        unsigned mask_hi, unsigned mask_lo,
+                                        int dfd, const char __user *pathname)
+{
+       u64 mask = ((u64)mask_hi << 32) | mask_lo;
+       return sys_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
+}
index ce53dfa7130dfc74f551c2360746f206154cf925..010406958d974a4d0275be31bbba90af2de5035a 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/posix-timers.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <asm/trace.h>
 
 #include <asm/io.h>
@@ -161,10 +161,9 @@ extern struct timezone sys_tz;
 static long timezone_offset;
 
 unsigned long ppc_proc_freq;
-EXPORT_SYMBOL(ppc_proc_freq);
+EXPORT_SYMBOL_GPL(ppc_proc_freq);
 unsigned long ppc_tb_freq;
-
-static DEFINE_PER_CPU(u64, last_jiffy);
+EXPORT_SYMBOL_GPL(ppc_tb_freq);
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -185,6 +184,8 @@ DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
 
 cputime_t cputime_one_jiffy;
 
+void (*dtl_consumer)(struct dtl_entry *, u64);
+
 static void calc_cputime_factors(void)
 {
        struct div_result res;
@@ -200,62 +201,153 @@ static void calc_cputime_factors(void)
 }
 
 /*
- * Read the PURR on systems that have it, otherwise the timebase.
+ * Read the SPURR on systems that have it, otherwise the PURR,
+ * or if that doesn't exist return the timebase value passed in.
  */
-static u64 read_purr(void)
+static u64 read_spurr(u64 tb)
 {
+       if (cpu_has_feature(CPU_FTR_SPURR))
+               return mfspr(SPRN_SPURR);
        if (cpu_has_feature(CPU_FTR_PURR))
                return mfspr(SPRN_PURR);
-       return mftb();
+       return tb;
 }
 
+#ifdef CONFIG_PPC_SPLPAR
+
 /*
- * Read the SPURR on systems that have it, otherwise the purr
+ * Scan the dispatch trace log and count up the stolen time.
+ * Should be called with interrupts disabled.
  */
-static u64 read_spurr(u64 purr)
+static u64 scan_dispatch_log(u64 stop_tb)
 {
-       /*
-        * cpus without PURR won't have a SPURR
-        * We already know the former when we use this, so tell gcc
-        */
-       if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR))
-               return mfspr(SPRN_SPURR);
-       return purr;
+       u64 i = local_paca->dtl_ridx;
+       struct dtl_entry *dtl = local_paca->dtl_curr;
+       struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
+       struct lppaca *vpa = local_paca->lppaca_ptr;
+       u64 tb_delta;
+       u64 stolen = 0;
+       u64 dtb;
+
+       if (i == vpa->dtl_idx)
+               return 0;
+       while (i < vpa->dtl_idx) {
+               if (dtl_consumer)
+                       dtl_consumer(dtl, i);
+               dtb = dtl->timebase;
+               tb_delta = dtl->enqueue_to_dispatch_time +
+                       dtl->ready_to_enqueue_time;
+               barrier();
+               if (i + N_DISPATCH_LOG < vpa->dtl_idx) {
+                       /* buffer has overflowed */
+                       i = vpa->dtl_idx - N_DISPATCH_LOG;
+                       dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
+                       continue;
+               }
+               if (dtb > stop_tb)
+                       break;
+               stolen += tb_delta;
+               ++i;
+               ++dtl;
+               if (dtl == dtl_end)
+                       dtl = local_paca->dispatch_log;
+       }
+       local_paca->dtl_ridx = i;
+       local_paca->dtl_curr = dtl;
+       return stolen;
 }
 
+/*
+ * Accumulate stolen time by scanning the dispatch trace log.
+ * Called on entry from user mode.
+ */
+void accumulate_stolen_time(void)
+{
+       u64 sst, ust;
+
+       sst = scan_dispatch_log(get_paca()->starttime_user);
+       ust = scan_dispatch_log(get_paca()->starttime);
+       get_paca()->system_time -= sst;
+       get_paca()->user_time -= ust;
+       get_paca()->stolen_time += ust + sst;
+}
+
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+       u64 stolen = 0;
+
+       if (get_paca()->dtl_ridx != get_paca()->lppaca_ptr->dtl_idx) {
+               stolen = scan_dispatch_log(stop_tb);
+               get_paca()->system_time -= stolen;
+       }
+
+       stolen += get_paca()->stolen_time;
+       get_paca()->stolen_time = 0;
+       return stolen;
+}
+
+#else /* CONFIG_PPC_SPLPAR */
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+       return 0;
+}
+
+#endif /* CONFIG_PPC_SPLPAR */
+
 /*
  * Account time for a transition between system, hard irq
  * or soft irq state.
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-       u64 now, nowscaled, delta, deltascaled, sys_time;
+       u64 now, nowscaled, delta, deltascaled;
        unsigned long flags;
+       u64 stolen, udelta, sys_scaled, user_scaled;
 
        local_irq_save(flags);
-       now = read_purr();
+       now = mftb();
        nowscaled = read_spurr(now);
-       delta = now - get_paca()->startpurr;
+       get_paca()->system_time += now - get_paca()->starttime;
+       get_paca()->starttime = now;
        deltascaled = nowscaled - get_paca()->startspurr;
-       get_paca()->startpurr = now;
        get_paca()->startspurr = nowscaled;
-       if (!in_interrupt()) {
-               /* deltascaled includes both user and system time.
-                * Hence scale it based on the purr ratio to estimate
-                * the system time */
-               sys_time = get_paca()->system_time;
-               if (get_paca()->user_time)
-                       deltascaled = deltascaled * sys_time /
-                            (sys_time + get_paca()->user_time);
-               delta += sys_time;
-               get_paca()->system_time = 0;
+
+       stolen = calculate_stolen_time(now);
+
+       delta = get_paca()->system_time;
+       get_paca()->system_time = 0;
+       udelta = get_paca()->user_time - get_paca()->utime_sspurr;
+       get_paca()->utime_sspurr = get_paca()->user_time;
+
+       /*
+        * Because we don't read the SPURR on every kernel entry/exit,
+        * deltascaled includes both user and system SPURR ticks.
+        * Apportion these ticks to system SPURR ticks and user
+        * SPURR ticks in the same ratio as the system time (delta)
+        * and user time (udelta) values obtained from the timebase
+        * over the same interval.  The system ticks get accounted here;
+        * the user ticks get saved up in paca->user_time_scaled to be
+        * used by account_process_tick.
+        */
+       sys_scaled = delta;
+       user_scaled = udelta;
+       if (deltascaled != delta + udelta) {
+               if (udelta) {
+                       sys_scaled = deltascaled * delta / (delta + udelta);
+                       user_scaled = deltascaled - sys_scaled;
+               } else {
+                       sys_scaled = deltascaled;
+               }
+       }
+       get_paca()->user_time_scaled += user_scaled;
+
+       if (in_irq() || idle_task(smp_processor_id()) != tsk) {
+               account_system_time(tsk, 0, delta, sys_scaled);
+               if (stolen)
+                       account_steal_time(stolen);
+       } else {
+               account_idle_time(delta + stolen);
        }
-       if (in_irq() || idle_task(smp_processor_id()) != tsk)
-               account_system_time(tsk, 0, delta, deltascaled);
-       else
-               account_idle_time(delta);
-       __get_cpu_var(cputime_last_delta) = delta;
-       __get_cpu_var(cputime_scaled_last_delta) = deltascaled;
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
@@ -265,125 +357,26 @@ EXPORT_SYMBOL_GPL(account_system_vtime);
  * by the exception entry and exit code to the generic process
  * user and system time records.
  * Must be called with interrupts disabled.
+ * Assumes that account_system_vtime() has been called recently
+ * (i.e. since the last entry from usermode) so that
+ * get_paca()->user_time_scaled is up to date.
  */
 void account_process_tick(struct task_struct *tsk, int user_tick)
 {
        cputime_t utime, utimescaled;
 
        utime = get_paca()->user_time;
+       utimescaled = get_paca()->user_time_scaled;
        get_paca()->user_time = 0;
-       utimescaled = cputime_to_scaled(utime);
+       get_paca()->user_time_scaled = 0;
+       get_paca()->utime_sspurr = 0;
        account_user_time(tsk, utime, utimescaled);
 }
 
-/*
- * Stuff for accounting stolen time.
- */
-struct cpu_purr_data {
-       int     initialized;                    /* thread is running */
-       u64     tb;                     /* last TB value read */
-       u64     purr;                   /* last PURR value read */
-       u64     spurr;                  /* last SPURR value read */
-};
-
-/*
- * Each entry in the cpu_purr_data array is manipulated only by its
- * "owner" cpu -- usually in the timer interrupt but also occasionally
- * in process context for cpu online.  As long as cpus do not touch
- * each others' cpu_purr_data, disabling local interrupts is
- * sufficient to serialize accesses.
- */
-static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
-
-static void snapshot_tb_and_purr(void *data)
-{
-       unsigned long flags;
-       struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
-
-       local_irq_save(flags);
-       p->tb = get_tb_or_rtc();
-       p->purr = mfspr(SPRN_PURR);
-       wmb();
-       p->initialized = 1;
-       local_irq_restore(flags);
-}
-
-/*
- * Called during boot when all cpus have come up.
- */
-void snapshot_timebases(void)
-{
-       if (!cpu_has_feature(CPU_FTR_PURR))
-               return;
-       on_each_cpu(snapshot_tb_and_purr, NULL, 1);
-}
-
-/*
- * Must be called with interrupts disabled.
- */
-void calculate_steal_time(void)
-{
-       u64 tb, purr;
-       s64 stolen;
-       struct cpu_purr_data *pme;
-
-       pme = &__get_cpu_var(cpu_purr_data);
-       if (!pme->initialized)
-               return;         /* !CPU_FTR_PURR or early in early boot */
-       tb = mftb();
-       purr = mfspr(SPRN_PURR);
-       stolen = (tb - pme->tb) - (purr - pme->purr);
-       if (stolen > 0) {
-               if (idle_task(smp_processor_id()) != current)
-                       account_steal_time(stolen);
-               else
-                       account_idle_time(stolen);
-       }
-       pme->tb = tb;
-       pme->purr = purr;
-}
-
-#ifdef CONFIG_PPC_SPLPAR
-/*
- * Must be called before the cpu is added to the online map when
- * a cpu is being brought up at runtime.
- */
-static void snapshot_purr(void)
-{
-       struct cpu_purr_data *pme;
-       unsigned long flags;
-
-       if (!cpu_has_feature(CPU_FTR_PURR))
-               return;
-       local_irq_save(flags);
-       pme = &__get_cpu_var(cpu_purr_data);
-       pme->tb = mftb();
-       pme->purr = mfspr(SPRN_PURR);
-       pme->initialized = 1;
-       local_irq_restore(flags);
-}
-
-#endif /* CONFIG_PPC_SPLPAR */
-
 #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
 #define calc_cputime_factors()
-#define calculate_steal_time()         do { } while (0)
-#endif
-
-#if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR))
-#define snapshot_purr()                        do { } while (0)
 #endif
 
-/*
- * Called when a cpu comes up after the system has finished booting,
- * i.e. as a result of a hotplug cpu action.
- */
-void snapshot_timebase(void)
-{
-       __get_cpu_var(last_jiffy) = get_tb_or_rtc();
-       snapshot_purr();
-}
-
 void __delay(unsigned long loops)
 {
        unsigned long start;
@@ -493,60 +486,60 @@ void __init iSeries_time_init_early(void)
 }
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
 
 /*
  * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
  */
 #ifdef CONFIG_PPC64
-static inline unsigned long test_perf_event_pending(void)
+static inline unsigned long test_irq_work_pending(void)
 {
        unsigned long x;
 
        asm volatile("lbz %0,%1(13)"
                : "=r" (x)
-               : "i" (offsetof(struct paca_struct, perf_event_pending)));
+               : "i" (offsetof(struct paca_struct, irq_work_pending)));
        return x;
 }
 
-static inline void set_perf_event_pending_flag(void)
+static inline void set_irq_work_pending_flag(void)
 {
        asm volatile("stb %0,%1(13)" : :
                "r" (1),
-               "i" (offsetof(struct paca_struct, perf_event_pending)));
+               "i" (offsetof(struct paca_struct, irq_work_pending)));
 }
 
-static inline void clear_perf_event_pending(void)
+static inline void clear_irq_work_pending(void)
 {
        asm volatile("stb %0,%1(13)" : :
                "r" (0),
-               "i" (offsetof(struct paca_struct, perf_event_pending)));
+               "i" (offsetof(struct paca_struct, irq_work_pending)));
 }
 
 #else /* 32-bit */
 
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
 
-#define set_perf_event_pending_flag()  __get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending()      __get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending()     __get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag()    __get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending()                __get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending()       __get_cpu_var(irq_work_pending) = 0
 
 #endif /* 32 vs 64 bit */
 
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
 {
        preempt_disable();
-       set_perf_event_pending_flag();
+       set_irq_work_pending_flag();
        set_dec(1);
        preempt_enable();
 }
 
-#else  /* CONFIG_PERF_EVENTS */
+#else  /* CONFIG_IRQ_WORK */
 
-#define test_perf_event_pending()      0
-#define clear_perf_event_pending()
+#define test_irq_work_pending()        0
+#define clear_irq_work_pending()
 
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -577,28 +570,17 @@ void timer_interrupt(struct pt_regs * regs)
         * some CPUs will continuue to take decrementer exceptions */
        set_dec(DECREMENTER_MAX);
 
-#ifdef CONFIG_PPC32
+#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
                do_IRQ(regs);
 #endif
 
-       now = get_tb_or_rtc();
-       if (now < decrementer->next_tb) {
-               /* not time for this event yet */
-               now = decrementer->next_tb - now;
-               if (now <= DECREMENTER_MAX)
-                       set_dec((int)now);
-               trace_timer_interrupt_exit(regs);
-               return;
-       }
        old_regs = set_irq_regs(regs);
        irq_enter();
 
-       calculate_steal_time();
-
-       if (test_perf_event_pending()) {
-               clear_perf_event_pending();
-               perf_event_do_pending();
+       if (test_irq_work_pending()) {
+               clear_irq_work_pending();
+               irq_work_run();
        }
 
 #ifdef CONFIG_PPC_ISERIES
@@ -606,8 +588,16 @@ void timer_interrupt(struct pt_regs * regs)
                get_lppaca()->int_dword.fields.decr_int = 0;
 #endif
 
-       if (evt->event_handler)
-               evt->event_handler(evt);
+       now = get_tb_or_rtc();
+       if (now >= decrementer->next_tb) {
+               decrementer->next_tb = ~(u64)0;
+               if (evt->event_handler)
+                       evt->event_handler(evt);
+       } else {
+               now = decrementer->next_tb - now;
+               if (now <= DECREMENTER_MAX)
+                       set_dec((int)now);
+       }
 
 #ifdef CONFIG_PPC_ISERIES
        if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
index a45a63c3a0c74bf4f8665afe6073ae13938754c9..1b2cdc8eec901fce78e21d279ca054684bec158c 100644 (file)
@@ -538,6 +538,11 @@ int machine_check_e500(struct pt_regs *regs)
 
        return 0;
 }
+
+int machine_check_generic(struct pt_regs *regs)
+{
+       return 0;
+}
 #elif defined(CONFIG_E200)
 int machine_check_e200(struct pt_regs *regs)
 {
index 13002fe206e7ce16ed79f5ad31e5aec58bc329cb..fd8728729abc9cb671d65bd8cb625fbaf22de12c 100644 (file)
@@ -159,7 +159,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
 {
        int i;
 
-       if (!vma || test_thread_flag(TIF_32BIT)) {
+       if (!vma || is_32bit_task()) {
                printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
                for (i=0; i<vdso32_pages; i++) {
                        struct page *pg = virt_to_page(vdso32_kbase +
@@ -170,7 +170,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
                        dump_one_vdso_page(pg, upg);
                }
        }
-       if (!vma || !test_thread_flag(TIF_32BIT)) {
+       if (!vma || !is_32bit_task()) {
                printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
                for (i=0; i<vdso64_pages; i++) {
                        struct page *pg = virt_to_page(vdso64_kbase +
@@ -200,7 +200,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                return 0;
 
 #ifdef CONFIG_PPC64
-       if (test_thread_flag(TIF_32BIT)) {
+       if (is_32bit_task()) {
                vdso_pagelist = vdso32_pagelist;
                vdso_pages = vdso32_pages;
                vdso_base = VDSO32_MBASE;
index 51ead52141bd083774ed3ed13d8c71dc831f0f23..9a7946c417387fdd0c56b4c3dd1010c4b642312f 100644 (file)
@@ -14,10 +14,10 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
 
 GCOV_PROFILE := n
 
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
                $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO32__ -s
+asflags-y := -D__VDSO32__ -s
 
 obj-y += vdso32_wrapper.o
 extra-y += vdso32.lds
index 79da65d44a2a78a01bf11f2c0bb5b2003560ae6c..8c500d8622e4d8d7696099b684b0ad519c63a8a4 100644 (file)
@@ -9,10 +9,10 @@ obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
 
 GCOV_PROFILE := n
 
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
                $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO64__ -s
+asflags-y := -D__VDSO64__ -s
 
 obj-y += vdso64_wrapper.o
 extra-y += vdso64.lds
index 00b9436f76525c501ecd8bcfab1abef5911a42d4..d692989a4318273c06fc1fdc024448afd15d322d 100644 (file)
@@ -1059,7 +1059,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
        if (!dma_window)
                return NULL;
 
-       tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+       tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
        if (tbl == NULL)
                return NULL;
 
@@ -1072,6 +1072,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
        tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
        tbl->it_busno = 0;
        tbl->it_type = TCE_VB;
+       tbl->it_blocksize = 16;
 
        return iommu_init_table(tbl, -1);
 }
@@ -1183,7 +1184,12 @@ EXPORT_SYMBOL(vio_unregister_driver);
 /* vio_dev refcount hit 0 */
 static void __devinit vio_dev_release(struct device *dev)
 {
-       /* XXX should free TCE table */
+       struct iommu_table *tbl = get_iommu_table_base(dev);
+
+       /* iSeries uses a common table for all vio devices */
+       if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl)
+               iommu_free_table(tbl, dev->of_node ?
+                       dev->of_node->full_name : dev_name(dev));
        of_node_put(dev->of_node);
        kfree(to_vio_dev(dev));
 }
@@ -1253,8 +1259,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
        if (device_register(&viodev->dev)) {
                printk(KERN_ERR "%s: failed to register device %s\n",
                                __func__, dev_name(&viodev->dev));
-               /* XXX free TCE table */
-               kfree(viodev);
+               put_device(&viodev->dev);
                return NULL;
        }
 
index d45c818a384c2281f0c8689272bcb130c18de98a..4d6863823f695ddabc15e6adc2e3c1fd62b82074 100644 (file)
@@ -4,7 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
+ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
 
 common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
index 474f2e24050a03a3d89ca85a7b34993d687a61f3..35a701f3ece479e5eb76849147e27c9bff22ea39 100644 (file)
 
 static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
 {
-       kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt], &vcpu->arch.fpscr);
+       kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt]);
 }
 
 static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
@@ -204,7 +204,7 @@ static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
        /* put in registers */
        switch (ls_type) {
        case FPU_LS_SINGLE:
-               kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+               kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs]);
                vcpu->arch.qpr[rs] = *((u32*)tmp);
                break;
        case FPU_LS_DOUBLE:
@@ -230,7 +230,7 @@ static int kvmppc_emulate_fpr_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        switch (ls_type) {
        case FPU_LS_SINGLE:
-               kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp, &vcpu->arch.fpscr);
+               kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp);
                val = *((u32*)tmp);
                len = sizeof(u32);
                break;
@@ -296,7 +296,7 @@ static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
        emulated = EMULATE_DONE;
 
        /* put in registers */
-       kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+       kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs]);
        vcpu->arch.qpr[rs] = tmp[1];
 
        dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0],
@@ -314,7 +314,7 @@ static int kvmppc_emulate_psq_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
        u32 tmp[2];
        int len = w ? sizeof(u32) : sizeof(u64);
 
-       kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0], &vcpu->arch.fpscr);
+       kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0]);
        tmp[1] = vcpu->arch.qpr[rs];
 
        r = kvmppc_st(vcpu, &addr, len, tmp, true);
@@ -516,9 +516,9 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc,
        WARN_ON(rc);
 
        /* PS0 */
-       kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
-       kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
-       kvm_cvt_df(&fpr[reg_in3], &ps0_in3, &vcpu->arch.fpscr);
+       kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
+       kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
+       kvm_cvt_df(&fpr[reg_in3], &ps0_in3);
 
        if (scalar & SCALAR_LOW)
                ps0_in2 = qpr[reg_in2];
@@ -529,7 +529,7 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc,
                          ps0_in1, ps0_in2, ps0_in3, ps0_out);
 
        if (!(scalar & SCALAR_NO_PS0))
-               kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+               kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 
        /* PS1 */
        ps1_in1 = qpr[reg_in1];
@@ -566,12 +566,12 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc,
        WARN_ON(rc);
 
        /* PS0 */
-       kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
+       kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
 
        if (scalar & SCALAR_LOW)
                ps0_in2 = qpr[reg_in2];
        else
-               kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
+               kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
 
        func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2);
 
@@ -579,7 +579,7 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc,
                dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n",
                                  ps0_in1, ps0_in2, ps0_out);
 
-               kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+               kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
        }
 
        /* PS1 */
@@ -615,13 +615,13 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
        WARN_ON(rc);
 
        /* PS0 */
-       kvm_cvt_df(&fpr[reg_in], &ps0_in, &vcpu->arch.fpscr);
+       kvm_cvt_df(&fpr[reg_in], &ps0_in);
        func(&vcpu->arch.fpscr, &ps0_out, &ps0_in);
 
        dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n",
                          ps0_in, ps0_out);
 
-       kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+       kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 
        /* PS1 */
        ps1_in = qpr[reg_in];
@@ -671,7 +671,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
 #ifdef DEBUG
        for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
                u32 f;
-               kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+               kvm_cvt_df(&vcpu->arch.fpr[i], &f);
                dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx    QPR[%d] = 0x%x\n",
                        i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]);
        }
@@ -796,8 +796,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra];
                        /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
                        kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
-                                  &vcpu->arch.qpr[ax_rd],
-                                  &vcpu->arch.fpscr);
+                                  &vcpu->arch.qpr[ax_rd]);
                        break;
                case OP_4X_PS_MERGE01:
                        WARN_ON(rcomp);
@@ -808,19 +807,16 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        WARN_ON(rcomp);
                        /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
                        kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
-                                  &vcpu->arch.fpr[ax_rd],
-                                  &vcpu->arch.fpscr);
+                                  &vcpu->arch.fpr[ax_rd]);
                        /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
                        kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
-                                  &vcpu->arch.qpr[ax_rd],
-                                  &vcpu->arch.fpscr);
+                                  &vcpu->arch.qpr[ax_rd]);
                        break;
                case OP_4X_PS_MERGE11:
                        WARN_ON(rcomp);
                        /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
                        kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
-                                  &vcpu->arch.fpr[ax_rd],
-                                  &vcpu->arch.fpscr);
+                                  &vcpu->arch.fpr[ax_rd]);
                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
                        break;
                }
@@ -1255,7 +1251,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
 #ifdef DEBUG
        for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
                u32 f;
-               kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+               kvm_cvt_df(&vcpu->arch.fpr[i], &f);
                dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
        }
 #endif
index 4568ec386c2aa858afe0a6024adfb476cac18c33..b83ba581fd8edb13e4d552ec8b6c9f5c6eb73076 100644 (file)
@@ -145,7 +145,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        /* this default type might be overwritten by subcategories */
        kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
 
-       pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
+       pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
 
        switch (get_op(inst)) {
        case OP_TRAP:
@@ -275,7 +275,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        {
                                u64 jd = get_tb() - vcpu->arch.dec_jiffies;
                                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd);
-                               pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n",
+                               pr_debug("mfDEC: %x - %llx = %lx\n",
                                         vcpu->arch.dec, jd,
                                         kvmppc_get_gpr(vcpu, rt));
                                break;
index cb34bbe1611365c4761ebd1d20c58e8f2997ae12..bf68d597549e4eaa72cb0cdeb7d57043b27c17eb 100644 (file)
@@ -273,19 +273,11 @@ FPD_THREE_IN(fnmsub)
 FPD_THREE_IN(fnmadd)
 
 _GLOBAL(kvm_cvt_fd)
-       lfd     0,0(r5)                 /* load up fpscr value */
-       MTFSF_L(0)
        lfs     0,0(r3)
        stfd    0,0(r4)
-       mffs    0
-       stfd    0,0(r5)                 /* save new fpscr value */
        blr
 
 _GLOBAL(kvm_cvt_df)
-       lfd     0,0(r5)                 /* load up fpscr value */
-       MTFSF_L(0)
        lfd     0,0(r3)
        stfs    0,0(r4)
-       mffs    0
-       stfd    0,0(r5)                 /* save new fpscr value */
        blr
index 5bb89c828070173a3b20496435b65c3928f18515..889f2bc106dd86af018b894dab475d79638f2694 100644 (file)
@@ -4,9 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS           += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
 
 CFLAGS_REMOVE_code-patching.o = -pg
 CFLAGS_REMOVE_feature-fixups.o = -pg
@@ -17,7 +15,8 @@ obj-$(CONFIG_PPC32)   += div64.o copy_32.o
 obj-$(CONFIG_HAS_IOMEM)        += devres.o
 
 obj-$(CONFIG_PPC64)    += copypage_64.o copyuser_64.o \
-                          memcpy_64.o usercopy_64.o mem_64.o string.o
+                          memcpy_64.o usercopy_64.o mem_64.o string.o \
+                          checksum_wrappers_64.o
 obj-$(CONFIG_XMON)     += sstep.o ldstfp.o
 obj-$(CONFIG_KPROBES)  += sstep.o ldstfp.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += sstep.o ldstfp.o
index ef96c6c58efc6644d68ac534fb1f4d40253aa605..18245af38aea7f747bd034dd5892c300ce73111c 100644 (file)
@@ -65,165 +65,393 @@ _GLOBAL(csum_tcpudp_magic)
        srwi    r3,r3,16
        blr
 
+#define STACKFRAMESIZE 256
+#define STK_REG(i)     (112 + ((i)-14)*8)
+
 /*
  * Computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit).
  *
- * This code assumes at least halfword alignment, though the length
- * can be any number of bytes.  The sum is accumulated in r5.
- *
  * csum_partial(r3=buff, r4=len, r5=sum)
  */
 _GLOBAL(csum_partial)
-        subi   r3,r3,8         /* we'll offset by 8 for the loads */
-        srdi.  r6,r4,3         /* divide by 8 for doubleword count */
-        addic   r5,r5,0         /* clear carry */
-        beq    3f              /* if we're doing < 8 bytes */
-        andi.  r0,r3,2         /* aligned on a word boundary already? */
-        beq+   1f
-        lhz     r6,8(r3)        /* do 2 bytes to get aligned */
-        addi    r3,r3,2
-        subi    r4,r4,2
-        addc    r5,r5,r6
-        srdi.   r6,r4,3         /* recompute number of doublewords */
-        beq     3f              /* any left? */
-1:      mtctr   r6
-2:      ldu     r6,8(r3)        /* main sum loop */
-        adde    r5,r5,r6
-        bdnz    2b
-        andi.  r4,r4,7         /* compute bytes left to sum after doublewords */
-3:     cmpwi   0,r4,4          /* is at least a full word left? */
-       blt     4f
-       lwz     r6,8(r3)        /* sum this word */
+       addic   r0,r5,0                 /* clear carry */
+
+       srdi.   r6,r4,3                 /* less than 8 bytes? */
+       beq     .Lcsum_tail_word
+
+       /*
+        * If only halfword aligned, align to a double word. Since odd
+        * aligned addresses should be rare and they would require more
+        * work to calculate the correct checksum, we ignore that case
+        * and take the potential slowdown of unaligned loads.
+        */
+       rldicl. r6,r3,64-1,64-2         /* r6 = (r3 & 0x3) >> 1 */
+       beq     .Lcsum_aligned
+
+       li      r7,4
+       sub     r6,r7,r6
+       mtctr   r6
+
+1:
+       lhz     r6,0(r3)                /* align to doubleword */
+       subi    r4,r4,2
+       addi    r3,r3,2
+       adde    r0,r0,r6
+       bdnz    1b
+
+.Lcsum_aligned:
+       /*
+        * We unroll the loop such that each iteration is 64 bytes with an
+        * entry and exit limb of 64 bytes, meaning a minimum size of
+        * 128 bytes.
+        */
+       srdi.   r6,r4,7
+       beq     .Lcsum_tail_doublewords         /* len < 128 */
+
+       srdi    r6,r4,6
+       subi    r6,r6,1
+       mtctr   r6
+
+       stdu    r1,-STACKFRAMESIZE(r1)
+       std     r14,STK_REG(r14)(r1)
+       std     r15,STK_REG(r15)(r1)
+       std     r16,STK_REG(r16)(r1)
+
+       ld      r6,0(r3)
+       ld      r9,8(r3)
+
+       ld      r10,16(r3)
+       ld      r11,24(r3)
+
+       /*
+        * On POWER6 and POWER7 back to back addes take 2 cycles because of
+        * the XER dependency. This means the fastest this loop can go is
+        * 16 cycles per iteration. The scheduling of the loop below has
+        * been shown to hit this on both POWER6 and POWER7.
+        */
+       .align 5
+2:
+       adde    r0,r0,r6
+       ld      r12,32(r3)
+       ld      r14,40(r3)
+
+       adde    r0,r0,r9
+       ld      r15,48(r3)
+       ld      r16,56(r3)
+       addi    r3,r3,64
+
+       adde    r0,r0,r10
+
+       adde    r0,r0,r11
+
+       adde    r0,r0,r12
+
+       adde    r0,r0,r14
+
+       adde    r0,r0,r15
+       ld      r6,0(r3)
+       ld      r9,8(r3)
+
+       adde    r0,r0,r16
+       ld      r10,16(r3)
+       ld      r11,24(r3)
+       bdnz    2b
+
+
+       adde    r0,r0,r6
+       ld      r12,32(r3)
+       ld      r14,40(r3)
+
+       adde    r0,r0,r9
+       ld      r15,48(r3)
+       ld      r16,56(r3)
+       addi    r3,r3,64
+
+       adde    r0,r0,r10
+       adde    r0,r0,r11
+       adde    r0,r0,r12
+       adde    r0,r0,r14
+       adde    r0,r0,r15
+       adde    r0,r0,r16
+
+       ld      r14,STK_REG(r14)(r1)
+       ld      r15,STK_REG(r15)(r1)
+       ld      r16,STK_REG(r16)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+
+       andi.   r4,r4,63
+
+.Lcsum_tail_doublewords:               /* Up to 127 bytes to go */
+       srdi.   r6,r4,3
+       beq     .Lcsum_tail_word
+
+       mtctr   r6
+3:
+       ld      r6,0(r3)
+       addi    r3,r3,8
+       adde    r0,r0,r6
+       bdnz    3b
+
+       andi.   r4,r4,7
+
+.Lcsum_tail_word:                      /* Up to 7 bytes to go */
+       srdi.   r6,r4,2
+       beq     .Lcsum_tail_halfword
+
+       lwz     r6,0(r3)
        addi    r3,r3,4
+       adde    r0,r0,r6
        subi    r4,r4,4
-       adde    r5,r5,r6
-4:     cmpwi   0,r4,2          /* is at least a halfword left? */
-        blt+   5f
-        lhz     r6,8(r3)        /* sum this halfword */
-        addi    r3,r3,2
-        subi    r4,r4,2
-        adde    r5,r5,r6
-5:     cmpwi   0,r4,1          /* is at least a byte left? */
-        bne+    6f
-        lbz     r6,8(r3)        /* sum this byte */
-        slwi    r6,r6,8         /* this byte is assumed to be the upper byte of a halfword */
-        adde    r5,r5,r6
-6:      addze  r5,r5           /* add in final carry */
-       rldicl  r4,r5,32,0      /* fold two 32-bit halves together */
-        add     r3,r4,r5
-        srdi    r3,r3,32
-        blr
+
+.Lcsum_tail_halfword:                  /* Up to 3 bytes to go */
+       srdi.   r6,r4,1
+       beq     .Lcsum_tail_byte
+
+       lhz     r6,0(r3)
+       addi    r3,r3,2
+       adde    r0,r0,r6
+       subi    r4,r4,2
+
+.Lcsum_tail_byte:                      /* Up to 1 byte to go */
+       andi.   r6,r4,1
+       beq     .Lcsum_finish
+
+       lbz     r6,0(r3)
+       sldi    r9,r6,8                 /* Pad the byte out to 16 bits */
+       adde    r0,r0,r9
+
+.Lcsum_finish:
+       addze   r0,r0                   /* add in final carry */
+       rldicl  r4,r0,32,0              /* fold two 32 bit halves together */
+       add     r3,r4,r0
+       srdi    r3,r3,32
+       blr
+
+
+       .macro source
+100:
+       .section __ex_table,"a"
+       .align 3
+       .llong 100b,.Lsrc_error
+       .previous
+       .endm
+
+       .macro dest
+200:
+       .section __ex_table,"a"
+       .align 3
+       .llong 200b,.Ldest_error
+       .previous
+       .endm
 
 /*
  * Computes the checksum of a memory block at src, length len,
  * and adds in "sum" (32-bit), while copying the block to dst.
  * If an access exception occurs on src or dst, it stores -EFAULT
- * to *src_err or *dst_err respectively, and (for an error on
- * src) zeroes the rest of dst.
- *
- * This code needs to be reworked to take advantage of 64 bit sum+copy.
- * However, due to tokenring halfword alignment problems this will be very
- * tricky.  For now we'll leave it until we instrument it somehow.
+ * to *src_err or *dst_err respectively. The caller must take any action
+ * required in this case (zeroing memory, recalculating partial checksum etc).
  *
  * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
  */
 _GLOBAL(csum_partial_copy_generic)
-       addic   r0,r6,0
-       subi    r3,r3,4
-       subi    r4,r4,4
-       srwi.   r6,r5,2
-       beq     3f              /* if we're doing < 4 bytes */
-       andi.   r9,r4,2         /* Align dst to longword boundary */
-       beq+    1f
-81:    lhz     r6,4(r3)        /* do 2 bytes to get aligned */
-       addi    r3,r3,2
+       addic   r0,r6,0                 /* clear carry */
+
+       srdi.   r6,r5,3                 /* less than 8 bytes? */
+       beq     .Lcopy_tail_word
+
+       /*
+        * If only halfword aligned, align to a double word. Since odd
+        * aligned addresses should be rare and they would require more
+        * work to calculate the correct checksum, we ignore that case
+        * and take the potential slowdown of unaligned loads.
+        *
+        * If the source and destination are relatively unaligned we only
+        * align the source. This keeps things simple.
+        */
+       rldicl. r6,r3,64-1,64-2         /* r6 = (r3 & 0x3) >> 1 */
+       beq     .Lcopy_aligned
+
+       li      r7,4
+       sub     r6,r7,r6
+       mtctr   r6
+
+1:
+source;        lhz     r6,0(r3)                /* align to doubleword */
        subi    r5,r5,2
-91:    sth     r6,4(r4)
-       addi    r4,r4,2
-       addc    r0,r0,r6
-       srwi.   r6,r5,2         /* # words to do */
-       beq     3f
-1:     mtctr   r6
-82:    lwzu    r6,4(r3)        /* the bdnz has zero overhead, so it should */
-92:    stwu    r6,4(r4)        /* be unnecessary to unroll this loop */
-       adde    r0,r0,r6
-       bdnz    82b
-       andi.   r5,r5,3
-3:     cmpwi   0,r5,2
-       blt+    4f
-83:    lhz     r6,4(r3)
        addi    r3,r3,2
-       subi    r5,r5,2
-93:    sth     r6,4(r4)
+       adde    r0,r0,r6
+dest;  sth     r6,0(r4)
        addi    r4,r4,2
+       bdnz    1b
+
+.Lcopy_aligned:
+       /*
+        * We unroll the loop such that each iteration is 64 bytes with an
+        * entry and exit limb of 64 bytes, meaning a minimum size of
+        * 128 bytes.
+        */
+       srdi.   r6,r5,7
+       beq     .Lcopy_tail_doublewords         /* len < 128 */
+
+       srdi    r6,r5,6
+       subi    r6,r6,1
+       mtctr   r6
+
+       stdu    r1,-STACKFRAMESIZE(r1)
+       std     r14,STK_REG(r14)(r1)
+       std     r15,STK_REG(r15)(r1)
+       std     r16,STK_REG(r16)(r1)
+
+source;        ld      r6,0(r3)
+source;        ld      r9,8(r3)
+
+source;        ld      r10,16(r3)
+source;        ld      r11,24(r3)
+
+       /*
+        * On POWER6 and POWER7 back to back addes take 2 cycles because of
+        * the XER dependency. This means the fastest this loop can go is
+        * 16 cycles per iteration. The scheduling of the loop below has
+        * been shown to hit this on both POWER6 and POWER7.
+        */
+       .align 5
+2:
        adde    r0,r0,r6
-4:     cmpwi   0,r5,1
-       bne+    5f
-84:    lbz     r6,4(r3)
-94:    stb     r6,4(r4)
-       slwi    r6,r6,8         /* Upper byte of word */
+source;        ld      r12,32(r3)
+source;        ld      r14,40(r3)
+
+       adde    r0,r0,r9
+source;        ld      r15,48(r3)
+source;        ld      r16,56(r3)
+       addi    r3,r3,64
+
+       adde    r0,r0,r10
+dest;  std     r6,0(r4)
+dest;  std     r9,8(r4)
+
+       adde    r0,r0,r11
+dest;  std     r10,16(r4)
+dest;  std     r11,24(r4)
+
+       adde    r0,r0,r12
+dest;  std     r12,32(r4)
+dest;  std     r14,40(r4)
+
+       adde    r0,r0,r14
+dest;  std     r15,48(r4)
+dest;  std     r16,56(r4)
+       addi    r4,r4,64
+
+       adde    r0,r0,r15
+source;        ld      r6,0(r3)
+source;        ld      r9,8(r3)
+
+       adde    r0,r0,r16
+source;        ld      r10,16(r3)
+source;        ld      r11,24(r3)
+       bdnz    2b
+
+
        adde    r0,r0,r6
-5:     addze   r3,r0           /* add in final carry (unlikely with 64-bit regs) */
-        rldicl  r4,r3,32,0      /* fold 64 bit value */
-        add     r3,r4,r3
-        srdi    r3,r3,32
-       blr
+source;        ld      r12,32(r3)
+source;        ld      r14,40(r3)
 
-/* These shouldn't go in the fixup section, since that would
-   cause the ex_table addresses to get out of order. */
+       adde    r0,r0,r9
+source;        ld      r15,48(r3)
+source;        ld      r16,56(r3)
+       addi    r3,r3,64
+
+       adde    r0,r0,r10
+dest;  std     r6,0(r4)
+dest;  std     r9,8(r4)
+
+       adde    r0,r0,r11
+dest;  std     r10,16(r4)
+dest;  std     r11,24(r4)
+
+       adde    r0,r0,r12
+dest;  std     r12,32(r4)
+dest;  std     r14,40(r4)
+
+       adde    r0,r0,r14
+dest;  std     r15,48(r4)
+dest;  std     r16,56(r4)
+       addi    r4,r4,64
+
+       adde    r0,r0,r15
+       adde    r0,r0,r16
+
+       ld      r14,STK_REG(r14)(r1)
+       ld      r15,STK_REG(r15)(r1)
+       ld      r16,STK_REG(r16)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+
+       andi.   r5,r5,63
+
+.Lcopy_tail_doublewords:               /* Up to 127 bytes to go */
+       srdi.   r6,r5,3
+       beq     .Lcopy_tail_word
 
-       .globl src_error_1
-src_error_1:
-       li      r6,0
-       subi    r5,r5,2
-95:    sth     r6,4(r4)
-       addi    r4,r4,2
-       srwi.   r6,r5,2
-       beq     3f
        mtctr   r6
-       .globl src_error_2
-src_error_2:
-       li      r6,0
-96:    stwu    r6,4(r4)
-       bdnz    96b
-3:     andi.   r5,r5,3
-       beq     src_error
-       .globl src_error_3
-src_error_3:
-       li      r6,0
-       mtctr   r5
-       addi    r4,r4,3
-97:    stbu    r6,1(r4)
-       bdnz    97b
-       .globl src_error
-src_error:
+3:
+source;        ld      r6,0(r3)
+       addi    r3,r3,8
+       adde    r0,r0,r6
+dest;  std     r6,0(r4)
+       addi    r4,r4,8
+       bdnz    3b
+
+       andi.   r5,r5,7
+
+.Lcopy_tail_word:                      /* Up to 7 bytes to go */
+       srdi.   r6,r5,2
+       beq     .Lcopy_tail_halfword
+
+source;        lwz     r6,0(r3)
+       addi    r3,r3,4
+       adde    r0,r0,r6
+dest;  stw     r6,0(r4)
+       addi    r4,r4,4
+       subi    r5,r5,4
+
+.Lcopy_tail_halfword:                  /* Up to 3 bytes to go */
+       srdi.   r6,r5,1
+       beq     .Lcopy_tail_byte
+
+source;        lhz     r6,0(r3)
+       addi    r3,r3,2
+       adde    r0,r0,r6
+dest;  sth     r6,0(r4)
+       addi    r4,r4,2
+       subi    r5,r5,2
+
+.Lcopy_tail_byte:                      /* Up to 1 byte to go */
+       andi.   r6,r5,1
+       beq     .Lcopy_finish
+
+source;        lbz     r6,0(r3)
+       sldi    r9,r6,8                 /* Pad the byte out to 16 bits */
+       adde    r0,r0,r9
+dest;  stb     r6,0(r4)
+
+.Lcopy_finish:
+       addze   r0,r0                   /* add in final carry */
+       rldicl  r4,r0,32,0              /* fold two 32 bit halves together */
+       add     r3,r4,r0
+       srdi    r3,r3,32
+       blr
+
+.Lsrc_error:
        cmpdi   0,r7,0
-       beq     1f
+       beqlr
        li      r6,-EFAULT
        stw     r6,0(r7)
-1:     addze   r3,r0
        blr
 
-       .globl dst_error
-dst_error:
+.Ldest_error:
        cmpdi   0,r8,0
-       beq     1f
+       beqlr
        li      r6,-EFAULT
        stw     r6,0(r8)
-1:     addze   r3,r0
        blr
-
-.section __ex_table,"a"
-       .align  3
-       .llong  81b,src_error_1
-       .llong  91b,dst_error
-       .llong  82b,src_error_2
-       .llong  92b,dst_error
-       .llong  83b,src_error_3
-       .llong  93b,dst_error
-       .llong  84b,src_error_3
-       .llong  94b,dst_error
-       .llong  95b,dst_error
-       .llong  96b,dst_error
-       .llong  97b,dst_error
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c
new file mode 100644 (file)
index 0000000..769b817
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+                              int len, __wsum sum, int *err_ptr)
+{
+       unsigned int csum;
+
+       might_sleep();
+
+       *err_ptr = 0;
+
+       if (!len) {
+               csum = 0;
+               goto out;
+       }
+
+       if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) {
+               *err_ptr = -EFAULT;
+               csum = (__force unsigned int)sum;
+               goto out;
+       }
+
+       csum = csum_partial_copy_generic((void __force *)src, dst,
+                                        len, sum, err_ptr, NULL);
+
+       if (unlikely(*err_ptr)) {
+               int missing = __copy_from_user(dst, src, len);
+
+               if (missing) {
+                       memset(dst + len - missing, 0, missing);
+                       *err_ptr = -EFAULT;
+               } else {
+                       *err_ptr = 0;
+               }
+
+               csum = csum_partial(dst, len, sum);
+       }
+
+out:
+       return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
+                            __wsum sum, int *err_ptr)
+{
+       unsigned int csum;
+
+       might_sleep();
+
+       *err_ptr = 0;
+
+       if (!len) {
+               csum = 0;
+               goto out;
+       }
+
+       if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
+               *err_ptr = -EFAULT;
+               csum = -1; /* invalid checksum */
+               goto out;
+       }
+
+       csum = csum_partial_copy_generic(src, (void __force *)dst,
+                                        len, sum, NULL, err_ptr);
+
+       if (unlikely(*err_ptr)) {
+               csum = csum_partial(src, len, sum);
+
+               if (copy_to_user(dst, src, len)) {
+                       *err_ptr = -EFAULT;
+                       csum = -1; /* invalid checksum */
+               }
+       }
+
+out:
+       return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
index 74a7f4130b4ce5ed34b797227568fa86545650b7..55f19f9fd70823f2320498a9d910ebe919633ffd 100644 (file)
@@ -62,7 +62,7 @@
 
        .text
        .stabs  "arch/powerpc/lib/",N_SO,0,0,0f
-       .stabs  "copy32.S",N_SO,0,0,0f
+       .stabs  "copy_32.S",N_SO,0,0,0f
 0:
 
 CACHELINE_BYTES = L1_CACHE_BYTES
index f6448636baf59eea3c6c3fef71f137f86d243e1c..6a85380520b61163dff57eab585bfa1c4352bffb 100644 (file)
@@ -17,6 +17,8 @@
 #include <asm/asm-offsets.h>
 #include <linux/errno.h>
 
+#ifdef CONFIG_PPC_FPU
+
 #define STKFRM (PPC_MIN_STKFRM + 16)
 
        .macro  extab   instr,handler
@@ -81,7 +83,7 @@ _GLOBAL(do_lfs)
        mfmsr   r6
        ori     r7,r6,MSR_FP
        cmpwi   cr7,r3,0
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stfd    fr0,STKFRM-16(r1)
@@ -93,7 +95,7 @@ _GLOBAL(do_lfs)
        lfd     fr0,STKFRM-16(r1)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -108,7 +110,7 @@ _GLOBAL(do_lfd)
        mfmsr   r6
        ori     r7,r6,MSR_FP
        cmpwi   cr7,r3,0
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stfd    fr0,STKFRM-16(r1)
@@ -120,7 +122,7 @@ _GLOBAL(do_lfd)
        lfd     fr0,STKFRM-16(r1)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -135,7 +137,7 @@ _GLOBAL(do_stfs)
        mfmsr   r6
        ori     r7,r6,MSR_FP
        cmpwi   cr7,r3,0
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stfd    fr0,STKFRM-16(r1)
@@ -147,7 +149,7 @@ _GLOBAL(do_stfs)
        lfd     fr0,STKFRM-16(r1)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -162,7 +164,7 @@ _GLOBAL(do_stfd)
        mfmsr   r6
        ori     r7,r6,MSR_FP
        cmpwi   cr7,r3,0
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stfd    fr0,STKFRM-16(r1)
@@ -174,7 +176,7 @@ _GLOBAL(do_stfd)
        lfd     fr0,STKFRM-16(r1)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -229,7 +231,7 @@ _GLOBAL(do_lvx)
        oris    r7,r6,MSR_VEC@h
        cmpwi   cr7,r3,0
        li      r8,STKFRM-16
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stvx    vr0,r1,r8
@@ -241,7 +243,7 @@ _GLOBAL(do_lvx)
        lvx     vr0,r1,r8
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -257,7 +259,7 @@ _GLOBAL(do_stvx)
        oris    r7,r6,MSR_VEC@h
        cmpwi   cr7,r3,0
        li      r8,STKFRM-16
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        stvx    vr0,r1,r8
@@ -269,7 +271,7 @@ _GLOBAL(do_stvx)
        lvx     vr0,r1,r8
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -325,7 +327,7 @@ _GLOBAL(do_lxvd2x)
        oris    r7,r6,MSR_VSX@h
        cmpwi   cr7,r3,0
        li      r8,STKFRM-16
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        STXVD2X(0,r1,r8)
@@ -337,7 +339,7 @@ _GLOBAL(do_lxvd2x)
        LXVD2X(0,r1,r8)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -353,7 +355,7 @@ _GLOBAL(do_stxvd2x)
        oris    r7,r6,MSR_VSX@h
        cmpwi   cr7,r3,0
        li      r8,STKFRM-16
-       mtmsrd  r7
+       MTMSRD(r7)
        isync
        beq     cr7,1f
        STXVD2X(0,r1,r8)
@@ -365,7 +367,7 @@ _GLOBAL(do_stxvd2x)
        LXVD2X(0,r1,r8)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
-       mtmsrd  r6
+       MTMSRD(r6)
        isync
        mr      r3,r9
        addi    r1,r1,STKFRM
@@ -373,3 +375,5 @@ _GLOBAL(do_stxvd2x)
        extab   2b,3b
 
 #endif /* CONFIG_VSX */
+
+#endif /* CONFIG_PPC_FPU */
index 58e14fba11b1d7472b982a9a91a992a20319c9cd..9b8182e82166aa1e431576c3098567c1e15b8fa5 100644 (file)
@@ -34,7 +34,7 @@ void __spin_yield(arch_spinlock_t *lock)
                return;
        holder_cpu = lock_value & 0xffff;
        BUG_ON(holder_cpu >= NR_CPUS);
-       yield_count = lppaca[holder_cpu].yield_count;
+       yield_count = lppaca_of(holder_cpu).yield_count;
        if ((yield_count & 1) == 0)
                return;         /* virtual cpu is currently running */
        rmb();
@@ -65,7 +65,7 @@ void __rw_yield(arch_rwlock_t *rw)
                return;         /* no write lock at present */
        holder_cpu = lock_value & 0xffff;
        BUG_ON(holder_cpu >= NR_CPUS);
-       yield_count = lppaca[holder_cpu].yield_count;
+       yield_count = lppaca_of(holder_cpu).yield_count;
        if ((yield_count & 1) == 0)
                return;         /* virtual cpu is currently running */
        rmb();
index e0a9858d537eaa624246aed33738c0d7240f3bf3..ae5189ab004926072e2f86e04b4b8aa33c0d0867 100644 (file)
@@ -30,6 +30,7 @@ extern char system_call_common[];
 #define XER_OV         0x40000000U
 #define XER_CA         0x20000000U
 
+#ifdef CONFIG_PPC_FPU
 /*
  * Functions in ldstfp.S
  */
@@ -41,6 +42,7 @@ extern int do_lvx(int rn, unsigned long ea);
 extern int do_stvx(int rn, unsigned long ea);
 extern int do_lxvd2x(int rn, unsigned long ea);
 extern int do_stxvd2x(int rn, unsigned long ea);
+#endif
 
 /*
  * Determine whether a conditional branch instruction would branch.
@@ -290,6 +292,7 @@ static int __kprobes write_mem(unsigned long val, unsigned long ea, int nb,
        return write_mem_unaligned(val, ea, nb, regs);
 }
 
+#ifdef CONFIG_PPC_FPU
 /*
  * Check the address and alignment, and call func to do the actual
  * load or store.
@@ -351,6 +354,7 @@ static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long),
        }
        return err;
 }
+#endif
 
 #ifdef CONFIG_ALTIVEC
 /* For Altivec/VMX, no need to worry about alignment */
@@ -1393,6 +1397,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                                regs->gpr[rd] = byterev_4(val);
                        goto ldst_done;
 
+#ifdef CONFIG_PPC_CPU
                case 535:       /* lfsx */
                case 567:       /* lfsux */
                        if (!(regs->msr & MSR_FP))
@@ -1424,6 +1429,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                        ea = xform_ea(instr, regs, u);
                        err = do_fp_store(rd, do_stfd, ea, 8, regs);
                        goto ldst_done;
+#endif
 
 #ifdef __powerpc64__
                case 660:       /* stdbrx */
@@ -1534,6 +1540,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                } while (++rd < 32);
                goto instr_done;
 
+#ifdef CONFIG_PPC_FPU
        case 48:        /* lfs */
        case 49:        /* lfsu */
                if (!(regs->msr & MSR_FP))
@@ -1565,6 +1572,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                ea = dform_ea(instr, regs);
                err = do_fp_store(rd, do_stfd, ea, 8, regs);
                goto ldst_done;
+#endif
 
 #ifdef __powerpc64__
        case 58:        /* ld[u], lwa */
index 0c16ab947f1f3f04990874562b604209012c60dc..7d1dba0d57f9e84daa25333a542d5bf6e88d69cc 100644 (file)
@@ -15,4 +15,4 @@ obj-$(CONFIG_SPE)             += math_efp.o
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
 
-EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
+ccflags-y = -I. -Iinclude/math-emu -w
index 1dc2fa5ce1bda72b05df8db2e4d249cfcc8642ab..5810967511d4d01ddef3b8ec96de9cf2ab40a01b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/memblock.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -47,6 +48,7 @@
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
+
 #include "mmu_decl.h"
 
 extern int __map_without_ltlbs;
@@ -139,8 +141,19 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
         * coverage with normal-sized pages (or other reasons) do not
         * attempt to allocate outside the allowed range.
         */
-
-       __initial_memory_limit_addr = memstart_addr + mapped;
+       memblock_set_current_limit(mapped);
 
        return mapped;
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+       /* 40x can only access 16MB at the moment (see head_40x.S) */
+       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
index d8c6efb32bc6af456095aefef37944b9cca4a99b..024acab588fd5bcf54b58dd194429727bc122ffd 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/memblock.h>
+
 #include <asm/mmu.h>
 #include <asm/system.h>
 #include <asm/page.h>
@@ -213,6 +215,18 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
        return total_lowmem;
 }
 
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+       /* 44x has a 256M TLB entry pinned at boot */
+       memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+}
+
 #ifdef CONFIG_SMP
 void __cpuinit mmu_init_secondary(int cpu)
 {
index ce68708bbad53c016986eabf7dfe2ef08ba33a97..bdca46e0838279ba6a9e26aa106925435865b5d6 100644 (file)
@@ -4,9 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS   += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
 
 obj-y                          := fault.o mem.o pgtable.o gup.o \
                                   init_$(CONFIG_WORD_SIZE).o \
@@ -25,7 +23,7 @@ obj-$(CONFIG_PPC_STD_MMU)     += hash_low_$(CONFIG_WORD_SIZE).o \
                                   mmu_context_hash$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_40x)              += 40x_mmu.o
 obj-$(CONFIG_44x)              += 44x_mmu.o
-obj-$(CONFIG_FSL_BOOKE)                += fsl_booke_mmu.o
+obj-$(CONFIG_PPC_FSL_BOOK3E)   += fsl_booke_mmu.o
 obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
 obj-$(CONFIG_PPC_MM_SLICES)    += slice.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
index 1bd712c33ce234b679289547ebd1a4f0c9f4ef01..54f4fb994e99aae549ccb38b4ebcd490d0df0e0d 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 #include <linux/perf_event.h>
+#include <linux/magic.h>
 
 #include <asm/firmware.h>
 #include <asm/page.h>
@@ -385,6 +386,7 @@ do_sigbus:
 void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
        const struct exception_table_entry *entry;
+       unsigned long *stackend;
 
        /* Are we prepared to handle this fault?  */
        if ((entry = search_exception_tables(regs->nip)) != NULL) {
@@ -413,5 +415,9 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
        printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
                regs->nip);
 
+       stackend = end_of_stack(current);
+       if (current != &init_task && *stackend != STACK_END_MAGIC)
+               printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+
        die("Kernel access of bad area", regs, sig);
 }
index 4b66a1ece6d8519b9184249811974d242c322c77..f7802c8bba0a6b31be879ecf1446f474c00d52b8 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/memblock.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 
 unsigned int tlbcam_index;
 
-
-#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
-#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
-#endif
-
 #define NUM_TLBCAMS    (64)
 struct tlbcam TLBCAM[NUM_TLBCAMS];
 
@@ -137,7 +133,8 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
        if (mmu_has_feature(MMU_FTR_BIG_PHYS))
                TLBCAM[index].MAS7 = (u64)phys >> 32;
 
-       if (flags & _PAGE_USER) {
+       /* Below is unlikely -- only for large user pages or similar */
+       if (pte_user(flags)) {
           TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
           TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
        }
@@ -184,6 +181,12 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
        return amount_mapped;
 }
 
+#ifdef CONFIG_PPC32
+
+#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
+#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
+#endif
+
 unsigned long __init mmu_mapin_ram(unsigned long top)
 {
        return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
@@ -213,5 +216,15 @@ void __init adjust_total_lowmem(void)
        pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20,
                (unsigned int)((total_lowmem - __max_low_memory) >> 20));
 
-       __initial_memory_limit_addr = memstart_addr + __max_low_memory;
+       memblock_set_current_limit(memstart_addr + __max_low_memory);
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       phys_addr_t limit = first_memblock_base + first_memblock_size;
+
+       /* 64M mapped initially according to head_fsl_booke.S */
+       memblock_set_current_limit(min_t(u64, limit, 0x04000000));
+}
+#endif
index 09dffe6efa46aeae84d62a922215f87fe0a8ca2d..83f534d862db2cd3934fca431e9b4d67b4ac7d38 100644 (file)
@@ -588,7 +588,7 @@ static void __init htab_initialize(void)
        unsigned long pteg_count;
        unsigned long prot;
        unsigned long base = 0, size = 0, limit;
-       int i;
+       struct memblock_region *reg;
 
        DBG(" -> htab_initialize()\n");
 
@@ -625,7 +625,7 @@ static void __init htab_initialize(void)
                if (machine_is(cell))
                        limit = 0x80000000;
                else
-                       limit = 0;
+                       limit = MEMBLOCK_ALLOC_ANYWHERE;
 
                table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit);
 
@@ -649,7 +649,7 @@ static void __init htab_initialize(void)
 #ifdef CONFIG_DEBUG_PAGEALLOC
        linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
        linear_map_hash_slots = __va(memblock_alloc_base(linear_map_hash_count,
-                                                   1, memblock.rmo_size));
+                                                   1, ppc64_rma_size));
        memset(linear_map_hash_slots, 0, linear_map_hash_count);
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
@@ -659,9 +659,9 @@ static void __init htab_initialize(void)
         */
 
        /* create bolted the linear mapping in the hash table */
-       for (i=0; i < memblock.memory.cnt; i++) {
-               base = (unsigned long)__va(memblock.memory.region[i].base);
-               size = memblock.memory.region[i].size;
+       for_each_memblock(memory, reg) {
+               base = (unsigned long)__va(reg->base);
+               size = reg->size;
 
                DBG("creating mapping for region: %lx..%lx (prot: %lx)\n",
                    base, size, prot);
@@ -696,7 +696,8 @@ static void __init htab_initialize(void)
 #endif /* CONFIG_U3_DART */
                BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
                                prot, mmu_linear_psize, mmu_kernel_ssize));
-       }
+       }
+       memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
 
        /*
         * If we have a memory_limit and we've allocated TCEs then we need to
@@ -1247,3 +1248,23 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
        local_irq_restore(flags);
 }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+       /* On LPAR systems, the first entry is our RMA region,
+        * non-LPAR 64-bit hash MMU systems don't have a limitation
+        * on real mode access, but using the first entry works well
+        * enough. We also clamp it to 1G to avoid some funky things
+        * such as RTAS bugs etc...
+        */
+       ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+       /* Finally limit subsequent allocations */
+       memblock_set_current_limit(ppc64_rma_size);
+}
index 6a6975dc265427bf39c15979374c52501755aa3c..742da43b4ab6ddffe75f0609d4d5021bafccac25 100644 (file)
@@ -91,12 +91,6 @@ int __allow_ioremap_reserved;
 /* max amount of low RAM to map in */
 unsigned long __max_low_memory = MAX_LOW_MEM;
 
-/*
- * address of the limit of what is accessible with initial MMU setup -
- * 256MB usually, but only 16MB on 601.
- */
-phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
-
 /*
  * Check for command-line options that affect what MMU_init will do.
  */
@@ -126,13 +120,6 @@ void __init MMU_init(void)
        if (ppc_md.progress)
                ppc_md.progress("MMU:enter", 0x111);
 
-       /* 601 can only access 16MB at the moment */
-       if (PVR_VER(mfspr(SPRN_PVR)) == 1)
-               __initial_memory_limit_addr = 0x01000000;
-       /* 8xx can only access 8MB at the moment */
-       if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
-               __initial_memory_limit_addr = 0x00800000;
-
        /* parse args from command line */
        MMU_setup();
 
@@ -190,20 +177,18 @@ void __init MMU_init(void)
 #ifdef CONFIG_BOOTX_TEXT
        btext_unmap();
 #endif
+
+       /* Shortly after that, the entire linear mapping will be available */
+       memblock_set_current_limit(lowmem_end_addr);
 }
 
 /* This is only called until mem_init is done. */
 void __init *early_get_page(void)
 {
-       void *p;
-
-       if (init_bootmem_done) {
-               p = alloc_bootmem_pages(PAGE_SIZE);
-       } else {
-               p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
-                                       __initial_memory_limit_addr));
-       }
-       return p;
+       if (init_bootmem_done)
+               return alloc_bootmem_pages(PAGE_SIZE);
+       else
+               return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 }
 
 /* Free up now-unused memory */
@@ -252,3 +237,17 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
+
+#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+       /* 8xx can only access 8MB at the moment */
+       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
+#endif /* CONFIG_8xx */
index 71f1415e2472399049a2273eded9c4fb8d173265..6374b2196a17a33b97589fb8097fc0c00a1f176b 100644 (file)
@@ -79,7 +79,9 @@
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 phys_addr_t memstart_addr = ~0;
+EXPORT_SYMBOL_GPL(memstart_addr);
 phys_addr_t kernstart_addr;
+EXPORT_SYMBOL_GPL(kernstart_addr);
 
 void free_initmem(void)
 {
@@ -328,3 +330,4 @@ int __meminit vmemmap_populate(struct page *start_page,
        return 0;
 }
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
index 1a84a8d0000503b495ff2d79355f4f756e80591a..a66499650909bb1bce5d97a48ca7894b22d5241e 100644 (file)
@@ -82,18 +82,11 @@ int page_is_ram(unsigned long pfn)
        return pfn < max_pfn;
 #else
        unsigned long paddr = (pfn << PAGE_SHIFT);
-       int i;
-       for (i=0; i < memblock.memory.cnt; i++) {
-               unsigned long base;
+       struct memblock_region *reg;
 
-               base = memblock.memory.region[i].base;
-
-               if ((paddr >= base) &&
-                       (paddr < (base + memblock.memory.region[i].size))) {
+       for_each_memblock(memory, reg)
+               if (paddr >= reg->base && paddr < (reg->base + reg->size))
                        return 1;
-               }
-       }
-
        return 0;
 #endif
 }
@@ -149,23 +142,19 @@ int
 walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
                void *arg, int (*func)(unsigned long, unsigned long, void *))
 {
-       struct memblock_property res;
-       unsigned long pfn, len;
-       u64 end;
+       struct memblock_region *reg;
+       unsigned long end_pfn = start_pfn + nr_pages;
+       unsigned long tstart, tend;
        int ret = -1;
 
-       res.base = (u64) start_pfn << PAGE_SHIFT;
-       res.size = (u64) nr_pages << PAGE_SHIFT;
-
-       end = res.base + res.size - 1;
-       while ((res.base < end) && (memblock_find(&res) >= 0)) {
-               pfn = (unsigned long)(res.base >> PAGE_SHIFT);
-               len = (unsigned long)(res.size >> PAGE_SHIFT);
-               ret = (*func)(pfn, len, arg);
+       for_each_memblock(memory, reg) {
+               tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
+               tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
+               if (tstart >= tend)
+                       continue;
+               ret = (*func)(tstart, tend - tstart, arg);
                if (ret)
                        break;
-               res.base += (res.size + 1);
-               res.size = (end - res.base + 1);
        }
        return ret;
 }
@@ -179,9 +168,9 @@ EXPORT_SYMBOL_GPL(walk_system_ram_range);
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init do_init_bootmem(void)
 {
-       unsigned long i;
        unsigned long start, bootmap_pages;
        unsigned long total_pages;
+       struct memblock_region *reg;
        int boot_mapsize;
 
        max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
@@ -204,10 +193,10 @@ void __init do_init_bootmem(void)
        boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
 
        /* Add active regions with valid PFNs */
-       for (i = 0; i < memblock.memory.cnt; i++) {
+       for_each_memblock(memory, reg) {
                unsigned long start_pfn, end_pfn;
-               start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-               end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                add_active_range(0, start_pfn, end_pfn);
        }
 
@@ -218,29 +207,21 @@ void __init do_init_bootmem(void)
        free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
 
        /* reserve the sections we're already using */
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               unsigned long addr = memblock.reserved.region[i].base +
-                                    memblock_size_bytes(&memblock.reserved, i) - 1;
-               if (addr < lowmem_end_addr)
-                       reserve_bootmem(memblock.reserved.region[i].base,
-                                       memblock_size_bytes(&memblock.reserved, i),
-                                       BOOTMEM_DEFAULT);
-               else if (memblock.reserved.region[i].base < lowmem_end_addr) {
-                       unsigned long adjusted_size = lowmem_end_addr -
-                                     memblock.reserved.region[i].base;
-                       reserve_bootmem(memblock.reserved.region[i].base,
-                                       adjusted_size, BOOTMEM_DEFAULT);
+       for_each_memblock(reserved, reg) {
+               unsigned long top = reg->base + reg->size - 1;
+               if (top < lowmem_end_addr)
+                       reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+               else if (reg->base < lowmem_end_addr) {
+                       unsigned long trunc_size = lowmem_end_addr - reg->base;
+                       reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT);
                }
        }
 #else
        free_bootmem_with_active_regions(0, max_pfn);
 
        /* reserve the sections we're already using */
-       for (i = 0; i < memblock.reserved.cnt; i++)
-               reserve_bootmem(memblock.reserved.region[i].base,
-                               memblock_size_bytes(&memblock.reserved, i),
-                               BOOTMEM_DEFAULT);
-
+       for_each_memblock(reserved, reg)
+               reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
 #endif
        /* XXX need to clip this if using highmem? */
        sparse_memory_present_with_active_regions(0);
@@ -251,22 +232,15 @@ void __init do_init_bootmem(void)
 /* mark pages that don't exist as nosave */
 static int __init mark_nonram_nosave(void)
 {
-       unsigned long memblock_next_region_start_pfn,
-                     memblock_region_max_pfn;
-       int i;
-
-       for (i = 0; i < memblock.memory.cnt - 1; i++) {
-               memblock_region_max_pfn =
-                       (memblock.memory.region[i].base >> PAGE_SHIFT) +
-                       (memblock.memory.region[i].size >> PAGE_SHIFT);
-               memblock_next_region_start_pfn =
-                       memblock.memory.region[i+1].base >> PAGE_SHIFT;
-
-               if (memblock_region_max_pfn < memblock_next_region_start_pfn)
-                       register_nosave_region(memblock_region_max_pfn,
-                                              memblock_next_region_start_pfn);
+       struct memblock_region *reg, *prev = NULL;
+
+       for_each_memblock(memory, reg) {
+               if (prev &&
+                   memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg))
+                       register_nosave_region(memblock_region_memory_end_pfn(prev),
+                                              memblock_region_memory_base_pfn(reg));
+               prev = reg;
        }
-
        return 0;
 }
 
@@ -327,7 +301,7 @@ void __init mem_init(void)
                swiotlb_init(1);
 #endif
 
-       num_physpages = memblock.memory.size >> PAGE_SHIFT;
+       num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
index ddfd7ad4e1d60ade761b5f039b745307d6ce5a82..5ce99848d91e49aa3fb03d90c0f8c116a4d9d42a 100644 (file)
@@ -334,7 +334,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self,
        /* We don't touch CPU 0 map, it's allocated at aboot and kept
         * around forever
         */
-       if (cpu == 0)
+       if (cpu == boot_cpuid)
                return NOTIFY_OK;
 
        switch (action) {
@@ -420,9 +420,11 @@ void __init mmu_context_init(void)
         */
        context_map = alloc_bootmem(CTX_MAP_SIZE);
        context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1));
+#ifndef CONFIG_SMP
        stale_map[0] = alloc_bootmem(CTX_MAP_SIZE);
+#else
+       stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE);
 
-#ifdef CONFIG_SMP
        register_cpu_notifier(&mmu_context_cpu_nb);
 #endif
 
index 63b84a0d3b10baccf4e252382c1b66640b2e56e2..dd0a2589591dc0a66fffe8f7eb4d5b3a17944224 100644 (file)
@@ -140,10 +140,13 @@ extern void wii_memory_fixups(void);
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
 
-#elif defined(CONFIG_FSL_BOOKE)
+#elif defined(CONFIG_PPC_FSL_BOOK3E)
+extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+#ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
 extern void adjust_total_lowmem(void);
+#endif
 extern void loadcam_entry(unsigned int index);
 
 struct tlbcam {
index 002878ccf90b04bc46b12e1556d6e7f8775595be..74505b245374e305d64625056271147ab4125b1d 100644 (file)
@@ -802,16 +802,17 @@ static void __init setup_nonnuma(void)
        unsigned long top_of_ram = memblock_end_of_DRAM();
        unsigned long total_ram = memblock_phys_mem_size();
        unsigned long start_pfn, end_pfn;
-       unsigned int i, nid = 0;
+       unsigned int nid = 0;
+       struct memblock_region *reg;
 
        printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
               top_of_ram, total_ram);
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (top_of_ram - total_ram) >> 20);
 
-       for (i = 0; i < memblock.memory.cnt; ++i) {
-               start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-               end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+       for_each_memblock(memory, reg) {
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
 
                fake_numa_create_new_node(end_pfn, &nid);
                add_active_range(nid, start_pfn, end_pfn);
@@ -947,11 +948,11 @@ static struct notifier_block __cpuinitdata ppc64_numa_nb = {
 static void mark_reserved_regions_for_nid(int nid)
 {
        struct pglist_data *node = NODE_DATA(nid);
-       int i;
+       struct memblock_region *reg;
 
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               unsigned long physbase = memblock.reserved.region[i].base;
-               unsigned long size = memblock.reserved.region[i].size;
+       for_each_memblock(reserved, reg) {
+               unsigned long physbase = reg->base;
+               unsigned long size = reg->size;
                unsigned long start_pfn = physbase >> PAGE_SHIFT;
                unsigned long end_pfn = PFN_UP(physbase + size);
                struct node_active_region node_ar;
index f8a01829d64fd4820921f3148a17c32b98e74b67..11571e118831404bf656bcb699ec9765e42b6c9d 100644 (file)
@@ -223,8 +223,7 @@ void __init MMU_init_hw(void)
         * Find some memory for the hash table.
         */
        if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
-       Hash = __va(memblock_alloc_base(Hash_size, Hash_size,
-                                  __initial_memory_limit_addr));
+       Hash = __va(memblock_alloc(Hash_size, Hash_size));
        cacheable_memzero(Hash, Hash_size);
        _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
@@ -272,3 +271,18 @@ void __init MMU_init_hw(void)
 
        if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+       /* 601 can only access 16MB at the moment */
+       if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+               memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000));
+       else /* Anything else has 256M mapped */
+               memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000));
+}
index fe391e942521bee44787a99387c304284184e16a..36c0c449a89993659c60d1b4c4b772fb5aa5f94c 100644 (file)
@@ -349,11 +349,47 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address)
 
 static void setup_page_sizes(void)
 {
-       unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);
-       unsigned int tlb0ps = mfspr(SPRN_TLB0PS);
-       unsigned int eptcfg = mfspr(SPRN_EPTCFG);
+       unsigned int tlb0cfg;
+       unsigned int tlb0ps;
+       unsigned int eptcfg;
        int i, psize;
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       unsigned int mmucfg = mfspr(SPRN_MMUCFG);
+
+       if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) &&
+               (mmu_has_feature(MMU_FTR_TYPE_FSL_E))) {
+               unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG);
+               unsigned int min_pg, max_pg;
+
+               min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+               max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
+
+               for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+                       struct mmu_psize_def *def;
+                       unsigned int shift;
+
+                       def = &mmu_psize_defs[psize];
+                       shift = def->shift;
+
+                       if (shift == 0)
+                               continue;
+
+                       /* adjust to be in terms of 4^shift Kb */
+                       shift = (shift - 10) >> 1;
+
+                       if ((shift >= min_pg) && (shift <= max_pg))
+                               def->flags |= MMU_PAGE_SIZE_DIRECT;
+               }
+
+               goto no_indirect;
+       }
+#endif
+
+       tlb0cfg = mfspr(SPRN_TLB0CFG);
+       tlb0ps = mfspr(SPRN_TLB0PS);
+       eptcfg = mfspr(SPRN_EPTCFG);
+
        /* Look for supported direct sizes */
        for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
                struct mmu_psize_def *def = &mmu_psize_defs[psize];
@@ -505,10 +541,26 @@ static void __early_init_mmu(int boot_cpu)
         */
        linear_map_top = memblock_end_of_DRAM();
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+               unsigned int num_cams;
+
+               /* use a quarter of the TLBCAM for bolted linear map */
+               num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
+               linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
+
+               /* limit memory so we dont have linear faults */
+               memblock_enforce_memory_limit(linear_map_top);
+               memblock_analyze();
+       }
+#endif
+
        /* A sync won't hurt us after mucking around with
         * the MMU configuration
         */
        mb();
+
+       memblock_set_current_limit(linear_map_top);
 }
 
 void __init early_init_mmu(void)
@@ -521,4 +573,18 @@ void __cpuinit early_init_mmu_secondary(void)
        __early_init_mmu(0);
 }
 
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* On Embedded 64-bit, we adjust the RMA size to match
+        * the bolted TLB entry. We know for now that only 1G
+        * entries are supported though that may eventually
+        * change. We crop it to the size of the first MEMBLOCK to
+        * avoid going over total available memory just in case...
+        */
+       ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+       /* Finally limit subsequent allocations */
+       memblock_set_current_limit(ppc64_memblock_base + ppc64_rma_size);
+}
 #endif /* CONFIG_PPC64 */
index cfa768203d085e3c3fd7486758513883e40c7ae6..af405eefe48d6b1f17b0f180eaab2682b56c716b 100644 (file)
@@ -200,6 +200,7 @@ _GLOBAL(_tlbivax_bcast)
        rlwimi  r5,r4,0,16,31
        wrteei  0
        mtspr   SPRN_MMUCR,r5
+       isync
 /*     tlbivax 0,r3 - use .long to avoid binutils deps */
        .long 0x7c000624 | (r3 << 11)
        isync
@@ -366,7 +367,7 @@ _GLOBAL(set_context)
 #error Unsupported processor type !
 #endif
 
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
 /*
  * extern void loadcam_entry(unsigned int index)
  *
index e219ca43962d0539f8b78d94ede969e7f1852d98..73456c4cec28aa102d43ea07fedf48ad48b73b6f 100644 (file)
@@ -1,8 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS   += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
index b4278cfd1f80cccb5596f29b6c5068961aad06c2..f75301f2c85fd2960acd21ee427527614934585e 100644 (file)
@@ -105,7 +105,7 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
                }
        } else {
 #ifdef CONFIG_PPC64
-               if (!test_thread_flag(TIF_32BIT)) {
+               if (!is_32bit_task()) {
                        while (depth--) {
                                sp = user_getsp64(sp, first_frame);
                                if (!sp)
index 62312abffa28793561a78f37aaf776bc85526ae1..d4e6507277b5ea6ee43dbc1110027f2c4534eef4 100644 (file)
@@ -2,7 +2,7 @@
  * Freescale Embedded oprofile support, based on ppc64 oprofile support
  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  *
- * Copyright (c) 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2004, 2010 Freescale Semiconductor, Inc
  *
  * Author: Andy Fleming
  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
@@ -321,9 +321,6 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs,
        int val;
        int i;
 
-       /* set the PMM bit (see comment below) */
-       mtmsr(mfmsr() | MSR_PMM);
-
        pc = regs->nip;
        is_kernel = is_kernel_addr(pc);
 
@@ -340,9 +337,13 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs,
        }
 
        /* The freeze bit was set by the interrupt. */
-       /* Clear the freeze bit, and reenable the interrupt.
-        * The counters won't actually start until the rfi clears
-        * the PMM bit */
+       /* Clear the freeze bit, and reenable the interrupt.  The
+        * counters won't actually start until the rfi clears the PMM
+        * bit.  The PMM bit should not be set until after the interrupt
+        * is cleared to avoid it getting lost in some hypervisor
+        * environments.
+        */
+       mtmsr(mfmsr() | MSR_PMM);
        pmc_start_ctrs(1);
 }
 
index 69d668c072aeab579aab54182d0c9bd544dac956..0f979c5c756b5ab129c5914b81869957d655cfe2 100644 (file)
@@ -17,6 +17,16 @@ config BAMBOO
        help
          This option enables support for the IBM PPC440EP evaluation board.
 
+config BLUESTONE
+       bool "Bluestone"
+       depends on 44x
+       default n
+       select PPC44x_SIMPLE
+       select APM821xx
+       select IBM_NEW_EMAC_RGMII
+       help
+         This option enables support for the APM APM821xx Evaluation board.
+
 config EBONY
        bool "Ebony"
        depends on 44x
@@ -293,6 +303,12 @@ config 460SX
        select IBM_NEW_EMAC_ZMII
        select IBM_NEW_EMAC_TAH
 
+config APM821xx
+       bool
+       select PPC_FPU
+       select IBM_NEW_EMAC_EMAC4
+       select IBM_NEW_EMAC_TAH
+
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
        bool
index 5f7a29d7f59091fa958e063b661421aa447e48fa..7ddcba3b93976c5ad46ba99ea7688b4d59786476 100644 (file)
@@ -52,6 +52,7 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe);
 static char *board[] __initdata = {
        "amcc,arches",
        "amcc,bamboo",
+       "amcc,bluestone",
        "amcc,canyonlands",
        "amcc,glacier",
        "ibm,ebony",
index 5b243bd3eb3b699ee6a0712340c9df51db2ed948..3dc2a8d262b8731aa4995b6c4b20621f06742fef 100644 (file)
@@ -57,7 +57,7 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
        int id_match = 0;
 
        if (dev == NULL || id == NULL)
-               return NULL;
+               return clk;
 
        mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
index 45c0cb9b67e6774958c621b6e3c8055d43e46163..18c10482019811fd4fa25cbf1b0972ef87d4d0c7 100644 (file)
@@ -99,7 +99,7 @@ static void __init efika_pcisetup(void)
        if (bus_range == NULL || len < 2 * sizeof(int)) {
                printk(KERN_WARNING EFIKA_PLATFORM_NAME
                       ": Can't get bus-range for %s\n", pcictrl->full_name);
-               return;
+               goto out_put;
        }
 
        if (bus_range[1] == bus_range[0])
@@ -111,12 +111,12 @@ static void __init efika_pcisetup(void)
        printk(" controlled by %s\n", pcictrl->full_name);
        printk("\n");
 
-       hose = pcibios_alloc_controller(of_node_get(pcictrl));
+       hose = pcibios_alloc_controller(pcictrl);
        if (!hose) {
                printk(KERN_WARNING EFIKA_PLATFORM_NAME
                       ": Can't allocate PCI controller structure for %s\n",
                       pcictrl->full_name);
-               return;
+               goto out_put;
        }
 
        hose->first_busno = bus_range[0];
@@ -124,6 +124,9 @@ static void __init efika_pcisetup(void)
        hose->ops = &rtas_pci_ops;
 
        pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+       return;
+out_put:
+       of_node_put(pcictrl);
 }
 
 #else
index 6e905314ad5d66035daf38a514adbfaa2aa60dfa..41f3a7eda1def670c1c12864de488788fc27ff98 100644 (file)
@@ -325,12 +325,16 @@ int mpc5200_psc_ac97_gpio_reset(int psc_number)
        clrbits32(&simple_gpio->simple_dvo, sync | out);
        clrbits8(&wkup_gpio->wkup_dvo, reset);
 
-       /* wait at lease 1 us */
-       udelay(2);
+       /* wait for 1 us */
+       udelay(1);
 
        /* Deassert reset */
        setbits8(&wkup_gpio->wkup_dvo, reset);
 
+       /* wait at least 200ns */
+       /* 7 ~= (200ns * timebase) / ns2sec */
+       __delay(7);
+
        /* Restore pin-muxing */
        out_be32(&simple_gpio->port_config, mux);
 
index 021763a32c2f66bed742c4fb2207b3bca4360e4a..73f4135f3a1a6e8780e976b83fa0afc4a73d902f 100644 (file)
@@ -10,12 +10,12 @@ menuconfig PPC_83xx
 if PPC_83xx
 
 config MPC830x_RDB
-       bool "Freescale MPC830x RDB"
+       bool "Freescale MPC830x RDB and derivatives"
        select DEFAULT_UIMAGE
        select PPC_MPC831x
        select FSL_GTM
        help
-         This option enables support for the MPC8308 RDB board.
+         This option enables support for the MPC8308 RDB and MPC8308 P1M boards.
 
 config MPC831x_RDB
        bool "Freescale MPC831x RDB"
index ac102ee9abe8f046f57134c0ef8e44980da338a1..846831d495b57f6c1c9e123308ed9e3f2013848f 100644 (file)
@@ -65,7 +65,8 @@ static int __init mpc830x_rdb_probe(void)
        unsigned long root = of_get_flat_dt_root();
 
        return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
-              of_flat_dt_is_compatible(root, "fsl,mpc8308rdb");
+              of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
+              of_flat_dt_is_compatible(root, "denx,mpc8308_p1m");
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
index f9751c8905be5db684a25555975a60b3b574d881..83068322abd154004325093e1db9a7b24b9da8d7 100644 (file)
@@ -48,8 +48,10 @@ static int mpc837xmds_usb_cfg(void)
                return -1;
 
        np = of_find_node_by_name(NULL, "usb");
-       if (!np)
-               return -ENODEV;
+       if (!np) {
+               ret = -ENODEV;
+               goto out;
+       }
        phy_type = of_get_property(np, "phy_type", NULL);
        if (phy_type && !strcmp(phy_type, "ulpi")) {
                clrbits8(bcsr_regs + 12, BCSR12_USB_SER_PIN);
@@ -65,8 +67,9 @@ static int mpc837xmds_usb_cfg(void)
        }
 
        of_node_put(np);
+out:
        iounmap(bcsr_regs);
-       return 0;
+       return ret;
 }
 
 /* ************************************************************************
index bea1f5905ad42a4e9f18bfba115d02ef824c12f6..b6976e1726e4c43585e87e689a4b6c0250bf39b3 100644 (file)
@@ -11,6 +11,8 @@ menuconfig FSL_SOC_BOOKE
 
 if FSL_SOC_BOOKE
 
+if PPC32
+
 config MPC8540_ADS
        bool "Freescale MPC8540 ADS"
        select DEFAULT_UIMAGE
@@ -153,10 +155,20 @@ config SBC8560
        help
          This option enables support for the Wind River SBC8560 board
 
+config P3041_DS
+       bool "Freescale P3041 DS"
+       select DEFAULT_UIMAGE
+       select PPC_E500MC
+       select PHYS_64BIT
+       select SWIOTLB
+       select MPC8xxx_GPIO
+       select HAS_RAPIDIO
+       help
+         This option enables support for the P3041 DS board
+
 config P4080_DS
        bool "Freescale P4080 DS"
        select DEFAULT_UIMAGE
-       select PPC_FSL_BOOK3E
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
@@ -165,6 +177,20 @@ config P4080_DS
        help
          This option enables support for the P4080 DS board
 
+endif # PPC32
+
+config P5020_DS
+       bool "Freescale P5020 DS"
+       select DEFAULT_UIMAGE
+       select E500
+       select PPC_E500MC
+       select PHYS_64BIT
+       select SWIOTLB
+       select MPC8xxx_GPIO
+       select HAS_RAPIDIO
+       help
+         This option enables support for the P5020 DS board
+
 endif # FSL_SOC_BOOKE
 
 config TQM85xx
index a2ec3f8f4d06bd01929d30f7fdce732282b27e14..dd70db77d63eb5d8d9a5bf08d1d28d649a61c887 100644 (file)
@@ -11,7 +11,9 @@ obj-$(CONFIG_MPC85xx_DS)  += mpc85xx_ds.o
 obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
+obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
+obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
 obj-$(CONFIG_TQM85xx)    += tqm85xx.o
 obj-$(CONFIG_SBC8560)     += sbc8560.o
index da64be19d0997b75518ea1cdde2ecd6a16cbf884..aa34cac4eb5cc5db47db0e233c32ea9dcf0c09f6 100644 (file)
@@ -357,6 +357,7 @@ static void __init mpc85xx_mds_setup_arch(void)
 {
 #ifdef CONFIG_PCI
        struct pci_controller *hose;
+       struct device_node *np;
 #endif
        dma_addr_t max = 0xffffffff;
 
index e1467c937450791af1ca1355176e780e22b6b86b..2b390d19a1d179bfd1d1c0d58498f693ed1f4c27 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/pci.h>
 #include <linux/of_platform.h>
-#include <linux/lmb.h>
+#include <linux/memblock.h>
 
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
@@ -97,7 +97,7 @@ static void __init p1022_ds_setup_arch(void)
 #endif
 
 #ifdef CONFIG_SWIOTLB
-       if (lmb_end_of_DRAM() > max) {
+       if (memblock_end_of_DRAM() > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
@@ -112,6 +112,8 @@ static struct of_device_id __initdata p1022_ds_ids[] = {
        { .compatible = "soc", },
        { .compatible = "simple-bus", },
        { .compatible = "gianfar", },
+       /* So that the DMA channel nodes can be probed individually: */
+       { .compatible = "fsl,eloplus-dma", },
        {},
 };
 
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
new file mode 100644 (file)
index 0000000..0ed52e1
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * P3041 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3041_ds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,P3041DS");
+}
+
+define_machine(p3041_ds) {
+       .name                   = "P3041 DS",
+       .probe                  = p3041_ds_probe,
+       .setup_arch             = corenet_ds_setup_arch,
+       .init_IRQ               = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_coreint_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
+
+machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
new file mode 100644 (file)
index 0000000..7467b71
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * P5020 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p5020_ds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,P5020DS");
+}
+
+define_machine(p5020_ds) {
+       .name                   = "P5020 DS",
+       .probe                  = p5020_ds_probe,
+       .setup_arch             = corenet_ds_setup_arch,
+       .init_IRQ               = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+       .get_irq                = mpic_get_irq,
+#else
+       .get_irq                = mpic_get_coreint_irq,
+#endif
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
+
+machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
+#endif
index a6b106557be4ac6e15d45663a7ea3d28ee3bc36f..5c91a992f02b82049a6dbdaf21dc2974501f8b22 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/kexec.h>
+#include <linux/highmem.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -79,6 +80,7 @@ smp_85xx_kick_cpu(int nr)
        local_irq_save(flags);
 
        out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+#ifdef CONFIG_PPC32
        out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
        if (!ioremappable)
@@ -88,6 +90,12 @@ smp_85xx_kick_cpu(int nr)
        /* Wait a bit for the CPU to ack. */
        while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
                mdelay(1);
+#else
+       out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
+               __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+
+       smp_generic_kick_cpu(nr);
+#endif
 
        local_irq_restore(flags);
 
@@ -114,19 +122,15 @@ struct smp_ops_t smp_85xx_ops = {
 };
 
 #ifdef CONFIG_KEXEC
-static int kexec_down_cpus = 0;
+atomic_t kexec_down_cpus = ATOMIC_INIT(0);
 
 void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-       mpic_teardown_this_cpu(1);
-
-       /* When crashing, this gets called on all CPU's we only
-        * take down the non-boot cpus */
-       if (smp_processor_id() != boot_cpuid)
-       {
-               local_irq_disable();
-               kexec_down_cpus++;
+       local_irq_disable();
 
+       if (secondary) {
+               atomic_inc(&kexec_down_cpus);
+               /* loop forever */
                while (1);
        }
 }
@@ -137,16 +141,65 @@ static void mpc85xx_smp_kexec_down(void *arg)
                ppc_md.kexec_cpu_down(0,1);
 }
 
-static void mpc85xx_smp_machine_kexec(struct kimage *image)
+static void map_and_flush(unsigned long paddr)
 {
-       int timeout = 2000;
+       struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+       unsigned long kaddr  = (unsigned long)kmap(page);
+
+       flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
+       kunmap(page);
+}
+
+/**
+ * Before we reset the other cores, we need to flush relevant cache
+ * out to memory so we don't get anything corrupted, some of these flushes
+ * are performed out of an overabundance of caution as interrupts are not
+ * disabled yet and we can switch cores
+ */
+static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image)
+{
+       kimage_entry_t *ptr, entry;
+       unsigned long paddr;
        int i;
 
-       set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
+       if (image->type == KEXEC_TYPE_DEFAULT) {
+               /* normal kexec images are stored in temporary pages */
+               for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+                    ptr = (entry & IND_INDIRECTION) ?
+                               phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+                       if (!(entry & IND_DESTINATION)) {
+                               map_and_flush(entry);
+                       }
+               }
+               /* flush out last IND_DONE page */
+               map_and_flush(entry);
+       } else {
+               /* crash type kexec images are copied to the crash region */
+               for (i = 0; i < image->nr_segments; i++) {
+                       struct kexec_segment *seg = &image->segment[i];
+                       for (paddr = seg->mem; paddr < seg->mem + seg->memsz;
+                            paddr += PAGE_SIZE) {
+                               map_and_flush(paddr);
+                       }
+               }
+       }
+
+       /* also flush the kimage struct to be passed in as well */
+       flush_dcache_range((unsigned long)image,
+                          (unsigned long)image + sizeof(*image));
+}
+
+static void mpc85xx_smp_machine_kexec(struct kimage *image)
+{
+       int timeout = INT_MAX;
+       int i, num_cpus = num_present_cpus();
+
+       mpc85xx_smp_flush_dcache_kexec(image);
 
-       smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
+       if (image->type == KEXEC_TYPE_DEFAULT)
+               smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
 
-       while ( (kexec_down_cpus != (num_online_cpus() - 1)) &&
+       while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) &&
                ( timeout > 0 ) )
        {
                timeout--;
@@ -155,7 +208,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
        if ( !timeout )
                printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-       for (i = 0; i < num_present_cpus(); i++)
+       for (i = 0; i < num_cpus; i++)
        {
                if ( i == smp_processor_id() ) continue;
                mpic_reset_core(i);
index d1663db7810f3809fd6ea7658299d15d6425c347..81c9208025fa42833b5472da2ccd75845c8b3cc0 100644 (file)
@@ -106,8 +106,7 @@ config MMIO_NVRAM
 
 config MPIC_U3_HT_IRQS
        bool
-       depends on PPC_MAPLE
-       default y
+       default n
 
 config MPIC_BROKEN_REGREAD
        bool
index d361f8119b1e50680511535f0c373147d8267c43..111138c55f9c909e87cfa040d36316bd2ecda96c 100644 (file)
@@ -125,6 +125,7 @@ config 8xx
 
 config E500
        select FSL_EMB_PERFMON
+       select PPC_FSL_BOOK3E
        bool
 
 config PPC_E500MC
@@ -166,9 +167,14 @@ config BOOKE
 
 config FSL_BOOKE
        bool
-       depends on E200 || E500
+       depends on (E200 || E500) && PPC32
        default y
 
+# this is for common code between PPC32 & PPC64 FSL BOOKE
+config PPC_FSL_BOOK3E
+       bool
+       select FSL_EMB_PERFMON
+       default y if FSL_BOOKE
 
 config PTE_64BIT
        bool
index 97085530aa63b291c677dfbeb5e198b1859a0daf..e3e379c6caa79c6a423707d21b1e08face564534 100644 (file)
@@ -310,9 +310,9 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
 }
 
 static struct irq_chip msic_irq_chip = {
-       .mask           = mask_msi_irq,
-       .unmask         = unmask_msi_irq,
-       .shutdown       = unmask_msi_irq,
+       .irq_mask       = mask_msi_irq,
+       .irq_unmask     = unmask_msi_irq,
+       .irq_shutdown   = mask_msi_irq,
        .name           = "AXON-MSI",
 };
 
index 58b13ce3847ec3c92453ef70d5ec4e653d6d886a..26a067122a54705ab07840269a6a9b4e9b9f41a5 100644 (file)
@@ -477,7 +477,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
 
        ioid = cell_iommu_get_ioid(np);
 
-       window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
+       window = kzalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
        BUG_ON(window == NULL);
 
        window->offset = offset;
index 1d3c4effea10d1592acf1ea7fdd62370bef7055f..5ec1e47a0d771eba56e8b8c42111a19aed7df25a 100644 (file)
@@ -173,8 +173,10 @@ static int __init cbe_ptcal_enable(void)
                return -ENODEV;
 
        size = of_get_property(np, "ibm,cbe-ptcal-size", NULL);
-       if (!size)
+       if (!size) {
+               of_node_put(np);
                return -ENODEV;
+       }
 
        pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size);
        order = get_order(*size);
index 5876e888e41251020c71495935125ea8bbe37f83..3f2e557344a31c719783923783c3b3275a7ef379 100644 (file)
@@ -258,8 +258,10 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
                return NO_IRQ;
        imap += intsize + 1;
        tmp = of_get_property(iic, "#interrupt-cells", NULL);
-       if (tmp == NULL)
+       if (tmp == NULL) {
+               of_node_put(iic);
                return NO_IRQ;
+       }
        intsize = *tmp;
        /* Assume unit is last entry of interrupt specifier */
        unit = imap[intsize - 1];
index 1a40da92154c99cab1568cf80d743eca5fab4d2c..02f7b113a31baf119c1528b04fdd319c156f770d 100644 (file)
@@ -154,6 +154,7 @@ static const struct file_operations __fops = {                              \
        .release = spufs_attr_release,                                  \
        .read    = spufs_attr_read,                                     \
        .write   = spufs_attr_write,                                    \
+       .llseek  = generic_file_llseek,                                 \
 };
 
 
@@ -521,6 +522,7 @@ static const struct file_operations spufs_cntl_fops = {
        .release = spufs_cntl_release,
        .read = simple_attr_read,
        .write = simple_attr_write,
+       .llseek = generic_file_llseek,
        .mmap = spufs_cntl_mmap,
 };
 
@@ -714,6 +716,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_mbox_fops = {
        .open   = spufs_pipe_open,
        .read   = spufs_mbox_read,
+       .llseek = no_llseek,
 };
 
 static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
@@ -743,6 +746,7 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_mbox_stat_fops = {
        .open   = spufs_pipe_open,
        .read   = spufs_mbox_stat_read,
+       .llseek = no_llseek,
 };
 
 /* low-level ibox access function */
@@ -863,6 +867,7 @@ static const struct file_operations spufs_ibox_fops = {
        .read   = spufs_ibox_read,
        .poll   = spufs_ibox_poll,
        .fasync = spufs_ibox_fasync,
+       .llseek = no_llseek,
 };
 
 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
@@ -890,6 +895,7 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_ibox_stat_fops = {
        .open   = spufs_pipe_open,
        .read   = spufs_ibox_stat_read,
+       .llseek = no_llseek,
 };
 
 /* low-level mailbox write */
@@ -1011,6 +1017,7 @@ static const struct file_operations spufs_wbox_fops = {
        .write  = spufs_wbox_write,
        .poll   = spufs_wbox_poll,
        .fasync = spufs_wbox_fasync,
+       .llseek = no_llseek,
 };
 
 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
@@ -1038,6 +1045,7 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_wbox_stat_fops = {
        .open   = spufs_pipe_open,
        .read   = spufs_wbox_stat_read,
+       .llseek = no_llseek,
 };
 
 static int spufs_signal1_open(struct inode *inode, struct file *file)
@@ -1166,6 +1174,7 @@ static const struct file_operations spufs_signal1_fops = {
        .read = spufs_signal1_read,
        .write = spufs_signal1_write,
        .mmap = spufs_signal1_mmap,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations spufs_signal1_nosched_fops = {
@@ -1173,6 +1182,7 @@ static const struct file_operations spufs_signal1_nosched_fops = {
        .release = spufs_signal1_release,
        .write = spufs_signal1_write,
        .mmap = spufs_signal1_mmap,
+       .llseek = no_llseek,
 };
 
 static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -1305,6 +1315,7 @@ static const struct file_operations spufs_signal2_fops = {
        .read = spufs_signal2_read,
        .write = spufs_signal2_write,
        .mmap = spufs_signal2_mmap,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations spufs_signal2_nosched_fops = {
@@ -1312,6 +1323,7 @@ static const struct file_operations spufs_signal2_nosched_fops = {
        .release = spufs_signal2_release,
        .write = spufs_signal2_write,
        .mmap = spufs_signal2_mmap,
+       .llseek = no_llseek,
 };
 
 /*
@@ -1451,6 +1463,7 @@ static const struct file_operations spufs_mss_fops = {
        .open    = spufs_mss_open,
        .release = spufs_mss_release,
        .mmap    = spufs_mss_mmap,
+       .llseek  = no_llseek,
 };
 
 static int
@@ -1508,6 +1521,7 @@ static const struct file_operations spufs_psmap_fops = {
        .open    = spufs_psmap_open,
        .release = spufs_psmap_release,
        .mmap    = spufs_psmap_mmap,
+       .llseek  = no_llseek,
 };
 
 
@@ -1871,6 +1885,7 @@ static const struct file_operations spufs_mfc_fops = {
        .fsync   = spufs_mfc_fsync,
        .fasync  = spufs_mfc_fasync,
        .mmap    = spufs_mfc_mmap,
+       .llseek  = no_llseek,
 };
 
 static int spufs_npc_set(void *data, u64 val)
@@ -2246,6 +2261,7 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_dma_info_fops = {
        .open = spufs_info_open,
        .read = spufs_dma_info_read,
+       .llseek = no_llseek,
 };
 
 static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
@@ -2299,6 +2315,7 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
 static const struct file_operations spufs_proxydma_info_fops = {
        .open = spufs_info_open,
        .read = spufs_proxydma_info_read,
+       .llseek = no_llseek,
 };
 
 static int spufs_show_tid(struct seq_file *s, void *private)
@@ -2585,6 +2602,7 @@ static const struct file_operations spufs_switch_log_fops = {
        .read           = spufs_switch_log_read,
        .poll           = spufs_switch_log_poll,
        .release        = spufs_switch_log_release,
+       .llseek         = no_llseek,
 };
 
 /**
index ba3588f2d8e0c2df441907788046d2f8128b092c..d3ceff04ffc79c6832b8b96087913e4fa02692e0 100644 (file)
@@ -74,8 +74,10 @@ void __init chrp_nvram_init(void)
                return;
 
        nbytes_p = of_get_property(nvram, "#bytes", &proplen);
-       if (nbytes_p == NULL || proplen != sizeof(unsigned int))
+       if (nbytes_p == NULL || proplen != sizeof(unsigned int)) {
+               of_node_put(nvram);
                return;
+       }
 
        nvram_size = *nbytes_p;
 
index 5cdcc7c8d9738416a8055840235ca5954d33abd2..649473a729b8843b251a2bbffaf26927b63ac15e 100644 (file)
@@ -65,7 +65,7 @@ static int __init page_aligned(unsigned long x)
 
 void __init wii_memory_fixups(void)
 {
-       struct memblock_property *p = memblock.memory.region;
+       struct memblock_region *p = memblock.memory.regions;
 
        /*
         * This is part of a workaround to allow the use of two
index ce014928d4605b9cf4489fe4e1d4e7a3a61b256f..a7602b11ed9d27e167bc77dd6bb2dfc56406e587 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS   += -mno-minimal-toc
+ccflags-y      := -mno-minimal-toc
 
 obj-y += exception.o
 obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
index 7f45a51fe793eadd7816c7a8cd41715aa33239a1..fdb7384c0c4f3fe372207d4ad8bdc48a364a97c0 100644 (file)
@@ -243,7 +243,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt)
        pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
 
        for (i = 0; i < NR_CPUS; i++) {
-               if (lppaca[i].dyn_proc_status >= 2)
+               if (lppaca_of(i).dyn_proc_status >= 2)
                        continue;
 
                snprintf(p, 32 - (p - buf), "@%d", i);
@@ -251,7 +251,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt)
 
                dt_prop_str(dt, "device_type", device_type_cpu);
 
-               index = lppaca[i].dyn_hv_phys_proc_index;
+               index = lppaca_of(i).dyn_hv_phys_proc_index;
                d = &xIoHriProcessorVpd[index];
 
                dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
index ce61cea0afb52cc77a4fa806da88cd7489518e88..d8b76335bd13d1d9f89dda4861bd928dccbf7703 100644 (file)
@@ -184,7 +184,7 @@ static void pci_dma_dev_setup_iseries(struct pci_dev *pdev)
 
        BUG_ON(lsn == NULL);
 
-       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+       tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
        iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
 
index 33e5fc7334fc508be63b52ce6cae473f24726a6c..42d0a886de0517a93daae17cbb852e223c204391 100644 (file)
@@ -1249,6 +1249,7 @@ out:
 
 static const struct file_operations proc_vmlinux_operations = {
        .write          = proc_mf_change_vmlinux,
+       .llseek         = default_llseek,
 };
 
 static int __init mf_proc_init(void)
index 6590850045afe0c9c4d6184725cdb7d5ca29fb81..6c6029914dbc36380a8a94d1ef8438afb64701de 100644 (file)
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr)
        BUG_ON((nr < 0) || (nr >= NR_CPUS));
 
        /* Verify that our partition has a processor nr */
-       if (lppaca[nr].dyn_proc_status >= 2)
+       if (lppaca_of(nr).dyn_proc_status >= 2)
                return;
 
        /* The processor is currently spinning, waiting
index 3fff8d979b41a809743ca28e4234fcaa28e81400..fe34c3d9bb741739411dc5f156e17c3aa1215c33 100644 (file)
@@ -358,6 +358,7 @@ static int __init maple_cpc925_edac_setup(void)
        model = (const unsigned char *)of_get_property(np, "model", NULL);
        if (!model) {
                printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
+               of_node_put(np);
                return -ENODEV;
        }
 
index 39df6ab1735a6161ff4d2581368d5127f6a8297a..df423993f17503997d4ba6e808a0f7754078548e 100644 (file)
@@ -2873,12 +2873,11 @@ set_initial_features(void)
 
                /* Switch airport off */
                for_each_node_by_name(np, "radio") {
-                       if (np && np->parent == macio_chips[0].of_node) {
+                       if (np->parent == macio_chips[0].of_node) {
                                macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
                                core99_airport_enable(np, 0, 0);
                        }
                }
-               of_node_put(np);
        }
 
        /* On all machines that support sound PM, switch sound off */
index ab2027cdf8936ea47fdc6579ee6455b5af5330ae..3bc075c788ef3af25bcf06223098cffee2808942 100644 (file)
@@ -1155,13 +1155,11 @@ void __init pmac_pcibios_after_init(void)
                        pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
                }
        }
-       of_node_put(nd);
        for_each_node_by_name(nd, "ethernet") {
                if (nd->parent && of_device_is_compatible(nd, "gmac")
                    && of_device_is_compatible(nd->parent, "uni-north"))
                        pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
        }
-       of_node_put(nd);
 }
 
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
index cec6359426573d87a8d42a3439fc10393d8918ae..b0c3777528a1e418387e312b4ae75183aa2de8c8 100644 (file)
@@ -837,8 +837,10 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
                return NULL;
  find_it:
        dev = pmf_find_device(actor);
-       if (dev == NULL)
-               return NULL;
+       if (dev == NULL) {
+               result = NULL;
+               goto out;
+       }
 
        list_for_each_entry(func, &dev->functions, link) {
                if (name && strcmp(name, func->name))
@@ -850,8 +852,9 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
                result = func;
                break;
        }
-       of_node_put(actor);
        pmf_put_device(dev);
+out:
+       of_node_put(actor);
        return result;
 }
 
index 046ace9c43819b86efcb2b241ae6ed5ebd6d02a2..59eb8bdaa79d0be02611c01df68351c5bcbf3ff8 100644 (file)
@@ -1,14 +1,9 @@
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS           += -mno-minimal-toc
-endif
-
-ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
-EXTRA_CFLAGS           += -DDEBUG
-endif
+ccflags-$(CONFIG_PPC64)                        := -mno-minimal-toc
+ccflags-$(CONFIG_PPC_PSERIES_DEBUG)    += -DDEBUG
 
 obj-y                  := lpar.o hvCall.o nvram.o reconfig.o \
                           setup.o iommu.o event_sources.o ras.o \
-                          firmware.o power.o dlpar.o
+                          firmware.o power.o dlpar.o mobility.o
 obj-$(CONFIG_SMP)      += smp.o
 obj-$(CONFIG_XICS)     += xics.o
 obj-$(CONFIG_SCANLOG)  += scanlog.o
@@ -23,7 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG)  += hotplug-memory.o
 obj-$(CONFIG_HVC_CONSOLE)      += hvconsole.o
 obj-$(CONFIG_HVCS)             += hvcserver.o
 obj-$(CONFIG_HCALL_STATS)      += hvCall_inst.o
-obj-$(CONFIG_PHYP_DUMP)        += phyp_dump.o
+obj-$(CONFIG_PHYP_DUMP)                += phyp_dump.o
 obj-$(CONFIG_CMM)              += cmm.o
 obj-$(CONFIG_DTL)              += dtl.o
 
index 227c1c3d585e028874cc895afc3241afff0b3caf..b74a9230edc9a0454856b5f4cf18d730f9a0c05e 100644 (file)
@@ -33,7 +33,7 @@ struct cc_workarea {
        u32     prop_offset;
 };
 
-static void dlpar_free_cc_property(struct property *prop)
+void dlpar_free_cc_property(struct property *prop)
 {
        kfree(prop->name);
        kfree(prop->value);
@@ -55,13 +55,12 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
 
        prop->length = ccwa->prop_length;
        value = (char *)ccwa + ccwa->prop_offset;
-       prop->value = kzalloc(prop->length, GFP_KERNEL);
+       prop->value = kmemdup(value, prop->length, GFP_KERNEL);
        if (!prop->value) {
                dlpar_free_cc_property(prop);
                return NULL;
        }
 
-       memcpy(prop->value, value, prop->length);
        return prop;
 }
 
@@ -102,7 +101,7 @@ static void dlpar_free_one_cc_node(struct device_node *dn)
        kfree(dn);
 }
 
-static void dlpar_free_cc_nodes(struct device_node *dn)
+void dlpar_free_cc_nodes(struct device_node *dn)
 {
        if (dn->child)
                dlpar_free_cc_nodes(dn->child);
@@ -129,20 +128,35 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
        struct property *property;
        struct property *last_property = NULL;
        struct cc_workarea *ccwa;
+       char *data_buf;
        int cc_token;
-       int rc;
+       int rc = -1;
 
        cc_token = rtas_token("ibm,configure-connector");
        if (cc_token == RTAS_UNKNOWN_SERVICE)
                return NULL;
 
-       spin_lock(&rtas_data_buf_lock);
-       ccwa = (struct cc_workarea *)&rtas_data_buf[0];
+       data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+       if (!data_buf)
+               return NULL;
+
+       ccwa = (struct cc_workarea *)&data_buf[0];
        ccwa->drc_index = drc_index;
        ccwa->zero = 0;
 
-       rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
-       while (rc) {
+       do {
+               /* Since we release the rtas_data_buf lock between configure
+                * connector calls we want to re-populate the rtas_data_buffer
+                * with the contents of the previous call.
+                */
+               spin_lock(&rtas_data_buf_lock);
+
+               memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE);
+               rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
+               memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+
+               spin_unlock(&rtas_data_buf_lock);
+
                switch (rc) {
                case NEXT_SIBLING:
                        dn = dlpar_parse_cc_node(ccwa);
@@ -197,18 +211,19 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
                               "returned from configure-connector\n", rc);
                        goto cc_error;
                }
+       } while (rc);
 
-               rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
+cc_error:
+       kfree(data_buf);
+
+       if (rc) {
+               if (first_dn)
+                       dlpar_free_cc_nodes(first_dn);
+
+               return NULL;
        }
 
-       spin_unlock(&rtas_data_buf_lock);
        return first_dn;
-
-cc_error:
-       if (first_dn)
-               dlpar_free_cc_nodes(first_dn);
-       spin_unlock(&rtas_data_buf_lock);
-       return NULL;
 }
 
 static struct device_node *derive_parent(const char *path)
index a00addb559456e6c3ea69658887f630378863ff1..c371bc06434bf5f4121db3b4b6d79c7b64073e3c 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/spinlock.h>
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
+#include <asm/lppaca.h>
 
 #include "plpar_wrappers.h"
 
-/*
- * Layout of entries in the hypervisor's DTL buffer. Although we don't
- * actually access the internals of an entry (we only need to know the size),
- * we might as well define it here for reference.
- */
-struct dtl_entry {
-       u8      dispatch_reason;
-       u8      preempt_reason;
-       u16     processor_id;
-       u32     enqueue_to_dispatch_time;
-       u32     ready_to_enqueue_time;
-       u32     waiting_to_ready_time;
-       u64     timebase;
-       u64     fault_addr;
-       u64     srr0;
-       u64     srr1;
-};
-
 struct dtl {
        struct dtl_entry        *buf;
        struct dentry           *file;
        int                     cpu;
        int                     buf_entries;
        u64                     last_idx;
+       spinlock_t              lock;
 };
 static DEFINE_PER_CPU(struct dtl, cpu_dtl);
 
@@ -72,25 +57,97 @@ static u8 dtl_event_mask = 0x7;
 static int dtl_buf_entries = (16 * 85);
 
 
-static int dtl_enable(struct dtl *dtl)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+struct dtl_ring {
+       u64     write_index;
+       struct dtl_entry *write_ptr;
+       struct dtl_entry *buf;
+       struct dtl_entry *buf_end;
+       u8      saved_dtl_mask;
+};
+
+static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
+
+static atomic_t dtl_count;
+
+/*
+ * The cpu accounting code controls the DTL ring buffer, and we get
+ * given entries as they are processed.
+ */
+static void consume_dtle(struct dtl_entry *dtle, u64 index)
 {
-       unsigned long addr;
-       int ret, hwcpu;
+       struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings);
+       struct dtl_entry *wp = dtlr->write_ptr;
+       struct lppaca *vpa = local_paca->lppaca_ptr;
 
-       /* only allow one reader */
-       if (dtl->buf)
-               return -EBUSY;
+       if (!wp)
+               return;
 
-       /* we need to store the original allocation size for use during read */
-       dtl->buf_entries = dtl_buf_entries;
+       *wp = *dtle;
+       barrier();
 
-       dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
-                       GFP_KERNEL, cpu_to_node(dtl->cpu));
-       if (!dtl->buf) {
-               printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
-                               __func__, dtl->cpu);
-               return -ENOMEM;
-       }
+       /* check for hypervisor ring buffer overflow, ignore this entry if so */
+       if (index + N_DISPATCH_LOG < vpa->dtl_idx)
+               return;
+
+       ++wp;
+       if (wp == dtlr->buf_end)
+               wp = dtlr->buf;
+       dtlr->write_ptr = wp;
+
+       /* incrementing write_index makes the new entry visible */
+       smp_wmb();
+       ++dtlr->write_index;
+}
+
+static int dtl_start(struct dtl *dtl)
+{
+       struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+       dtlr->buf = dtl->buf;
+       dtlr->buf_end = dtl->buf + dtl->buf_entries;
+       dtlr->write_index = 0;
+
+       /* setting write_ptr enables logging into our buffer */
+       smp_wmb();
+       dtlr->write_ptr = dtl->buf;
+
+       /* enable event logging */
+       dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask;
+       lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask;
+
+       dtl_consumer = consume_dtle;
+       atomic_inc(&dtl_count);
+       return 0;
+}
+
+static void dtl_stop(struct dtl *dtl)
+{
+       struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+       dtlr->write_ptr = NULL;
+       smp_wmb();
+
+       dtlr->buf = NULL;
+
+       /* restore dtl_enable_mask */
+       lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask;
+
+       if (atomic_dec_and_test(&dtl_count))
+               dtl_consumer = NULL;
+}
+
+static u64 dtl_current_index(struct dtl *dtl)
+{
+       return per_cpu(dtl_rings, dtl->cpu).write_index;
+}
+
+#else /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_start(struct dtl *dtl)
+{
+       unsigned long addr;
+       int ret, hwcpu;
 
        /* Register our dtl buffer with the hypervisor. The HV expects the
         * buffer size to be passed in the second word of the buffer */
@@ -102,34 +159,82 @@ static int dtl_enable(struct dtl *dtl)
        if (ret) {
                printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
                       "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
-               kfree(dtl->buf);
                return -EIO;
        }
 
        /* set our initial buffer indices */
-       dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
+       lppaca_of(dtl->cpu).dtl_idx = 0;
 
        /* ensure that our updates to the lppaca fields have occurred before
         * we actually enable the logging */
        smp_wmb();
 
        /* enable event logging */
-       lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
+       lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask;
 
        return 0;
 }
 
-static void dtl_disable(struct dtl *dtl)
+static void dtl_stop(struct dtl *dtl)
 {
        int hwcpu = get_hard_smp_processor_id(dtl->cpu);
 
-       lppaca[dtl->cpu].dtl_enable_mask = 0x0;
+       lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
 
        unregister_dtl(hwcpu, __pa(dtl->buf));
+}
+
+static u64 dtl_current_index(struct dtl *dtl)
+{
+       return lppaca_of(dtl->cpu).dtl_idx;
+}
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_enable(struct dtl *dtl)
+{
+       long int n_entries;
+       long int rc;
+       struct dtl_entry *buf = NULL;
 
+       /* only allow one reader */
+       if (dtl->buf)
+               return -EBUSY;
+
+       n_entries = dtl_buf_entries;
+       buf = kmalloc_node(n_entries * sizeof(struct dtl_entry),
+                       GFP_KERNEL, cpu_to_node(dtl->cpu));
+       if (!buf) {
+               printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
+                               __func__, dtl->cpu);
+               return -ENOMEM;
+       }
+
+       spin_lock(&dtl->lock);
+       rc = -EBUSY;
+       if (!dtl->buf) {
+               /* store the original allocation size for use during read */
+               dtl->buf_entries = n_entries;
+               dtl->buf = buf;
+               dtl->last_idx = 0;
+               rc = dtl_start(dtl);
+               if (rc)
+                       dtl->buf = NULL;
+       }
+       spin_unlock(&dtl->lock);
+
+       if (rc)
+               kfree(buf);
+       return rc;
+}
+
+static void dtl_disable(struct dtl *dtl)
+{
+       spin_lock(&dtl->lock);
+       dtl_stop(dtl);
        kfree(dtl->buf);
        dtl->buf = NULL;
        dtl->buf_entries = 0;
+       spin_unlock(&dtl->lock);
 }
 
 /* file interface */
@@ -157,8 +262,9 @@ static int dtl_file_release(struct inode *inode, struct file *filp)
 static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
                loff_t *pos)
 {
-       int rc, cur_idx, last_idx, n_read, n_req, read_size;
+       long int rc, n_read, n_req, read_size;
        struct dtl *dtl;
+       u64 cur_idx, last_idx, i;
 
        if ((len % sizeof(struct dtl_entry)) != 0)
                return -EINVAL;
@@ -171,41 +277,48 @@ static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
        /* actual number of entries read */
        n_read = 0;
 
-       cur_idx = lppaca[dtl->cpu].dtl_idx;
+       spin_lock(&dtl->lock);
+
+       cur_idx = dtl_current_index(dtl);
        last_idx = dtl->last_idx;
 
-       if (cur_idx - last_idx > dtl->buf_entries) {
-               pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
-                               __func__, dtl->cpu);
-       }
+       if (last_idx + dtl->buf_entries <= cur_idx)
+               last_idx = cur_idx - dtl->buf_entries + 1;
+
+       if (last_idx + n_req > cur_idx)
+               n_req = cur_idx - last_idx;
+
+       if (n_req > 0)
+               dtl->last_idx = last_idx + n_req;
+
+       spin_unlock(&dtl->lock);
+
+       if (n_req <= 0)
+               return 0;
 
-       cur_idx  %= dtl->buf_entries;
-       last_idx %= dtl->buf_entries;
+       i = last_idx % dtl->buf_entries;
 
        /* read the tail of the buffer if we've wrapped */
-       if (last_idx > cur_idx) {
-               read_size = min(n_req, dtl->buf_entries - last_idx);
+       if (i + n_req > dtl->buf_entries) {
+               read_size = dtl->buf_entries - i;
 
-               rc = copy_to_user(buf, &dtl->buf[last_idx],
+               rc = copy_to_user(buf, &dtl->buf[i],
                                read_size * sizeof(struct dtl_entry));
                if (rc)
                        return -EFAULT;
 
-               last_idx = 0;
+               i = 0;
                n_req -= read_size;
                n_read += read_size;
                buf += read_size * sizeof(struct dtl_entry);
        }
 
        /* .. and now the head */
-       read_size = min(n_req, cur_idx - last_idx);
-       rc = copy_to_user(buf, &dtl->buf[last_idx],
-                       read_size * sizeof(struct dtl_entry));
+       rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry));
        if (rc)
                return -EFAULT;
 
-       n_read += read_size;
-       dtl->last_idx += n_read;
+       n_read += n_req;
 
        return n_read * sizeof(struct dtl_entry);
 }
@@ -263,6 +376,7 @@ static int dtl_init(void)
        /* set up the per-cpu log structures */
        for_each_possible_cpu(i) {
                struct dtl *dtl = &per_cpu(cpu_dtl, i);
+               spin_lock_init(&dtl->lock);
                dtl->cpu = i;
 
                rc = dtl_setup_file(dtl);
index 395848e30c523b36f7b31bbd258610777e87b4dd..a77bcaed80af8fa1c037444bf0aac0b0f5f0e1ea 100644 (file)
@@ -403,7 +403,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
        pci->phb->dma_window_size = 0x8000000ul;
        pci->phb->dma_window_base_cur = 0x8000000ul;
 
-       tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+       tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
                           pci->phb->node);
 
        iommu_table_setparms(pci->phb, dn, tbl);
@@ -448,7 +448,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
                 pdn->full_name, ppci->iommu_table);
 
        if (!ppci->iommu_table) {
-               tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+               tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
                                   ppci->phb->node);
                iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
                        bus->number);
@@ -478,7 +478,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
                struct pci_controller *phb = PCI_DN(dn)->phb;
 
                pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
-               tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+               tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
                                   phb->node);
                iommu_table_setparms(phb, dn, tbl);
                PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
@@ -544,7 +544,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 
        pci = PCI_DN(pdn);
        if (!pci->iommu_table) {
-               tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+               tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
                                   pci->phb->node);
                iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
                        pci->phb->bus->number);
index cf79b46d8f885539d28bc4ca9bcb4f766a2e107c..f129040d974ce2a9faffc1d0899d6eb7410dc31e 100644 (file)
@@ -248,11 +248,13 @@ void vpa_init(int cpu)
        int hwcpu = get_hard_smp_processor_id(cpu);
        unsigned long addr;
        long ret;
+       struct paca_struct *pp;
+       struct dtl_entry *dtl;
 
        if (cpu_has_feature(CPU_FTR_ALTIVEC))
-               lppaca[cpu].vmxregs_in_use = 1;
+               lppaca_of(cpu).vmxregs_in_use = 1;
 
-       addr = __pa(&lppaca[cpu]);
+       addr = __pa(&lppaca_of(cpu));
        ret = register_vpa(hwcpu, addr);
 
        if (ret) {
@@ -274,6 +276,25 @@ void vpa_init(int cpu)
                               "registration for cpu %d (hw %d) of area %lx "
                               "returns %ld\n", cpu, hwcpu, addr, ret);
        }
+
+       /*
+        * Register dispatch trace log, if one has been allocated.
+        */
+       pp = &paca[cpu];
+       dtl = pp->dispatch_log;
+       if (dtl) {
+               pp->dtl_ridx = 0;
+               pp->dtl_curr = dtl;
+               lppaca_of(cpu).dtl_idx = 0;
+
+               /* hypervisor reads buffer length from this field */
+               dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+               ret = register_dtl(hwcpu, __pa(dtl));
+               if (ret)
+                       pr_warn("DTL registration failed for cpu %d (%ld)\n",
+                               cpu, ret);
+               lppaca_of(cpu).dtl_enable_mask = 2;
+       }
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
new file mode 100644 (file)
index 0000000..3e7f651
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Support for Partition Mobility/Migration
+ *
+ * Copyright (C) 2010 Nathan Fontenot
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <asm/rtas.h>
+#include "pseries.h"
+
+static struct kobject *mobility_kobj;
+
+struct update_props_workarea {
+       u32 phandle;
+       u32 state;
+       u64 reserved;
+       u32 nprops;
+};
+
+#define NODE_ACTION_MASK       0xff000000
+#define NODE_COUNT_MASK                0x00ffffff
+
+#define DELETE_DT_NODE 0x01000000
+#define UPDATE_DT_NODE 0x02000000
+#define ADD_DT_NODE    0x03000000
+
+static int mobility_rtas_call(int token, char *buf)
+{
+       int rc;
+
+       spin_lock(&rtas_data_buf_lock);
+
+       memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
+       rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, 1);
+       memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+
+       spin_unlock(&rtas_data_buf_lock);
+       return rc;
+}
+
+static int delete_dt_node(u32 phandle)
+{
+       struct device_node *dn;
+
+       dn = of_find_node_by_phandle(phandle);
+       if (!dn)
+               return -ENOENT;
+
+       dlpar_detach_node(dn);
+       return 0;
+}
+
+static int update_dt_property(struct device_node *dn, struct property **prop,
+                             const char *name, u32 vd, char *value)
+{
+       struct property *new_prop = *prop;
+       struct property *old_prop;
+       int more = 0;
+
+       /* A negative 'vd' value indicates that only part of the new property
+        * value is contained in the buffer and we need to call
+        * ibm,update-properties again to get the rest of the value.
+        *
+        * A negative value is also the two's compliment of the actual value.
+        */
+       if (vd & 0x80000000) {
+               vd = ~vd + 1;
+               more = 1;
+       }
+
+       if (new_prop) {
+               /* partial property fixup */
+               char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
+               if (!new_data)
+                       return -ENOMEM;
+
+               memcpy(new_data, new_prop->value, new_prop->length);
+               memcpy(new_data + new_prop->length, value, vd);
+
+               kfree(new_prop->value);
+               new_prop->value = new_data;
+               new_prop->length += vd;
+       } else {
+               new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+               if (!new_prop)
+                       return -ENOMEM;
+
+               new_prop->name = kstrdup(name, GFP_KERNEL);
+               if (!new_prop->name) {
+                       kfree(new_prop);
+                       return -ENOMEM;
+               }
+
+               new_prop->length = vd;
+               new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
+               if (!new_prop->value) {
+                       kfree(new_prop->name);
+                       kfree(new_prop);
+                       return -ENOMEM;
+               }
+
+               memcpy(new_prop->value, value, vd);
+               *prop = new_prop;
+       }
+
+       if (!more) {
+               old_prop = of_find_property(dn, new_prop->name, NULL);
+               if (old_prop)
+                       prom_update_property(dn, new_prop, old_prop);
+               else
+                       prom_add_property(dn, new_prop);
+
+               new_prop = NULL;
+       }
+
+       return 0;
+}
+
+static int update_dt_node(u32 phandle)
+{
+       struct update_props_workarea *upwa;
+       struct device_node *dn;
+       struct property *prop = NULL;
+       int i, rc;
+       char *prop_data;
+       char *rtas_buf;
+       int update_properties_token;
+
+       update_properties_token = rtas_token("ibm,update-properties");
+       if (update_properties_token == RTAS_UNKNOWN_SERVICE)
+               return -EINVAL;
+
+       rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+       if (!rtas_buf)
+               return -ENOMEM;
+
+       dn = of_find_node_by_phandle(phandle);
+       if (!dn) {
+               kfree(rtas_buf);
+               return -ENOENT;
+       }
+
+       upwa = (struct update_props_workarea *)&rtas_buf[0];
+       upwa->phandle = phandle;
+
+       do {
+               rc = mobility_rtas_call(update_properties_token, rtas_buf);
+               if (rc < 0)
+                       break;
+
+               prop_data = rtas_buf + sizeof(*upwa);
+
+               for (i = 0; i < upwa->nprops; i++) {
+                       char *prop_name;
+                       u32 vd;
+
+                       prop_name = prop_data + 1;
+                       prop_data += strlen(prop_name) + 1;
+                       vd = *prop_data++;
+
+                       switch (vd) {
+                       case 0x00000000:
+                               /* name only property, nothing to do */
+                               break;
+
+                       case 0x80000000:
+                               prop = of_find_property(dn, prop_name, NULL);
+                               prom_remove_property(dn, prop);
+                               prop = NULL;
+                               break;
+
+                       default:
+                               rc = update_dt_property(dn, &prop, prop_name,
+                                                       vd, prop_data);
+                               if (rc) {
+                                       printk(KERN_ERR "Could not update %s"
+                                              " property\n", prop_name);
+                               }
+
+                               prop_data += vd;
+                       }
+               }
+       } while (rc == 1);
+
+       of_node_put(dn);
+       kfree(rtas_buf);
+       return 0;
+}
+
+static int add_dt_node(u32 parent_phandle, u32 drc_index)
+{
+       struct device_node *dn;
+       struct device_node *parent_dn;
+       int rc;
+
+       dn = dlpar_configure_connector(drc_index);
+       if (!dn)
+               return -ENOENT;
+
+       parent_dn = of_find_node_by_phandle(parent_phandle);
+       if (!parent_dn) {
+               dlpar_free_cc_nodes(dn);
+               return -ENOENT;
+       }
+
+       dn->parent = parent_dn;
+       rc = dlpar_attach_node(dn);
+       if (rc)
+               dlpar_free_cc_nodes(dn);
+
+       of_node_put(parent_dn);
+       return rc;
+}
+
+static int pseries_devicetree_update(void)
+{
+       char *rtas_buf;
+       u32 *data;
+       int update_nodes_token;
+       int rc;
+
+       update_nodes_token = rtas_token("ibm,update-nodes");
+       if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
+               return -EINVAL;
+
+       rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+       if (!rtas_buf)
+               return -ENOMEM;
+
+       do {
+               rc = mobility_rtas_call(update_nodes_token, rtas_buf);
+               if (rc && rc != 1)
+                       break;
+
+               data = (u32 *)rtas_buf + 4;
+               while (*data & NODE_ACTION_MASK) {
+                       int i;
+                       u32 action = *data & NODE_ACTION_MASK;
+                       int node_count = *data & NODE_COUNT_MASK;
+
+                       data++;
+
+                       for (i = 0; i < node_count; i++) {
+                               u32 phandle = *data++;
+                               u32 drc_index;
+
+                               switch (action) {
+                               case DELETE_DT_NODE:
+                                       delete_dt_node(phandle);
+                                       break;
+                               case UPDATE_DT_NODE:
+                                       update_dt_node(phandle);
+                                       break;
+                               case ADD_DT_NODE:
+                                       drc_index = *data++;
+                                       add_dt_node(phandle, drc_index);
+                                       break;
+                               }
+                       }
+               }
+       } while (rc == 1);
+
+       kfree(rtas_buf);
+       return rc;
+}
+
+void post_mobility_fixup(void)
+{
+       int rc;
+       int activate_fw_token;
+
+       rc = pseries_devicetree_update();
+       if (rc) {
+               printk(KERN_ERR "Initial post-mobility device tree update "
+                      "failed: %d\n", rc);
+               return;
+       }
+
+       activate_fw_token = rtas_token("ibm,activate-firmware");
+       if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_ERR "Could not make post-mobility "
+                      "activate-fw call.\n");
+               return;
+       }
+
+       rc = rtas_call(activate_fw_token, 0, 1, NULL);
+       if (!rc) {
+               rc = pseries_devicetree_update();
+               if (rc)
+                       printk(KERN_ERR "Secondary post-mobility device tree "
+                              "update failed: %d\n", rc);
+       } else {
+               printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
+               return;
+       }
+
+       return;
+}
+
+static ssize_t migrate_store(struct class *class, struct class_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct rtas_args args;
+       u64 streamid;
+       int rc;
+
+       rc = strict_strtoull(buf, 0, &streamid);
+       if (rc)
+               return rc;
+
+       memset(&args, 0, sizeof(args));
+       args.token = rtas_token("ibm,suspend-me");
+       args.nargs = 2;
+       args.nret = 1;
+
+       args.args[0] = streamid >> 32 ;
+       args.args[1] = streamid & 0xffffffff;
+       args.rets = &args.args[args.nargs];
+
+       do {
+               args.rets[0] = 0;
+               rc = rtas_ibm_suspend_me(&args);
+               if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE)
+                       ssleep(1);
+       } while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE);
+
+       if (rc)
+               return rc;
+       else if (args.rets[0])
+               return args.rets[0];
+
+       post_mobility_fixup();
+       return count;
+}
+
+static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store);
+
+static int __init mobility_sysfs_init(void)
+{
+       int rc;
+
+       mobility_kobj = kobject_create_and_add("mobility", kernel_kobj);
+       if (!mobility_kobj)
+               return -ENOMEM;
+
+       rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
+
+       return rc;
+}
+device_initcall(mobility_sysfs_init);
index 40c93cad91d211e05dd2b4362068a14ce7701f45..e9f6d2859c3cf3dd67b5a27a34fd77992d56b4cc 100644 (file)
@@ -17,6 +17,8 @@ struct device_node;
 extern void request_event_sources_irqs(struct device_node *np,
                                       irq_handler_t handler, const char *name);
 
+#include <linux/of.h>
+
 extern void __init fw_feature_init(const char *hypertas, unsigned long len);
 
 struct pt_regs;
@@ -47,4 +49,11 @@ extern unsigned long rtas_poweron_auto;
 
 extern void find_udbg_vterm(void);
 
+/* Dynamic logical Partitioning/Mobility */
+extern void dlpar_free_cc_nodes(struct device_node *);
+extern void dlpar_free_cc_property(struct property *);
+extern struct device_node *dlpar_configure_connector(u32);
+extern int dlpar_attach_node(struct device_node *);
+extern int dlpar_detach_node(struct device_node *);
+
 #endif /* _PSERIES_PSERIES_H */
index 57ddbb43b33ae869854b7ffa2eb27ab036d423df..1de2cbb92303c880cf9c41b4635baf03f13d1a6b 100644 (file)
@@ -539,7 +539,8 @@ out:
 }
 
 static const struct file_operations ofdt_fops = {
-       .write = ofdt_write
+       .write = ofdt_write,
+       .llseek = noop_llseek,
 };
 
 /* create /proc/powerpc/ofdt write-only by root */
index 80e9e7652a4d1371b0a17032fa4eb4edc7e0fbf1..554457294a2b5c8f4429b6ba4a2f99d26602c022 100644 (file)
@@ -170,6 +170,7 @@ const struct file_operations scanlog_fops = {
        .write          = scanlog_write,
        .open           = scanlog_open,
        .release        = scanlog_release,
+       .llseek         = noop_llseek,
 };
 
 static int __init scanlog_init(void)
index a6d19e3a505e62b15958573ca7f95a093aef5394..d345bfd56bbe35ead2c45e166704a98264524bf9 100644 (file)
@@ -273,6 +273,58 @@ static struct notifier_block pci_dn_reconfig_nb = {
        .notifier_call = pci_dn_reconfig_notifier,
 };
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+/*
+ * Allocate space for the dispatch trace log for all possible cpus
+ * and register the buffers with the hypervisor.  This is used for
+ * computing time stolen by the hypervisor.
+ */
+static int alloc_dispatch_logs(void)
+{
+       int cpu, ret;
+       struct paca_struct *pp;
+       struct dtl_entry *dtl;
+
+       if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+               return 0;
+
+       for_each_possible_cpu(cpu) {
+               pp = &paca[cpu];
+               dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL,
+                                  cpu_to_node(cpu));
+               if (!dtl) {
+                       pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
+                               cpu);
+                       pr_warn("Stolen time statistics will be unreliable\n");
+                       break;
+               }
+
+               pp->dtl_ridx = 0;
+               pp->dispatch_log = dtl;
+               pp->dispatch_log_end = dtl + N_DISPATCH_LOG;
+               pp->dtl_curr = dtl;
+       }
+
+       /* Register the DTL for the current (boot) cpu */
+       dtl = get_paca()->dispatch_log;
+       get_paca()->dtl_ridx = 0;
+       get_paca()->dtl_curr = dtl;
+       get_paca()->lppaca_ptr->dtl_idx = 0;
+
+       /* hypervisor reads buffer length from this field */
+       dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+       ret = register_dtl(hard_smp_processor_id(), __pa(dtl));
+       if (ret)
+               pr_warn("DTL registration failed for boot cpu %d (%d)\n",
+                       smp_processor_id(), ret);
+       get_paca()->lppaca_ptr->dtl_enable_mask = 2;
+
+       return 0;
+}
+
+early_initcall(alloc_dispatch_logs);
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
 static void __init pSeries_setup_arch(void)
 {
        /* Discover PIC type and setup ppc_md accordingly */
index 3b1bf61c45bebda01f084e9229a2c764adb48b2f..0317cce877c647c28e66525dffa24ff1987deedf 100644 (file)
@@ -182,10 +182,13 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
        /* Special case - we inhibit secondary thread startup
         * during boot if the user requests it.
         */
-       if (system_state < SYSTEM_RUNNING &&
-           cpu_has_feature(CPU_FTR_SMT) &&
-           !smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
-               return 0;
+       if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+               if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+                       return 0;
+               if (smt_enabled_at_boot
+                   && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+                       return 0;
+       }
 
        return 1;
 }
index 5b22b07c8f67aa19da32832c6b553220445489ee..7b96e5a270ce7b768ad13a8f4de2de3d84f4c692 100644 (file)
@@ -178,7 +178,7 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask,
        if (!distribute_irqs)
                return default_server;
 
-       if (!cpumask_equal(cpumask, cpu_all_mask)) {
+       if (!cpumask_subset(cpu_possible_mask, cpumask)) {
                int server = cpumask_first_and(cpu_online_mask, cpumask);
 
                if (server < nr_cpu_ids)
@@ -243,7 +243,7 @@ static unsigned int xics_startup(unsigned int virq)
         * at that level, so we do it here by hand.
         */
        if (irq_to_desc(virq)->msi_desc)
-               unmask_msi_irq(virq);
+               unmask_msi_irq(irq_get_irq_data(virq));
 
        /* unmask it */
        xics_unmask_irq(virq);
@@ -928,8 +928,10 @@ void xics_migrate_irqs_away(void)
                if (xics_status[0] != hw_cpu)
                        goto unlock;
 
-               printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
-                      virq, cpu);
+               /* This is expected during cpu offline. */
+               if (cpu_online(cpu))
+                       printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
+                              virq, cpu);
 
                /* Reset affinity to all cpus */
                cpumask_setall(irq_to_desc(virq)->affinity);
index 5642924fb9fb437637d4fe963253ce9d0b75a58d..0bef9dacb64e4586ef16dca61434604663204e8e 100644 (file)
@@ -1,8 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS                   += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)                := -mno-minimal-toc
 
 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
@@ -20,6 +18,7 @@ obj-$(CONFIG_FSL_PMC)         += fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
 obj-$(CONFIG_MPC8xxx_GPIO)     += mpc8xxx_gpio.o
+obj-$(CONFIG_FSL_85XX_CACHE_SRAM)      += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)      += simple_gpio.o
 obj-$(CONFIG_RAPIDIO)          += fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)    += tsi108_pci.o tsi108_dev.o
index 559db2b846a9dcd4428d4feb0467ff14bdd4cdbc..17cf15ec38be1d111eab991ebe74c6c9b6279e27 100644 (file)
@@ -70,6 +70,8 @@ static int iommu_table_dart_inited;
 static int dart_dirty;
 static int dart_is_u4;
 
+#define DART_U4_BYPASS_BASE    0x8000000000ull
+
 #define DBG(...)
 
 static inline void dart_tlb_invalidate_all(void)
@@ -292,12 +294,20 @@ static void iommu_table_dart_setup(void)
        set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
 }
 
-static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+static void dma_dev_setup_dart(struct device *dev)
 {
        /* We only have one iommu table on the mac for now, which makes
         * things simple. Setup all PCI devices to point to this table
         */
-       set_iommu_table_base(&dev->dev, &iommu_table_dart);
+       if (get_dma_ops(dev) == &dma_direct_ops)
+               set_dma_offset(dev, DART_U4_BYPASS_BASE);
+       else
+               set_iommu_table_base(dev, &iommu_table_dart);
+}
+
+static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+{
+       dma_dev_setup_dart(&dev->dev);
 }
 
 static void pci_dma_bus_setup_dart(struct pci_bus *bus)
@@ -315,6 +325,45 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus)
                PCI_DN(dn)->iommu_table = &iommu_table_dart;
 }
 
+static bool dart_device_on_pcie(struct device *dev)
+{
+       struct device_node *np = of_node_get(dev->of_node);
+
+       while(np) {
+               if (of_device_is_compatible(np, "U4-pcie") ||
+                   of_device_is_compatible(np, "u4-pcie")) {
+                       of_node_put(np);
+                       return true;
+               }
+               np = of_get_next_parent(np);
+       }
+       return false;
+}
+
+static int dart_dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+               return -EIO;
+
+       /* U4 supports a DART bypass, we use it for 64-bit capable
+        * devices to improve performances. However, that only works
+        * for devices connected to U4 own PCIe interface, not bridged
+        * through hypertransport. We need the device to support at
+        * least 40 bits of addresses.
+        */
+       if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) {
+               dev_info(dev, "Using 64-bit DMA iommu bypass\n");
+               set_dma_ops(dev, &dma_direct_ops);
+       } else {
+               dev_info(dev, "Using 32-bit DMA via iommu\n");
+               set_dma_ops(dev, &dma_iommu_ops);
+       }
+       dma_dev_setup_dart(dev);
+
+       *dev->dma_mask = dma_mask;
+       return 0;
+}
+
 void __init iommu_init_early_dart(void)
 {
        struct device_node *dn;
@@ -328,20 +377,25 @@ void __init iommu_init_early_dart(void)
                dart_is_u4 = 1;
        }
 
+       /* Initialize the DART HW */
+       if (dart_init(dn) != 0)
+               goto bail;
+
        /* Setup low level TCE operations for the core IOMMU code */
        ppc_md.tce_build = dart_build;
        ppc_md.tce_free  = dart_free;
        ppc_md.tce_flush = dart_flush;
 
-       /* Initialize the DART HW */
-       if (dart_init(dn) == 0) {
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
-               ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+       /* Setup bypass if supported */
+       if (dart_is_u4)
+               ppc_md.dma_set_mask = dart_dma_set_mask;
 
-               /* Setup pci_dma ops */
-               set_pci_dma_ops(&dma_iommu_ops);
-               return;
-       }
+       ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
+       ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+
+       /* Setup pci_dma ops */
+       set_pci_dma_ops(&dma_iommu_ops);
+       return;
 
  bail:
        /* If init failed, use direct iommu and null setup functions */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
new file mode 100644 (file)
index 0000000..60c9c0b
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc
+ *
+ * QorIQ based Cache Controller Memory Mapped Registers
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FSL_85XX_CACHE_CTLR_H__
+#define __FSL_85XX_CACHE_CTLR_H__
+
+#define L2CR_L2FI              0x40000000      /* L2 flash invalidate */
+#define L2CR_L2IO              0x00200000      /* L2 instruction only */
+#define L2CR_SRAM_ZERO         0x00000000      /* L2SRAM zero size */
+#define L2CR_SRAM_FULL         0x00010000      /* L2SRAM full size */
+#define L2CR_SRAM_HALF         0x00020000      /* L2SRAM half size */
+#define L2CR_SRAM_TWO_HALFS    0x00030000      /* L2SRAM two half sizes */
+#define L2CR_SRAM_QUART                0x00040000      /* L2SRAM one quarter size */
+#define L2CR_SRAM_TWO_QUARTS   0x00050000      /* L2SRAM two quarter size */
+#define L2CR_SRAM_EIGHTH       0x00060000      /* L2SRAM one eighth size */
+#define L2CR_SRAM_TWO_EIGHTH   0x00070000      /* L2SRAM two eighth size */
+
+#define L2SRAM_OPTIMAL_SZ_SHIFT        0x00000003      /* Optimum size for L2SRAM */
+
+#define L2SRAM_BAR_MSK_LO18    0xFFFFC000      /* Lower 18 bits */
+#define L2SRAM_BARE_MSK_HI4    0x0000000F      /* Upper 4 bits */
+
+enum cache_sram_lock_ways {
+       LOCK_WAYS_ZERO,
+       LOCK_WAYS_EIGHTH,
+       LOCK_WAYS_TWO_EIGHTH,
+       LOCK_WAYS_HALF = 4,
+       LOCK_WAYS_FULL = 8,
+};
+
+struct mpc85xx_l2ctlr {
+       u32     ctl;            /* 0x000 - L2 control */
+       u8      res1[0xC];
+       u32     ewar0;          /* 0x010 - External write address 0 */
+       u32     ewarea0;        /* 0x014 - External write address extended 0 */
+       u32     ewcr0;          /* 0x018 - External write ctrl */
+       u8      res2[4];
+       u32     ewar1;          /* 0x020 - External write address 1 */
+       u32     ewarea1;        /* 0x024 - External write address extended 1 */
+       u32     ewcr1;          /* 0x028 - External write ctrl 1 */
+       u8      res3[4];
+       u32     ewar2;          /* 0x030 - External write address 2 */
+       u32     ewarea2;        /* 0x034 - External write address extended 2 */
+       u32     ewcr2;          /* 0x038 - External write ctrl 2 */
+       u8      res4[4];
+       u32     ewar3;          /* 0x040 - External write address 3 */
+       u32     ewarea3;        /* 0x044 - External write address extended 3 */
+       u32     ewcr3;          /* 0x048 - External write ctrl 3 */
+       u8      res5[0xB4];
+       u32     srbar0;         /* 0x100 - SRAM base address 0 */
+       u32     srbarea0;       /* 0x104 - SRAM base addr reg ext address 0 */
+       u32     srbar1;         /* 0x108 - SRAM base address 1 */
+       u32     srbarea1;       /* 0x10C - SRAM base addr reg ext address 1 */
+       u8      res6[0xCF0];
+       u32     errinjhi;       /* 0xE00 - Error injection mask high */
+       u32     errinjlo;       /* 0xE04 - Error injection mask low */
+       u32     errinjctl;      /* 0xE08 - Error injection tag/ecc control */
+       u8      res7[0x14];
+       u32     captdatahi;     /* 0xE20 - Error data high capture */
+       u32     captdatalo;     /* 0xE24 - Error data low capture */
+       u32     captecc;        /* 0xE28 - Error syndrome */
+       u8      res8[0x14];
+       u32     errdet;         /* 0xE40 - Error detect */
+       u32     errdis;         /* 0xE44 - Error disable */
+       u32     errinten;       /* 0xE48 - Error interrupt enable */
+       u32     errattr;        /* 0xE4c - Error attribute capture */
+       u32     erradrrl;       /* 0xE50 - Error address capture low */
+       u32     erradrrh;       /* 0xE54 - Error address capture high */
+       u32     errctl;         /* 0xE58 - Error control */
+       u8      res9[0x1A4];
+};
+
+struct sram_parameters {
+       unsigned int sram_size;
+       uint64_t sram_offset;
+};
+
+extern int instantiate_cache_sram(struct platform_device *dev,
+               struct sram_parameters sram_params);
+extern void remove_cache_sram(struct platform_device *dev);
+
+#endif /* __FSL_85XX_CACHE_CTLR_H__ */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
new file mode 100644 (file)
index 0000000..54fb192
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <asm/pgtable.h>
+#include <asm/fsl_85xx_cache_sram.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+struct mpc85xx_cache_sram *cache_sram;
+
+void *mpc85xx_cache_sram_alloc(unsigned int size,
+                               phys_addr_t *phys, unsigned int align)
+{
+       unsigned long offset;
+       unsigned long flags;
+
+       if (unlikely(cache_sram == NULL))
+               return NULL;
+
+       if (!size || (size > cache_sram->size) || (align > cache_sram->size)) {
+               pr_err("%s(): size(=%x) or align(=%x) zero or too big\n",
+                       __func__, size, align);
+               return NULL;
+       }
+
+       if ((align & (align - 1)) || align <= 1) {
+               pr_err("%s(): align(=%x) must be power of two and >1\n",
+                       __func__, align);
+               return NULL;
+       }
+
+       spin_lock_irqsave(&cache_sram->lock, flags);
+       offset = rh_alloc_align(cache_sram->rh, size, align, NULL);
+       spin_unlock_irqrestore(&cache_sram->lock, flags);
+
+       if (IS_ERR_VALUE(offset))
+               return NULL;
+
+       *phys = cache_sram->base_phys + offset;
+
+       return (unsigned char *)cache_sram->base_virt + offset;
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_alloc);
+
+void mpc85xx_cache_sram_free(void *ptr)
+{
+       unsigned long flags;
+       BUG_ON(!ptr);
+
+       spin_lock_irqsave(&cache_sram->lock, flags);
+       rh_free(cache_sram->rh, ptr - cache_sram->base_virt);
+       spin_unlock_irqrestore(&cache_sram->lock, flags);
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_free);
+
+int __init instantiate_cache_sram(struct platform_device *dev,
+               struct sram_parameters sram_params)
+{
+       int ret = 0;
+
+       if (cache_sram) {
+               dev_err(&dev->dev, "Already initialized cache-sram\n");
+               return -EBUSY;
+       }
+
+       cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL);
+       if (!cache_sram) {
+               dev_err(&dev->dev, "Out of memory for cache_sram structure\n");
+               return -ENOMEM;
+       }
+
+       cache_sram->base_phys = sram_params.sram_offset;
+       cache_sram->size = sram_params.sram_size;
+
+       if (!request_mem_region(cache_sram->base_phys, cache_sram->size,
+                                               "fsl_85xx_cache_sram")) {
+               dev_err(&dev->dev, "%s: request memory failed\n",
+                               dev->dev.of_node->full_name);
+               ret = -ENXIO;
+               goto out_free;
+       }
+
+       cache_sram->base_virt = ioremap_flags(cache_sram->base_phys,
+                               cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL);
+       if (!cache_sram->base_virt) {
+               dev_err(&dev->dev, "%s: ioremap_flags failed\n",
+                               dev->dev.of_node->full_name);
+               ret = -ENOMEM;
+               goto out_release;
+       }
+
+       cache_sram->rh = rh_create(sizeof(unsigned int));
+       if (IS_ERR(cache_sram->rh)) {
+               dev_err(&dev->dev, "%s: Unable to create remote heap\n",
+                               dev->dev.of_node->full_name);
+               ret = PTR_ERR(cache_sram->rh);
+               goto out_unmap;
+       }
+
+       rh_attach_region(cache_sram->rh, 0, cache_sram->size);
+       spin_lock_init(&cache_sram->lock);
+
+       dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n",
+               (unsigned long long)cache_sram->base_phys, cache_sram->size);
+
+       return 0;
+
+out_unmap:
+       iounmap(cache_sram->base_virt);
+
+out_release:
+       release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+out_free:
+       kfree(cache_sram);
+       return ret;
+}
+
+void remove_cache_sram(struct platform_device *dev)
+{
+       BUG_ON(!cache_sram);
+
+       rh_detach_region(cache_sram->rh, 0, cache_sram->size);
+       rh_destroy(cache_sram->rh);
+
+       iounmap(cache_sram->base_virt);
+       release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+       kfree(cache_sram);
+       cache_sram = NULL;
+
+       dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n");
+}
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
new file mode 100644 (file)
index 0000000..cc8d655
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+static char *sram_size;
+static char *sram_offset;
+struct mpc85xx_l2ctlr __iomem *l2ctlr;
+
+static long get_cache_sram_size(void)
+{
+       unsigned long val;
+
+       if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0))
+               return -EINVAL;
+
+       return val;
+}
+
+static long get_cache_sram_offset(void)
+{
+       unsigned long val;
+
+       if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0))
+               return -EINVAL;
+
+       return val;
+}
+
+static int __init get_size_from_cmdline(char *str)
+{
+       if (!str)
+               return 0;
+
+       sram_size = str;
+       return 1;
+}
+
+static int __init get_offset_from_cmdline(char *str)
+{
+       if (!str)
+               return 0;
+
+       sram_offset = str;
+       return 1;
+}
+
+__setup("cache-sram-size=", get_size_from_cmdline);
+__setup("cache-sram-offset=", get_offset_from_cmdline);
+
+static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
+                                         const struct of_device_id *match)
+{
+       long rval;
+       unsigned int rem;
+       unsigned char ways;
+       const unsigned int *prop;
+       unsigned int l2cache_size;
+       struct sram_parameters sram_params;
+
+       if (!dev->dev.of_node) {
+               dev_err(&dev->dev, "Device's OF-node is NULL\n");
+               return -EINVAL;
+       }
+
+       prop = of_get_property(dev->dev.of_node, "cache-size", NULL);
+       if (!prop) {
+               dev_err(&dev->dev, "Missing L2 cache-size\n");
+               return -EINVAL;
+       }
+       l2cache_size = *prop;
+
+       sram_params.sram_size  = get_cache_sram_size();
+       if (sram_params.sram_size <= 0) {
+               dev_err(&dev->dev,
+                       "Entire L2 as cache, Aborting Cache-SRAM stuff\n");
+               return -EINVAL;
+       }
+
+       sram_params.sram_offset  = get_cache_sram_offset();
+       if (sram_params.sram_offset <= 0) {
+               dev_err(&dev->dev,
+                       "Entire L2 as cache, provide a valid sram offset\n");
+               return -EINVAL;
+       }
+
+
+       rem = l2cache_size % sram_params.sram_size;
+       ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size;
+       if (rem || (ways & (ways - 1))) {
+               dev_err(&dev->dev, "Illegal cache-sram-size in command line\n");
+               return -EINVAL;
+       }
+
+       l2ctlr = of_iomap(dev->dev.of_node, 0);
+       if (!l2ctlr) {
+               dev_err(&dev->dev, "Can't map L2 controller\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Write bits[0-17] to srbar0
+        */
+       out_be32(&l2ctlr->srbar0,
+               sram_params.sram_offset & L2SRAM_BAR_MSK_LO18);
+
+       /*
+        * Write bits[18-21] to srbare0
+        */
+#ifdef CONFIG_PHYS_64BIT
+       out_be32(&l2ctlr->srbarea0,
+               (sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4);
+#endif
+
+       clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI);
+
+       switch (ways) {
+       case LOCK_WAYS_EIGHTH:
+               setbits32(&l2ctlr->ctl,
+                       L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH);
+               break;
+
+       case LOCK_WAYS_TWO_EIGHTH:
+               setbits32(&l2ctlr->ctl,
+                       L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART);
+               break;
+
+       case LOCK_WAYS_HALF:
+               setbits32(&l2ctlr->ctl,
+                       L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF);
+               break;
+
+       case LOCK_WAYS_FULL:
+       default:
+               setbits32(&l2ctlr->ctl,
+                       L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL);
+               break;
+       }
+       eieio();
+
+       rval = instantiate_cache_sram(dev, sram_params);
+       if (rval < 0) {
+               dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n");
+               iounmap(l2ctlr);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
+{
+       BUG_ON(!l2ctlr);
+
+       iounmap(l2ctlr);
+       remove_cache_sram(dev);
+       dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n");
+
+       return 0;
+}
+
+static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
+       {
+               .compatible = "fsl,p2020-l2-cache-controller",
+       },
+       {
+               .compatible = "fsl,p2010-l2-cache-controller",
+       },
+       {
+               .compatible = "fsl,p1020-l2-cache-controller",
+       },
+       {
+               .compatible = "fsl,p1011-l2-cache-controller",
+       },
+       {
+               .compatible = "fsl,p1013-l2-cache-controller",
+       },
+       {
+               .compatible = "fsl,p1022-l2-cache-controller",
+       },
+       {},
+};
+
+static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+       .driver = {
+               .name           = "fsl-l2ctlr",
+               .owner          = THIS_MODULE,
+               .of_match_table = mpc85xx_l2ctlr_of_match,
+       },
+       .probe          = mpc85xx_l2ctlr_of_probe,
+       .remove         = __devexit_p(mpc85xx_l2ctlr_of_remove),
+};
+
+static __init int mpc85xx_l2ctlr_of_init(void)
+{
+       return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+static void __exit mpc85xx_l2ctlr_of_exit(void)
+{
+       of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+subsys_initcall(mpc85xx_l2ctlr_of_init);
+module_exit(mpc85xx_l2ctlr_of_exit);
+
+MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init");
+MODULE_LICENSE("GPL v2");
index 87991d3abbab1c2e90268386be666764112cab38..108d76fa8f1c997f566a1a3448402ce9e55d3bae 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/ppc-pci.h>
 #include <asm/mpic.h>
 #include "fsl_msi.h"
+#include "fsl_pci.h"
 
 LIST_HEAD(msi_head);
 
@@ -51,8 +52,8 @@ static void fsl_msi_end_irq(unsigned int virq)
 }
 
 static struct irq_chip fsl_msi_chip = {
-       .mask           = mask_msi_irq,
-       .unmask         = unmask_msi_irq,
+       .irq_mask       = mask_msi_irq,
+       .irq_unmask     = unmask_msi_irq,
        .ack            = fsl_msi_end_irq,
        .name           = "FSL-MSI",
 };
@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
 {
        struct fsl_msi *msi_data = fsl_msi_data;
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-       u32 base = 0;
+       u64 base = fsl_pci_immrbar_base(hose);
 
-       pci_bus_read_config_dword(hose->bus,
-               PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+       msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
+       msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
 
-       msg->address_lo = msi_data->msi_addr_lo + base;
-       msg->address_hi = msi_data->msi_addr_hi;
        msg->data = hwirq;
 
        pr_debug("%s: allocated srs: %d, ibs: %d\n",
index 209384b6e0396e232be5c0a53ed0519d3b5e6a3b..818f7c6c8fa1f907adda6d911f323b808fadbb4d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
  * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -34,7 +34,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
-static int fsl_pcie_bus_fixup;
+static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
 static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
 {
@@ -399,16 +399,26 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
@@ -428,6 +438,13 @@ struct mpc83xx_pcie_priv {
        u32 dev_base;
 };
 
+struct pex_inbound_window {
+       u32 ar;
+       u32 tar;
+       u32 barl;
+       u32 barh;
+};
+
 /*
  * With the convention of u-boot, the PCIE outbound window 0 serves
  * as configuration transactions outbound.
@@ -435,6 +452,8 @@ struct mpc83xx_pcie_priv {
 #define PEX_OUTWIN0_BAR                0xCA4
 #define PEX_OUTWIN0_TAL                0xCA8
 #define PEX_OUTWIN0_TAH                0xCAC
+#define PEX_RC_INWIN_BASE      0xE60
+#define PEX_RCIWARn_EN         0x1
 
 static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
 {
@@ -602,6 +621,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
        const int *bus_range;
        int primary;
 
+       is_mpc83xx_pci = 1;
+
        if (!of_device_is_available(dev)) {
                pr_warning("%s: disabled by the firmware.\n",
                           dev->full_name);
@@ -681,3 +702,40 @@ err0:
        return ret;
 }
 #endif /* CONFIG_PPC_83xx */
+
+u64 fsl_pci_immrbar_base(struct pci_controller *hose)
+{
+#ifdef CONFIG_PPC_83xx
+       if (is_mpc83xx_pci) {
+               struct mpc83xx_pcie_priv *pcie = hose->dn->data;
+               struct pex_inbound_window *in;
+               int i;
+
+               /* Walk the Root Complex Inbound windows to match IMMR base */
+               in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
+               for (i = 0; i < 4; i++) {
+                       /* not enabled, skip */
+                       if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
+                                continue;
+
+                       if (get_immrbase() == in_le32(&in[i].tar))
+                               return (u64)in_le32(&in[i].barh) << 32 |
+                                           in_le32(&in[i].barl);
+               }
+
+               printk(KERN_WARNING "could not find PCI BAR matching IMMR\n");
+       }
+#endif
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+       if (!is_mpc83xx_pci) {
+               u32 base;
+
+               pci_bus_read_config_dword(hose->bus,
+                       PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+               return base;
+       }
+#endif
+
+       return 0;
+}
index a9d8bbebed80b231511bf862d594c769798a16d3..8ad72a11f77bec20ee473602b503423f77370d55 100644 (file)
@@ -88,6 +88,7 @@ struct ccsr_pci {
 extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
+u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
index 6425abe5b7dbfe809cd41d8a06634a56367d9d1d..412763672d23faa754e26d5b655cccd21046f4ad 100644 (file)
@@ -117,44 +117,59 @@ struct rio_atmu_regs {
 };
 
 struct rio_msg_regs {
-       u32 omr;
-       u32 osr;
+       u32 omr;        /* 0xD_3000 - Outbound message 0 mode register */
+       u32 osr;        /* 0xD_3004 - Outbound message 0 status register */
        u32 pad1;
-       u32 odqdpar;
+       u32 odqdpar;    /* 0xD_300C - Outbound message 0 descriptor queue
+                          dequeue pointer address register */
        u32 pad2;
-       u32 osar;
-       u32 odpr;
-       u32 odatr;
-       u32 odcr;
+       u32 osar;       /* 0xD_3014 - Outbound message 0 source address
+                          register */
+       u32 odpr;       /* 0xD_3018 - Outbound message 0 destination port
+                          register */
+       u32 odatr;      /* 0xD_301C - Outbound message 0 destination attributes
+                          Register*/
+       u32 odcr;       /* 0xD_3020 - Outbound message 0 double-word count
+                          register */
        u32 pad3;
-       u32 odqepar;
+       u32 odqepar;    /* 0xD_3028 - Outbound message 0 descriptor queue
+                          enqueue pointer address register */
        u32 pad4[13];
-       u32 imr;
-       u32 isr;
+       u32 imr;        /* 0xD_3060 - Inbound message 0 mode register */
+       u32 isr;        /* 0xD_3064 - Inbound message 0 status register */
        u32 pad5;
-       u32 ifqdpar;
+       u32 ifqdpar;    /* 0xD_306C - Inbound message 0 frame queue dequeue
+                          pointer address register*/
        u32 pad6;
-       u32 ifqepar;
+       u32 ifqepar;    /* 0xD_3074 - Inbound message 0 frame queue enqueue
+                          pointer address register */
        u32 pad7[226];
-       u32 odmr;
-       u32 odsr;
+       u32 odmr;       /* 0xD_3400 - Outbound doorbell mode register */
+       u32 odsr;       /* 0xD_3404 - Outbound doorbell status register */
        u32 res0[4];
-       u32 oddpr;
-       u32 oddatr;
+       u32 oddpr;      /* 0xD_3418 - Outbound doorbell destination port
+                          register */
+       u32 oddatr;     /* 0xD_341c - Outbound doorbell destination attributes
+                          register */
        u32 res1[3];
-       u32 odretcr;
+       u32 odretcr;    /* 0xD_342C - Outbound doorbell retry error threshold
+                          configuration register */
        u32 res2[12];
-       u32 dmr;
-       u32 dsr;
+       u32 dmr;        /* 0xD_3460 - Inbound doorbell mode register */
+       u32 dsr;        /* 0xD_3464 - Inbound doorbell status register */
        u32 pad8;
-       u32 dqdpar;
+       u32 dqdpar;     /* 0xD_346C - Inbound doorbell queue dequeue Pointer
+                          address register */
        u32 pad9;
-       u32 dqepar;
+       u32 dqepar;     /* 0xD_3474 - Inbound doorbell Queue enqueue pointer
+                          address register */
        u32 pad10[26];
-       u32 pwmr;
-       u32 pwsr;
-       u32 epwqbar;
-       u32 pwqbar;
+       u32 pwmr;       /* 0xD_34E0 - Inbound port-write mode register */
+       u32 pwsr;       /* 0xD_34E4 - Inbound port-write status register */
+       u32 epwqbar;    /* 0xD_34E8 - Extended Port-Write Queue Base Address
+                          register */
+       u32 pwqbar;     /* 0xD_34EC - Inbound port-write queue base address
+                          register */
 };
 
 struct rio_tx_desc {
@@ -240,12 +255,13 @@ struct rio_priv {
 
 static void __iomem *rio_regs_win;
 
+#ifdef CONFIG_E500
 static int (*saved_mcheck_exception)(struct pt_regs *regs);
 
 static int fsl_rio_mcheck_exception(struct pt_regs *regs)
 {
        const struct exception_table_entry *entry = NULL;
-       unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK);
+       unsigned long reason = mfspr(SPRN_MCSR);
 
        if (reason & MCSR_BUS_RBERR) {
                reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
@@ -269,6 +285,7 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
        else
                return cur_cpu_spec->machine_check(regs);
 }
+#endif
 
 /**
  * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
@@ -1517,8 +1534,10 @@ int fsl_rio_setup(struct platform_device *dev)
        fsl_rio_doorbell_init(port);
        fsl_rio_port_write_init(port);
 
+#ifdef CONFIG_E500
        saved_mcheck_exception = ppc_md.machine_check_exception;
        ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
+#endif
        /* Ensure that RFXE is set */
        mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
 
index b91f7acdda6f72aa09d49669258d18e2d9527a73..6c67d9ebf1669e80886614e1e3d3b78528716e62 100644 (file)
@@ -378,17 +378,23 @@ static __be32 __iomem *rstcr;
 static int __init setup_rstcr(void)
 {
        struct device_node *np;
-       np = of_find_node_by_name(NULL, "global-utilities");
-       if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
-               rstcr = of_iomap(np, 0) + 0xb0;
-               if (!rstcr)
-                       printk (KERN_EMERG "Error: reset control register "
-                                       "not mapped!\n");
-       } else if (ppc_md.restart == fsl_rstcr_restart)
+
+       for_each_node_by_name(np, "global-utilities") {
+               if ((of_get_property(np, "fsl,has-rstcr", NULL))) {
+                       rstcr = of_iomap(np, 0) + 0xb0;
+                       if (!rstcr)
+                               printk (KERN_ERR "Error: reset control "
+                                               "register not mapped!\n");
+                       break;
+               }
+       }
+
+       if (!rstcr && ppc_md.restart == fsl_rstcr_restart)
                printk(KERN_ERR "No RSTCR register, warm reboot won't work\n");
 
        if (np)
                of_node_put(np);
+
        return 0;
 }
 
index 2b69084d0f0cb7f9cc0acdb4a0d4d1c024bb1a69..c0ea05e87f1db143dfe4439c69eb14f08fed03d0 100644 (file)
@@ -330,6 +330,9 @@ static int __init mpc8xxx_add_gpiochips(void)
        for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
                mpc8xxx_add_controller(np);
 
+       for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
+               mpc8xxx_add_controller(np);
+
        return 0;
 }
 arch_initcall(mpc8xxx_add_gpiochips);
index 3b6a9a43718fb46ba240f52fa581c256075129cc..320ad5a9a25d3b649dddbc3f8a787dc6759dbb26 100644 (file)
 static struct mpic *msi_mpic;
 
 
-static void mpic_pasemi_msi_mask_irq(unsigned int irq)
+static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
 {
-       pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq);
-       mask_msi_irq(irq);
-       mpic_mask_irq(irq);
+       pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
+       mask_msi_irq(data);
+       mpic_mask_irq(data->irq);
 }
 
-static void mpic_pasemi_msi_unmask_irq(unsigned int irq)
+static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
 {
-       pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq);
-       mpic_unmask_irq(irq);
-       unmask_msi_irq(irq);
+       pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
+       mpic_unmask_irq(data->irq);
+       unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_pasemi_msi_chip = {
-       .shutdown       = mpic_pasemi_msi_mask_irq,
-       .mask           = mpic_pasemi_msi_mask_irq,
-       .unmask         = mpic_pasemi_msi_unmask_irq,
+       .irq_shutdown   = mpic_pasemi_msi_mask_irq,
+       .irq_mask       = mpic_pasemi_msi_mask_irq,
+       .irq_unmask     = mpic_pasemi_msi_unmask_irq,
        .eoi            = mpic_end_irq,
        .set_type       = mpic_set_irq_type,
        .set_affinity   = mpic_set_affinity,
index bcbfe79c704bb42f6e8bcebe893eadf6aaf341da..a2b028b4a2020db8c609c80d8b2444107502bce8 100644 (file)
 /* A bit ugly, can we get this from the pci_dev somehow? */
 static struct mpic *msi_mpic;
 
-static void mpic_u3msi_mask_irq(unsigned int irq)
+static void mpic_u3msi_mask_irq(struct irq_data *data)
 {
-       mask_msi_irq(irq);
-       mpic_mask_irq(irq);
+       mask_msi_irq(data);
+       mpic_mask_irq(data->irq);
 }
 
-static void mpic_u3msi_unmask_irq(unsigned int irq)
+static void mpic_u3msi_unmask_irq(struct irq_data *data)
 {
-       mpic_unmask_irq(irq);
-       unmask_msi_irq(irq);
+       mpic_unmask_irq(data->irq);
+       unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_u3msi_chip = {
-       .shutdown       = mpic_u3msi_mask_irq,
-       .mask           = mpic_u3msi_mask_irq,
-       .unmask         = mpic_u3msi_unmask_irq,
+       .irq_shutdown   = mpic_u3msi_mask_irq,
+       .irq_mask       = mpic_u3msi_mask_irq,
+       .irq_unmask     = mpic_u3msi_unmask_irq,
        .eoi            = mpic_end_irq,
        .set_type       = mpic_set_irq_type,
        .set_affinity   = mpic_set_affinity,
index 24a0bb955b184bba92c6d0d9efda52ac568bee74..4260f368db5233391769204de3da3f67db1cf07c 100644 (file)
@@ -114,7 +114,7 @@ static void pmi_notify_handlers(struct work_struct *work)
 
        spin_lock(&data->handler_spinlock);
        list_for_each_entry(handler, &data->handler, node) {
-               pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+               pr_debug("pmi: notifying handler %p\n", handler);
                if (handler->type == data->msg.type)
                        handler->handle_pmi_message(data->msg);
        }
index 3da8014931c9c7a99afcebf52814b50d03d02f35..90020de4dcf2c7570e371569997506e5642c8c5f 100644 (file)
@@ -640,6 +640,7 @@ unsigned int qe_get_num_of_snums(void)
                if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
                        /* No QE ever has fewer than 28 SNUMs */
                        pr_err("QE: number of snum is invalid\n");
+                       of_node_put(qe);
                        return -EINVAL;
                }
        }
index faa81b6a66126531c87f94897f33d2affc7c43f3..c168c54e3c40caed0ead0ad449ebe00ad0232fd0 100644 (file)
@@ -4,9 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 GCOV_PROFILE := n
 
-ifdef CONFIG_PPC64
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
 
 obj-y                  += xmon.o start.o nonstdio.o
 
index 0554445200bfd1417a1fe6076b0d258b74e69a02..d17d04cfb2cd4095c77adb306fcb690161c09fbf 100644 (file)
@@ -2880,15 +2880,14 @@ static void xmon_init(int enable)
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
-static void sysrq_handle_xmon(int key, struct tty_struct *tty) 
+static void sysrq_handle_xmon(int key)
 {
        /* ensure xmon is enabled */
        xmon_init(1);
        debugger(get_irq_regs());
 }
 
-static struct sysrq_key_op sysrq_xmon_op = 
-{
+static struct sysrq_key_op sysrq_xmon_op = {
        .handler =      sysrq_handle_xmon,
        .help_msg =     "Xmon",
        .action_msg =   "Entering xmon",
index f0777a47e3a531c17156a76694648aaf89cacd44..75976a14194770390154ca124d9e94f95eedecf4 100644 (file)
@@ -95,6 +95,7 @@ config S390
        select HAVE_KVM if 64BIT
        select HAVE_ARCH_TRACEHOOK
        select INIT_ALL_POSSIBLE
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
@@ -198,6 +199,13 @@ config HOTPLUG_CPU
          can be controlled through /sys/devices/system/cpu/cpu#.
          Say N if you want to disable CPU hotplug.
 
+config SCHED_BOOK
+       bool "Book scheduler support"
+       depends on SMP
+       help
+         Book scheduler support improves the CPU scheduler's decision making
+         when dealing with machines that have several books.
+
 config MATHEMU
        bool "IEEE FPU emulation"
        depends on MARCH_G5
index aa819dac2360e946bf4712fc4f56c129a3113355..975e3ab13cb5477b29ac4ffd504d34e6cacd4325 100644 (file)
@@ -152,6 +152,7 @@ static const struct file_operations prng_fops = {
        .open           = &prng_open,
        .release        = NULL,
        .read           = &prng_read,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice prng_dev = {
index 1211bb1d2f24c810d11b79ef8d755ff3e8b0e04d..020e51c063d2d4d52c7c2f5a39690197a22979d7 100644 (file)
@@ -618,6 +618,7 @@ static const struct file_operations dbfs_d204_ops = {
        .open           = dbfs_d204_open,
        .read           = dbfs_d204_read,
        .release        = dbfs_d204_release,
+       .llseek         = no_llseek,
 };
 
 static int hypfs_dbfs_init(void)
index ee5ab1a578e75dcf5fb56f30e710ce89a31b0b89..26cf177f6a3a09d90f610d49eaef13175ae5ba8e 100644 (file)
@@ -275,6 +275,7 @@ static const struct file_operations dbfs_d2fc_ops = {
        .open           = dbfs_d2fc_open,
        .read           = dbfs_d2fc_read,
        .release        = dbfs_d2fc_release,
+       .llseek         = no_llseek,
 };
 
 int hypfs_vm_init(void)
index 98a4a4c267a7818765ab88bcbd0c01f11b512a15..74d98670be27023241aff6ba8a2b02c35a052e0b 100644 (file)
@@ -449,6 +449,7 @@ static const struct file_operations hypfs_file_ops = {
        .write          = do_sync_write,
        .aio_read       = hypfs_aio_read,
        .aio_write      = hypfs_aio_write,
+       .llseek         = no_llseek,
 };
 
 static struct file_system_type hypfs_type = {
index 104f2007f097720b339e469d37b7732c120c8168..a875c2f542e1070a120b484c96a0d2fc10fc55cb 100644 (file)
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
 
 #endif
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        unsigned long stack;
 
index 498bc38923856ddb1957ddd0ac934b7c7e510003..881d94590aeb4c84efb8e5c58fae68b73b70f6e5 100644 (file)
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/cache.h>
-#include <linux/interrupt.h>
 #include <asm/lowcore.h>
 
 #define local_softirq_pending() (S390_lowcore.softirq_pending)
index 670a1d1745d271e6e89a8246e6432c0c281b3d94..bb8343d157bc18b6117d02aa4ef164039b06f108 100644 (file)
@@ -97,6 +97,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 {
        pte_t pte = huge_ptep_get(ptep);
 
+       mm->context.flush_mm = 1;
        pmd_clear((pmd_t *) ptep);
        return pte;
 }
@@ -167,7 +168,8 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
 ({                                                                     \
        pte_t __pte = huge_ptep_get(__ptep);                            \
        if (pte_write(__pte)) {                                         \
-               if (atomic_read(&(__mm)->mm_users) > 1 ||               \
+               (__mm)->context.flush_mm = 1;                           \
+               if (atomic_read(&(__mm)->context.attach_count) > 1 ||   \
                    (__mm) != current->active_mm)                       \
                        huge_ptep_invalidate(__mm, __addr, __ptep);     \
                set_huge_pte_at(__mm, __addr, __ptep,                   \
index 15b3ac253898d8029e886c192f5d887bf1b3948f..865d6d891ace56f0b45d7d50aeca02f7daf46a23 100644 (file)
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 
-/* store then or system mask. */
-#define __raw_local_irq_stosm(__or)                                    \
+/* store then OR system mask. */
+#define __arch_local_irq_stosm(__or)                                   \
 ({                                                                     \
        unsigned long __mask;                                           \
        asm volatile(                                                   \
@@ -18,8 +18,8 @@
        __mask;                                                         \
 })
 
-/* store then and system mask. */
-#define __raw_local_irq_stnsm(__and)                                   \
+/* store then AND system mask. */
+#define __arch_local_irq_stnsm(__and)                                  \
 ({                                                                     \
        unsigned long __mask;                                           \
        asm volatile(                                                   \
 })
 
 /* set system mask. */
-#define __raw_local_irq_ssm(__mask)                                    \
-({                                                                     \
-       asm volatile("ssm   %0" : : "Q" (__mask) : "memory");           \
-})
+static inline void __arch_local_irq_ssm(unsigned long flags)
+{
+       asm volatile("ssm   %0" : : "Q" (flags) : "memory");
+}
 
-/* interrupt control.. */
-static inline unsigned long raw_local_irq_enable(void)
+static inline unsigned long arch_local_save_flags(void)
 {
-       return __raw_local_irq_stosm(0x03);
+       return __arch_local_irq_stosm(0x00);
 }
 
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_save(void)
 {
-       return __raw_local_irq_stnsm(0xfc);
+       return __arch_local_irq_stnsm(0xfc);
 }
 
-#define raw_local_save_flags(x)                                                \
-do {                                                                   \
-       typecheck(unsigned long, x);                                    \
-       (x) = __raw_local_irq_stosm(0x00);                              \
-} while (0)
+static inline void arch_local_irq_disable(void)
+{
+       arch_local_irq_save();
+}
 
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_enable(void)
 {
-       __raw_local_irq_ssm(flags);
+       __arch_local_irq_stosm(0x03);
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       __arch_local_irq_ssm(flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
-/* For spinlocks etc */
-#define raw_local_irq_save(x)  ((x) = raw_local_irq_disable())
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #endif /* __ASM_IRQFLAGS_H */
index 99e3409102b9d955960ad9c75e1dba563358b21a..78522cdefdd42334c7b4f72be1180a6a2ed2f327 100644 (file)
@@ -2,6 +2,8 @@
 #define __MMU_H
 
 typedef struct {
+       atomic_t attach_count;
+       unsigned int flush_mm;
        spinlock_t list_lock;
        struct list_head crst_list;
        struct list_head pgtable_list;
index 976e273988c2ab2147722d46e76372f00e7ece10..a6f0e7cc9cde2f341fba3fef347ea93240bb9372 100644 (file)
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
+#include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
 
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
+       atomic_set(&mm->context.attach_count, 0);
+       mm->context.flush_mm = 0;
        mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
 #ifdef CONFIG_64BIT
        mm->context.asce_bits |= _ASCE_TYPE_REGION3;
@@ -76,6 +79,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
        update_mm(next, tsk);
+       atomic_dec(&prev->context.attach_count);
+       WARN_ON(atomic_read(&prev->context.attach_count) < 0);
+       atomic_inc(&next->context.attach_count);
+       /* Check for TLBs not flushed yet */
+       if (next->context.flush_mm)
+               __tlb_flush_mm(next);
 }
 
 #define enter_lazy_tlb(mm,tsk) do { } while (0)
index 3840cbe77637fe1ffef8c5baceb2c82c8ed7759d..a75f168d2718578544914c8a00eb0e1245ef9c8f 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright 2009 Martin Schwidefsky, IBM Corporation.
  */
 
-static inline void set_perf_event_pending(void) {}
-static inline void clear_perf_event_pending(void) {}
+/* Empty, just to avoid compiling error */
 
 #define PERF_EVENT_INDEX_OFFSET 0
index 89a504c3f12ec13f89fdcb34ab2b3602ce0c75a0..3157441ee1da287345a1f1a6bfe79769939bd7d7 100644 (file)
@@ -880,7 +880,8 @@ static inline void ptep_invalidate(struct mm_struct *mm,
 #define ptep_get_and_clear(__mm, __address, __ptep)                    \
 ({                                                                     \
        pte_t __pte = *(__ptep);                                        \
-       if (atomic_read(&(__mm)->mm_users) > 1 ||                       \
+       (__mm)->context.flush_mm = 1;                                   \
+       if (atomic_read(&(__mm)->context.attach_count) > 1 ||           \
            (__mm) != current->active_mm)                               \
                ptep_invalidate(__mm, __address, __ptep);               \
        else                                                            \
@@ -923,7 +924,8 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
 ({                                                                     \
        pte_t __pte = *(__ptep);                                        \
        if (pte_write(__pte)) {                                         \
-               if (atomic_read(&(__mm)->mm_users) > 1 ||               \
+               (__mm)->context.flush_mm = 1;                           \
+               if (atomic_read(&(__mm)->context.attach_count) > 1 ||   \
                    (__mm) != current->active_mm)                       \
                        ptep_invalidate(__mm, __addr, __ptep);          \
                set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
index cef66210c8466d68e13eaccce453582060c18a4f..1f2ebc4afd828f47da56d6763be4a16ba713263c 100644 (file)
@@ -97,7 +97,6 @@ static inline void restore_access_regs(unsigned int *acrs)
 
 extern void account_vtime(struct task_struct *, struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
-extern void account_system_vtime(struct task_struct *);
 
 #ifdef CONFIG_PFAULT
 extern void pfault_irq_init(void);
@@ -399,7 +398,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 static inline void
 __set_psw_mask(unsigned long mask)
 {
-       __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
+       __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
 }
 
 #define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
index 81150b0536890b7d664052a33f22d397bb05b852..fd1c00d08bf57ca1ead5095746ba082847f52752 100644 (file)
@@ -50,8 +50,7 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
        struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
 
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) ||
-               (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm);
+       tlb->fullmm = full_mm_flush;
        tlb->nr_ptes = 0;
        tlb->nr_pxds = TLB_NR_PTRS;
        if (tlb->fullmm)
index 304cffa623e158041e128c738999abbed1d3aa5b..29d5d6d4becc7e12a4a5a0b9801a0de554c44b68 100644 (file)
@@ -94,8 +94,12 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
 
 static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
 {
-       if (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm)
+       spin_lock(&mm->page_table_lock);
+       if (mm->context.flush_mm) {
                __tlb_flush_mm(mm);
+               mm->context.flush_mm = 0;
+       }
+       spin_unlock(&mm->page_table_lock);
 }
 
 /*
index 831bd033ea77b3f2c72c408f40621a82d22ac017..051107a2c5e249397f71163544ae105dbde6d302 100644 (file)
@@ -3,15 +3,32 @@
 
 #include <linux/cpumask.h>
 
-#define mc_capable()   (1)
-
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
-
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
+static inline const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+       return &cpu_core_map[cpu];
+}
+
 #define topology_core_id(cpu)          (cpu_core_id[cpu])
 #define topology_core_cpumask(cpu)     (&cpu_core_map[cpu])
+#define mc_capable()                   (1)
+
+#ifdef CONFIG_SCHED_BOOK
+
+extern unsigned char cpu_book_id[NR_CPUS];
+extern cpumask_t cpu_book_map[NR_CPUS];
+
+static inline const struct cpumask *cpu_book_mask(unsigned int cpu)
+{
+       return &cpu_book_map[cpu];
+}
+
+#define topology_book_id(cpu)          (cpu_book_id[cpu])
+#define topology_book_cpumask(cpu)     (&cpu_book_map[cpu])
+
+#endif /* CONFIG_SCHED_BOOK */
 
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
@@ -30,6 +47,8 @@ static inline void s390_init_cpu_topology(void)
 };
 #endif
 
+#define SD_BOOK_INIT   SD_CPU_INIT
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_S390_TOPOLOGY_H */
index 98192261491de90d5951dc95530ba0a666bc02fe..5ad6bc078bfdef7577a69ea958d3c33323707ffa 100644 (file)
@@ -174,6 +174,7 @@ static const struct file_operations debug_file_ops = {
        .write   = debug_input,
        .open    = debug_open,
        .release = debug_close,
+       .llseek  = no_llseek,
 };
 
 static struct dentry *debug_debugfs_root_entry;
index 403fb430a896104b0c5f7982a9dd76ecf80d5e95..ff579b6bde066e35b306669039773733d61509ef 100644 (file)
@@ -42,8 +42,8 @@ long sys_clone(unsigned long newsp, unsigned long clone_flags,
               int __user *parent_tidptr, int __user *child_tidptr);
 long sys_vfork(void);
 void execve_tail(void);
-long sys_execve(const char __user *name, char __user * __user *argv,
-               char __user * __user *envp);
+long sys_execve(const char __user *name, const char __user *const __user *argv,
+               const char __user *const __user *envp);
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
                   struct old_sigaction __user *oact);
index 559af0d07878867cb0e382226c33852af5e17e62..0fbe4e32f7ba298c83b22dfe831b66545fba8ace 100644 (file)
@@ -54,11 +54,11 @@ void detect_memory_layout(struct mem_chunk chunk[])
         * right thing and we don't get scheduled away with low address
         * protection disabled.
         */
-       flags = __raw_local_irq_stnsm(0xf8);
+       flags = __arch_local_irq_stnsm(0xf8);
        __ctl_store(cr0, 0, 0);
        __ctl_clear_bit(0, 28);
        find_memory_chunks(chunk);
        __ctl_load(cr0, 0, 0);
-       __raw_local_irq_ssm(flags);
+       arch_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(detect_memory_layout);
index 22cfd634c35531b7f8a1d4057f92b4af72e20d1a..f7167ee4604cf7033e30eb3845aa8f9ba9fd538b 100644 (file)
@@ -407,10 +407,9 @@ int module_finalize(const Elf_Ehdr *hdr,
 {
        vfree(me->arch.syminfo);
        me->arch.syminfo = NULL;
-       return module_bug_finalize(hdr, sechdrs, me);
+       return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-       module_bug_cleanup(mod);
 }
index 541053ed234ea1c0cd8a893de5bf16c9c30d9022..8127ebd59c4d81f4e8368e7728ad49bf3a173900 100644 (file)
@@ -583,6 +583,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
        sf->gprs[9] = (unsigned long) sf;
        cpu_lowcore->save_area[15] = (unsigned long) sf;
        __ctl_store(cpu_lowcore->cregs_save_area, 0, 15);
+       atomic_inc(&init_mm.context.attach_count);
        asm volatile(
                "       stam    0,15,0(%0)"
                : : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
@@ -659,6 +660,7 @@ void __cpu_die(unsigned int cpu)
        while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy)
                udelay(10);
        smp_free_lowcore(cpu);
+       atomic_dec(&init_mm.context.attach_count);
        pr_info("Processor %d stopped\n", cpu);
 }
 
index bcef00766a646dec0a5158bdf10c0574d8177293..13559c9938470b9d7d0c2597f6418e518d865c78 100644 (file)
@@ -57,8 +57,8 @@ struct tl_info {
        union tl_entry tle[0];
 };
 
-struct core_info {
-       struct core_info *next;
+struct mask_info {
+       struct mask_info *next;
        unsigned char id;
        cpumask_t mask;
 };
@@ -66,7 +66,6 @@ struct core_info {
 static int topology_enabled;
 static void topology_work_fn(struct work_struct *work);
 static struct tl_info *tl_info;
-static struct core_info core_info;
 static int machine_has_topology;
 static struct timer_list topology_timer;
 static void set_topology_timer(void);
@@ -74,38 +73,37 @@ static DECLARE_WORK(topology_work, topology_work_fn);
 /* topology_lock protects the core linked list */
 static DEFINE_SPINLOCK(topology_lock);
 
+static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
 
-static cpumask_t cpu_coregroup_map(unsigned int cpu)
+#ifdef CONFIG_SCHED_BOOK
+static struct mask_info book_info;
+cpumask_t cpu_book_map[NR_CPUS];
+unsigned char cpu_book_id[NR_CPUS];
+#endif
+
+static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
-       struct core_info *core = &core_info;
-       unsigned long flags;
        cpumask_t mask;
 
        cpus_clear(mask);
        if (!topology_enabled || !machine_has_topology)
                return cpu_possible_map;
-       spin_lock_irqsave(&topology_lock, flags);
-       while (core) {
-               if (cpu_isset(cpu, core->mask)) {
-                       mask = core->mask;
+       while (info) {
+               if (cpu_isset(cpu, info->mask)) {
+                       mask = info->mask;
                        break;
                }
-               core = core->next;
+               info = info->next;
        }
-       spin_unlock_irqrestore(&topology_lock, flags);
        if (cpus_empty(mask))
                mask = cpumask_of_cpu(cpu);
        return mask;
 }
 
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
-{
-       return &cpu_core_map[cpu];
-}
-
-static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
+static void add_cpus_to_mask(struct tl_cpu *tl_cpu, struct mask_info *book,
+                            struct mask_info *core)
 {
        unsigned int cpu;
 
@@ -117,23 +115,35 @@ static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
 
                rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
                for_each_present_cpu(lcpu) {
-                       if (cpu_logical_map(lcpu) == rcpu) {
-                               cpu_set(lcpu, core->mask);
-                               cpu_core_id[lcpu] = core->id;
-                               smp_cpu_polarization[lcpu] = tl_cpu->pp;
-                       }
+                       if (cpu_logical_map(lcpu) != rcpu)
+                               continue;
+#ifdef CONFIG_SCHED_BOOK
+                       cpu_set(lcpu, book->mask);
+                       cpu_book_id[lcpu] = book->id;
+#endif
+                       cpu_set(lcpu, core->mask);
+                       cpu_core_id[lcpu] = core->id;
+                       smp_cpu_polarization[lcpu] = tl_cpu->pp;
                }
        }
 }
 
-static void clear_cores(void)
+static void clear_masks(void)
 {
-       struct core_info *core = &core_info;
+       struct mask_info *info;
 
-       while (core) {
-               cpus_clear(core->mask);
-               core = core->next;
+       info = &core_info;
+       while (info) {
+               cpus_clear(info->mask);
+               info = info->next;
+       }
+#ifdef CONFIG_SCHED_BOOK
+       info = &book_info;
+       while (info) {
+               cpus_clear(info->mask);
+               info = info->next;
        }
+#endif
 }
 
 static union tl_entry *next_tle(union tl_entry *tle)
@@ -146,29 +156,36 @@ static union tl_entry *next_tle(union tl_entry *tle)
 
 static void tl_to_cores(struct tl_info *info)
 {
+#ifdef CONFIG_SCHED_BOOK
+       struct mask_info *book = &book_info;
+#else
+       struct mask_info *book = NULL;
+#endif
+       struct mask_info *core = &core_info;
        union tl_entry *tle, *end;
-       struct core_info *core = &core_info;
+
 
        spin_lock_irq(&topology_lock);
-       clear_cores();
+       clear_masks();
        tle = info->tle;
        end = (union tl_entry *)((unsigned long)info + info->length);
        while (tle < end) {
                switch (tle->nl) {
-               case 5:
-               case 4:
-               case 3:
+#ifdef CONFIG_SCHED_BOOK
                case 2:
+                       book = book->next;
+                       book->id = tle->container.id;
                        break;
+#endif
                case 1:
                        core = core->next;
                        core->id = tle->container.id;
                        break;
                case 0:
-                       add_cpus_to_core(&tle->cpu, core);
+                       add_cpus_to_mask(&tle->cpu, book, core);
                        break;
                default:
-                       clear_cores();
+                       clear_masks();
                        machine_has_topology = 0;
                        goto out;
                }
@@ -221,10 +238,29 @@ int topology_set_cpu_management(int fc)
 
 static void update_cpu_core_map(void)
 {
+       unsigned long flags;
        int cpu;
 
-       for_each_possible_cpu(cpu)
-               cpu_core_map[cpu] = cpu_coregroup_map(cpu);
+       spin_lock_irqsave(&topology_lock, flags);
+       for_each_possible_cpu(cpu) {
+               cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
+#ifdef CONFIG_SCHED_BOOK
+               cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
+#endif
+       }
+       spin_unlock_irqrestore(&topology_lock, flags);
+}
+
+static void store_topology(struct tl_info *info)
+{
+#ifdef CONFIG_SCHED_BOOK
+       int rc;
+
+       rc = stsi(info, 15, 1, 3);
+       if (rc != -ENOSYS)
+               return;
+#endif
+       stsi(info, 15, 1, 2);
 }
 
 int arch_update_cpu_topology(void)
@@ -238,7 +274,7 @@ int arch_update_cpu_topology(void)
                topology_update_polarization_simple();
                return 0;
        }
-       stsi(info, 15, 1, 2);
+       store_topology(info);
        tl_to_cores(info);
        update_cpu_core_map();
        for_each_online_cpu(cpu) {
@@ -299,12 +335,24 @@ out:
 }
 __initcall(init_topology_update);
 
+static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset)
+{
+       int i, nr_masks;
+
+       nr_masks = info->mag[NR_MAG - offset];
+       for (i = 0; i < info->mnest - offset; i++)
+               nr_masks *= info->mag[NR_MAG - offset - 1 - i];
+       nr_masks = max(nr_masks, 1);
+       for (i = 0; i < nr_masks; i++) {
+               mask->next = alloc_bootmem(sizeof(struct mask_info));
+               mask = mask->next;
+       }
+}
+
 void __init s390_init_cpu_topology(void)
 {
        unsigned long long facility_bits;
        struct tl_info *info;
-       struct core_info *core;
-       int nr_cores;
        int i;
 
        if (stfle(&facility_bits, 1) <= 0)
@@ -315,25 +363,13 @@ void __init s390_init_cpu_topology(void)
 
        tl_info = alloc_bootmem_pages(PAGE_SIZE);
        info = tl_info;
-       stsi(info, 15, 1, 2);
-
-       nr_cores = info->mag[NR_MAG - 2];
-       for (i = 0; i < info->mnest - 2; i++)
-               nr_cores *= info->mag[NR_MAG - 3 - i];
-
+       store_topology(info);
        pr_info("The CPU configuration topology of the machine is:");
        for (i = 0; i < NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
-
-       core = &core_info;
-       for (i = 0; i < nr_cores; i++) {
-               core->next = alloc_bootmem(sizeof(struct core_info));
-               core = core->next;
-               if (!core)
-                       goto error;
-       }
-       return;
-error:
-       machine_has_topology = 0;
+       alloc_masks(info, &core_info, 2);
+#ifdef CONFIG_SCHED_BOOK
+       alloc_masks(info, &book_info, 3);
+#endif
 }
index acc91c75bc94a7e4a3b8f87600cbe312c4bdcc90..94b8ba2ec8575d814613bab79fa191ba5a2564ca 100644 (file)
@@ -50,7 +50,6 @@ EXPORT_SYMBOL(empty_zero_page);
  */
 void __init paging_init(void)
 {
-       static const int ssm_mask = 0x04000000L;
        unsigned long max_zone_pfns[MAX_NR_ZONES];
        unsigned long pgd_type;
 
@@ -72,7 +71,9 @@ void __init paging_init(void)
        __ctl_load(S390_lowcore.kernel_asce, 1, 1);
        __ctl_load(S390_lowcore.kernel_asce, 7, 7);
        __ctl_load(S390_lowcore.kernel_asce, 13, 13);
-       __raw_local_irq_ssm(ssm_mask);
+       arch_local_irq_restore(4UL << (BITS_PER_LONG - 8));
+
+       atomic_set(&init_mm.context.attach_count, 1);
 
        sparse_memory_present_with_active_regions(MAX_NUMNODES);
        sparse_init();
index a8c2af8c650fabd9c96a4f9efaf3c0c4f530f294..71a4b0d34be09625c2fecfd28a23d61b47e29019 100644 (file)
@@ -71,7 +71,7 @@ int memcpy_real(void *dest, void *src, size_t count)
 
        if (!count)
                return 0;
-       flags = __raw_local_irq_stnsm(0xf8UL);
+       flags = __arch_local_irq_stnsm(0xf8UL);
        asm volatile (
                "0:     mvcle   %1,%2,0x0\n"
                "1:     jo      0b\n"
@@ -82,6 +82,6 @@ int memcpy_real(void *dest, void *src, size_t count)
                  "+d" (_len2), "=m" (*((long *) dest))
                : "m" (*((long *) src))
                : "cc", "memory");
-       __raw_local_irq_ssm(flags);
+       arch_local_irq_restore(flags);
        return rc;
 }
index 690a6cae729416807b5120d20d45beb047487ffe..5c7563891e288e9b972e9ecc38b8a1b1dd361ee0 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-#define raw_local_irq_save(x)                  \
-{                                              \
-       __asm__ __volatile__(                   \
-               "mfcr   r8, cr0;"               \
-               "li     r9, 0xfffffffe;"        \
-               "nop;"                          \
-               "mv     %0, r8;"                \
-               "and    r8, r8, r9;"            \
-               "mtcr   r8, cr0;"               \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               : "=r" (x)                      \
-               :                               \
-               : "r8", "r9"                    \
-               );                              \
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+
+       asm volatile(
+               "       mfcr    r8, cr0         \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       mv      %0, r8          \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       ldi     r9, 0x1         \n"
+               "       and     %0, %0, r9      \n"
+               : "=r" (flags)
+               :
+               : "r8", "r9");
+       return flags;
 }
 
-#define raw_local_irq_restore(x)               \
-{                                              \
-       __asm__ __volatile__(                   \
-               "mfcr   r8, cr0;"               \
-               "ldi    r9, 0x1;"               \
-               "and    %0, %0, r9;"            \
-               "or     r8, r8, %0;"            \
-               "mtcr   r8, cr0;"               \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               :                               \
-               : "r"(x)                        \
-               : "r8", "r9"                    \
-               );                              \
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags
+
+       asm volatile(
+               "       mfcr    r8, cr0         \n"
+               "       li      r9, 0xfffffffe  \n"
+               "       nop                     \n"
+               "       mv      %0, r8          \n"
+               "       and     r8, r8, r9      \n"
+               "       mtcr    r8, cr0         \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               : "=r" (flags)
+               :
+               : "r8", "r9", "memory");
+
+       return flags;
 }
 
-#define raw_local_irq_enable(void)             \
-{                                              \
-       __asm__ __volatile__(                   \
-               "mfcr\tr8,cr0;"                 \
-               "nop;"                          \
-               "nop;"                          \
-               "ori\tr8,0x1;"                  \
-               "mtcr\tr8,cr0;"                 \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               :                               \
-               :                               \
-               : "r8");                        \
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile(
+               "       mfcr    r8, cr0         \n"
+               "       ldi     r9, 0x1         \n"
+               "       and     %0, %0, r9      \n"
+               "       or      r8, r8, %0      \n"
+               "       mtcr    r8, cr0         \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               :
+               : "r"(flags)
+               : "r8", "r9", "memory");
 }
 
-#define raw_local_irq_disable(void)            \
-{                                              \
-       __asm__ __volatile__(                   \
-               "mfcr\tr8,cr0;"                 \
-               "nop;"                          \
-               "nop;"                          \
-               "srli\tr8,r8,1;"                \
-               "slli\tr8,r8,1;"                \
-               "mtcr\tr8,cr0;"                 \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               :                               \
-               :                               \
-               : "r8");                        \
+static inline void arch_local_irq_enable(void)
+{
+       asm volatile(
+               "       mfcr    r8,cr0          \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       ori     r8,0x1          \n"
+               "       mtcr    r8,cr0          \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               :
+               :
+               : "r8", "memory");
 }
 
-#define raw_local_save_flags(x)                        \
-{                                              \
-       __asm__ __volatile__(                   \
-               "mfcr   r8, cr0;"               \
-               "nop;"                          \
-               "nop;"                          \
-               "mv     %0, r8;"                \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "nop;"                          \
-               "ldi    r9, 0x1;"               \
-               "and    %0, %0, r9;"            \
-               : "=r" (x)                      \
-               :                               \
-               : "r8", "r9"                    \
-               );                              \
+static inline void arch_local_irq_disable(void)
+{
+       asm volatile(
+               "       mfcr    r8,cr0          \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       srli    r8,r8,1         \n"
+               "       slli    r8,r8,1         \n"
+               "       mtcr    r8,cr0          \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               "       nop                     \n"
+               :
+               :
+               : "r8", "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return !(flags & 1);
 }
 
-#endif
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_SCORE_IRQFLAGS_H */
index 33990fa95af013a64e081c4bfc411f58228f64cb..35b6879628a04feccd1dd2071846cb92563f5586 100644 (file)
@@ -16,6 +16,7 @@ config SUPERH
        select HAVE_ARCH_TRACEHOOK
        select HAVE_DMA_API_DEBUG
        select HAVE_DMA_ATTRS
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_KERNEL_GZIP
@@ -249,6 +250,11 @@ config ARCH_SHMOBILE
        select PM
        select PM_RUNTIME
 
+config CPU_HAS_PMU
+       depends on CPU_SH4 || CPU_SH4A
+       default y
+       bool
+
 if SUPERH32
 
 choice
@@ -738,6 +744,14 @@ config GUSA_RB
          LLSC, this should be more efficient than the other alternative of
          disabling interrupts around the atomic sequence.
 
+config HW_PERF_EVENTS
+       bool "Enable hardware performance counter support for perf events"
+       depends on PERF_EVENTS && CPU_HAS_PMU
+       default y
+       help
+         Enable hardware performance counter support for perf events. If
+         disabled, perf events will use software events only.
+
 source "drivers/sh/Kconfig"
 
 endmenu
index 01e6abb769b9ede9d901df10e2161ac0c106cd34..8132dff078fbd2d5e2ee63d7614acd83df729f24 100644 (file)
@@ -128,6 +128,7 @@ static const struct file_operations gio_fops = {
        .open = gio_open,       /* open */
        .release = gio_close,   /* release */
        .unlocked_ioctl = gio_ioctl,
+       .llseek = noop_llseek,
 };
 
 static int __init gio_init(void)
index a741153b41c2d1eb5eb4c4e428410bac86f81135..43b7608606c32434f6508a07153a2c4847c4bcf6 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ASM_SH_IRQFLAGS_H
 #define __ASM_SH_IRQFLAGS_H
 
-#define RAW_IRQ_DISABLED       0xf0
-#define RAW_IRQ_ENABLED                0x00
+#define ARCH_IRQ_DISABLED      0xf0
+#define ARCH_IRQ_ENABLED       0x00
 
 #include <asm-generic/irqflags.h>
 
index dfe683b88075fa98b7f28f6f1ef98f34752e7981..e87063fad2ea7ecd558aeba712e68760fb7d80b3 100644 (file)
@@ -1,6 +1,4 @@
 #ifndef __ASM_SH_MEMBLOCK_H
 #define __ASM_SH_MEMBLOCK_H
 
-#define MEMBLOCK_REAL_LIMIT    0
-
 #endif /* __ASM_SH_MEMBLOCK_H */
index 3d0c9f36d15050bb049fe8cfdbe4e7ae73f08f6d..14308bed7ea510cb6b43429887ca727cf1f0510d 100644 (file)
@@ -26,11 +26,4 @@ extern int register_sh_pmu(struct sh_pmu *);
 extern int reserve_pmc_hardware(void);
 extern void release_pmc_hardware(void);
 
-static inline void set_perf_event_pending(void)
-{
-       /* Nothing to see here, move along. */
-}
-
-#define PERF_EVENT_INDEX_OFFSET        0
-
 #endif /* __ASM_SH_PERF_EVENT_H */
index be201fdc97aa79bbf5470c8a582e20ecb7e78991..ae717e3c26d6d4178c1260c1602099d86534caed 100644 (file)
@@ -19,9 +19,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs __regs);
-asmlinkage int sys_execve(const char __user *ufilename, char __user * __user *uargv,
-                         char __user * __user *uenvp, unsigned long r7,
-                         struct pt_regs __regs);
+asmlinkage int sys_execve(const char __user *ufilename,
+                         const char __user *const __user *uargv,
+                         const char __user *const __user *uenvp,
+                         unsigned long r7, struct pt_regs __regs);
 asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
                              unsigned long r6, unsigned long r7,
                              struct pt_regs __regs);
index 257de1f0692b19ade90daefcf1089c3c127ce72c..ae5bac39b896d052e0b3b1b663e3edb69a754339 100644 (file)
@@ -290,7 +290,7 @@ void __init init_IRQ(void)
 int __init arch_probe_nr_irqs(void)
 {
        nr_irqs = sh_mv.mv_nr_irqs;
-       return 0;
+       return NR_IRQS_LEGACY;
 }
 #endif
 
index e33ab15831f94dc62dc1d3b19e426de038db916d..e5a755be9129a1c9d497be4851ac0948fbd8a210 100644 (file)
 #include <linux/irqflags.h>
 #include <linux/module.h>
 
-void notrace raw_local_irq_restore(unsigned long flags)
+void notrace arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __dummy0, __dummy1;
 
-       if (flags == RAW_IRQ_DISABLED) {
+       if (flags == ARCH_IRQ_DISABLED) {
                __asm__ __volatile__ (
                        "stc    sr, %0\n\t"
                        "or     #0xf0, %0\n\t"
@@ -33,14 +33,14 @@ void notrace raw_local_irq_restore(unsigned long flags)
 #endif
                        "ldc    %0, sr\n\t"
                        : "=&r" (__dummy0), "=r" (__dummy1)
-                       : "1" (~RAW_IRQ_DISABLED)
+                       : "1" (~ARCH_IRQ_DISABLED)
                        : "memory"
                );
        }
 }
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 
-unsigned long notrace __raw_local_save_flags(void)
+unsigned long notrace arch_local_save_flags(void)
 {
        unsigned long flags;
 
@@ -54,4 +54,4 @@ unsigned long notrace __raw_local_save_flags(void)
 
        return flags;
 }
-EXPORT_SYMBOL(__raw_local_save_flags);
+EXPORT_SYMBOL(arch_local_save_flags);
index 43adddfe4c04b6d2eee9acfa8cad99a7788dfcc4..ae0be697a89e4b220f527a2bdb34f4da7ec7d318 100644 (file)
@@ -149,13 +149,11 @@ int module_finalize(const Elf_Ehdr *hdr,
        int ret = 0;
 
        ret |= module_dwarf_finalize(hdr, sechdrs, me);
-       ret |= module_bug_finalize(hdr, sechdrs, me);
 
        return ret;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-       module_bug_cleanup(mod);
        module_dwarf_cleanup(mod);
 }
index a9dd3abde28e3f45bbd7d7654e8717c13aed8f34..d5ca1ef50fa9694a1942a8c304bd2c5aa69d9388 100644 (file)
 #include <asm/unwinder.h>
 #include <asm/ptrace.h>
 
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-       if (entry->nr < PERF_MAX_STACK_DEPTH)
-               entry->ip[entry->nr++] = ip;
-}
 
 static void callchain_warning(void *data, char *msg)
 {
@@ -39,7 +34,7 @@ static void callchain_address(void *data, unsigned long addr, int reliable)
        struct perf_callchain_entry *entry = data;
 
        if (reliable)
-               callchain_store(entry, addr);
+               perf_callchain_store(entry, addr);
 }
 
 static const struct stacktrace_ops callchain_ops = {
@@ -49,47 +44,10 @@ static const struct stacktrace_ops callchain_ops = {
        .address        = callchain_address,
 };
 
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-       callchain_store(entry, PERF_CONTEXT_KERNEL);
-       callchain_store(entry, regs->pc);
+       perf_callchain_store(entry, regs->pc);
 
        unwind_stack(NULL, regs, NULL, &callchain_ops, entry);
 }
-
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-       int is_user;
-
-       if (!regs)
-               return;
-
-       is_user = user_mode(regs);
-
-       if (is_user && current->state != TASK_RUNNING)
-               return;
-
-       /*
-        * Only the kernel side is implemented for now.
-        */
-       if (!is_user)
-               perf_callchain_kernel(regs, entry);
-}
-
-/*
- * No need for separate IRQ and NMI entries.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-       struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
-       entry->nr = 0;
-
-       perf_do_callchain(regs, entry);
-
-       return entry;
-}
index 7a3dc356725839f2cf8579491efd8d02ba11b483..5a4b33435650c8ea108668d8e7e30786a20bd335 100644 (file)
@@ -59,6 +59,24 @@ static inline int sh_pmu_initialized(void)
        return !!sh_pmu;
 }
 
+const char *perf_pmu_name(void)
+{
+       if (!sh_pmu)
+               return NULL;
+
+       return sh_pmu->name;
+}
+EXPORT_SYMBOL_GPL(perf_pmu_name);
+
+int perf_num_counters(void)
+{
+       if (!sh_pmu)
+               return 0;
+
+       return sh_pmu->num_events;
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
 /*
  * Release the PMU if this is the last perf_event.
  */
@@ -206,50 +224,80 @@ again:
        local64_add(delta, &event->count);
 }
 
-static void sh_pmu_disable(struct perf_event *event)
+static void sh_pmu_stop(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
-       clear_bit(idx, cpuc->active_mask);
-       sh_pmu->disable(hwc, idx);
+       if (!(event->hw.state & PERF_HES_STOPPED)) {
+               sh_pmu->disable(hwc, idx);
+               cpuc->events[idx] = NULL;
+               event->hw.state |= PERF_HES_STOPPED;
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
+               sh_perf_event_update(event, &event->hw, idx);
+               event->hw.state |= PERF_HES_UPTODATE;
+       }
+}
+
+static void sh_pmu_start(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (WARN_ON_ONCE(idx == -1))
+               return;
+
+       if (flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
 
-       barrier();
+       cpuc->events[idx] = event;
+       event->hw.state = 0;
+       sh_pmu->enable(hwc, idx);
+}
 
-       sh_perf_event_update(event, &event->hw, idx);
+static void sh_pmu_del(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
-       cpuc->events[idx] = NULL;
-       clear_bit(idx, cpuc->used_mask);
+       sh_pmu_stop(event, PERF_EF_UPDATE);
+       __clear_bit(event->hw.idx, cpuc->used_mask);
 
        perf_event_update_userpage(event);
 }
 
-static int sh_pmu_enable(struct perf_event *event)
+static int sh_pmu_add(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
+       int ret = -EAGAIN;
+
+       perf_pmu_disable(event->pmu);
 
-       if (test_and_set_bit(idx, cpuc->used_mask)) {
+       if (__test_and_set_bit(idx, cpuc->used_mask)) {
                idx = find_first_zero_bit(cpuc->used_mask, sh_pmu->num_events);
                if (idx == sh_pmu->num_events)
-                       return -EAGAIN;
+                       goto out;
 
-               set_bit(idx, cpuc->used_mask);
+               __set_bit(idx, cpuc->used_mask);
                hwc->idx = idx;
        }
 
        sh_pmu->disable(hwc, idx);
 
-       cpuc->events[idx] = event;
-       set_bit(idx, cpuc->active_mask);
-
-       sh_pmu->enable(hwc, idx);
+       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (flags & PERF_EF_START)
+               sh_pmu_start(event, PERF_EF_RELOAD);
 
        perf_event_update_userpage(event);
-
-       return 0;
+       ret = 0;
+out:
+       perf_pmu_enable(event->pmu);
+       return ret;
 }
 
 static void sh_pmu_read(struct perf_event *event)
@@ -257,24 +305,56 @@ static void sh_pmu_read(struct perf_event *event)
        sh_perf_event_update(event, &event->hw, event->hw.idx);
 }
 
-static const struct pmu pmu = {
-       .enable         = sh_pmu_enable,
-       .disable        = sh_pmu_disable,
-       .read           = sh_pmu_read,
-};
-
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int sh_pmu_event_init(struct perf_event *event)
 {
-       int err = __hw_perf_event_init(event);
+       int err;
+
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+       case PERF_TYPE_HW_CACHE:
+       case PERF_TYPE_HARDWARE:
+               err = __hw_perf_event_init(event);
+               break;
+
+       default:
+               return -ENOENT;
+       }
+
        if (unlikely(err)) {
                if (event->destroy)
                        event->destroy(event);
-               return ERR_PTR(err);
        }
 
-       return &pmu;
+       return err;
+}
+
+static void sh_pmu_enable(struct pmu *pmu)
+{
+       if (!sh_pmu_initialized())
+               return;
+
+       sh_pmu->enable_all();
+}
+
+static void sh_pmu_disable(struct pmu *pmu)
+{
+       if (!sh_pmu_initialized())
+               return;
+
+       sh_pmu->disable_all();
 }
 
+static struct pmu pmu = {
+       .pmu_enable     = sh_pmu_enable,
+       .pmu_disable    = sh_pmu_disable,
+       .event_init     = sh_pmu_event_init,
+       .add            = sh_pmu_add,
+       .del            = sh_pmu_del,
+       .start          = sh_pmu_start,
+       .stop           = sh_pmu_stop,
+       .read           = sh_pmu_read,
+};
+
 static void sh_pmu_setup(int cpu)
 {
        struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
@@ -299,32 +379,17 @@ sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
        return NOTIFY_OK;
 }
 
-void hw_perf_enable(void)
-{
-       if (!sh_pmu_initialized())
-               return;
-
-       sh_pmu->enable_all();
-}
-
-void hw_perf_disable(void)
-{
-       if (!sh_pmu_initialized())
-               return;
-
-       sh_pmu->disable_all();
-}
-
-int __cpuinit register_sh_pmu(struct sh_pmu *pmu)
+int __cpuinit register_sh_pmu(struct sh_pmu *_pmu)
 {
        if (sh_pmu)
                return -EBUSY;
-       sh_pmu = pmu;
+       sh_pmu = _pmu;
 
-       pr_info("Performance Events: %s support registered\n", pmu->name);
+       pr_info("Performance Events: %s support registered\n", _pmu->name);
 
-       WARN_ON(pmu->num_events > MAX_HWEVENTS);
+       WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
+       perf_pmu_register(&pmu);
        perf_cpu_notifier(sh_pmu_notifier);
        return 0;
 }
index d0e249100e98d044b804414b80d725a0ebd7e43d..552bea5113f550c415f2d9d70b86082e905b0814 100644 (file)
@@ -200,7 +200,6 @@ static void __init bootmem_init_one_node(unsigned int nid)
        unsigned long total_pages, paddr;
        unsigned long end_pfn;
        struct pglist_data *p;
-       int i;
 
        p = NODE_DATA(nid);
 
@@ -226,11 +225,12 @@ static void __init bootmem_init_one_node(unsigned int nid)
         * reservations in other nodes.
         */
        if (nid == 0) {
+               struct memblock_region *reg;
+
                /* Reserve the sections we're already using. */
-               for (i = 0; i < memblock.reserved.cnt; i++)
-                       reserve_bootmem(memblock.reserved.region[i].base,
-                                       memblock_size_bytes(&memblock.reserved, i),
-                                       BOOTMEM_DEFAULT);
+               for_each_memblock(reserved, reg) {
+                       reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+               }
        }
 
        sparse_memory_present_with_active_regions(nid);
@@ -238,13 +238,14 @@ static void __init bootmem_init_one_node(unsigned int nid)
 
 static void __init do_init_bootmem(void)
 {
+       struct memblock_region *reg;
        int i;
 
        /* Add active regions with valid PFNs. */
-       for (i = 0; i < memblock.memory.cnt; i++) {
+       for_each_memblock(memory, reg) {
                unsigned long start_pfn, end_pfn;
-               start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-               end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                __add_active_range(0, start_pfn, end_pfn);
        }
 
index 4886c5c1786c24dbacadccd492a9dbf5fa8bd075..e85aae73e3dcf12a4ef1bb06b344b901efd54c6f 100644 (file)
@@ -6,4 +6,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                oprofilefs.o oprofile_stats.o \
                timer_int.o )
 
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
 oprofile-y     := $(DRIVER_OBJS) common.o backtrace.o
index ac604937f3ee16fde018d6f5b0c094a189f4d2b5..e10d89376f9b79140adaa44f7fb63f0681604482 100644 (file)
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 #include <asm/processor.h>
-#include "op_impl.h"
-
-static struct op_sh_model *model;
-
-static struct op_counter_config ctr[20];
 
+#ifdef CONFIG_HW_PERF_EVENTS
 extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
 
-static int op_sh_setup(void)
-{
-       /* Pre-compute the values to stuff in the hardware registers.  */
-       model->reg_setup(ctr);
-
-       /* Configure the registers on all cpus.  */
-       on_each_cpu(model->cpu_setup, NULL, 1);
-
-        return 0;
-}
-
-static int op_sh_create_files(struct super_block *sb, struct dentry *root)
+char *op_name_from_perf_id(void)
 {
-       int i, ret = 0;
+       const char *pmu;
+       char buf[20];
+       int size;
 
-       for (i = 0; i < model->num_counters; i++) {
-               struct dentry *dir;
-               char buf[4];
+       pmu = perf_pmu_name();
+       if (!pmu)
+               return NULL;
 
-               snprintf(buf, sizeof(buf), "%d", i);
-               dir = oprofilefs_mkdir(sb, root, buf);
+       size = snprintf(buf, sizeof(buf), "sh/%s", pmu);
+       if (size > -1 && size < sizeof(buf))
+               return buf;
 
-               ret |= oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
-               ret |= oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
-               ret |= oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
-               ret |= oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
-
-               if (model->create_files)
-                       ret |= model->create_files(sb, dir);
-               else
-                       ret |= oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
-
-               /* Dummy entries */
-               ret |= oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
-       }
-
-       return ret;
+       return NULL;
 }
 
-static int op_sh_start(void)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-       /* Enable performance monitoring for all counters.  */
-       on_each_cpu(model->cpu_start, NULL, 1);
+       ops->backtrace = sh_backtrace;
 
-       return 0;
+       return oprofile_perf_init(ops);
 }
 
-static void op_sh_stop(void)
+void __exit oprofile_arch_exit(void)
 {
-       /* Disable performance monitoring for all counters.  */
-       on_each_cpu(model->cpu_stop, NULL, 1);
+       oprofile_perf_exit();
 }
-
+#else
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-       struct op_sh_model *lmodel = NULL;
-       int ret;
-
-       /*
-        * Always assign the backtrace op. If the counter initialization
-        * fails, we fall back to the timer which will still make use of
-        * this.
-        */
-       ops->backtrace = sh_backtrace;
-
-       /*
-        * XXX
-        *
-        * All of the SH7750/SH-4A counters have been converted to perf,
-        * this infrastructure hook is left for other users until they've
-        * had a chance to convert over, at which point all of this
-        * will be deleted.
-        */
-
-       if (!lmodel)
-               return -ENODEV;
-       if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
-               return -ENODEV;
-
-       ret = lmodel->init();
-       if (unlikely(ret != 0))
-               return ret;
-
-       model = lmodel;
-
-       ops->setup              = op_sh_setup;
-       ops->create_files       = op_sh_create_files;
-       ops->start              = op_sh_start;
-       ops->stop               = op_sh_stop;
-       ops->cpu_type           = lmodel->cpu_type;
-
-       printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
-              lmodel->cpu_type);
-
-       return 0;
-}
-
-void oprofile_arch_exit(void)
-{
-       if (model && model->exit)
-               model->exit();
+       pr_info("oprofile: hardware counters not available\n");
+       return -ENODEV;
 }
+void __exit oprofile_arch_exit(void) {}
+#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/sh/oprofile/op_impl.h b/arch/sh/oprofile/op_impl.h
deleted file mode 100644 (file)
index 1244479..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __OP_IMPL_H
-#define __OP_IMPL_H
-
-/* Per-counter configuration as set via oprofilefs.  */
-struct op_counter_config {
-       unsigned long enabled;
-       unsigned long event;
-
-       unsigned long count;
-
-       /* Dummy values for userspace tool compliance */
-       unsigned long kernel;
-       unsigned long user;
-       unsigned long unit_mask;
-};
-
-/* Per-architecture configury and hooks.  */
-struct op_sh_model {
-       void (*reg_setup)(struct op_counter_config *);
-       int (*create_files)(struct super_block *sb, struct dentry *dir);
-       void (*cpu_setup)(void *dummy);
-       int (*init)(void);
-       void (*exit)(void);
-       void (*cpu_start)(void *args);
-       void (*cpu_stop)(void *args);
-       char *cpu_type;
-       unsigned char num_counters;
-};
-
-/* arch/sh/oprofile/common.c */
-extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
-
-#endif /* __OP_IMPL_H */
index 491e9d6de1912d56cea2b21f51bf8cfd7980e278..3e9d31401fb24e9dd1b6b3e67add09a4ea7f1468 100644 (file)
@@ -26,10 +26,12 @@ config SPARC
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select RTC_CLASS
        select RTC_DRV_M48T59
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
+       select HAVE_ARCH_JUMP_LABEL
 
 config SPARC32
        def_bool !64BIT
@@ -53,6 +55,7 @@ config SPARC64
        select RTC_DRV_BQ4802
        select RTC_DRV_SUN4V
        select RTC_DRV_STARFIRE
+       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
 
index f0c74227c737e0a94efb33c95640375ad38c89bc..bdb2ff880bdd68f58c0b4357479f31bd32ff19d9 100644 (file)
 #define atomic64_set(v, i)     (((v)->counter) = i)
 
 extern void atomic_add(int, atomic_t *);
-extern void atomic64_add(int, atomic64_t *);
+extern void atomic64_add(long, atomic64_t *);
 extern void atomic_sub(int, atomic_t *);
-extern void atomic64_sub(int, atomic64_t *);
+extern void atomic64_sub(long, atomic64_t *);
 
 extern int atomic_add_ret(int, atomic_t *);
-extern long atomic64_add_ret(int, atomic64_t *);
+extern long atomic64_add_ret(long, atomic64_t *);
 extern int atomic_sub_ret(int, atomic_t *);
-extern long atomic64_sub_ret(int, atomic64_t *);
+extern long atomic64_sub_ret(long, atomic64_t *);
 
 #define atomic_dec_return(v) atomic_sub_ret(1, v)
 #define atomic64_dec_return(v) atomic64_sub_ret(1, v)
index fa1fdf67e350e07d950107289f25bdf3c41a73b3..db3af0d30fb10129124c594d1f1195bb59f2a6f2 100644 (file)
@@ -8,6 +8,9 @@
 #define BACKOFF_SETUP(reg)     \
        mov     1, reg
 
+#define BACKOFF_LABEL(spin_label, continue_label) \
+       spin_label
+
 #define BACKOFF_SPIN(reg, tmp, label)  \
        mov     reg, tmp; \
 88:    brnz,pt tmp, 88b; \
 #else
 
 #define BACKOFF_SETUP(reg)
-#define BACKOFF_SPIN(reg, tmp, label) \
-       ba,pt   %xcc, label; \
-        nop;
+
+#define BACKOFF_LABEL(spin_label, continue_label) \
+       continue_label
+
+#define BACKOFF_SPIN(reg, tmp, label)
 
 #endif
 
index 5016f76ea98a6f38510d3dc5a8593a1d871d4f53..6f57325bb883c5553b4781691cd699952bb90ff8 100644 (file)
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = current_thread_info()->kregs;
        unsigned long usp = regs->u_regs[UREG_I6];
index 0fca9d97d44f15bd1a3832de7e02a990e0fa6577..d4d0711de0f9f5031439927d02517d6a5e743509 100644 (file)
@@ -5,33 +5,40 @@
  *
  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
 #ifndef __ASSEMBLY__
 
-extern void raw_local_irq_restore(unsigned long);
-extern unsigned long __raw_local_irq_save(void);
-extern void raw_local_irq_enable(void);
+#include <linux/types.h>
 
-static inline unsigned long getipl(void)
+extern void arch_local_irq_restore(unsigned long);
+extern unsigned long arch_local_irq_save(void);
+extern void arch_local_irq_enable(void);
+
+static inline unsigned long arch_local_save_flags(void)
 {
-        unsigned long retval;
+       unsigned long flags;
+
+       asm volatile("rd        %%psr, %0" : "=r" (flags));
+       return flags;
+}
 
-        __asm__ __volatile__("rd        %%psr, %0" : "=r" (retval));
-        return retval;
+static inline void arch_local_irq_disable(void)
+{
+       arch_local_irq_save();
 }
 
-#define raw_local_save_flags(flags) ((flags) = getipl())
-#define raw_local_irq_save(flags)   ((flags) = __raw_local_irq_save())
-#define raw_local_irq_disable()     ((void) __raw_local_irq_save())
-#define raw_irqs_disabled()         ((getipl() & PSR_PIL) != 0)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & PSR_PIL) != 0;
+}
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled(void)
 {
-        return ((flags & PSR_PIL) != 0);
+       return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
 #endif /* (__ASSEMBLY__) */
index bfa1ea45b4cdb893ee9814e077c9fafdda3daff8..aab969c82c2b654391089b180d77d45e62416058 100644 (file)
@@ -5,7 +5,7 @@
  *
  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
@@ -14,7 +14,7 @@
 
 #ifndef __ASSEMBLY__
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
 
@@ -26,10 +26,7 @@ static inline unsigned long __raw_local_save_flags(void)
        return flags;
 }
 
-#define raw_local_save_flags(flags) \
-               do { (flags) = __raw_local_save_flags(); } while (0)
-
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
        __asm__ __volatile__(
                "wrpr   %0, %%pil"
@@ -39,7 +36,7 @@ static inline void raw_local_irq_restore(unsigned long flags)
        );
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
        __asm__ __volatile__(
                "wrpr   %0, %%pil"
@@ -49,7 +46,7 @@ static inline void raw_local_irq_disable(void)
        );
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
        __asm__ __volatile__(
                "wrpr   0, %%pil"
@@ -59,22 +56,17 @@ static inline void raw_local_irq_enable(void)
        );
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
        return (flags > 0);
 }
 
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
 {
-       unsigned long flags = __raw_local_save_flags();
-
-       return raw_irqs_disabled_flags(flags);
+       return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-/*
- * For spinlocks, etc:
- */
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
        unsigned long flags, tmp;
 
@@ -100,9 +92,6 @@ static inline unsigned long __raw_local_irq_save(void)
        return flags;
 }
 
-#define raw_local_irq_save(flags) \
-               do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* (__ASSEMBLY__) */
 
 #endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..62e66d7
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _ASM_SPARC_JUMP_LABEL_H
+#define _ASM_SPARC_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#define JUMP_LABEL(key, label)                                 \
+       do {                                                    \
+               asm goto("1:\n\t"                               \
+                        "nop\n\t"                              \
+                        "nop\n\t"                              \
+                        ".pushsection __jump_table,  \"a\"\n\t"\
+                        ".word 1b, %l[" #label "], %c0\n\t"    \
+                        ".popsection \n\t"                     \
+                        : :  "i" (key) :  : label);\
+       } while (0)
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+};
+
+#endif
index f12af880649bcd70a029ca03f7bb59c778cefe13..c67b047ef85e3d23d8db079641e827d668cf7269 100644 (file)
@@ -5,6 +5,4 @@
 
 #define MEMBLOCK_DBG(fmt...) prom_printf(fmt)
 
-#define MEMBLOCK_REAL_LIMIT    0
-
 #endif /* !(_SPARC64_MEMBLOCK_H) */
index a5db0317b5fbfecc523e82b7a27172252cb1f4a2..3e0b2d62303df55133d1f9547e8c984ba5dbbeb2 100644 (file)
@@ -185,9 +185,8 @@ extern int prom_getunumber(int syndrome_code,
                           char *buf, int buflen);
 
 /* Retain physical memory to the caller across soft resets. */
-extern unsigned long prom_retain(const char *name,
-                                unsigned long pa_low, unsigned long pa_high,
-                                long size, long align);
+extern int prom_retain(const char *name, unsigned long size,
+                      unsigned long align, unsigned long *paddr);
 
 /* Load explicit I/D TLB entries into the calling processor. */
 extern long prom_itlb_load(unsigned long index,
@@ -287,26 +286,6 @@ extern void prom_sun4v_guest_soft_state(void);
 extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
 
 /* Client interface level routines. */
-extern long p1275_cmd(const char *, long, ...);
-
-#if 0
-#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
-#else
-#define P1275_SIZE(x) x
-#endif
-
-/* We support at most 16 input and 1 output argument */
-#define P1275_ARG_NUMBER               0
-#define P1275_ARG_IN_STRING            1
-#define P1275_ARG_OUT_BUF              2
-#define P1275_ARG_OUT_32B              3
-#define P1275_ARG_IN_FUNCTION          4
-#define P1275_ARG_IN_BUF               5
-#define P1275_ARG_IN_64B               6
-
-#define P1275_IN(x) ((x) & 0xf)
-#define P1275_OUT(x) (((x) << 4) & 0xf0)
-#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
-#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
+extern void p1275_cmd_direct(unsigned long *);
 
 #endif /* !(__SPARC64_OPLIB_H) */
index 727af70646cbddff92f36e6c47ad782c9018ea11..6e8bfa1786dab1f45d3dff5a1dcacc31a08d4844 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef __ASM_SPARC_PERF_EVENT_H
 #define __ASM_SPARC_PERF_EVENT_H
 
-extern void set_perf_event_pending(void);
-
-#define        PERF_EVENT_INDEX_OFFSET 0
-
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
diff --git a/arch/sparc/include/asm/rwsem-const.h b/arch/sparc/include/asm/rwsem-const.h
deleted file mode 100644 (file)
index e4c61a1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* rwsem-const.h: RW semaphore counter constants.  */
-#ifndef _SPARC64_RWSEM_CONST_H
-#define _SPARC64_RWSEM_CONST_H
-
-#define RWSEM_UNLOCKED_VALUE           0x00000000
-#define RWSEM_ACTIVE_BIAS              0x00000001
-#define RWSEM_ACTIVE_MASK              0x0000ffff
-#define RWSEM_WAITING_BIAS             (-0x00010000)
-#define RWSEM_ACTIVE_READ_BIAS         RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-#endif /* _SPARC64_RWSEM_CONST_H */
index 6e5621006f85114d3356090b1ce66681021375a9..a2b4302869bcfb8ffe1d54ee3282293a18aeae83 100644 (file)
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
-#include <asm/rwsem-const.h>
 
 struct rwsem_waiter;
 
 struct rw_semaphore {
-       signed int count;
-       spinlock_t              wait_lock;
-       struct list_head        wait_list;
+       signed long                     count;
+#define RWSEM_UNLOCKED_VALUE           0x00000000L
+#define RWSEM_ACTIVE_BIAS              0x00000001L
+#define RWSEM_ACTIVE_MASK              0xffffffffL
+#define RWSEM_WAITING_BIAS             (-RWSEM_ACTIVE_MASK-1)
+#define RWSEM_ACTIVE_READ_BIAS         RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+       spinlock_t                      wait_lock;
+       struct list_head                wait_list;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-       struct lockdep_map      dep_map;
+       struct lockdep_map              dep_map;
 #endif
 };
 
@@ -41,6 +46,11 @@ struct rw_semaphore {
 #define DECLARE_RWSEM(name) \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
 
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
 extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
                         struct lock_class_key *key);
 
@@ -51,27 +61,103 @@ do {                                                               \
        __init_rwsem((sem), #sem, &__key);                      \
 } while (0)
 
-extern void __down_read(struct rw_semaphore *sem);
-extern int __down_read_trylock(struct rw_semaphore *sem);
-extern void __down_write(struct rw_semaphore *sem);
-extern int __down_write_trylock(struct rw_semaphore *sem);
-extern void __up_read(struct rw_semaphore *sem);
-extern void __up_write(struct rw_semaphore *sem);
-extern void __downgrade_write(struct rw_semaphore *sem);
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+       if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L))
+               rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+       long tmp;
+
+       while ((tmp = sem->count) >= 0L) {
+               if (tmp == cmpxchg(&sem->count, tmp,
+                                  tmp + RWSEM_ACTIVE_READ_BIAS)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
 
+/*
+ * lock for writing
+ */
 static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
-       __down_write(sem);
+       long tmp;
+
+       tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+                                 (atomic64_t *)(&sem->count));
+       if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
+               rwsem_down_write_failed(sem);
 }
 
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+static inline void __down_write(struct rw_semaphore *sem)
 {
-       return atomic_add_return(delta, (atomic_t *)(&sem->count));
+       __down_write_nested(sem, 0);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+       long tmp;
+
+       tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+                     RWSEM_ACTIVE_WRITE_BIAS);
+       return tmp == RWSEM_UNLOCKED_VALUE;
 }
 
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+       long tmp;
+
+       tmp = atomic64_dec_return((atomic64_t *)(&sem->count));
+       if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L))
+               rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+       if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+                                        (atomic64_t *)(&sem->count)) < 0L))
+               rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
+{
+       atomic64_add(delta, (atomic64_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+       long tmp;
+
+       tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count));
+       if (tmp < 0L)
+               rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-       atomic_add(delta, (atomic_t *)(&sem->count));
+       return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
 }
 
 static inline int rwsem_is_locked(struct rw_semaphore *sem)
index d24cfe16afc1babc4feb78f0c697555754304346..e3b65d8cf41b715bb71b9339c9184e42feea01d0 100644 (file)
@@ -106,6 +106,7 @@ do {        __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
  */
 #define write_pic(__p)                                         \
        __asm__ __volatile__("ba,pt     %%xcc, 99f\n\t"         \
+                            " nop\n\t"                         \
                             ".align    64\n"                   \
                          "99:wr        %0, 0x0, %%pic\n\t"     \
                             "rd        %%pic, %%g0" : : "r" (__p))
index 0c2dc1f24a9a74adb05299a89ee07f8ed2bc1eb9..599398fbbc7cb78fd2f8849400d9092a95ffa786 100644 (file)
@@ -119,3 +119,5 @@ obj-$(CONFIG_COMPAT)    += $(audit--y)
 
 pc--$(CONFIG_PERF_EVENTS) := perf_event.o
 obj-$(CONFIG_SPARC64)  += $(pc--y)
+
+obj-$(CONFIG_SPARC64)  += jump_label.o
index 2c0046ecc7155592401d56c340c275e2697348a7..52de4a9424e86a781a034770352e8b0b5df2ffac 100644 (file)
@@ -132,6 +132,7 @@ static const struct file_operations apc_fops = {
        .unlocked_ioctl =       apc_ioctl,
        .open =                 apc_open,
        .release =              apc_release,
+       .llseek =               noop_llseek,
 };
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
index e1af4372832979eb363e3b3f6d2e54a3057d3b29..0116d8d10def21a4ad9c3b73c27a95383ae4cdc2 100644 (file)
@@ -57,7 +57,7 @@
 #define SMP_NOP2
 #define SMP_NOP3
 #endif /* SMP */
-unsigned long __raw_local_irq_save(void)
+unsigned long arch_local_irq_save(void)
 {
        unsigned long retval;
        unsigned long tmp;
@@ -74,8 +74,9 @@ unsigned long __raw_local_irq_save(void)
 
        return retval;
 }
+EXPORT_SYMBOL(arch_local_irq_save);
 
-void raw_local_irq_enable(void)
+void arch_local_irq_enable(void)
 {
        unsigned long tmp;
 
@@ -89,8 +90,9 @@ void raw_local_irq_enable(void)
                : "i" (PSR_PIL)
                : "memory");
 }
+EXPORT_SYMBOL(arch_local_irq_enable);
 
-void raw_local_irq_restore(unsigned long old_psr)
+void arch_local_irq_restore(unsigned long old_psr)
 {
        unsigned long tmp;
 
@@ -105,10 +107,7 @@ void raw_local_irq_restore(unsigned long old_psr)
                : "i" (PSR_PIL), "r" (old_psr)
                : "memory");
 }
-
-EXPORT_SYMBOL(__raw_local_irq_save);
-EXPORT_SYMBOL(raw_local_irq_enable);
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..ea2dafc
--- /dev/null
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       u32 val;
+       u32 *insn = (u32 *) (unsigned long) entry->code;
+
+       if (type == JUMP_LABEL_ENABLE) {
+               s32 off = (s32)entry->target - (s32)entry->code;
+
+#ifdef CONFIG_SPARC64
+               /* ba,pt %xcc, . + (off << 2) */
+               val = 0x10680000 | ((u32) off >> 2);
+#else
+               /* ba . + (off << 2) */
+               val = 0x10800000 | ((u32) off >> 2);
+#endif
+       } else {
+               val = 0x01000000;
+       }
+
+       get_online_cpus();
+       mutex_lock(&text_mutex);
+       *insn = val;
+       flushi(insn);
+       mutex_unlock(&text_mutex);
+       put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+       u32 *insn_p = (u32 *) (unsigned long) addr;
+
+       *insn_p = 0x01000000;
+       flushi(insn_p);
+}
+
+#endif
index 83e85c2e802ad6a075b08d0d0e5dfccb50e81108..6addb914fcc8edca6aae25d0b9210165b9422dde 100644 (file)
@@ -890,6 +890,7 @@ static ssize_t mdesc_read(struct file *file, char __user *buf,
 static const struct file_operations mdesc_fops = {
        .read   = mdesc_read,
        .owner  = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice mdesc_misc = {
index f848aadf54dc1c2c1feb537752fdf3410efbe9d8..ee3c7dde8d9fbd5af21f5dbf555628eff1c64b9c 100644 (file)
@@ -18,6 +18,9 @@
 #include <asm/spitfire.h>
 
 #ifdef CONFIG_SPARC64
+
+#include <linux/jump_label.h>
+
 static void *module_map(unsigned long size)
 {
        struct vm_struct *area;
@@ -227,6 +230,9 @@ int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
 {
+       /* make jump label nops */
+       jump_label_apply_nops(me);
+
        /* Cheetah's I-cache is fully coherent.  */
        if (tlb_type == spitfire) {
                unsigned long va;
index 548b8ca9c2106d7b7fa88d602db86a125a2a283e..b210416ace7b8f74773768cbc65f5f05f0cb9cc6 100644 (file)
@@ -114,10 +114,10 @@ static void free_msi(struct pci_pbm_info *pbm, int msi_num)
 
 static struct irq_chip msi_irq = {
        .name           = "PCI-MSI",
-       .mask           = mask_msi_irq,
-       .unmask         = unmask_msi_irq,
-       .enable         = unmask_msi_irq,
-       .disable        = mask_msi_irq,
+       .irq_mask       = mask_msi_irq,
+       .irq_unmask     = unmask_msi_irq,
+       .irq_enable     = unmask_msi_irq,
+       .irq_disable    = mask_msi_irq,
        /* XXX affinity XXX */
 };
 
index c4a6a50b4849a64c0f98759921267fbe76c3cfe7..b87873c0e8ea5f72be8ffe784e1035911b05a68c 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <linux/ftrace.h>
 
 #include <asm/pil.h>
@@ -43,14 +43,14 @@ void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)
 
        old_regs = set_irq_regs(regs);
        irq_enter();
-#ifdef CONFIG_PERF_EVENTS
-       perf_event_do_pending();
+#ifdef CONFIG_IRQ_WORK
+       irq_work_run();
 #endif
        irq_exit();
        set_irq_regs(old_regs);
 }
 
-void set_perf_event_pending(void)
+void arch_irq_work_raise(void)
 {
        set_softint(1 << PIL_DEFERRED_PCR_WORK);
 }
index 357ced3c33ffac87a992e01b6820a77084cfb8de..0d6deb55a2ae7e4189b5ab60aec81cd8df28adb6 100644 (file)
@@ -658,13 +658,16 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
 
                enc = perf_event_get_enc(cpuc->events[i]);
                pcr &= ~mask_for_index(idx);
-               pcr |= event_encoding(enc, idx);
+               if (hwc->state & PERF_HES_STOPPED)
+                       pcr |= nop_for_index(idx);
+               else
+                       pcr |= event_encoding(enc, idx);
        }
 out:
        return pcr;
 }
 
-void hw_perf_enable(void)
+static void sparc_pmu_enable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        u64 pcr;
@@ -691,7 +694,7 @@ void hw_perf_enable(void)
        pcr_ops->write(cpuc->pcr);
 }
 
-void hw_perf_disable(void)
+static void sparc_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        u64 val;
@@ -710,19 +713,65 @@ void hw_perf_disable(void)
        pcr_ops->write(cpuc->pcr);
 }
 
-static void sparc_pmu_disable(struct perf_event *event)
+static int active_event_index(struct cpu_hw_events *cpuc,
+                             struct perf_event *event)
+{
+       int i;
+
+       for (i = 0; i < cpuc->n_events; i++) {
+               if (cpuc->event[i] == event)
+                       break;
+       }
+       BUG_ON(i == cpuc->n_events);
+       return cpuc->current_idx[i];
+}
+
+static void sparc_pmu_start(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int idx = active_event_index(cpuc, event);
+
+       if (flags & PERF_EF_RELOAD) {
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+               sparc_perf_event_set_period(event, &event->hw, idx);
+       }
+
+       event->hw.state = 0;
+
+       sparc_pmu_enable_event(cpuc, &event->hw, idx);
+}
+
+static void sparc_pmu_stop(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int idx = active_event_index(cpuc, event);
+
+       if (!(event->hw.state & PERF_HES_STOPPED)) {
+               sparc_pmu_disable_event(cpuc, &event->hw, idx);
+               event->hw.state |= PERF_HES_STOPPED;
+       }
+
+       if (!(event->hw.state & PERF_HES_UPTODATE) && (flags & PERF_EF_UPDATE)) {
+               sparc_perf_event_update(event, &event->hw, idx);
+               event->hw.state |= PERF_HES_UPTODATE;
+       }
+}
+
+static void sparc_pmu_del(struct perf_event *event, int _flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
        unsigned long flags;
        int i;
 
        local_irq_save(flags);
-       perf_disable();
+       perf_pmu_disable(event->pmu);
 
        for (i = 0; i < cpuc->n_events; i++) {
                if (event == cpuc->event[i]) {
-                       int idx = cpuc->current_idx[i];
+                       /* Absorb the final count and turn off the
+                        * event.
+                        */
+                       sparc_pmu_stop(event, PERF_EF_UPDATE);
 
                        /* Shift remaining entries down into
                         * the existing slot.
@@ -734,13 +783,6 @@ static void sparc_pmu_disable(struct perf_event *event)
                                        cpuc->current_idx[i];
                        }
 
-                       /* Absorb the final count and turn off the
-                        * event.
-                        */
-                       sparc_pmu_disable_event(cpuc, hwc, idx);
-                       barrier();
-                       sparc_perf_event_update(event, hwc, idx);
-
                        perf_event_update_userpage(event);
 
                        cpuc->n_events--;
@@ -748,23 +790,10 @@ static void sparc_pmu_disable(struct perf_event *event)
                }
        }
 
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
-static int active_event_index(struct cpu_hw_events *cpuc,
-                             struct perf_event *event)
-{
-       int i;
-
-       for (i = 0; i < cpuc->n_events; i++) {
-               if (cpuc->event[i] == event)
-                       break;
-       }
-       BUG_ON(i == cpuc->n_events);
-       return cpuc->current_idx[i];
-}
-
 static void sparc_pmu_read(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -774,15 +803,6 @@ static void sparc_pmu_read(struct perf_event *event)
        sparc_perf_event_update(event, hwc, idx);
 }
 
-static void sparc_pmu_unthrottle(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       int idx = active_event_index(cpuc, event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       sparc_pmu_enable_event(cpuc, hwc, idx);
-}
-
 static atomic_t active_events = ATOMIC_INIT(0);
 static DEFINE_MUTEX(pmc_grab_mutex);
 
@@ -877,7 +897,7 @@ static int sparc_check_constraints(struct perf_event **evts,
        if (!n_ev)
                return 0;
 
-       if (n_ev > perf_max_events)
+       if (n_ev > MAX_HWEVENTS)
                return -1;
 
        msk0 = perf_event_get_msk(events[0]);
@@ -984,23 +1004,27 @@ static int collect_events(struct perf_event *group, int max_count,
        return n;
 }
 
-static int sparc_pmu_enable(struct perf_event *event)
+static int sparc_pmu_add(struct perf_event *event, int ef_flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int n0, ret = -EAGAIN;
        unsigned long flags;
 
        local_irq_save(flags);
-       perf_disable();
+       perf_pmu_disable(event->pmu);
 
        n0 = cpuc->n_events;
-       if (n0 >= perf_max_events)
+       if (n0 >= MAX_HWEVENTS)
                goto out;
 
        cpuc->event[n0] = event;
        cpuc->events[n0] = event->hw.event_base;
        cpuc->current_idx[n0] = PIC_NO_INDEX;
 
+       event->hw.state = PERF_HES_UPTODATE;
+       if (!(ef_flags & PERF_EF_START))
+               event->hw.state |= PERF_HES_STOPPED;
+
        /*
         * If group events scheduling transaction was started,
         * skip the schedulability test here, it will be peformed
@@ -1020,12 +1044,12 @@ nocheck:
 
        ret = 0;
 out:
-       perf_enable();
+       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
        return ret;
 }
 
-static int __hw_perf_event_init(struct perf_event *event)
+static int sparc_pmu_event_init(struct perf_event *event)
 {
        struct perf_event_attr *attr = &event->attr;
        struct perf_event *evts[MAX_HWEVENTS];
@@ -1038,16 +1062,37 @@ static int __hw_perf_event_init(struct perf_event *event)
        if (atomic_read(&nmi_active) < 0)
                return -ENODEV;
 
-       if (attr->type == PERF_TYPE_HARDWARE) {
+       switch (attr->type) {
+       case PERF_TYPE_HARDWARE:
                if (attr->config >= sparc_pmu->max_events)
                        return -EINVAL;
                pmap = sparc_pmu->event_map(attr->config);
-       } else if (attr->type == PERF_TYPE_HW_CACHE) {
+               break;
+
+       case PERF_TYPE_HW_CACHE:
                pmap = sparc_map_cache_event(attr->config);
                if (IS_ERR(pmap))
                        return PTR_ERR(pmap);
-       } else
-               return -EOPNOTSUPP;
+               break;
+
+       case PERF_TYPE_RAW:
+               pmap = NULL;
+               break;
+
+       default:
+               return -ENOENT;
+
+       }
+
+       if (pmap) {
+               hwc->event_base = perf_event_encode(pmap);
+       } else {
+               /*
+                * User gives us "(encoding << 16) | pic_mask" for
+                * PERF_TYPE_RAW events.
+                */
+               hwc->event_base = attr->config;
+       }
 
        /* We save the enable bits in the config_base.  */
        hwc->config_base = sparc_pmu->irq_bit;
@@ -1058,12 +1103,10 @@ static int __hw_perf_event_init(struct perf_event *event)
        if (!attr->exclude_hv)
                hwc->config_base |= sparc_pmu->hv_bit;
 
-       hwc->event_base = perf_event_encode(pmap);
-
        n = 0;
        if (event->group_leader != event) {
                n = collect_events(event->group_leader,
-                                  perf_max_events - 1,
+                                  MAX_HWEVENTS - 1,
                                   evts, events, current_idx_dmy);
                if (n < 0)
                        return -EINVAL;
@@ -1099,10 +1142,11 @@ static int __hw_perf_event_init(struct perf_event *event)
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-static void sparc_pmu_start_txn(const struct pmu *pmu)
+static void sparc_pmu_start_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
+       perf_pmu_disable(pmu);
        cpuhw->group_flag |= PERF_EVENT_TXN;
 }
 
@@ -1111,11 +1155,12 @@ static void sparc_pmu_start_txn(const struct pmu *pmu)
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-static void sparc_pmu_cancel_txn(const struct pmu *pmu)
+static void sparc_pmu_cancel_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
        cpuhw->group_flag &= ~PERF_EVENT_TXN;
+       perf_pmu_enable(pmu);
 }
 
 /*
@@ -1123,7 +1168,7 @@ static void sparc_pmu_cancel_txn(const struct pmu *pmu)
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-static int sparc_pmu_commit_txn(const struct pmu *pmu)
+static int sparc_pmu_commit_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int n;
@@ -1139,28 +1184,24 @@ static int sparc_pmu_commit_txn(const struct pmu *pmu)
                return -EAGAIN;
 
        cpuc->group_flag &= ~PERF_EVENT_TXN;
+       perf_pmu_enable(pmu);
        return 0;
 }
 
-static const struct pmu pmu = {
-       .enable         = sparc_pmu_enable,
-       .disable        = sparc_pmu_disable,
+static struct pmu pmu = {
+       .pmu_enable     = sparc_pmu_enable,
+       .pmu_disable    = sparc_pmu_disable,
+       .event_init     = sparc_pmu_event_init,
+       .add            = sparc_pmu_add,
+       .del            = sparc_pmu_del,
+       .start          = sparc_pmu_start,
+       .stop           = sparc_pmu_stop,
        .read           = sparc_pmu_read,
-       .unthrottle     = sparc_pmu_unthrottle,
        .start_txn      = sparc_pmu_start_txn,
        .cancel_txn     = sparc_pmu_cancel_txn,
        .commit_txn     = sparc_pmu_commit_txn,
 };
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
-{
-       int err = __hw_perf_event_init(event);
-
-       if (err)
-               return ERR_PTR(err);
-       return &pmu;
-}
-
 void perf_event_print_debug(void)
 {
        unsigned long flags;
@@ -1236,7 +1277,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
                        continue;
 
                if (perf_event_overflow(event, 1, &data, regs))
-                       sparc_pmu_disable_event(cpuc, hwc, idx);
+                       sparc_pmu_stop(event, 0);
        }
 
        return NOTIFY_STOP;
@@ -1277,28 +1318,21 @@ void __init init_hw_perf_events(void)
 
        pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-       /* All sparc64 PMUs currently have 2 events.  */
-       perf_max_events = 2;
-
+       perf_pmu_register(&pmu);
        register_die_notifier(&perf_event_nmi_notifier);
 }
 
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-       if (entry->nr < PERF_MAX_STACK_DEPTH)
-               entry->ip[entry->nr++] = ip;
-}
-
-static void perf_callchain_kernel(struct pt_regs *regs,
-                                 struct perf_callchain_entry *entry)
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+                          struct pt_regs *regs)
 {
        unsigned long ksp, fp;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        int graph = 0;
 #endif
 
-       callchain_store(entry, PERF_CONTEXT_KERNEL);
-       callchain_store(entry, regs->tpc);
+       stack_trace_flush();
+
+       perf_callchain_store(entry, regs->tpc);
 
        ksp = regs->u_regs[UREG_I6];
        fp = ksp + STACK_BIAS;
@@ -1322,13 +1356,13 @@ static void perf_callchain_kernel(struct pt_regs *regs,
                        pc = sf->callers_pc;
                        fp = (unsigned long)sf->fp + STACK_BIAS;
                }
-               callchain_store(entry, pc);
+               perf_callchain_store(entry, pc);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
                if ((pc + 8UL) == (unsigned long) &return_to_handler) {
                        int index = current->curr_ret_stack;
                        if (current->ret_stack && index >= graph) {
                                pc = current->ret_stack[index - graph].ret;
-                               callchain_store(entry, pc);
+                               perf_callchain_store(entry, pc);
                                graph++;
                        }
                }
@@ -1336,13 +1370,12 @@ static void perf_callchain_kernel(struct pt_regs *regs,
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-static void perf_callchain_user_64(struct pt_regs *regs,
-                                  struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+                                  struct pt_regs *regs)
 {
        unsigned long ufp;
 
-       callchain_store(entry, PERF_CONTEXT_USER);
-       callchain_store(entry, regs->tpc);
+       perf_callchain_store(entry, regs->tpc);
 
        ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
        do {
@@ -1355,17 +1388,16 @@ static void perf_callchain_user_64(struct pt_regs *regs,
 
                pc = sf.callers_pc;
                ufp = (unsigned long)sf.fp + STACK_BIAS;
-               callchain_store(entry, pc);
+               perf_callchain_store(entry, pc);
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-static void perf_callchain_user_32(struct pt_regs *regs,
-                                  struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+                                  struct pt_regs *regs)
 {
        unsigned long ufp;
 
-       callchain_store(entry, PERF_CONTEXT_USER);
-       callchain_store(entry, regs->tpc);
+       perf_callchain_store(entry, regs->tpc);
 
        ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
        do {
@@ -1378,34 +1410,16 @@ static void perf_callchain_user_32(struct pt_regs *regs,
 
                pc = sf.callers_pc;
                ufp = (unsigned long)sf.fp;
-               callchain_store(entry, pc);
+               perf_callchain_store(entry, pc);
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-/* Like powerpc we can't get PMU interrupts within the PMU handler,
- * so no need for separate NMI and IRQ chains as on x86.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-       struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
-       entry->nr = 0;
-       if (!user_mode(regs)) {
-               stack_trace_flush();
-               perf_callchain_kernel(regs, entry);
-               if (current->mm)
-                       regs = task_pt_regs(current);
-               else
-                       regs = NULL;
-       }
-       if (regs) {
-               flushw_user();
-               if (test_thread_flag(TIF_32BIT))
-                       perf_callchain_user_32(regs, entry);
-               else
-                       perf_callchain_user_64(regs, entry);
-       }
-       return entry;
+       flushw_user();
+       if (test_thread_flag(TIF_32BIT))
+               perf_callchain_user_32(entry, regs);
+       else
+               perf_callchain_user_64(entry, regs);
 }
index 485f547483847da14aebfaa0e327c6cbb75dce24..c158a95ec664f1301d78ceb433d99a1c94098dbc 100644 (file)
@@ -303,7 +303,7 @@ void arch_trigger_all_cpu_backtrace(void)
 
 #ifdef CONFIG_MAGIC_SYSRQ
 
-static void sysrq_handle_globreg(int key, struct tty_struct *tty)
+static void sysrq_handle_globreg(int key)
 {
        arch_trigger_all_cpu_backtrace();
 }
index ea22cd373c64f4bc371478d2b7be14f71cd32560..75fad425e249bc40559f98d14ead5699839bbbb8 100644 (file)
@@ -453,8 +453,66 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
        return err;
 }
 
-static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
-                         int signo, sigset_t *oldset)
+/* The I-cache flush instruction only works in the primary ASI, which
+ * right now is the nucleus, aka. kernel space.
+ *
+ * Therefore we have to kick the instructions out using the kernel
+ * side linear mapping of the physical address backing the user
+ * instructions.
+ */
+static void flush_signal_insns(unsigned long address)
+{
+       unsigned long pstate, paddr;
+       pte_t *ptep, pte;
+       pgd_t *pgdp;
+       pud_t *pudp;
+       pmd_t *pmdp;
+
+       /* Commit all stores of the instructions we are about to flush.  */
+       wmb();
+
+       /* Disable cross-call reception.  In this way even a very wide
+        * munmap() on another cpu can't tear down the page table
+        * hierarchy from underneath us, since that can't complete
+        * until the IPI tlb flush returns.
+        */
+
+       __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
+       __asm__ __volatile__("wrpr %0, %1, %%pstate"
+                               : : "r" (pstate), "i" (PSTATE_IE));
+
+       pgdp = pgd_offset(current->mm, address);
+       if (pgd_none(*pgdp))
+               goto out_irqs_on;
+       pudp = pud_offset(pgdp, address);
+       if (pud_none(*pudp))
+               goto out_irqs_on;
+       pmdp = pmd_offset(pudp, address);
+       if (pmd_none(*pmdp))
+               goto out_irqs_on;
+
+       ptep = pte_offset_map(pmdp, address);
+       pte = *ptep;
+       if (!pte_present(pte))
+               goto out_unmap;
+
+       paddr = (unsigned long) page_address(pte_page(pte));
+
+       __asm__ __volatile__("flush     %0 + %1"
+                            : /* no outputs */
+                            : "r" (paddr),
+                              "r" (address & (PAGE_SIZE - 1))
+                            : "memory");
+
+out_unmap:
+       pte_unmap(ptep);
+out_irqs_on:
+       __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
+
+}
+
+static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+                        int signo, sigset_t *oldset)
 {
        struct signal_frame32 __user *sf;
        int sigframe_size;
@@ -547,13 +605,7 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        if (ka->ka_restorer) {
                regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
        } else {
-               /* Flush instruction space. */
                unsigned long address = ((unsigned long)&(sf->insns[0]));
-               pgd_t *pgdp = pgd_offset(current->mm, address);
-               pud_t *pudp = pud_offset(pgdp, address);
-               pmd_t *pmdp = pmd_offset(pudp, address);
-               pte_t *ptep;
-               pte_t pte;
 
                regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
        
@@ -562,34 +614,22 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                if (err)
                        goto sigsegv;
 
-               preempt_disable();
-               ptep = pte_offset_map(pmdp, address);
-               pte = *ptep;
-               if (pte_present(pte)) {
-                       unsigned long page = (unsigned long)
-                               page_address(pte_page(pte));
-
-                       wmb();
-                       __asm__ __volatile__("flush     %0 + %1"
-                                            : /* no outputs */
-                                            : "r" (page),
-                                              "r" (address & (PAGE_SIZE - 1))
-                                            : "memory");
-               }
-               pte_unmap(ptep);
-               preempt_enable();
+               flush_signal_insns(address);
        }
-       return;
+       return 0;
 
 sigill:
        do_exit(SIGILL);
+       return -EINVAL;
+
 sigsegv:
        force_sigsegv(signo, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
-                            unsigned long signr, sigset_t *oldset,
-                            siginfo_t *info)
+static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+                           unsigned long signr, sigset_t *oldset,
+                           siginfo_t *info)
 {
        struct rt_signal_frame32 __user *sf;
        int sigframe_size;
@@ -687,12 +727,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        if (ka->ka_restorer)
                regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
        else {
-               /* Flush instruction space. */
                unsigned long address = ((unsigned long)&(sf->insns[0]));
-               pgd_t *pgdp = pgd_offset(current->mm, address);
-               pud_t *pudp = pud_offset(pgdp, address);
-               pmd_t *pmdp = pmd_offset(pudp, address);
-               pte_t *ptep;
 
                regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
        
@@ -704,38 +739,32 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                if (err)
                        goto sigsegv;
 
-               preempt_disable();
-               ptep = pte_offset_map(pmdp, address);
-               if (pte_present(*ptep)) {
-                       unsigned long page = (unsigned long)
-                               page_address(pte_page(*ptep));
-
-                       wmb();
-                       __asm__ __volatile__("flush     %0 + %1"
-                                            : /* no outputs */
-                                            : "r" (page),
-                                              "r" (address & (PAGE_SIZE - 1))
-                                            : "memory");
-               }
-               pte_unmap(ptep);
-               preempt_enable();
+               flush_signal_insns(address);
        }
-       return;
+       return 0;
 
 sigill:
        do_exit(SIGILL);
+       return -EINVAL;
+
 sigsegv:
        force_sigsegv(signr, current);
+       return -EFAULT;
 }
 
-static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
-                                  siginfo_t *info,
-                                  sigset_t *oldset, struct pt_regs *regs)
+static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
+                                 siginfo_t *info,
+                                 sigset_t *oldset, struct pt_regs *regs)
 {
+       int err;
+
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame32(ka, regs, signr, oldset, info);
+               err = setup_rt_frame32(ka, regs, signr, oldset, info);
        else
-               setup_frame32(ka, regs, signr, oldset);
+               err = setup_frame32(ka, regs, signr, oldset);
+
+       if (err)
+               return err;
 
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -743,6 +772,10 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
                sigaddset(&current->blocked,signr);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
+
+       tracehook_signal_handler(signr, info, ka, regs, 0);
+
+       return 0;
 }
 
 static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
@@ -789,16 +822,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart32(orig_i0, regs, &ka.sa);
-               handle_signal32(signr, &ka, &info, oldset, regs);
-
-               /* A signal was successfully delivered; the saved
-                * sigmask will have been stored in the signal frame,
-                * and will be restored by sigreturn, so we can simply
-                * clear the TS_RESTORE_SIGMASK flag.
-                */
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-               tracehook_signal_handler(signr, &info, &ka, regs, 0);
+               if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) {
+                       /* A signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+               }
                return;
        }
        if (restart_syscall &&
@@ -809,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
                regs->u_regs[UREG_I0] = orig_i0;
                regs->tpc -= 4;
                regs->tnpc -= 4;
+               pt_regs_clear_syscall(regs);
        }
        if (restart_syscall &&
            regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                regs->tpc -= 4;
                regs->tnpc -= 4;
+               pt_regs_clear_syscall(regs);
        }
 
        /* If there's no signal to deliver, we just put the saved sigmask
index 9882df92ba0a2c8b8da4639f7e181214930c8ed6..5e5c5fd03783c997f5c344025e8f4784182a0ddc 100644 (file)
@@ -315,8 +315,8 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
        return err;
 }
 
-static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
-                       int signo, sigset_t *oldset)
+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;
@@ -384,16 +384,19 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
                /* Flush instruction space. */
                flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
        }
-       return;
+       return 0;
 
 sigill_and_return:
        do_exit(SIGILL);
+       return -EINVAL;
+
 sigsegv:
        force_sigsegv(signo, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
-                          int signo, sigset_t *oldset, siginfo_t *info)
+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;
@@ -466,22 +469,30 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
                /* Flush instruction space. */
                flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
        }
-       return;
+       return 0;
 
 sigill:
        do_exit(SIGILL);
+       return -EINVAL;
+
 sigsegv:
        force_sigsegv(signo, current);
+       return -EFAULT;
 }
 
-static inline void
+static inline int
 handle_signal(unsigned long signr, struct k_sigaction *ka,
              siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
+       int err;
+
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(ka, regs, signr, oldset, info);
+               err = setup_rt_frame(ka, regs, signr, oldset, info);
        else
-               setup_frame(ka, regs, signr, oldset);
+               err = setup_frame(ka, regs, signr, oldset);
+
+       if (err)
+               return err;
 
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -489,6 +500,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
                sigaddset(&current->blocked, signr);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
+
+       tracehook_signal_handler(signr, info, ka, regs, 0);
+
+       return 0;
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -546,17 +561,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart(orig_i0, regs, &ka.sa);
-               handle_signal(signr, &ka, &info, oldset, regs);
-
-               /* a signal was successfully delivered; the saved
-                * sigmask will have been stored in the signal frame,
-                * and will be restored by sigreturn, so we can simply
-                * clear the TIF_RESTORE_SIGMASK flag.
-                */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-               tracehook_signal_handler(signr, &info, &ka, regs, 0);
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag.
+                        */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
                return;
        }
        if (restart_syscall &&
@@ -567,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                regs->u_regs[UREG_I0] = orig_i0;
                regs->pc -= 4;
                regs->npc -= 4;
+               pt_regs_clear_syscall(regs);
        }
        if (restart_syscall &&
            regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                regs->pc -= 4;
                regs->npc -= 4;
+               pt_regs_clear_syscall(regs);
        }
 
        /* if there's no signal to deliver, we just put the saved sigmask
index 9fa48c30037e5356c2f686be695ea8bcfb3613f3..006fe4515886dc6ae2a7a8e6cc9b6df9c16fda46 100644 (file)
@@ -409,7 +409,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
        return (void __user *) sp;
 }
 
-static inline void
+static inline int
 setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
               int signo, sigset_t *oldset, siginfo_t *info)
 {
@@ -483,26 +483,37 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        }
        /* 4. return to kernel instructions */
        regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
-       return;
+       return 0;
 
 sigill:
        do_exit(SIGILL);
+       return -EINVAL;
+
 sigsegv:
        force_sigsegv(signo, current);
+       return -EFAULT;
 }
 
-static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
-                                siginfo_t *info,
-                                sigset_t *oldset, struct pt_regs *regs)
+static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
+                               siginfo_t *info,
+                               sigset_t *oldset, struct pt_regs *regs)
 {
-       setup_rt_frame(ka, regs, signr, oldset,
-                      (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
+       int err;
+
+       err = setup_rt_frame(ka, regs, signr, oldset,
+                            (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
+       if (err)
+               return err;
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NOMASK))
                sigaddset(&current->blocked,signr);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
+
+       tracehook_signal_handler(signr, info, ka, regs, 0);
+
+       return 0;
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -571,16 +582,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart(orig_i0, regs, &ka.sa);
-               handle_signal(signr, &ka, &info, oldset, regs);
-
-               /* A signal was successfully delivered; the saved
-                * sigmask will have been stored in the signal frame,
-                * and will be restored by sigreturn, so we can simply
-                * clear the TS_RESTORE_SIGMASK flag.
-                */
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-               tracehook_signal_handler(signr, &info, &ka, regs, 0);
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       /* A signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+               }
                return;
        }
        if (restart_syscall &&
@@ -591,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                regs->u_regs[UREG_I0] = orig_i0;
                regs->tpc -= 4;
                regs->tnpc -= 4;
+               pt_regs_clear_syscall(regs);
        }
        if (restart_syscall &&
            regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                regs->tpc -= 4;
                regs->tnpc -= 4;
+               pt_regs_clear_syscall(regs);
        }
 
        /* If there's no signal to deliver, we just put the saved sigmask
index 50794137d710d71bfa197cbb055d14377f2cd770..675c9e11ada5541085e2fd6e6129272c05713df4 100644 (file)
@@ -166,7 +166,6 @@ sparc_breakpoint (struct pt_regs *regs)
 {
        siginfo_t info;
 
-       lock_kernel();
 #ifdef DEBUG_SPARC_BREAKPOINT
         printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc);
 #endif
@@ -180,7 +179,6 @@ sparc_breakpoint (struct pt_regs *regs)
 #ifdef DEBUG_SPARC_BREAKPOINT
        printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc);
 #endif
-       unlock_kernel();
 }
 
 asmlinkage int
index f8514e291e1559ecda6994ff5be883cc6805128c..12b9f352595f44e26c3f5730d3a84e8557d8cca8 100644 (file)
@@ -323,7 +323,6 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 {
        enum direction dir;
 
-       lock_kernel();
        if(!(current->thread.flags & SPARC_FLAG_UNALIGNED) ||
           (((insn >> 30) & 3) != 3))
                goto kill_user;
@@ -377,5 +376,5 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 kill_user:
        user_mna_trap_fault(regs, insn);
 out:
-       unlock_kernel();
+       ;
 }
index f24d298bda29d1ca0457b0b7060a366ace463756..b351770cbdd6aded05ca53554b30c8716a24a4ce 100644 (file)
@@ -112,7 +112,6 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
        struct thread_info *tp = current_thread_info();
        int window;
 
-       lock_kernel();
        flush_user_windows();
        for(window = 0; window < tp->w_saved; window++) {
                unsigned long sp = tp->rwbuf_stkptrs[window];
@@ -123,5 +122,4 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
                        do_exit(SIGILL);
        }
        tp->w_saved = 0;
-       unlock_kernel();
 }
index c4b5e03af11557efa6ae42aa11f9ce0d74dfa42a..846d1c4374ea9c0c24a64bc4088185388274afd3 100644 (file)
@@ -15,7 +15,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
 lib-$(CONFIG_SPARC32) += copy_user.o locks.o
 lib-y                 += atomic_$(BITS).o
 lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
-lib-y                 += rwsem_$(BITS).o
+lib-$(CONFIG_SPARC32) += rwsem_32.o
 lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
 
 lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
index 0268210ca1683f7bd0bb018953d93a22e207c701..59186e0fcf398feb5880b37fa28624230e0c756b 100644 (file)
@@ -21,7 +21,7 @@ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
        add     %g1, %o0, %g7
        cas     [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %icc, 2f
+       bne,pn  %icc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -36,7 +36,7 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
        sub     %g1, %o0, %g7
        cas     [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %icc, 2f
+       bne,pn  %icc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -51,11 +51,10 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
        add     %g1, %o0, %g7
        cas     [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %icc, 2f
-        add    %g7, %o0, %g7
-       sra     %g7, 0, %o0
+       bne,pn  %icc, BACKOFF_LABEL(2f, 1b)
+        add    %g1, %o0, %g1
        retl
-        nop
+        sra    %g1, 0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
        .size   atomic_add_ret, .-atomic_add_ret
 
@@ -67,11 +66,10 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
        sub     %g1, %o0, %g7
        cas     [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %icc, 2f
-        sub    %g7, %o0, %g7
-       sra     %g7, 0, %o0
+       bne,pn  %icc, BACKOFF_LABEL(2f, 1b)
+        sub    %g1, %o0, %g1
        retl
-        nop
+        sra    %g1, 0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
        .size   atomic_sub_ret, .-atomic_sub_ret
 
@@ -83,7 +81,7 @@ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
        add     %g1, %o0, %g7
        casx    [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -98,7 +96,7 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
        sub     %g1, %o0, %g7
        casx    [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -113,11 +111,10 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
        add     %g1, %o0, %g7
        casx    [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %xcc, 2f
-        add    %g7, %o0, %g7
-       mov     %g7, %o0
-       retl
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
+       retl
+        add    %g1, %o0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
        .size   atomic64_add_ret, .-atomic64_add_ret
 
@@ -129,10 +126,9 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
        sub     %g1, %o0, %g7
        casx    [%o1], %g1, %g7
        cmp     %g1, %g7
-       bne,pn  %xcc, 2f
-        sub    %g7, %o0, %g7
-       mov     %g7, %o0
-       retl
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
+       retl
+        sub    %g1, %o0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
        .size   atomic64_sub_ret, .-atomic64_sub_ret
index 2b7228cb8c2209332000d429257f16f4dbcf730f..3dc61d5537c08a6ad56f37b90df340a527298bb7 100644 (file)
@@ -22,7 +22,7 @@ test_and_set_bit:     /* %o0=nr, %o1=addr */
        or      %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         and    %g7, %o2, %g2
        clr     %o0
        movrne  %g2, 1, %o0
@@ -45,7 +45,7 @@ test_and_clear_bit:   /* %o0=nr, %o1=addr */
        andn    %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         and    %g7, %o2, %g2
        clr     %o0
        movrne  %g2, 1, %o0
@@ -68,7 +68,7 @@ test_and_change_bit:  /* %o0=nr, %o1=addr */
        xor     %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         and    %g7, %o2, %g2
        clr     %o0
        movrne  %g2, 1, %o0
@@ -91,7 +91,7 @@ set_bit:              /* %o0=nr, %o1=addr */
        or      %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -112,7 +112,7 @@ clear_bit:          /* %o0=nr, %o1=addr */
        andn    %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
@@ -133,7 +133,7 @@ change_bit:         /* %o0=nr, %o1=addr */
        xor     %g7, %o2, %g1
        casx    [%o1], %g7, %g1
        cmp     %g7, %g1
-       bne,pn  %xcc, 2f
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
         nop
        retl
         nop
diff --git a/arch/sparc/lib/rwsem_64.S b/arch/sparc/lib/rwsem_64.S
deleted file mode 100644 (file)
index 91a7d29..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/* rwsem.S: RW semaphore assembler.
- *
- * Written by David S. Miller (davem@redhat.com), 2001.
- * Derived from asm-i386/rwsem.h
- */
-
-#include <asm/rwsem-const.h>
-
-       .section        .sched.text, "ax"
-
-       .globl          __down_read
-__down_read:
-1:     lduw            [%o0], %g1
-       add             %g1, 1, %g7
-       cas             [%o0], %g1, %g7
-       cmp             %g1, %g7
-       bne,pn          %icc, 1b
-        add            %g7, 1, %g7
-       cmp             %g7, 0
-       bl,pn           %icc, 3f
-        nop
-2:
-       retl
-        nop
-3:
-       save            %sp, -192, %sp
-       call            rwsem_down_read_failed
-        mov            %i0, %o0
-       ret
-        restore
-       .size           __down_read, .-__down_read
-
-       .globl          __down_read_trylock
-__down_read_trylock:
-1:     lduw            [%o0], %g1
-       add             %g1, 1, %g7
-       cmp             %g7, 0
-       bl,pn           %icc, 2f
-        mov            0, %o1
-       cas             [%o0], %g1, %g7
-       cmp             %g1, %g7
-       bne,pn          %icc, 1b
-        mov            1, %o1
-2:     retl
-        mov            %o1, %o0
-       .size           __down_read_trylock, .-__down_read_trylock
-
-       .globl          __down_write
-__down_write:
-       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
-       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
-1:
-       lduw            [%o0], %g3
-       add             %g3, %g1, %g7
-       cas             [%o0], %g3, %g7
-       cmp             %g3, %g7
-       bne,pn          %icc, 1b
-        cmp            %g7, 0
-       bne,pn          %icc, 3f
-        nop
-2:     retl
-        nop
-3:
-       save            %sp, -192, %sp
-       call            rwsem_down_write_failed
-        mov            %i0, %o0
-       ret
-        restore
-       .size           __down_write, .-__down_write
-
-       .globl          __down_write_trylock
-__down_write_trylock:
-       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
-       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
-1:
-       lduw            [%o0], %g3
-       cmp             %g3, 0
-       bne,pn          %icc, 2f
-        mov            0, %o1
-       add             %g3, %g1, %g7
-       cas             [%o0], %g3, %g7
-       cmp             %g3, %g7
-       bne,pn          %icc, 1b
-        mov            1, %o1
-2:     retl
-        mov            %o1, %o0
-       .size           __down_write_trylock, .-__down_write_trylock
-
-       .globl          __up_read
-__up_read:
-1:
-       lduw            [%o0], %g1
-       sub             %g1, 1, %g7
-       cas             [%o0], %g1, %g7
-       cmp             %g1, %g7
-       bne,pn          %icc, 1b
-        cmp            %g7, 0
-       bl,pn           %icc, 3f
-        nop
-2:     retl
-        nop
-3:     sethi           %hi(RWSEM_ACTIVE_MASK), %g1
-       sub             %g7, 1, %g7
-       or              %g1, %lo(RWSEM_ACTIVE_MASK), %g1
-       andcc           %g7, %g1, %g0
-       bne,pn          %icc, 2b
-        nop
-       save            %sp, -192, %sp
-       call            rwsem_wake
-        mov            %i0, %o0
-       ret
-        restore
-       .size           __up_read, .-__up_read
-
-       .globl          __up_write
-__up_write:
-       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
-       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
-1:
-       lduw            [%o0], %g3
-       sub             %g3, %g1, %g7
-       cas             [%o0], %g3, %g7
-       cmp             %g3, %g7
-       bne,pn          %icc, 1b
-        sub            %g7, %g1, %g7
-       cmp             %g7, 0
-       bl,pn           %icc, 3f
-        nop
-2:
-       retl
-        nop
-3:
-       save            %sp, -192, %sp
-       call            rwsem_wake
-        mov            %i0, %o0
-       ret
-        restore
-       .size           __up_write, .-__up_write
-
-       .globl          __downgrade_write
-__downgrade_write:
-       sethi           %hi(RWSEM_WAITING_BIAS), %g1
-       or              %g1, %lo(RWSEM_WAITING_BIAS), %g1
-1:
-       lduw            [%o0], %g3
-       sub             %g3, %g1, %g7
-       cas             [%o0], %g3, %g7
-       cmp             %g3, %g7
-       bne,pn          %icc, 1b
-        sub            %g7, %g1, %g7
-       cmp             %g7, 0
-       bl,pn           %icc, 3f
-        nop
-2:
-       retl
-        nop
-3:
-       save            %sp, -192, %sp
-       call            rwsem_downgrade_wake
-        mov            %i0, %o0
-       ret
-        restore
-       .size           __downgrade_write, .-__downgrade_write
index f0434513df159301da052662442b281bea30b5c5..4c2572773b55a330868933b633882f9520a155ba 100644 (file)
@@ -785,8 +785,7 @@ static int find_node(unsigned long addr)
        return -1;
 }
 
-static unsigned long long nid_range(unsigned long long start,
-                                   unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
        *nid = find_node(start);
        start += PAGE_SIZE;
@@ -804,8 +803,7 @@ static unsigned long long nid_range(unsigned long long start,
        return start;
 }
 #else
-static unsigned long long nid_range(unsigned long long start,
-                                   unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
        *nid = 0;
        return end;
@@ -822,8 +820,7 @@ static void __init allocate_node_data(int nid)
        struct pglist_data *p;
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-       paddr = memblock_alloc_nid(sizeof(struct pglist_data),
-                             SMP_CACHE_BYTES, nid, nid_range);
+       paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid);
        if (!paddr) {
                prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
                prom_halt();
@@ -843,8 +840,7 @@ static void __init allocate_node_data(int nid)
        if (p->node_spanned_pages) {
                num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
 
-               paddr = memblock_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
-                                     nid_range);
+               paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid);
                if (!paddr) {
                        prom_printf("Cannot allocate bootmap for nid[%d]\n",
                                  nid);
@@ -972,19 +968,19 @@ int of_node_to_nid(struct device_node *dp)
 
 static void __init add_node_ranges(void)
 {
-       int i;
+       struct memblock_region *reg;
 
-       for (i = 0; i < memblock.memory.cnt; i++) {
-               unsigned long size = memblock_size_bytes(&memblock.memory, i);
+       for_each_memblock(memory, reg) {
+               unsigned long size = reg->size;
                unsigned long start, end;
 
-               start = memblock.memory.region[i].base;
+               start = reg->base;
                end = start + size;
                while (start < end) {
                        unsigned long this_end;
                        int nid;
 
-                       this_end = nid_range(start, end, &nid);
+                       this_end = memblock_nid_range(start, end, &nid);
 
                        numadbg("Adding active range nid[%d] "
                                "start[%lx] end[%lx]\n",
@@ -1281,7 +1277,7 @@ static void __init bootmem_init_nonnuma(void)
 {
        unsigned long top_of_ram = memblock_end_of_DRAM();
        unsigned long total_ram = memblock_phys_mem_size();
-       unsigned int i;
+       struct memblock_region *reg;
 
        numadbg("bootmem_init_nonnuma()\n");
 
@@ -1292,15 +1288,14 @@ static void __init bootmem_init_nonnuma(void)
 
        init_node_masks_nonnuma();
 
-       for (i = 0; i < memblock.memory.cnt; i++) {
-               unsigned long size = memblock_size_bytes(&memblock.memory, i);
+       for_each_memblock(memory, reg) {
                unsigned long start_pfn, end_pfn;
 
-               if (!size)
+               if (!reg->size)
                        continue;
 
-               start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-               end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                add_active_range(0, start_pfn, end_pfn);
        }
 
@@ -1318,7 +1313,7 @@ static void __init reserve_range_in_node(int nid, unsigned long start,
                unsigned long this_end;
                int n;
 
-               this_end = nid_range(start, end, &n);
+               this_end = memblock_nid_range(start, end, &n);
                if (n == nid) {
                        numadbg("      MATCH reserving range [%lx:%lx]\n",
                                start, this_end);
@@ -1334,17 +1329,12 @@ static void __init reserve_range_in_node(int nid, unsigned long start,
 
 static void __init trim_reserved_in_node(int nid)
 {
-       int i;
+       struct memblock_region *reg;
 
        numadbg("  trim_reserved_in_node(%d)\n", nid);
 
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               unsigned long start = memblock.reserved.region[i].base;
-               unsigned long size = memblock_size_bytes(&memblock.reserved, i);
-               unsigned long end = start + size;
-
-               reserve_range_in_node(nid, start, end);
-       }
+       for_each_memblock(reserved, reg)
+               reserve_range_in_node(nid, reg->base, reg->base + reg->size);
 }
 
 static void __init bootmem_init_one_node(int nid)
index 5f27ad779c0c578097218e44b005eaed770acf7d..9c86b4b7d4290b75a5967c28790c59b3ee24b5c9 100644 (file)
@@ -9,18 +9,18 @@
 #include <asm/thread_info.h>
 
        .text
-       .globl  prom_cif_interface
-prom_cif_interface:
-       sethi   %hi(p1275buf), %o0
-       or      %o0, %lo(p1275buf), %o0
-       ldx     [%o0 + 0x010], %o1      ! prom_cif_stack
-       save    %o1, -192, %sp
-       ldx     [%i0 + 0x008], %l2      ! prom_cif_handler
+       .globl  prom_cif_direct
+prom_cif_direct:
+       sethi   %hi(p1275buf), %o1
+       or      %o1, %lo(p1275buf), %o1
+       ldx     [%o1 + 0x0010], %o2     ! prom_cif_stack
+       save    %o2, -192, %sp
+       ldx     [%i1 + 0x0008], %l2     ! prom_cif_handler
        mov     %g4, %l0
        mov     %g5, %l1
        mov     %g6, %l3
        call    %l2
-        add    %i0, 0x018, %o0         ! prom_args
+        mov    %i0, %o0                ! prom_args
        mov     %l0, %g4
        mov     %l1, %g5
        mov     %l3, %g6
index f55d58a8a1567a653f8517598edcfe7f777b4257..10322dc2f557a22d5befcc17dd4a27d8b6604f89 100644 (file)
@@ -21,14 +21,22 @@ extern int prom_stdin, prom_stdout;
 inline int
 prom_nbgetchar(void)
 {
+       unsigned long args[7];
        char inc;
 
-       if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
-                             P1275_INOUT(3,1),
-                             prom_stdin, &inc, P1275_SIZE(1)) == 1)
+       args[0] = (unsigned long) "read";
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) prom_stdin;
+       args[4] = (unsigned long) &inc;
+       args[5] = 1;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       if (args[6] == 1)
                return inc;
-       else
-               return -1;
+       return -1;
 }
 
 /* Non blocking put character to console device, returns -1 if
@@ -37,12 +45,22 @@ prom_nbgetchar(void)
 inline int
 prom_nbputchar(char c)
 {
+       unsigned long args[7];
        char outc;
        
        outc = c;
-       if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
-                              P1275_INOUT(3,1),
-                              prom_stdout, &outc, P1275_SIZE(1)) == 1)
+
+       args[0] = (unsigned long) "write";
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) prom_stdout;
+       args[4] = (unsigned long) &outc;
+       args[5] = 1;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       if (args[6] == 1)
                return 0;
        else
                return -1;
@@ -67,7 +85,15 @@ prom_putchar(char c)
 void
 prom_puts(const char *s, int len)
 {
-       p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
-                          P1275_INOUT(3,1),
-                          prom_stdout, s, P1275_SIZE(len));
+       unsigned long args[7];
+
+       args[0] = (unsigned long) "write";
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) prom_stdout;
+       args[4] = (unsigned long) s;
+       args[5] = len;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
 }
index 9dbd803e46e1f4c460300c6f5f2485f3d6c54e7d..a017119e7ef17c40ee8fa8328252f921c59a6ca8 100644 (file)
 int
 prom_devopen(const char *dstr)
 {
-       return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
-                                 P1275_INOUT(1,1),
-                                 dstr);
+       unsigned long args[5];
+
+       args[0] = (unsigned long) "open";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned long) dstr;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[4];
 }
 
 /* Close the device described by device handle 'dhandle'. */
 int
 prom_devclose(int dhandle)
 {
-       p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
+       unsigned long args[4];
+
+       args[0] = (unsigned long) "close";
+       args[1] = 1;
+       args[2] = 0;
+       args[3] = (unsigned int) dhandle;
+
+       p1275_cmd_direct(args);
+
        return 0;
 }
 
@@ -37,5 +53,15 @@ prom_devclose(int dhandle)
 void
 prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
 {
-       p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
+       unsigned long args[7];
+
+       args[0] = (unsigned long) "seek";
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) dhandle;
+       args[4] = seekhi;
+       args[5] = seeklo;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
 }
index 39fc6af21b7c55ddc0e752c80c745ed6c018820a..6cb1581d6aef507fca9c036708cebe24e5ab053c 100644 (file)
 
 int prom_service_exists(const char *service_name)
 {
-       int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
-                           P1275_INOUT(1, 1), service_name);
+       unsigned long args[5];
 
-       if (err)
+       args[0] = (unsigned long) "test";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned long) service_name;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       if (args[4])
                return 0;
        return 1;
 }
@@ -31,30 +38,47 @@ int prom_service_exists(const char *service_name)
 void prom_sun4v_guest_soft_state(void)
 {
        const char *svc = "SUNW,soft-state-supported";
+       unsigned long args[3];
 
        if (!prom_service_exists(svc))
                return;
-       p1275_cmd(svc, P1275_INOUT(0, 0));
+       args[0] = (unsigned long) svc;
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
 }
 
 /* Reset and reboot the machine with the command 'bcommand'. */
 void prom_reboot(const char *bcommand)
 {
+       unsigned long args[4];
+
 #ifdef CONFIG_SUN_LDOMS
        if (ldom_domaining_enabled)
                ldom_reboot(bcommand);
 #endif
-       p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
-                 P1275_INOUT(1, 0), bcommand);
+       args[0] = (unsigned long) "boot";
+       args[1] = 1;
+       args[2] = 0;
+       args[3] = (unsigned long) bcommand;
+
+       p1275_cmd_direct(args);
 }
 
 /* Forth evaluate the expression contained in 'fstring'. */
 void prom_feval(const char *fstring)
 {
+       unsigned long args[5];
+
        if (!fstring || fstring[0] == 0)
                return;
-       p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
-                 P1275_INOUT(1, 1), fstring);
+       args[0] = (unsigned long) "interpret";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned long) fstring;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
 }
 EXPORT_SYMBOL(prom_feval);
 
@@ -68,6 +92,7 @@ extern void smp_release(void);
  */
 void prom_cmdline(void)
 {
+       unsigned long args[3];
        unsigned long flags;
 
        local_irq_save(flags);
@@ -76,7 +101,11 @@ void prom_cmdline(void)
        smp_capture();
 #endif
 
-       p1275_cmd("enter", P1275_INOUT(0, 0));
+       args[0] = (unsigned long) "enter";
+       args[1] = 0;
+       args[2] = 0;
+
+       p1275_cmd_direct(args);
 
 #ifdef CONFIG_SMP
        smp_release();
@@ -90,22 +119,32 @@ void prom_cmdline(void)
  */
 void notrace prom_halt(void)
 {
+       unsigned long args[3];
+
 #ifdef CONFIG_SUN_LDOMS
        if (ldom_domaining_enabled)
                ldom_power_off();
 #endif
 again:
-       p1275_cmd("exit", P1275_INOUT(0, 0));
+       args[0] = (unsigned long) "exit";
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
        goto again; /* PROM is out to get me -DaveM */
 }
 
 void prom_halt_power_off(void)
 {
+       unsigned long args[3];
+
 #ifdef CONFIG_SUN_LDOMS
        if (ldom_domaining_enabled)
                ldom_power_off();
 #endif
-       p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
+       args[0] = (unsigned long) "SUNW,power-off";
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
 
        /* if nothing else helps, we just halt */
        prom_halt();
@@ -114,10 +153,15 @@ void prom_halt_power_off(void)
 /* Set prom sync handler to call function 'funcp'. */
 void prom_setcallback(callback_func_t funcp)
 {
+       unsigned long args[5];
        if (!funcp)
                return;
-       p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
-                 P1275_INOUT(1, 1), funcp);
+       args[0] = (unsigned long) "set-callback";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned long) funcp;
+       args[4] = (unsigned long) -1;
+       p1275_cmd_direct(args);
 }
 
 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
@@ -173,57 +217,61 @@ static int prom_get_memory_ihandle(void)
 }
 
 /* Load explicit I/D TLB entries. */
+static long tlb_load(const char *type, unsigned long index,
+                    unsigned long tte_data, unsigned long vaddr)
+{
+       unsigned long args[9];
+
+       args[0] = (unsigned long) prom_callmethod_name;
+       args[1] = 5;
+       args[2] = 1;
+       args[3] = (unsigned long) type;
+       args[4] = (unsigned int) prom_get_mmu_ihandle();
+       args[5] = vaddr;
+       args[6] = tte_data;
+       args[7] = index;
+       args[8] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (long) args[8];
+}
+
 long prom_itlb_load(unsigned long index,
                    unsigned long tte_data,
                    unsigned long vaddr)
 {
-       return p1275_cmd(prom_callmethod_name,
-                        (P1275_ARG(0, P1275_ARG_IN_STRING) |
-                         P1275_ARG(2, P1275_ARG_IN_64B) |
-                         P1275_ARG(3, P1275_ARG_IN_64B) |
-                         P1275_INOUT(5, 1)),
-                        "SUNW,itlb-load",
-                        prom_get_mmu_ihandle(),
-                        /* And then our actual args are pushed backwards. */
-                        vaddr,
-                        tte_data,
-                        index);
+       return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
 }
 
 long prom_dtlb_load(unsigned long index,
                    unsigned long tte_data,
                    unsigned long vaddr)
 {
-       return p1275_cmd(prom_callmethod_name,
-                        (P1275_ARG(0, P1275_ARG_IN_STRING) |
-                         P1275_ARG(2, P1275_ARG_IN_64B) |
-                         P1275_ARG(3, P1275_ARG_IN_64B) |
-                         P1275_INOUT(5, 1)),
-                        "SUNW,dtlb-load",
-                        prom_get_mmu_ihandle(),
-                        /* And then our actual args are pushed backwards. */
-                        vaddr,
-                        tte_data,
-                        index);
+       return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
 }
 
 int prom_map(int mode, unsigned long size,
             unsigned long vaddr, unsigned long paddr)
 {
-       int ret = p1275_cmd(prom_callmethod_name,
-                           (P1275_ARG(0, P1275_ARG_IN_STRING) |
-                            P1275_ARG(3, P1275_ARG_IN_64B) |
-                            P1275_ARG(4, P1275_ARG_IN_64B) |
-                            P1275_ARG(6, P1275_ARG_IN_64B) |
-                            P1275_INOUT(7, 1)),
-                           prom_map_name,
-                           prom_get_mmu_ihandle(),
-                           mode,
-                           size,
-                           vaddr,
-                           0,
-                           paddr);
-
+       unsigned long args[11];
+       int ret;
+
+       args[0] = (unsigned long) prom_callmethod_name;
+       args[1] = 7;
+       args[2] = 1;
+       args[3] = (unsigned long) prom_map_name;
+       args[4] = (unsigned int) prom_get_mmu_ihandle();
+       args[5] = (unsigned int) mode;
+       args[6] = size;
+       args[7] = vaddr;
+       args[8] = 0;
+       args[9] = paddr;
+       args[10] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       ret = (int) args[10];
        if (ret == 0)
                ret = -1;
        return ret;
@@ -231,40 +279,51 @@ int prom_map(int mode, unsigned long size,
 
 void prom_unmap(unsigned long size, unsigned long vaddr)
 {
-       p1275_cmd(prom_callmethod_name,
-                 (P1275_ARG(0, P1275_ARG_IN_STRING) |
-                  P1275_ARG(2, P1275_ARG_IN_64B) |
-                  P1275_ARG(3, P1275_ARG_IN_64B) |
-                  P1275_INOUT(4, 0)),
-                 prom_unmap_name,
-                 prom_get_mmu_ihandle(),
-                 size,
-                 vaddr);
+       unsigned long args[7];
+
+       args[0] = (unsigned long) prom_callmethod_name;
+       args[1] = 4;
+       args[2] = 0;
+       args[3] = (unsigned long) prom_unmap_name;
+       args[4] = (unsigned int) prom_get_mmu_ihandle();
+       args[5] = size;
+       args[6] = vaddr;
+
+       p1275_cmd_direct(args);
 }
 
 /* Set aside physical memory which is not touched or modified
  * across soft resets.
  */
-unsigned long prom_retain(const char *name,
-                         unsigned long pa_low, unsigned long pa_high,
-                         long size, long align)
+int prom_retain(const char *name, unsigned long size,
+               unsigned long align, unsigned long *paddr)
 {
-       /* XXX I don't think we return multiple values correctly.
-        * XXX OBP supposedly returns pa_low/pa_high here, how does
-        * XXX it work?
+       unsigned long args[11];
+
+       args[0] = (unsigned long) prom_callmethod_name;
+       args[1] = 5;
+       args[2] = 3;
+       args[3] = (unsigned long) "SUNW,retain";
+       args[4] = (unsigned int) prom_get_memory_ihandle();
+       args[5] = align;
+       args[6] = size;
+       args[7] = (unsigned long) name;
+       args[8] = (unsigned long) -1;
+       args[9] = (unsigned long) -1;
+       args[10] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       if (args[8])
+               return (int) args[8];
+
+       /* Next we get "phys_high" then "phys_low".  On 64-bit
+        * the phys_high cell is don't care since the phys_low
+        * cell has the full value.
         */
+       *paddr = args[10];
 
-       /* If align is zero, the pa_low/pa_high args are passed,
-        * else they are not.
-        */
-       if (align == 0)
-               return p1275_cmd("SUNW,retain",
-                                (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
-                                name, pa_low, pa_high, size, align);
-       else
-               return p1275_cmd("SUNW,retain",
-                                (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
-                                name, size, align);
+       return 0;
 }
 
 /* Get "Unumber" string for the SIMM at the given
@@ -277,62 +336,129 @@ int prom_getunumber(int syndrome_code,
                    unsigned long phys_addr,
                    char *buf, int buflen)
 {
-       return p1275_cmd(prom_callmethod_name,
-                        (P1275_ARG(0, P1275_ARG_IN_STRING)     |
-                         P1275_ARG(3, P1275_ARG_OUT_BUF)       |
-                         P1275_ARG(6, P1275_ARG_IN_64B)        |
-                         P1275_INOUT(8, 2)),
-                        "SUNW,get-unumber", prom_get_memory_ihandle(),
-                        buflen, buf, P1275_SIZE(buflen),
-                        0, phys_addr, syndrome_code);
+       unsigned long args[12];
+
+       args[0] = (unsigned long) prom_callmethod_name;
+       args[1] = 7;
+       args[2] = 2;
+       args[3] = (unsigned long) "SUNW,get-unumber";
+       args[4] = (unsigned int) prom_get_memory_ihandle();
+       args[5] = buflen;
+       args[6] = (unsigned long) buf;
+       args[7] = 0;
+       args[8] = phys_addr;
+       args[9] = (unsigned int) syndrome_code;
+       args[10] = (unsigned long) -1;
+       args[11] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[10];
 }
 
 /* Power management extensions. */
 void prom_sleepself(void)
 {
-       p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
+       unsigned long args[3];
+
+       args[0] = (unsigned long) "SUNW,sleep-self";
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
 }
 
 int prom_sleepsystem(void)
 {
-       return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
+       unsigned long args[4];
+
+       args[0] = (unsigned long) "SUNW,sleep-system";
+       args[1] = 0;
+       args[2] = 1;
+       args[3] = (unsigned long) -1;
+       p1275_cmd_direct(args);
+
+       return (int) args[3];
 }
 
 int prom_wakeupsystem(void)
 {
-       return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
+       unsigned long args[4];
+
+       args[0] = (unsigned long) "SUNW,wakeup-system";
+       args[1] = 0;
+       args[2] = 1;
+       args[3] = (unsigned long) -1;
+       p1275_cmd_direct(args);
+
+       return (int) args[3];
 }
 
 #ifdef CONFIG_SMP
 void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
 {
-       p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
+       unsigned long args[6];
+
+       args[0] = (unsigned long) "SUNW,start-cpu";
+       args[1] = 3;
+       args[2] = 0;
+       args[3] = (unsigned int) cpunode;
+       args[4] = pc;
+       args[5] = arg;
+       p1275_cmd_direct(args);
 }
 
 void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
 {
-       p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
-                 cpuid, pc, arg);
+       unsigned long args[6];
+
+       args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
+       args[1] = 3;
+       args[2] = 0;
+       args[3] = (unsigned int) cpuid;
+       args[4] = pc;
+       args[5] = arg;
+       p1275_cmd_direct(args);
 }
 
 void prom_stopcpu_cpuid(int cpuid)
 {
-       p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
-                 cpuid);
+       unsigned long args[4];
+
+       args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
+       args[1] = 1;
+       args[2] = 0;
+       args[3] = (unsigned int) cpuid;
+       p1275_cmd_direct(args);
 }
 
 void prom_stopself(void)
 {
-       p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
+       unsigned long args[3];
+
+       args[0] = (unsigned long) "SUNW,stop-self";
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
 }
 
 void prom_idleself(void)
 {
-       p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
+       unsigned long args[3];
+
+       args[0] = (unsigned long) "SUNW,idle-self";
+       args[1] = 0;
+       args[2] = 0;
+       p1275_cmd_direct(args);
 }
 
 void prom_resumecpu(int cpunode)
 {
-       p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
+       unsigned long args[4];
+
+       args[0] = (unsigned long) "SUNW,resume-cpu";
+       args[1] = 1;
+       args[2] = 0;
+       args[3] = (unsigned int) cpunode;
+       p1275_cmd_direct(args);
 }
 #endif
index 2d8b70d397f154318612858c1bf7811160ee7f49..d9850c2b9bf21275fb6e2de0ba69842a6c35b723 100644 (file)
@@ -22,13 +22,11 @@ struct {
        long prom_callback;                     /* 0x00 */
        void (*prom_cif_handler)(long *);       /* 0x08 */
        unsigned long prom_cif_stack;           /* 0x10 */
-       unsigned long prom_args [23];           /* 0x18 */
-       char prom_buffer [3000];
 } p1275buf;
 
 extern void prom_world(int);
 
-extern void prom_cif_interface(void);
+extern void prom_cif_direct(unsigned long *args);
 extern void prom_cif_callback(void);
 
 /*
@@ -36,114 +34,20 @@ extern void prom_cif_callback(void);
  */
 DEFINE_RAW_SPINLOCK(prom_entry_lock);
 
-long p1275_cmd(const char *service, long fmt, ...)
+void p1275_cmd_direct(unsigned long *args)
 {
-       char *p, *q;
        unsigned long flags;
-       int nargs, nrets, i;
-       va_list list;
-       long attrs, x;
-       
-       p = p1275buf.prom_buffer;
 
        raw_local_save_flags(flags);
-       raw_local_irq_restore(PIL_NMI);
+       raw_local_irq_restore((unsigned long)PIL_NMI);
        raw_spin_lock(&prom_entry_lock);
 
-       p1275buf.prom_args[0] = (unsigned long)p;               /* service */
-       strcpy (p, service);
-       p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
-       p1275buf.prom_args[1] = nargs = (fmt & 0x0f);           /* nargs */
-       p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4);    /* nrets */
-       attrs = fmt >> 8;
-       va_start(list, fmt);
-       for (i = 0; i < nargs; i++, attrs >>= 3) {
-               switch (attrs & 0x7) {
-               case P1275_ARG_NUMBER:
-                       p1275buf.prom_args[i + 3] =
-                                               (unsigned)va_arg(list, long);
-                       break;
-               case P1275_ARG_IN_64B:
-                       p1275buf.prom_args[i + 3] =
-                               va_arg(list, unsigned long);
-                       break;
-               case P1275_ARG_IN_STRING:
-                       strcpy (p, va_arg(list, char *));
-                       p1275buf.prom_args[i + 3] = (unsigned long)p;
-                       p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
-                       break;
-               case P1275_ARG_OUT_BUF:
-                       (void) va_arg(list, char *);
-                       p1275buf.prom_args[i + 3] = (unsigned long)p;
-                       x = va_arg(list, long);
-                       i++; attrs >>= 3;
-                       p = (char *)(((long)(p + (int)x + 7)) & ~7);
-                       p1275buf.prom_args[i + 3] = x;
-                       break;
-               case P1275_ARG_IN_BUF:
-                       q = va_arg(list, char *);
-                       p1275buf.prom_args[i + 3] = (unsigned long)p;
-                       x = va_arg(list, long);
-                       i++; attrs >>= 3;
-                       memcpy (p, q, (int)x);
-                       p = (char *)(((long)(p + (int)x + 7)) & ~7);
-                       p1275buf.prom_args[i + 3] = x;
-                       break;
-               case P1275_ARG_OUT_32B:
-                       (void) va_arg(list, char *);
-                       p1275buf.prom_args[i + 3] = (unsigned long)p;
-                       p += 32;
-                       break;
-               case P1275_ARG_IN_FUNCTION:
-                       p1275buf.prom_args[i + 3] =
-                                       (unsigned long)prom_cif_callback;
-                       p1275buf.prom_callback = va_arg(list, long);
-                       break;
-               }
-       }
-       va_end(list);
-
        prom_world(1);
-       prom_cif_interface();
+       prom_cif_direct(args);
        prom_world(0);
 
-       attrs = fmt >> 8;
-       va_start(list, fmt);
-       for (i = 0; i < nargs; i++, attrs >>= 3) {
-               switch (attrs & 0x7) {
-               case P1275_ARG_NUMBER:
-                       (void) va_arg(list, long);
-                       break;
-               case P1275_ARG_IN_STRING:
-                       (void) va_arg(list, char *);
-                       break;
-               case P1275_ARG_IN_FUNCTION:
-                       (void) va_arg(list, long);
-                       break;
-               case P1275_ARG_IN_BUF:
-                       (void) va_arg(list, char *);
-                       (void) va_arg(list, long);
-                       i++; attrs >>= 3;
-                       break;
-               case P1275_ARG_OUT_BUF:
-                       p = va_arg(list, char *);
-                       x = va_arg(list, long);
-                       memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
-                       i++; attrs >>= 3;
-                       break;
-               case P1275_ARG_OUT_32B:
-                       p = va_arg(list, char *);
-                       memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
-                       break;
-               }
-       }
-       va_end(list);
-       x = p1275buf.prom_args [nargs + 3];
-
        raw_spin_unlock(&prom_entry_lock);
        raw_local_irq_restore(flags);
-
-       return x;
 }
 
 void prom_cif_init(void *cif_handler, void *cif_stack)
index 3c0d2dd9f6939faf1daf53f61141c785001429b4..9d3f9137a43ae1307ea698d81e13896af7504453 100644 (file)
 #include <asm/oplib.h>
 #include <asm/ldc.h>
 
+static int prom_node_to_node(const char *type, int node)
+{
+       unsigned long args[5];
+
+       args[0] = (unsigned long) type;
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[4];
+}
+
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
 inline int __prom_getchild(int node)
 {
-       return p1275_cmd ("child", P1275_INOUT(1, 1), node);
+       return prom_node_to_node("child", node);
 }
 
 inline int prom_getchild(int node)
 {
        int cnode;
 
-       if(node == -1) return 0;
+       if (node == -1)
+               return 0;
        cnode = __prom_getchild(node);
-       if(cnode == -1) return 0;
-       return (int)cnode;
+       if (cnode == -1)
+               return 0;
+       return cnode;
 }
 EXPORT_SYMBOL(prom_getchild);
 
@@ -39,10 +56,12 @@ inline int prom_getparent(int node)
 {
        int cnode;
 
-       if(node == -1) return 0;
-       cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
-       if(cnode == -1) return 0;
-       return (int)cnode;
+       if (node == -1)
+               return 0;
+       cnode = prom_node_to_node("parent", node);
+       if (cnode == -1)
+               return 0;
+       return cnode;
 }
 
 /* Return the next sibling of node 'node' or zero if no more siblings
@@ -50,7 +69,7 @@ inline int prom_getparent(int node)
  */
 inline int __prom_getsibling(int node)
 {
-       return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
+       return prom_node_to_node(prom_peer_name, node);
 }
 
 inline int prom_getsibling(int node)
@@ -72,11 +91,21 @@ EXPORT_SYMBOL(prom_getsibling);
  */
 inline int prom_getproplen(int node, const char *prop)
 {
-       if((!node) || (!prop)) return -1;
-       return p1275_cmd ("getproplen", 
-                         P1275_ARG(1,P1275_ARG_IN_STRING)|
-                         P1275_INOUT(2, 1), 
-                         node, prop);
+       unsigned long args[6];
+
+       if (!node || !prop)
+               return -1;
+
+       args[0] = (unsigned long) "getproplen";
+       args[1] = 2;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = (unsigned long) prop;
+       args[5] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[5];
 }
 EXPORT_SYMBOL(prom_getproplen);
 
@@ -87,19 +116,25 @@ EXPORT_SYMBOL(prom_getproplen);
 inline int prom_getproperty(int node, const char *prop,
                            char *buffer, int bufsize)
 {
+       unsigned long args[8];
        int plen;
 
        plen = prom_getproplen(node, prop);
-       if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
+       if ((plen > bufsize) || (plen == 0) || (plen == -1))
                return -1;
-       } else {
-               /* Ok, things seem all right. */
-               return p1275_cmd(prom_getprop_name, 
-                                P1275_ARG(1,P1275_ARG_IN_STRING)|
-                                P1275_ARG(2,P1275_ARG_OUT_BUF)|
-                                P1275_INOUT(4, 1), 
-                                node, prop, buffer, P1275_SIZE(plen));
-       }
+
+       args[0] = (unsigned long) prom_getprop_name;
+       args[1] = 4;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = (unsigned long) prop;
+       args[5] = (unsigned long) buffer;
+       args[6] = bufsize;
+       args[7] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[7];
 }
 EXPORT_SYMBOL(prom_getproperty);
 
@@ -110,7 +145,7 @@ inline int prom_getint(int node, const char *prop)
 {
        int intprop;
 
-       if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
+       if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
                return intprop;
 
        return -1;
@@ -126,7 +161,8 @@ int prom_getintdefault(int node, const char *property, int deflt)
        int retval;
 
        retval = prom_getint(node, property);
-       if(retval == -1) return deflt;
+       if (retval == -1)
+               return deflt;
 
        return retval;
 }
@@ -138,7 +174,8 @@ int prom_getbool(int node, const char *prop)
        int retval;
 
        retval = prom_getproplen(node, prop);
-       if(retval == -1) return 0;
+       if (retval == -1)
+               return 0;
        return 1;
 }
 EXPORT_SYMBOL(prom_getbool);
@@ -152,7 +189,8 @@ void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
        int len;
 
        len = prom_getproperty(node, prop, user_buf, ubuf_size);
-       if(len != -1) return;
+       if (len != -1)
+               return;
        user_buf[0] = 0;
 }
 EXPORT_SYMBOL(prom_getstring);
@@ -164,7 +202,8 @@ int prom_nodematch(int node, const char *name)
 {
        char namebuf[128];
        prom_getproperty(node, "name", namebuf, sizeof(namebuf));
-       if(strcmp(namebuf, name) == 0) return 1;
+       if (strcmp(namebuf, name) == 0)
+               return 1;
        return 0;
 }
 
@@ -190,16 +229,29 @@ int prom_searchsiblings(int node_start, const char *nodename)
 }
 EXPORT_SYMBOL(prom_searchsiblings);
 
+static const char *prom_nextprop_name = "nextprop";
+
 /* Return the first property type for node 'node'.
  * buffer should be at least 32B in length
  */
 inline char *prom_firstprop(int node, char *buffer)
 {
+       unsigned long args[7];
+
        *buffer = 0;
-       if(node == -1) return buffer;
-       p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
-                              P1275_INOUT(3, 0), 
-                              node, (char *) 0x0, buffer);
+       if (node == -1)
+               return buffer;
+
+       args[0] = (unsigned long) prom_nextprop_name;
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = 0;
+       args[5] = (unsigned long) buffer;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
        return buffer;
 }
 EXPORT_SYMBOL(prom_firstprop);
@@ -210,9 +262,10 @@ EXPORT_SYMBOL(prom_firstprop);
  */
 inline char *prom_nextprop(int node, const char *oprop, char *buffer)
 {
+       unsigned long args[7];
        char buf[32];
 
-       if(node == -1) {
+       if (node == -1) {
                *buffer = 0;
                return buffer;
        }
@@ -220,10 +273,17 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
                strcpy (buf, oprop);
                oprop = buf;
        }
-       p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
-                                   P1275_ARG(2,P1275_ARG_OUT_32B)|
-                                   P1275_INOUT(3, 0), 
-                                   node, oprop, buffer); 
+
+       args[0] = (unsigned long) prom_nextprop_name;
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = (unsigned long) oprop;
+       args[5] = (unsigned long) buffer;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
        return buffer;
 }
 EXPORT_SYMBOL(prom_nextprop);
@@ -231,12 +291,19 @@ EXPORT_SYMBOL(prom_nextprop);
 int
 prom_finddevice(const char *name)
 {
+       unsigned long args[5];
+
        if (!name)
                return 0;
-       return p1275_cmd(prom_finddev_name,
-                        P1275_ARG(0,P1275_ARG_IN_STRING)|
-                        P1275_INOUT(1, 1), 
-                        name);
+       args[0] = (unsigned long) "finddevice";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned long) name;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[4];
 }
 EXPORT_SYMBOL(prom_finddevice);
 
@@ -247,7 +314,7 @@ int prom_node_has_property(int node, const char *prop)
        *buf = 0;
        do {
                prom_nextprop(node, buf, buf);
-               if(!strcmp(buf, prop))
+               if (!strcmp(buf, prop))
                        return 1;
        } while (*buf);
        return 0;
@@ -260,6 +327,8 @@ EXPORT_SYMBOL(prom_node_has_property);
 int
 prom_setprop(int node, const char *pname, char *value, int size)
 {
+       unsigned long args[8];
+
        if (size == 0)
                return 0;
        if ((pname == 0) || (value == 0))
@@ -271,19 +340,37 @@ prom_setprop(int node, const char *pname, char *value, int size)
                return 0;
        }
 #endif
-       return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
-                                         P1275_ARG(2,P1275_ARG_IN_BUF)|
-                                         P1275_INOUT(4, 1), 
-                                         node, pname, value, P1275_SIZE(size));
+       args[0] = (unsigned long) "setprop";
+       args[1] = 4;
+       args[2] = 1;
+       args[3] = (unsigned int) node;
+       args[4] = (unsigned long) pname;
+       args[5] = (unsigned long) value;
+       args[6] = size;
+       args[7] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[7];
 }
 EXPORT_SYMBOL(prom_setprop);
 
 inline int prom_inst2pkg(int inst)
 {
+       unsigned long args[5];
        int node;
        
-       node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
-       if (node == -1) return 0;
+       args[0] = (unsigned long) "instance-to-package";
+       args[1] = 1;
+       args[2] = 1;
+       args[3] = (unsigned int) inst;
+       args[4] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       node = (int) args[4];
+       if (node == -1)
+               return 0;
        return node;
 }
 
@@ -296,17 +383,28 @@ prom_pathtoinode(const char *path)
        int node, inst;
 
        inst = prom_devopen (path);
-       if (inst == 0) return 0;
-       node = prom_inst2pkg (inst);
-       prom_devclose (inst);
-       if (node == -1) return 0;
+       if (inst == 0)
+               return 0;
+       node = prom_inst2pkg(inst);
+       prom_devclose(inst);
+       if (node == -1)
+               return 0;
        return node;
 }
 
 int prom_ihandle2path(int handle, char *buffer, int bufsize)
 {
-       return p1275_cmd("instance-to-path",
-                        P1275_ARG(1,P1275_ARG_OUT_BUF)|
-                        P1275_INOUT(3, 1),
-                        handle, buffer, P1275_SIZE(bufsize));
+       unsigned long args[7];
+
+       args[0] = (unsigned long) "instance-to-path";
+       args[1] = 3;
+       args[2] = 1;
+       args[3] = (unsigned int) handle;
+       args[4] = (unsigned long) buffer;
+       args[5] = bufsize;
+       args[6] = (unsigned long) -1;
+
+       p1275_cmd_direct(args);
+
+       return (int) args[6];
 }
index 1246573be59ee78b872ed5d8fa5d583cf16860ac..261aaba092d4bb424d336caa645b222a1fdb1068 100644 (file)
 /** Is the PROC_STATUS SPR supported? */
 #define CHIP_HAS_PROC_STATUS_SPR() 0
 
+/** Is the DSTREAM_PF SPR supported? */
+#define CHIP_HAS_DSTREAM_PF() 0
+
 /** Log of the number of mshims we have. */
 #define CHIP_LOG_NUM_MSHIMS() 2
 
index e864c47fc89cce6cd7c366784e8d76d22a43e280..70017699a74ce0e37e30d0c7c8e62865e9577e3b 100644 (file)
 /** Is the PROC_STATUS SPR supported? */
 #define CHIP_HAS_PROC_STATUS_SPR() 1
 
+/** Is the DSTREAM_PF SPR supported? */
+#define CHIP_HAS_DSTREAM_PF() 0
+
 /** Log of the number of mshims we have. */
 #define CHIP_LOG_NUM_MSHIMS() 2
 
index 6832b4be8990da16a28a3a287a24c4da65f2f230..6d4f0ff2c68cad734d9cb59df5c74e799e47a5ce 100644 (file)
@@ -120,6 +120,7 @@ static inline unsigned long __arch_hweight64(__u64 w)
 
 #include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/minix.h>
index 5a34da6cdd79a18802d437056393c41d6e2f6fba..8b60ec8b2d194f6e352df18eba598e3a61ef52f3 100644 (file)
@@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr)
        return (long)(int)(long __force)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = task_pt_regs(current);
        return (void __user *)regs->sp - len;
@@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
 struct compat_sigaction;
 struct compat_siginfo;
 struct compat_sigaltstack;
-long compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
-                      compat_uptr_t __user *envp);
+long compat_sys_execve(const char __user *path,
+                      const compat_uptr_t __user *argv,
+                      const compat_uptr_t __user *envp);
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
                             struct compat_sigaction __user *oact,
                             size_t sigsetsize);
index 8c95bef3fa45a185a1ec5610bc7a1c21e6f96c13..ee43328713abf2ace9f76e885e9e26ce7b615b3a 100644 (file)
@@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr)
 #define iowrite32 writel
 #define iowrite64 writeq
 
-static inline void *memcpy_fromio(void *dst, void *src, int len)
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+                                size_t len)
 {
        int x;
        BUG_ON((unsigned long)src & 0x3);
        for (x = 0; x < len; x += 4)
                *(u32 *)(dst + x) = readl(src + x);
-       return dst;
 }
 
-static inline void *memcpy_toio(void *dst, void *src, int len)
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+                               size_t len)
 {
        int x;
        BUG_ON((unsigned long)dst & 0x3);
        for (x = 0; x < len; x += 4)
                writel(*(u32 *)(src + x), dst + x);
-       return dst;
 }
 
 /*
index 45cf67c2f2864e195544e21a42b750bb68b82a13..a11d4837ee4d6526137858e8fdd6226deb0a95d0 100644 (file)
@@ -103,55 +103,57 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 #define INITIAL_INTERRUPTS_ENABLED INT_MASK(INT_MEM_ERROR)
 
 /* Disable interrupts. */
-#define raw_local_irq_disable() \
+#define arch_local_irq_disable() \
        interrupt_mask_set_mask(LINUX_MASKABLE_INTERRUPTS)
 
 /* Disable all interrupts, including NMIs. */
-#define raw_local_irq_disable_all() \
+#define arch_local_irq_disable_all() \
        interrupt_mask_set_mask(-1UL)
 
 /* Re-enable all maskable interrupts. */
-#define raw_local_irq_enable() \
+#define arch_local_irq_enable() \
        interrupt_mask_reset_mask(__get_cpu_var(interrupts_enabled_mask))
 
 /* Disable or enable interrupts based on flag argument. */
-#define raw_local_irq_restore(disabled) do { \
+#define arch_local_irq_restore(disabled) do { \
        if (disabled) \
-               raw_local_irq_disable(); \
+               arch_local_irq_disable(); \
        else \
-               raw_local_irq_enable(); \
+               arch_local_irq_enable(); \
 } while (0)
 
 /* Return true if "flags" argument means interrupts are disabled. */
-#define raw_irqs_disabled_flags(flags) ((flags) != 0)
+#define arch_irqs_disabled_flags(flags) ((flags) != 0)
 
 /* Return true if interrupts are currently disabled. */
-#define raw_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
+#define arch_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
 
 /* Save whether interrupts are currently disabled. */
-#define raw_local_save_flags(flags) ((flags) = raw_irqs_disabled())
+#define arch_local_save_flags() arch_irqs_disabled()
 
 /* Save whether interrupts are currently disabled, then disable them. */
-#define raw_local_irq_save(flags) \
-       do { raw_local_save_flags(flags); raw_local_irq_disable(); } while (0)
+#define arch_local_irq_save() ({ \
+       unsigned long __flags = arch_local_save_flags(); \
+       arch_local_irq_disable(); \
+       __flags; })
 
 /* Prevent the given interrupt from being enabled next time we enable irqs. */
-#define raw_local_irq_mask(interrupt) \
+#define arch_local_irq_mask(interrupt) \
        (__get_cpu_var(interrupts_enabled_mask) &= ~INT_MASK(interrupt))
 
 /* Prevent the given interrupt from being enabled immediately. */
-#define raw_local_irq_mask_now(interrupt) do { \
-       raw_local_irq_mask(interrupt); \
+#define arch_local_irq_mask_now(interrupt) do { \
+       arch_local_irq_mask(interrupt); \
        interrupt_mask_set(interrupt); \
 } while (0)
 
 /* Allow the given interrupt to be enabled next time we enable irqs. */
-#define raw_local_irq_unmask(interrupt) \
+#define arch_local_irq_unmask(interrupt) \
        (__get_cpu_var(interrupts_enabled_mask) |= INT_MASK(interrupt))
 
 /* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */
-#define raw_local_irq_unmask_now(interrupt) do { \
-       raw_local_irq_unmask(interrupt); \
+#define arch_local_irq_unmask_now(interrupt) do { \
+       arch_local_irq_unmask(interrupt); \
        if (!irqs_disabled()) \
                interrupt_mask_reset(interrupt); \
 } while (0)
index d942d09b252e4012d251d6d09eaa1af6c7df7c3f..ccd5f84256886c7526edd78bc58ab621f14ef2ac 100644 (file)
@@ -103,6 +103,18 @@ struct thread_struct {
        /* Any other miscellaneous processor state bits */
        unsigned long proc_status;
 #endif
+#if !CHIP_HAS_FIXED_INTVEC_BASE()
+       /* Interrupt base for PL0 interrupts */
+       unsigned long interrupt_vector_base;
+#endif
+#if CHIP_HAS_TILE_RTF_HWM()
+       /* Tile cache retry fifo high-water mark */
+       unsigned long tile_rtf_hwm;
+#endif
+#if CHIP_HAS_DSTREAM_PF()
+       /* Data stream prefetch control */
+       unsigned long dstream_pf;
+#endif
 #ifdef CONFIG_HARDWALL
        /* Is this task tied to an activated hardwall? */
        struct hardwall_info *hardwall;
index acdae814e0161b967f6289e265f6aad1516b2aac..4a02bb07397993a2eb025ae7cd79caf618ae03d6 100644 (file)
@@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t;
 
 /*
  * This struct defines the way the registers are stored on the stack during a
- * system call/exception.  It should be a multiple of 8 bytes to preserve
- * normal stack alignment rules.
- *
- * Must track <sys/ucontext.h> and <sys/procfs.h>
+ * system call or exception.  "struct sigcontext" has the same shape.
  */
 struct pt_regs {
        /* Saved main processor registers; 56..63 are special. */
@@ -80,11 +77,6 @@ struct pt_regs {
 
 #endif /* __ASSEMBLY__ */
 
-/* Flag bits in pt_regs.flags */
-#define PT_FLAGS_DISABLE_IRQ    1  /* on return to kernel, disable irqs */
-#define PT_FLAGS_CALLER_SAVES   2  /* caller-save registers are valid */
-#define PT_FLAGS_RESTORE_REGS   4  /* restore callee-save regs on return */
-
 #define PTRACE_GETREGS         12
 #define PTRACE_SETREGS         13
 #define PTRACE_GETFPREGS       14
@@ -101,6 +93,11 @@ struct pt_regs {
 
 #ifdef __KERNEL__
 
+/* Flag bits in pt_regs.flags */
+#define PT_FLAGS_DISABLE_IRQ    1  /* on return to kernel, disable irqs */
+#define PT_FLAGS_CALLER_SAVES   2  /* caller-save registers are valid */
+#define PT_FLAGS_RESTORE_REGS   4  /* restore callee-save regs on return */
+
 #ifndef __ASSEMBLY__
 
 #define instruction_pointer(regs) ((regs)->pc)
index 7cd7672e3ad4043072a6b6ac9c393491426f08a1..5e2d03336f5335ae99151a383a855e5db7cae6b0 100644 (file)
 #ifndef _ASM_TILE_SIGCONTEXT_H
 #define _ASM_TILE_SIGCONTEXT_H
 
-/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */
-#include <asm/ptrace.h>
-
-/* Must track <sys/ucontext.h> */
+#include <arch/abi.h>
 
+/*
+ * struct sigcontext has the same shape as struct pt_regs,
+ * but is simplified since we know the fault is from userspace.
+ */
 struct sigcontext {
-       struct pt_regs regs;
+       uint_reg_t gregs[53];   /* General-purpose registers.  */
+       uint_reg_t tp;          /* Aliases gregs[TREG_TP].  */
+       uint_reg_t sp;          /* Aliases gregs[TREG_SP].  */
+       uint_reg_t lr;          /* Aliases gregs[TREG_LR].  */
+       uint_reg_t pc;          /* Program counter.  */
+       uint_reg_t ics;         /* In Interrupt Critical Section?  */
+       uint_reg_t faultnum;    /* Fault number.  */
+       uint_reg_t pad[5];
 };
 
 #endif /* _ASM_TILE_SIGCONTEXT_H */
index eb0253f32202c0b52b65012b7c4a8c839aae47dc..c1ee1d61d44ca8a07c504b9af425df3a9c7185c7 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm-generic/signal.h>
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+struct pt_regs;
 int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
index af165a74537f84ff1f377ce22951848bba58d9e0..ce99ffefeacff351c5523d574581e1092d57ca06 100644 (file)
@@ -62,10 +62,12 @@ long sys_fork(void);
 long _sys_fork(struct pt_regs *regs);
 long sys_vfork(void);
 long _sys_vfork(struct pt_regs *regs);
-long sys_execve(char __user *filename, char __user * __user *argv,
-               char __user * __user *envp);
-long _sys_execve(char __user *filename, char __user * __user *argv,
-                char __user * __user *envp, struct pt_regs *regs);
+long sys_execve(const char __user *filename,
+               const char __user *const __user *argv,
+               const char __user *const __user *envp);
+long _sys_execve(const char __user *filename,
+                const char __user *const __user *argv,
+                const char __user *const __user *envp, struct pt_regs *regs);
 
 /* kernel/signal.c */
 long sys_sigaltstack(const stack_t __user *, stack_t __user *);
@@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
 #endif
 
 #ifdef CONFIG_COMPAT
-long compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
-                      compat_uptr_t __user *envp);
-long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
-                       compat_uptr_t __user *envp, struct pt_regs *regs);
+long compat_sys_execve(const char __user *path,
+                      const compat_uptr_t __user *argv,
+                      const compat_uptr_t __user *envp);
+long _compat_sys_execve(const char __user *path,
+                       const compat_uptr_t __user *argv,
+                       const compat_uptr_t __user *envp,
+                       struct pt_regs *regs);
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
                            struct compat_sigaltstack __user *uoss_ptr);
 long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
index 584b965dc82455e16df1597d1abef680c0a1929d..1e54a7843410e57d021dbac9921acf4f39e2f481 100644 (file)
@@ -774,6 +774,7 @@ static const struct file_operations dev_hardwall_fops = {
 #endif
        .flush          = hardwall_flush,
        .release        = hardwall_release,
+       .llseek         = noop_llseek,
 };
 
 static struct cdev hardwall_dev;
index 84f296ca9e63c85da528ee9a8d403cc8362c4097..8f58bdff20d7f7dd9b77d16a6901eb9db82f056b 100644 (file)
@@ -1506,13 +1506,6 @@ handle_ill:
        }
        STD_ENDPROC(handle_ill)
 
-       .pushsection .rodata, "a"
-       .align  8
-bpt_code:
-       bpt
-       ENDPROC(bpt_code)
-       .popsection
-
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
index 596c600869305ade6f13025a18a20039193ddd64..9a27d563fc30968ce3efb46ac11ce241e10d8cc0 100644 (file)
@@ -208,7 +208,7 @@ static void tile_irq_chip_eoi(unsigned int irq)
 }
 
 static struct irq_chip tile_irq_chip = {
-       .typename = "tile_irq_chip",
+       .name = "tile_irq_chip",
        .ack = tile_irq_chip_ack,
        .eoi = tile_irq_chip_eoi,
        .mask = tile_irq_chip_mask,
@@ -288,7 +288,7 @@ int show_interrupts(struct seq_file *p, void *v)
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
 
                for (action = action->next; action; action = action->next)
index 985cc28c74c5696f91adcf82d6347439999bfa41..84c29111756c2212f02cd5bc841691c1cc0a0fd9 100644 (file)
@@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t)
 #if CHIP_HAS_PROC_STATUS_SPR()
        t->proc_status = __insn_mfspr(SPR_PROC_STATUS);
 #endif
+#if !CHIP_HAS_FIXED_INTVEC_BASE()
+       t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0);
+#endif
+#if CHIP_HAS_TILE_RTF_HWM()
+       t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM);
+#endif
+#if CHIP_HAS_DSTREAM_PF()
+       t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF);
+#endif
 }
 
 static void restore_arch_state(const struct thread_struct *t)
@@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t)
 #if CHIP_HAS_PROC_STATUS_SPR()
        __insn_mtspr(SPR_PROC_STATUS, t->proc_status);
 #endif
+#if !CHIP_HAS_FIXED_INTVEC_BASE()
+       __insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base);
+#endif
 #if CHIP_HAS_TILE_RTF_HWM()
-       /*
-        * Clear this whenever we switch back to a process in case
-        * the previous process was monkeying with it.  Even if enabled
-        * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a
-        * performance hint, so isn't worth a full save/restore.
-        */
-       __insn_mtspr(SPR_TILE_RTF_HWM, 0);
+       __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm);
+#endif
+#if CHIP_HAS_DSTREAM_PF()
+       __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf);
 #endif
 }
 
@@ -561,8 +570,9 @@ out:
 }
 
 #ifdef CONFIG_COMPAT
-long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
-                       compat_uptr_t __user *envp, struct pt_regs *regs)
+long _compat_sys_execve(const char __user *path,
+                       const compat_uptr_t __user *argv,
+                       const compat_uptr_t __user *envp, struct pt_regs *regs)
 {
        long error;
        char *filename;
@@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs)
               regs->regs[51], regs->regs[52], regs->tp);
        pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
 #else
-       for (i = 0; i < 52; i += 3)
+       for (i = 0; i < 52; i += 4)
                pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT
                       " r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
                       i, regs->regs[i], i+1, regs->regs[i+1],
index 45b66a3c991ffbc79a7f93e3f00543e50b20de8a..ce183aa1492c7abfaadfca95d54ec76bddc11455 100644 (file)
@@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs,
        /* Always make any pending restarted system calls return -EINTR */
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
+       /*
+        * Enforce that sigcontext is like pt_regs, and doesn't mess
+        * up our stack alignment rules.
+        */
+       BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
+       BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);
+
        for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
-               err |= __get_user(((long *)regs)[i],
-                                 &((long __user *)(&sc->regs))[i]);
+               err |= __get_user(regs->regs[i], &sc->gregs[i]);
 
        regs->faultnum = INT_SWINT_1_SIGRETURN;
 
-       err |= __get_user(*pr0, &sc->regs.regs[0]);
+       err |= __get_user(*pr0, &sc->gregs[0]);
        return err;
 }
 
@@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
        int i, err = 0;
 
        for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
-               err |= __put_user(((long *)regs)[i],
-                                 &((long __user *)(&sc->regs))[i]);
+               err |= __put_user(regs->regs[i], &sc->gregs[i]);
 
        return err;
 }
@@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         * Set up registers for signal handler.
         * Registers that we don't modify keep the value they had from
         * user-space at the time we took the signal.
+        * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
+        * since some things rely on this (e.g. glibc's debug/segfault.c).
         */
        regs->pc = (unsigned long) ka->sa.sa_handler;
        regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
        regs->sp = (unsigned long) frame;
        regs->lr = restorer;
        regs->regs[0] = (unsigned long) usig;
-
-       if (ka->sa.sa_flags & SA_SIGINFO) {
-               /* Need extra arguments, so mark to restore caller-saves. */
-               regs->regs[1] = (unsigned long) &frame->info;
-               regs->regs[2] = (unsigned long) &frame->uc;
-               regs->flags |= PT_FLAGS_CALLER_SAVES;
-       }
+       regs->regs[1] = (unsigned long) &frame->info;
+       regs->regs[2] = (unsigned long) &frame->uc;
+       regs->flags |= PT_FLAGS_CALLER_SAVES;
 
        /*
         * Notify any tracer that was single-stepping it.
index 38a68b0b45813474a791f18aabaa35eb33b8a38a..ea2e0ce28380a2d3fa59391cfc02cb4ca0022f1e 100644 (file)
@@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
                        pr_err("  <received signal %d>\n",
                               frame->info.si_signo);
                }
-               return &frame->uc.uc_mcontext.regs;
+               return (struct pt_regs *)&frame->uc.uc_mcontext;
        }
        return NULL;
 }
index cfcac1ff4cf20276d19ee8fb137dfc84a6cf8abb..2d0266d0254d5eef5477a7da2d5e9ea36378ca46 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
@@ -50,6 +50,7 @@
 
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(harddog_mutex);
 static DEFINE_SPINLOCK(lock);
 static int timer_alive;
 static int harddog_in_fd = -1;
@@ -66,7 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
        int err = -EBUSY;
        char *sock = NULL;
 
-       lock_kernel();
+       mutex_lock(&harddog_mutex);
        spin_lock(&lock);
        if(timer_alive)
                goto err;
@@ -83,11 +84,11 @@ static int harddog_open(struct inode *inode, struct file *file)
 
        timer_alive = 1;
        spin_unlock(&lock);
-       unlock_kernel();
+       mutex_unlock(&harddog_mutex);
        return nonseekable_open(inode, file);
 err:
        spin_unlock(&lock);
-       unlock_kernel();
+       mutex_unlock(&harddog_mutex);
        return err;
 }
 
@@ -153,9 +154,9 @@ static long harddog_ioctl(struct file *file,
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&harddog_mutex);
        ret = harddog_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&harddog_mutex);
 
        return ret;
 }
@@ -166,6 +167,7 @@ static const struct file_operations harddog_fops = {
        .unlocked_ioctl = harddog_ioctl,
        .open           = harddog_open,
        .release        = harddog_release,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice harddog_miscdev = {
index 0c46e398cd8f313d89a3ff07187916aa6021b93f..f9f6a4e205901ee603d56d0167fb3c6e0807e868 100644 (file)
@@ -8,7 +8,7 @@
 #include "linux/slab.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "asm/uaccess.h"
 #include "init.h"
 #include "os.h"
@@ -40,6 +40,11 @@ static char *mixer = HOSTAUDIO_DEV_MIXER;
 "    This is used to specify the host mixer device to the hostaudio driver.\n"\
 "    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
 
+module_param(dsp, charp, 0644);
+MODULE_PARM_DESC(dsp, DSP_HELP);
+module_param(mixer, charp, 0644);
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
@@ -56,17 +61,10 @@ static int set_mixer(char *name, int *add)
 }
 
 __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
-
-#else /*MODULE*/
-
-module_param(dsp, charp, 0644);
-MODULE_PARM_DESC(dsp, DSP_HELP);
-
-module_param(mixer, charp, 0644);
-MODULE_PARM_DESC(mixer, MIXER_HELP);
-
 #endif
 
+static DEFINE_MUTEX(hostaudio_mutex);
+
 /* /dev/dsp file operations */
 
 static ssize_t hostaudio_read(struct file *file, char __user *buffer,
@@ -202,9 +200,9 @@ static int hostaudio_open(struct inode *inode, struct file *file)
                w = 1;
 
        kparam_block_sysfs_write(dsp);
-       lock_kernel();
+       mutex_lock(&hostaudio_mutex);
        ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-       unlock_kernel();
+       mutex_unlock(&hostaudio_mutex);
        kparam_unblock_sysfs_write(dsp);
 
        if (ret < 0) {
@@ -263,9 +261,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
                w = 1;
 
        kparam_block_sysfs_write(mixer);
-       lock_kernel();
+       mutex_lock(&hostaudio_mutex);
        ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-       unlock_kernel();
+       mutex_unlock(&hostaudio_mutex);
        kparam_unblock_sysfs_write(mixer);
 
        if (ret < 0) {
index de317d0c329486b57efb3568f7c4514393ac5677..975613b23dcfb9cd0b60d46afa05260e733d90c2 100644 (file)
@@ -690,7 +690,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
 static void sysrq_proc(void *arg)
 {
        char *op = arg;
-       handle_sysrq(*op, NULL);
+       handle_sysrq(*op);
 }
 
 void mconsole_sysrq(struct mc_request *req)
@@ -843,6 +843,7 @@ static ssize_t mconsole_proc_write(struct file *file,
 static const struct file_operations mconsole_proc_fops = {
        .owner          = THIS_MODULE,
        .write          = mconsole_proc_write,
+       .llseek         = noop_llseek,
 };
 
 static int create_proc_mconsole(void)
index 7158393b67933371250f029ef0ce7ea1e1c705dc..8501e7d0015c7b301b1e2d4773315dc5eba74e7a 100644 (file)
@@ -93,6 +93,7 @@ static const struct file_operations mmapper_fops = {
        .mmap           = mmapper_mmap,
        .open           = mmapper_open,
        .release        = mmapper_release,
+       .llseek         = default_llseek,
 };
 
 /*
index 2ab233ba32c1564f8323884017108b0d53978366..47d0c37897d5874d0bfb95d3d2b87441bd2df6a0 100644 (file)
@@ -255,18 +255,6 @@ static void uml_net_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
-static int uml_net_set_mac(struct net_device *dev, void *addr)
-{
-       struct uml_net_private *lp = netdev_priv(dev);
-       struct sockaddr *hwaddr = addr;
-
-       spin_lock_irq(&lp->lock);
-       eth_mac_addr(dev, hwaddr->sa_data);
-       spin_unlock_irq(&lp->lock);
-
-       return 0;
-}
-
 static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
 {
        dev->mtu = new_mtu;
@@ -373,7 +361,7 @@ static const struct net_device_ops uml_netdev_ops = {
        .ndo_start_xmit         = uml_net_start_xmit,
        .ndo_set_multicast_list = uml_net_set_multicast_list,
        .ndo_tx_timeout         = uml_net_tx_timeout,
-       .ndo_set_mac_address    = uml_net_set_mac,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = uml_net_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -472,7 +460,8 @@ static void eth_configure(int n, void *init, char *mac,
            ((*transport->user->init)(&lp->user, dev) != 0))
                goto out_unregister;
 
-       eth_mac_addr(dev, device->mac);
+       /* don't use eth_mac_addr, it will not work here */
+       memcpy(dev->dev_addr, device->mac, ETH_ALEN);
        dev->mtu = transport->user->mtu;
        dev->netdev_ops = &uml_netdev_ops;
        dev->ethtool_ops = &uml_net_ethtool_ops;
index 4949044773ba78b93797d43701ab751b0a1bce23..981085a93f30c4a48539e81b0cabce905a39de53 100644 (file)
@@ -100,6 +100,7 @@ static const struct file_operations rng_chrdev_ops = {
        .owner          = THIS_MODULE,
        .open           = rng_dev_open,
        .read           = rng_dev_read,
+       .llseek         = noop_llseek,
 };
 
 /* rng_init shouldn't be called more than once at boot time */
index 1bcd208c459f609ab3634f951e1c11b3b2e50038..ba4a98ba39c0322989f32deaf36f7df990cd61f9 100644 (file)
@@ -33,7 +33,7 @@
 #include "linux/mm.h"
 #include "linux/slab.h"
 #include "linux/vmalloc.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
 #include "linux/spinlock.h"
@@ -100,6 +100,7 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
 #define DRIVER_NAME "uml-blkdev"
 
 static DEFINE_MUTEX(ubd_lock);
+static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */
 
 static int ubd_open(struct block_device *bdev, fmode_t mode);
 static int ubd_release(struct gendisk *disk, fmode_t mode);
@@ -163,6 +164,7 @@ struct ubd {
        struct scatterlist sg[MAX_SG];
        struct request *request;
        int start_sg, end_sg;
+       sector_t rq_pos;
 };
 
 #define DEFAULT_COW { \
@@ -187,6 +189,7 @@ struct ubd {
        .request =              NULL, \
        .start_sg =             0, \
        .end_sg =               0, \
+       .rq_pos =               0, \
 }
 
 /* Protected by ubd_lock */
@@ -1099,7 +1102,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
        struct ubd *ubd_dev = disk->private_data;
        int err = 0;
 
-       lock_kernel();
+       mutex_lock(&ubd_mutex);
        if(ubd_dev->count == 0){
                err = ubd_open_dev(ubd_dev);
                if(err){
@@ -1118,7 +1121,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
                err = -EROFS;
        }*/
 out:
-       unlock_kernel();
+       mutex_unlock(&ubd_mutex);
        return err;
 }
 
@@ -1126,10 +1129,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode)
 {
        struct ubd *ubd_dev = disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&ubd_mutex);
        if(--ubd_dev->count == 0)
                ubd_close_dev(ubd_dev);
-       unlock_kernel();
+       mutex_unlock(&ubd_mutex);
        return 0;
 }
 
@@ -1228,7 +1231,6 @@ static void do_ubd_request(struct request_queue *q)
 {
        struct io_thread_req *io_req;
        struct request *req;
-       sector_t sector;
        int n;
 
        while(1){
@@ -1239,12 +1241,12 @@ static void do_ubd_request(struct request_queue *q)
                                return;
 
                        dev->request = req;
+                       dev->rq_pos = blk_rq_pos(req);
                        dev->start_sg = 0;
                        dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
                }
 
                req = dev->request;
-               sector = blk_rq_pos(req);
                while(dev->start_sg < dev->end_sg){
                        struct scatterlist *sg = &dev->sg[dev->start_sg];
 
@@ -1256,10 +1258,9 @@ static void do_ubd_request(struct request_queue *q)
                                return;
                        }
                        prepare_request(req, io_req,
-                                       (unsigned long long)sector << 9,
+                                       (unsigned long long)dev->rq_pos << 9,
                                        sg->offset, sg->length, sg_page(sg));
 
-                       sector += sg->length >> 9;
                        n = os_write_file(thread_fd, &io_req,
                                          sizeof(struct io_thread_req *));
                        if(n != sizeof(struct io_thread_req *)){
@@ -1272,6 +1273,7 @@ static void do_ubd_request(struct request_queue *q)
                                return;
                        }
 
+                       dev->rq_pos += sg->length >> 9;
                        dev->start_sg++;
                }
                dev->end_sg = 0;
index cd145eda357950b66b1ad2f05f55bd0094df6006..340268be00b5a934f6fc3ac632c26e53b58623ec 100644 (file)
@@ -62,7 +62,7 @@ static long execve1(const char *file,
        return error;
 }
 
-long um_execve(const char *file, char __user *__user *argv, char __user *__user *env)
+long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
 {
        long err;
 
@@ -72,19 +72,17 @@ long um_execve(const char *file, char __user *__user *argv, char __user *__user
        return err;
 }
 
-long sys_execve(const char __user *file, char __user *__user *argv,
-               char __user *__user *env)
+long sys_execve(const char __user *file, const char __user *const __user *argv,
+               const char __user *const __user *env)
 {
        long error;
        char *filename;
 
-       lock_kernel();
        filename = getname(file);
        error = PTR_ERR(filename);
        if (IS_ERR(filename)) goto out;
        error = execve1(filename, argv, env);
        putname(filename);
  out:
-       unlock_kernel();
        return error;
 }
index 1303a105fe91dc5aabca314e4e94faf8573b9c65..5bf97db24a046283f8704e2f7e0ee91e7b4d4844 100644 (file)
@@ -1 +1 @@
-extern long um_execve(const char *file, char __user *__user *argv, char __user *__user *env);
+extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
index a3f0b04d7101ccb1fea64254339328fbec12412f..a746e3037a5bc896462affb2c62ab493a625cc58 100644 (file)
@@ -46,7 +46,7 @@ int show_interrupts(struct seq_file *p, void *v)
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
 
                for (action=action->next; action; action = action->next)
@@ -369,7 +369,7 @@ static void dummy(unsigned int irq)
 
 /* This is used for everything else than the timer. */
 static struct irq_chip normal_irq_type = {
-       .typename = "SIGIO",
+       .name = "SIGIO",
        .release = free_irq_by_irq_and_dev,
        .disable = dummy,
        .enable = dummy,
@@ -378,7 +378,7 @@ static struct irq_chip normal_irq_type = {
 };
 
 static struct irq_chip SIGVTALRM_irq_type = {
-       .typename = "SIGVTALRM",
+       .name = "SIGVTALRM",
        .release = free_irq_by_irq_and_dev,
        .shutdown = dummy, /* never called */
        .disable = dummy,
index 5ddb246626dbb87afe7484b87c0c495c8643de8f..f958cb876ee3d3e47ddff71094e8026c0a110f5d 100644 (file)
@@ -60,8 +60,8 @@ int kernel_execve(const char *filename,
 
        fs = get_fs();
        set_fs(KERNEL_DS);
-       ret = um_execve(filename, (char __user *__user *)argv,
-                       (char __user *__user *) envp);
+       ret = um_execve(filename, (const char __user *const __user *)argv,
+                       (const char __user *const __user *) envp);
        set_fs(fs);
 
        return ret;
index cea0cd9a316fb987bfa611a1dffa06cdba1f0332..dfabfefc21c48981c456faa683108dd9b6b7a9a8 100644 (file)
@@ -25,14 +25,17 @@ config X86
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS if (!M386 && !M486)
+       select HAVE_IRQ_WORK
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
+       select HAVE_MEMBLOCK
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_WANT_FRAME_POINTERS
        select HAVE_DMA_ATTRS
        select HAVE_KRETPROBES
        select HAVE_OPTPROBES
        select HAVE_FTRACE_MCOUNT_RECORD
+       select HAVE_C_RECORDMCOUNT
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
@@ -59,6 +62,12 @@ config X86
        select ANON_INODES
        select HAVE_ARCH_KMEMCHECK
        select HAVE_USER_RETURN_NOTIFIER
+       select HAVE_ARCH_JUMP_LABEL
+       select HAVE_TEXT_POKE_SMP
+       select HAVE_GENERIC_HARDIRQS
+       select HAVE_SPARSE_IRQ
+       select GENERIC_IRQ_PROBE
+       select GENERIC_PENDING_IRQ if SMP
 
 config INSTRUCTION_DECODER
        def_bool (KPROBES || PERF_EVENTS)
@@ -193,27 +202,10 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
 
-config HAVE_EARLY_RES
-       def_bool y
-
 config HAVE_INTEL_TXT
        def_bool y
        depends on EXPERIMENTAL && DMAR && ACPI
 
-# Use the generic interrupt handling code in kernel/irq/:
-config GENERIC_HARDIRQS
-       def_bool y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-       def_bool y
-
-config GENERIC_IRQ_PROBE
-       def_bool y
-
-config GENERIC_PENDING_IRQ
-       def_bool y
-       depends on GENERIC_HARDIRQS && SMP
-
 config USE_GENERIC_SMP_HELPERS
        def_bool y
        depends on SMP
@@ -296,23 +288,6 @@ config X86_X2APIC
 
          If you don't know what to do here, say N.
 
-config SPARSE_IRQ
-       bool "Support sparse irq numbering"
-       depends on PCI_MSI || HT_IRQ
-       ---help---
-         This enables support for sparse irqs. This is useful for distro
-         kernels that want to define a high CONFIG_NR_CPUS value but still
-         want to have low kernel memory footprint on smaller machines.
-
-         ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
-           out the irq_desc[] array in a more NUMA-friendly way. )
-
-         If you don't know what to do here, say N.
-
-config NUMA_IRQ_DESC
-       def_bool y
-       depends on SPARSE_IRQ && NUMA
-
 config X86_MPPARSE
        bool "Enable MPS table" if ACPI
        default y
@@ -517,25 +492,6 @@ if PARAVIRT_GUEST
 
 source "arch/x86/xen/Kconfig"
 
-config VMI
-       bool "VMI Guest support (DEPRECATED)"
-       select PARAVIRT
-       depends on X86_32
-       ---help---
-         VMI provides a paravirtualized interface to the VMware ESX server
-         (it could be used by other hypervisors in theory too, but is not
-         at the moment), by linking the kernel to a GPL-ed ROM module
-         provided by the hypervisor.
-
-         As of September 2009, VMware has started a phased retirement
-         of this feature from VMware's products. Please see
-         feature-removal-schedule.txt for details.  If you are
-         planning to enable this option, please note that you cannot
-         live migrate a VMI enabled VM to a future VMware product,
-         which doesn't support VMI. So if you expect your kernel to
-         seamlessly migrate to newer VMware products, keep this
-         disabled.
-
 config KVM_CLOCK
        bool "KVM paravirtualized clock"
        select PARAVIRT
@@ -590,16 +546,7 @@ config PARAVIRT_DEBUG
          a paravirt_op is missing when it is called.
 
 config NO_BOOTMEM
-       default y
-       bool "Disable Bootmem code"
-       ---help---
-         Use early_res directly instead of bootmem before slab is ready.
-               - allocator (buddy) [generic]
-               - early allocator (bootmem) [generic]
-               - very early allocator (reserve_early*()) [x86]
-               - very very early allocator (early brk model) [x86]
-         So reduce one layer between early allocator to final allocator
-
+       def_bool y
 
 config MEMTEST
        bool "Memtest"
@@ -670,7 +617,7 @@ config GART_IOMMU
        bool "GART IOMMU support" if EMBEDDED
        default y
        select SWIOTLB
-       depends on X86_64 && PCI && K8_NB
+       depends on X86_64 && PCI && AMD_NB
        ---help---
          Support for full DMA access of devices with 32bit memory access only
          on systems with more than 3GB. This is usually needed for USB,
@@ -795,6 +742,17 @@ config SCHED_MC
          making when dealing with multi-core CPU chips at a cost of slightly
          increased overhead in some places. If unsure say N here.
 
+config IRQ_TIME_ACCOUNTING
+       bool "Fine granularity task level IRQ time accounting"
+       default n
+       ---help---
+         Select this option to enable fine granularity task irq time
+         accounting. This is done by reading a timestamp on each
+         transitions between softirq and hardirq state, so there can be a
+         small performance impact.
+
+         If in doubt, say N here.
+
 source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
@@ -1148,6 +1106,9 @@ config X86_PAE
 config ARCH_PHYS_ADDR_T_64BIT
        def_bool X86_64 || X86_PAE
 
+config ARCH_DMA_ADDR_T_64BIT
+       def_bool X86_64 || HIGHMEM64G
+
 config DIRECT_GBPAGES
        bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
        default y
@@ -1326,25 +1287,34 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
          Set whether the default state of memory_corruption_check is
          on or off.
 
-config X86_RESERVE_LOW_64K
-       bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
-       default y
+config X86_RESERVE_LOW
+       int "Amount of low memory, in kilobytes, to reserve for the BIOS"
+       default 64
+       range 4 640
        ---help---
-         Reserve the first 64K of physical RAM on BIOSes that are known
-         to potentially corrupt that memory range. A numbers of BIOSes are
-         known to utilize this area during suspend/resume, so it must not
-         be used by the kernel.
+         Specify the amount of low memory to reserve for the BIOS.
+
+         The first page contains BIOS data structures that the kernel
+         must not use, so that page must always be reserved.
+
+         By default we reserve the first 64K of physical RAM, as a
+         number of BIOSes are known to corrupt that memory range
+         during events such as suspend/resume or monitor cable
+         insertion, so it must not be used by the kernel.
 
-         Set this to N if you are absolutely sure that you trust the BIOS
-         to get all its memory reservations and usages right.
+         You can set this to 4 if you are absolutely sure that you
+         trust the BIOS to get all its memory reservations and usages
+         right.  If you know your BIOS have problems beyond the
+         default 64K area, you can set this to 640 to avoid using the
+         entire low memory range.
 
-         If you have doubts about the BIOS (e.g. suspend/resume does not
-         work or there's kernel crashes after certain hardware hotplug
-         events) and it's not AMI or Phoenix, then you might want to enable
-         X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical
-         corruption patterns.
+         If you have doubts about the BIOS (e.g. suspend/resume does
+         not work or there's kernel crashes after certain hardware
+         hotplug events) then you might want to enable
+         X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check
+         typical corruption patterns.
 
-         Say Y if unsure.
+         Leave this to the default value of 64 if you are unsure.
 
 config MATH_EMULATION
        bool
@@ -1900,7 +1870,7 @@ config PCI_GODIRECT
        bool "Direct"
 
 config PCI_GOOLPC
-       bool "OLPC"
+       bool "OLPC XO-1"
        depends on OLPC
 
 config PCI_GOANY
@@ -2061,14 +2031,21 @@ config SCx200HR_TIMER
 config OLPC
        bool "One Laptop Per Child support"
        select GPIOLIB
+       select OLPC_OPENFIRMWARE
        ---help---
          Add support for detecting the unique features of the OLPC
          XO hardware.
 
+config OLPC_XO1
+       tristate "OLPC XO-1 support"
+       depends on OLPC && PCI
+       ---help---
+         Add support for non-essential features of the OLPC XO-1 laptop.
+
 config OLPC_OPENFIRMWARE
        bool "Support for OLPC's Open Firmware"
        depends on !X86_64 && !X86_PAE
-       default y if OLPC
+       default n
        help
          This option adds support for the implementation of Open Firmware
          that is used on the OLPC XO-1 Children's Machine.
@@ -2076,7 +2053,7 @@ config OLPC_OPENFIRMWARE
 
 endif # X86_32
 
-config K8_NB
+config AMD_NB
        def_bool y
        depends on CPU_SUP_AMD && PCI
 
@@ -2125,6 +2102,10 @@ config HAVE_ATOMIC_IOMAP
        def_bool y
        depends on X86_32
 
+config HAVE_TEXT_POKE_SMP
+       bool
+       select STOP_MACHINE if SMP
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 75085080b63e2f74d32d4fa2b4bd2f8972d2b7de..b59ee765414ea3891d6d4914485ba366fcee5663 100644 (file)
@@ -43,6 +43,10 @@ config EARLY_PRINTK
          with klogd/syslogd or the X server. You should normally N here,
          unless you want to debug such a crash.
 
+config EARLY_PRINTK_MRST
+       bool "Early printk for MRST platform support"
+       depends on EARLY_PRINTK && X86_MRST
+
 config EARLY_PRINTK_DBGP
        bool "Early printk via EHCI debug port"
        depends on EARLY_PRINTK && PCI
@@ -121,16 +125,6 @@ config DEBUG_NX_TEST
          and the software setup of this feature.
          If in doubt, say "N"
 
-config 4KSTACKS
-       bool "Use 4Kb for kernel stacks instead of 8Kb"
-       depends on X86_32
-       ---help---
-         If you say Y here the kernel will use a 4Kb stacksize for the
-         kernel stack attached to each process/thread. This facilitates
-         running more threads on a system and also reduces the pressure
-         on the VM subsystem for higher order allocations. This option
-         will also use IRQ stacks to compensate for the reduced stackspace.
-
 config DOUBLEFAULT
        default y
        bool "Enable doublefault exception handler" if EMBEDDED
index 8aa1b59b9074586e1fe9930b85d0cf945f14a695..b02e509072a790b1fbea3387f8749b5326beb822 100644 (file)
@@ -74,7 +74,7 @@ endif
 
 ifdef CONFIG_CC_STACKPROTECTOR
        cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh
-        ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(biarch)),y)
+        ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
                 stackp-y := -fstack-protector
                 KBUILD_CFLAGS += $(stackp-y)
         else
@@ -96,8 +96,12 @@ cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_en
 # is .cfi_signal_frame supported too?
 cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
 cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
+
+# does binutils support specific instructions?
+asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
+
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
 
 LDFLAGS := -m elf_$(UTS_MACHINE)
 
index 030f4b93e255ac00c9cd646a733eda26733a5324..5df2869c874baced33de00a78a7b693f3237ea0f 100644 (file)
@@ -58,7 +58,19 @@ static void parse_earlyprintk(void)
                if (arg[pos] == ',')
                        pos++;
 
-               if (!strncmp(arg, "ttyS", 4)) {
+               /*
+                * make sure we have
+                *      "serial,0x3f8,115200"
+                *      "serial,ttyS0,115200"
+                *      "ttyS0,115200"
+                */
+               if (pos == 7 && !strncmp(arg + pos, "0x", 2)) {
+                       port = simple_strtoull(arg + pos, &e, 16);
+                       if (port == 0 || arg + pos == e)
+                               port = DEFAULT_SERIAL_PORT;
+                       else
+                               pos = e - arg;
+               } else if (!strncmp(arg + pos, "ttyS", 4)) {
                        static const int bases[] = { 0x3f8, 0x2f8 };
                        int idx = 0;
 
index 0350311906ae731ca91e9ecedbc3e7acbaa668d0..2d93bdbc9ac026f2c0ef1e3fcd9c9a208b609787 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/ia32.h>
 
 #undef WARN_OLD
-#undef CORE_DUMP /* probably broken */
+#undef CORE_DUMP /* definitely broken */
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs);
 static int load_aout_library(struct file *);
@@ -131,21 +131,15 @@ static void set_brk(unsigned long start, unsigned long end)
  * macros to write out all the necessary info.
  */
 
-static int dump_write(struct file *file, const void *addr, int nr)
-{
-       return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
+#include <linux/coredump.h>
 
 #define DUMP_WRITE(addr, nr)                        \
        if (!dump_write(file, (void *)(addr), (nr))) \
                goto end_coredump;
 
-#define DUMP_SEEK(offset)                                              \
-       if (file->f_op->llseek) {                                       \
-               if (file->f_op->llseek(file, (offset), 0) != (offset))  \
-                       goto end_coredump;                              \
-       } else                                                          \
-               file->f_pos = (offset)
+#define DUMP_SEEK(offset)              \
+       if (!dump_seek(file, offset))   \
+               goto end_coredump;
 
 #define START_DATA()   (u.u_tsize << PAGE_SHIFT)
 #define START_STACK(u) (u.start_stack)
@@ -217,12 +211,6 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
                dump_size = dump.u_ssize << PAGE_SHIFT;
                DUMP_WRITE(dump_start, dump_size);
        }
-       /*
-        * Finally dump the task struct.  Not be used by gdb, but
-        * could be useful
-        */
-       set_fs(KERNEL_DS);
-       DUMP_WRITE(current, sizeof(*current));
 end_coredump:
        set_fs(fs);
        return has_dumped;
index b86feabed69bfe8e74f81f179c91fbe3a4b799d8..518bb99c339480820fc3995b1456d29704d67f07 100644 (file)
        /*
         * Reload arg registers from stack in case ptrace changed them.
         * We don't reload %eax because syscall_trace_enter() returned
-        * the value it wants us to use in the table lookup.
+        * the %rax value we should see.  Instead, we just truncate that
+        * value to 32 bits again as we did on entry from user mode.
+        * If it's a new value set by user_regset during entry tracing,
+        * this matches the normal truncation of the user-mode value.
+        * If it's -1 to make us punt the syscall, then (u32)-1 is still
+        * an appropriately invalid value.
         */
        .macro LOAD_ARGS32 offset, _r9=0
        .if \_r9
@@ -60,6 +65,7 @@
        movl \offset+48(%rsp),%edx
        movl \offset+56(%rsp),%esi
        movl \offset+64(%rsp),%edi
+       movl %eax,%eax                  /* zero extension */
        .endm
        
        .macro CFI_STARTPROC32 simple
@@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target)
        testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
        CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
-       cmpl    $(IA32_NR_syscalls-1),%eax
+       cmpq    $(IA32_NR_syscalls-1),%rax
        ja      ia32_badsys
 sysenter_do_call:
        IA32_ARG_FIXUP
@@ -195,7 +201,7 @@ sysexit_from_sys_call:
        movl $AUDIT_ARCH_I386,%edi      /* 1st arg: audit arch */
        call audit_syscall_entry
        movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
-       cmpl $(IA32_NR_syscalls-1),%eax
+       cmpq $(IA32_NR_syscalls-1),%rax
        ja ia32_badsys
        movl %ebx,%edi                  /* reload 1st syscall arg */
        movl RCX-ARGOFFSET(%rsp),%esi   /* reload 2nd syscall arg */
@@ -248,7 +254,7 @@ sysenter_tracesys:
        call    syscall_trace_enter
        LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
-       cmpl    $(IA32_NR_syscalls-1),%eax
+       cmpq    $(IA32_NR_syscalls-1),%rax
        ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
        jmp     sysenter_do_call
        CFI_ENDPROC
@@ -314,7 +320,7 @@ ENTRY(ia32_cstar_target)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
        CFI_REMEMBER_STATE
        jnz   cstar_tracesys
-       cmpl $IA32_NR_syscalls-1,%eax
+       cmpq $IA32_NR_syscalls-1,%rax
        ja  ia32_badsys
 cstar_do_call:
        IA32_ARG_FIXUP 1
@@ -367,7 +373,7 @@ cstar_tracesys:
        LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        xchgl %ebp,%r9d
-       cmpl $(IA32_NR_syscalls-1),%eax
+       cmpq $(IA32_NR_syscalls-1),%rax
        ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
        jmp cstar_do_call
 END(ia32_cstar_target)
@@ -425,7 +431,7 @@ ENTRY(ia32_syscall)
        orl   $TS_COMPAT,TI_status(%r10)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
        jnz ia32_tracesys
-       cmpl $(IA32_NR_syscalls-1),%eax
+       cmpq $(IA32_NR_syscalls-1),%rax
        ja ia32_badsys
 ia32_do_call:
        IA32_ARG_FIXUP
@@ -444,7 +450,7 @@ ia32_tracesys:
        call syscall_trace_enter
        LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
-       cmpl $(IA32_NR_syscalls-1),%eax
+       cmpq $(IA32_NR_syscalls-1),%rax
        ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
        jmp ia32_do_call
 END(ia32_syscall)
index bc6abb7bc7ee3084aa8b5d87ae19244715469990..76561d20ea2f27f0edfd0eee6d043b98c6aa6e90 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/stringify.h>
+#include <linux/jump_label.h>
 #include <asm/asm.h>
 
 /*
@@ -160,6 +161,8 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
 #define __parainstructions_end NULL
 #endif
 
+extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+
 /*
  * Clear and restore the kernel write-protection flag on the local CPU.
  * Allows the kernel to edit read-only pages.
@@ -180,4 +183,12 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
 
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+#define IDEAL_NOP_SIZE_5 5
+extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+extern void arch_init_ideal_nop5(void);
+#else
+static inline void arch_init_ideal_nop5(void) {}
+#endif
+
 #endif /* _ASM_X86_ALTERNATIVE_H */
index 5af2982133b5435b492372c447eef8c849b0eac4..a6863a2dec1f6883b6be0b3fd68ca7f6d8982d83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
 
 #ifdef CONFIG_AMD_IOMMU
 
-extern void amd_iommu_detect(void);
+extern int amd_iommu_detect(void);
 
 #else
 
-static inline void amd_iommu_detect(void) { }
+static inline int amd_iommu_detect(void) { return -ENODEV; }
 
 #endif
 
index d2544f1d705d3eb9cad310ac3486f94c2358b51d..916bc8111a01fa5de3a5df9f35ce3b8b60113342 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { }
 
 #endif /* !CONFIG_AMD_IOMMU_STATS */
 
+static inline bool is_rd890_iommu(struct pci_dev *pdev)
+{
+       return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
+              (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
+}
+
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
index 7014e88bc7798af33f681724ff90cf09eda52af5..e3509fc303bf5a54069e5b9b6b6edbc9ec390a49 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -368,6 +368,9 @@ struct amd_iommu {
        /* capabilities of that IOMMU read from ACPI */
        u32 cap;
 
+       /* flags read from acpi table */
+       u8 acpi_flags;
+
        /*
         * Capability pointer. There could be more than one IOMMU per PCI
         * device function if there are more than one AMD IOMMU capability
@@ -411,6 +414,24 @@ struct amd_iommu {
 
        /* default dma_ops domain for that IOMMU */
        struct dma_ops_domain *default_dom;
+
+       /*
+        * We can't rely on the BIOS to restore all values on reinit, so we
+        * need to stash them
+        */
+
+       /* The iommu BAR */
+       u32 stored_addr_lo;
+       u32 stored_addr_hi;
+
+       /*
+        * Each iommu has 6 l1s, each of which is documented as having 0x12
+        * registers
+        */
+       u32 stored_l1[6][0x12];
+
+       /* The l2 indirect registers */
+       u32 stored_l2[0x83];
 };
 
 /*
similarity index 61%
rename from arch/x86/include/asm/k8.h
rename to arch/x86/include/asm/amd_nb.h
index af00bd1d208934941f00ba7e911c20dd868a3f2b..c8517f81b21e73f9f2c428a26f2fb8995f73011f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_K8_H
-#define _ASM_X86_K8_H
+#ifndef _ASM_X86_AMD_NB_H
+#define _ASM_X86_AMD_NB_H
 
 #include <linux/pci.h>
 
@@ -7,24 +7,27 @@ extern struct pci_device_id k8_nb_ids[];
 struct bootnode;
 
 extern int early_is_k8_nb(u32 value);
-extern struct pci_dev **k8_northbridges;
-extern int num_k8_northbridges;
 extern int cache_k8_northbridges(void);
 extern void k8_flush_garts(void);
 extern int k8_get_nodes(struct bootnode *nodes);
 extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
 extern int k8_scan_nodes(void);
 
-#ifdef CONFIG_K8_NB
-extern int num_k8_northbridges;
+struct k8_northbridge_info {
+       u16 num;
+       u8 gart_supported;
+       struct pci_dev **nb_misc;
+};
+extern struct k8_northbridge_info k8_northbridges;
+
+#ifdef CONFIG_AMD_NB
 
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
-       return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
+       return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL;
 }
 
 #else
-#define num_k8_northbridges 0
 
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
@@ -33,4 +36,4 @@ static inline struct pci_dev *node_to_k8_nb_misc(int node)
 #endif
 
 
-#endif /* _ASM_X86_K8_H */
+#endif /* _ASM_X86_AMD_NB_H */
index a69b1ac9eaf82d639fd0ae51459d2dfdc79fbd1b..2fefa501d3ba64ee5db2e3541555a28ebe27598e 100644 (file)
@@ -54,7 +54,6 @@ extern struct clock_event_device *global_clock_event;
 extern unsigned long apbt_quick_calibrate(void);
 extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
 extern void apbt_setup_secondary_clock(void);
-extern unsigned int boot_cpu_id;
 
 extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
 extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
index 1fa03e04ae4475e9bdc342aa117d9048a4e93105..286de34b0ed6773c6ccb2b7b052023394b93396f 100644 (file)
@@ -252,9 +252,7 @@ static inline int apic_is_clustered_box(void)
 }
 #endif
 
-extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
-extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
-
+extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
 
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
index 7fe3b3060f08cc8e57f18d3e4ff04519f358d00e..a859ca461fb0432585f952e08337610b1165a204 100644 (file)
 #define APIC_EILVTn(n) (0x500 + 0x10 * n)
 #define                APIC_EILVT_NR_AMD_K8    1       /* # of extended interrupts */
 #define                APIC_EILVT_NR_AMD_10H   4
+#define                APIC_EILVT_NR_MAX       APIC_EILVT_NR_AMD_10H
 #define                APIC_EILVT_LVTOFF(x)    (((x) >> 4) & 0xF)
 #define                APIC_EILVT_MSG_FIX      0x0
 #define                APIC_EILVT_MSG_SMI      0x2
index 545776efeb164c72d523f2c78f2c501e1535344c..903683b07e423fde4189c8340bfa4fcf0725b206 100644 (file)
@@ -309,7 +309,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
 {
        return ((1UL << (nr % BITS_PER_LONG)) &
-               (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
+               (addr[nr / BITS_PER_LONG])) != 0;
 }
 
 static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
@@ -440,6 +440,8 @@ static inline int fls(int x)
 
 #ifdef __KERNEL__
 
+#include <asm-generic/bitops/find.h>
+
 #include <asm-generic/bitops/sched.h>
 
 #define ARCH_HAS_FAST_MULTIPLIER 1
index 0918654305af5975bdef505fe7c3003cbc49ef73..0d467b33883544121860305ab7bb7459b98112eb 100644 (file)
@@ -62,9 +62,9 @@ struct cal_chipset_ops {
 extern int use_calgary;
 
 #ifdef CONFIG_CALGARY_IOMMU
-extern void detect_calgary(void);
+extern int detect_calgary(void);
 #else
-static inline void detect_calgary(void) { return; }
+static inline int detect_calgary(void) { return -ENODEV; }
 #endif
 
 #endif /* _ASM_X86_CALGARY_H */
index 306160e58b48772ccef1f65c803a3a3813ff5d1e..1d9cd27c2920a326e5ac2440ebdbd998d0b925c0 100644 (file)
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
        struct pt_regs *regs = task_pt_regs(current);
        return (void __user *)regs->sp - len;
index b185091bf19ce39f67a325ecd6aafb7c13f8cd23..4fab24de26b18404069994b908c79d3e4e481c50 100644 (file)
@@ -32,6 +32,5 @@ extern void arch_unregister_cpu(int);
 
 DECLARE_PER_CPU(int, cpu_state);
 
-extern unsigned int boot_cpu_id;
 
 #endif /* _ASM_X86_CPU_H */
index 781a50b29a4917545e71c3e74bdcbbda7faa383d..220e2ea08e80b3b2f40b33771913c4d80e2d815e 100644 (file)
 #define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
 #define X86_FEATURE_OSVW       (6*32+ 9) /* OS Visible Workaround */
 #define X86_FEATURE_IBS                (6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_SSE5       (6*32+11) /* SSE-5 */
+#define X86_FEATURE_XOP                (6*32+11) /* extended AVX instructions */
 #define X86_FEATURE_SKINIT     (6*32+12) /* SKINIT/STGI instructions */
 #define X86_FEATURE_WDT                (6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP                (6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4       (6*32+16) /* 4 operands MAC instructions */
 #define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
+#define X86_FEATURE_TBM                (6*32+21) /* trailing bit manipulations */
+#define X86_FEATURE_TOPOEXT    (6*32+22) /* topology extensions CPUID leafs */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
 #define X86_FEATURE_XSAVEOPT   (7*32+ 4) /* Optimized Xsave */
 #define X86_FEATURE_PLN                (7*32+ 5) /* Intel Power Limit Notification */
 #define X86_FEATURE_PTS                (7*32+ 6) /* Intel Package Thermal Status */
+#define X86_FEATURE_DTS                (7*32+ 7) /* Digital Thermal Sensor */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  (8*32+ 0) /* Intel TPR Shadow */
 #define X86_FEATURE_LBRV       (8*32+ 6) /* AMD LBR Virtualization support */
 #define X86_FEATURE_SVML       (8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
 #define X86_FEATURE_NRIPS      (8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR  (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN   (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */
+
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
 #define X86_FEATURE_FSGSBASE   (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
@@ -296,6 +308,7 @@ extern const char * const x86_power_flags[32];
 
 #endif /* CONFIG_X86_64 */
 
+#if __GNUC__ >= 4
 /*
  * Static testing of CPU features.  Used the same as boot_cpu_has().
  * These are only valid after alternatives have run, but will statically
@@ -304,7 +317,7 @@ extern const char * const x86_power_flags[32];
  */
 static __always_inline __pure bool __static_cpu_has(u16 bit)
 {
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5
                asm goto("1: jmp %l[t_no]\n"
                         "2:\n"
                         ".section .altinstructions,\"a\"\n"
@@ -345,7 +358,6 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 #endif
 }
 
-#if __GNUC__ >= 4
 #define static_cpu_has(bit)                                    \
 (                                                              \
        __builtin_constant_p(boot_cpu_has(bit)) ?               \
index 733f7e91e7a99f45435a6b46c831ff3e6e9c05da..326099199318c4ce1066a03a04220c08914ca890 100644 (file)
        CFI_ADJUST_CFA_OFFSET -8
        .endm
 
+       .macro pushfq_cfi
+       pushfq
+       CFI_ADJUST_CFA_OFFSET 8
+       .endm
+
+       .macro popfq_cfi
+       popfq
+       CFI_ADJUST_CFA_OFFSET -8
+       .endm
+
        .macro movq_cfi reg offset=0
        movq %\reg, \offset(%rsp)
        CFI_REL_OFFSET \reg, \offset
        CFI_ADJUST_CFA_OFFSET -4
        .endm
 
+       .macro pushfl_cfi
+       pushfl
+       CFI_ADJUST_CFA_OFFSET 4
+       .endm
+
+       .macro popfl_cfi
+       popfl
+       CFI_ADJUST_CFA_OFFSET -4
+       .endm
+
        .macro movl_cfi reg offset=0
        movl %\reg, \offset(%esp)
        CFI_REL_OFFSET \reg, \offset
index ec8a52d14ab179e4ef086e9c65c5a28917cdfd70..5be1542fbfaf73bfccd03a101e94a1cca47d36b0 100644 (file)
@@ -112,23 +112,13 @@ static inline void early_memtest(unsigned long start, unsigned long end)
 }
 #endif
 
-extern unsigned long end_user_pfn;
-
-extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);
-extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align);
-extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
-#include <linux/early_res.h>
-
 extern unsigned long e820_end_of_ram_pfn(void);
 extern unsigned long e820_end_of_low_ram_pfn(void);
-extern int e820_find_active_region(const struct e820entry *ei,
-                                 unsigned long start_pfn,
-                                 unsigned long last_pfn,
-                                 unsigned long *ei_startpfn,
-                                 unsigned long *ei_endpfn);
-extern void e820_register_active_regions(int nid, unsigned long start_pfn,
-                                        unsigned long end_pfn);
-extern u64 e820_hole_size(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
+
+void memblock_x86_fill(void);
+void memblock_find_dma_reserve(void);
+
 extern void finish_e820_parsing(void);
 extern void e820_reserve_resources(void);
 extern void e820_reserve_resources_late(void);
index 8406ed7f99269f97c469bc9b03e0cb8d00276f84..8e4a16508d4e89641919cd39979c14532459af96 100644 (file)
@@ -90,7 +90,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
-extern void efi_reserve_early(void);
+extern void efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 
index 8e8ec663a98fab4b771123fa1bfd6f7aef2f5931..b8e96a18676b872e751c4635921fb479f615c74e 100644 (file)
@@ -49,8 +49,8 @@ BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
 BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
 BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
 
-#ifdef CONFIG_PERF_EVENTS
-BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR)
+#ifdef CONFIG_IRQ_WORK
+BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR)
 #endif
 
 #ifdef CONFIG_X86_THERMAL_VECTOR
index d07b44f7d1dc014b3d1cb77e49138ef5f97f5d24..4d293dced62f4c178cd19e6cb2eae882678afb33 100644 (file)
@@ -214,5 +214,20 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
        BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
        return __virt_to_fix(vaddr);
 }
+
+/* Return an pointer with offset calculated */
+static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx,
+                               phys_addr_t phys, pgprot_t flags)
+{
+       __set_fixmap(idx, phys, flags);
+       return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1));
+}
+
+#define set_fixmap_offset(idx, phys)                   \
+       __set_fixmap_offset(idx, phys, PAGE_KERNEL)
+
+#define set_fixmap_offset_nocache(idx, phys)                   \
+       __set_fixmap_offset(idx, phys, PAGE_KERNEL_NOCACHE)
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_X86_FIXMAP_H */
index 4ac5b0f33fc1017b3760eb01b1a4ed7f7155dbce..43085bfc99c30f963b929a9c7afdcff932ad9236 100644 (file)
@@ -17,6 +17,7 @@ extern int fix_aperture;
 #define GARTEN         (1<<0)
 #define DISGARTCPU     (1<<4)
 #define DISGARTIO      (1<<5)
+#define DISTLBWALKPRB  (1<<6)
 
 /* GART cache control register bits. */
 #define INVGART                (1<<0)
@@ -27,7 +28,6 @@ extern int fix_aperture;
 #define AMD64_GARTAPERTUREBASE 0x94
 #define AMD64_GARTTABLEBASE    0x98
 #define AMD64_GARTCACHECTL     0x9c
-#define AMD64_GARTEN           (1<<0)
 
 #ifdef CONFIG_GART_IOMMU
 extern int gart_iommu_aperture;
@@ -37,7 +37,7 @@ extern int gart_iommu_aperture_disabled;
 extern void early_gart_iommu_check(void);
 extern int gart_iommu_init(void);
 extern void __init gart_parse_options(char *);
-extern void gart_iommu_hole_init(void);
+extern int gart_iommu_hole_init(void);
 
 #else
 #define gart_iommu_aperture            0
@@ -50,13 +50,27 @@ static inline void early_gart_iommu_check(void)
 static inline void gart_parse_options(char *options)
 {
 }
-static inline void gart_iommu_hole_init(void)
+static inline int gart_iommu_hole_init(void)
 {
+       return -ENODEV;
 }
 #endif
 
 extern int agp_amd64_init(void);
 
+static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
+{
+       u32 ctl;
+
+       /*
+        * Don't enable translation but enable GART IO and CPU accesses.
+        * Also, set DISTLBWALKPRB since GART tables memory is UC.
+        */
+       ctl = DISTLBWALKPRB | order << 1;
+
+       pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+}
+
 static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
 {
        u32 tmp, ctl;
index aeab29aee617240fbf479d2945572879be4525ec..55e4de613f0ee72471fd3cfaf28dee21150b276c 100644 (file)
@@ -14,7 +14,7 @@ typedef struct {
 #endif
        unsigned int x86_platform_ipis; /* arch dependent */
        unsigned int apic_perf_irqs;
-       unsigned int apic_pending_irqs;
+       unsigned int apic_irq_work_irqs;
 #ifdef CONFIG_SMP
        unsigned int irq_resched_count;
        unsigned int irq_call_count;
index 004e6e25e91301dd8a6d188d84a9c9ee795a7100..2c392d663dcee3f899d28c195b05fb92d63930cf 100644 (file)
@@ -68,17 +68,18 @@ extern unsigned long force_hpet_address;
 extern u8 hpet_blockid;
 extern int hpet_force_user;
 extern u8 hpet_msi_disable;
-extern u8 hpet_readback_cmp;
 extern int is_hpet_enabled(void);
 extern int hpet_enable(void);
 extern void hpet_disable(void);
 extern unsigned int hpet_readl(unsigned int a);
 extern void force_hpet_resume(void);
 
-extern void hpet_msi_unmask(unsigned int irq);
-extern void hpet_msi_mask(unsigned int irq);
-extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg);
-extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg);
+struct irq_data;
+extern void hpet_msi_unmask(struct irq_data *data);
+extern void hpet_msi_mask(struct irq_data *data);
+struct hpet_dev;
+extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
+extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
 
 #ifdef CONFIG_PCI_MSI
 extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id);
index 528a11e8d3e35f64fea90202d6f196d77d48e708..824ca07860d012cdcc9c46886500d056fdb2aeed 100644 (file)
@@ -20,7 +20,7 @@ struct arch_hw_breakpoint {
 #include <linux/list.h>
 
 /* Available HW breakpoint length encodings */
-#define X86_BREAKPOINT_LEN_X           0x00
+#define X86_BREAKPOINT_LEN_X           0x40
 #define X86_BREAKPOINT_LEN_1           0x40
 #define X86_BREAKPOINT_LEN_2           0x44
 #define X86_BREAKPOINT_LEN_4           0x4c
index 46c0fe05f230112b5aa5e176d4292e56526f8279..0274ec5a7e6285c18bbdd9908bc04d4b829fd9cc 100644 (file)
@@ -29,7 +29,7 @@
 extern void apic_timer_interrupt(void);
 extern void x86_platform_ipi(void);
 extern void error_interrupt(void);
-extern void perf_pending_interrupt(void);
+extern void irq_work_interrupt(void);
 
 extern void spurious_interrupt(void);
 extern void thermal_interrupt(void);
@@ -78,6 +78,13 @@ static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
        irq_attr->polarity      = polarity;
 }
 
+struct irq_2_iommu {
+       struct intel_iommu *iommu;
+       u16 irte_index;
+       u16 sub_handle;
+       u8  irte_mask;
+};
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -89,15 +96,17 @@ struct irq_cfg {
        cpumask_var_t           old_domain;
        u8                      vector;
        u8                      move_in_progress : 1;
+#ifdef CONFIG_INTR_REMAP
+       struct irq_2_iommu      irq_2_iommu;
+#endif
 };
 
-extern struct irq_cfg *irq_cfg(unsigned int);
 extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *);
 extern void send_cleanup_vector(struct irq_cfg *);
 
-struct irq_desc;
-extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *,
-                                     unsigned int *dest_id);
+struct irq_data;
+int __ioapic_set_affinity(struct irq_data *, const struct cpumask *,
+                         unsigned int *dest_id);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr);
 extern void setup_ioapic_dest(void);
 
index a73a8d5a5e6963e6fef9b52c28666e913a74160c..4aa2bb3b242ab76733e0f7e5ba95454471297c1a 100644 (file)
@@ -55,6 +55,12 @@ extern int save_i387_xstate_ia32(void __user *buf);
 extern int restore_i387_xstate_ia32(void __user *buf);
 #endif
 
+#ifdef CONFIG_MATH_EMULATION
+extern void finit_soft_fpu(struct i387_soft_struct *soft);
+#else
+static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
+#endif
+
 #define X87_FSW_ES (1 << 7)    /* Exception Summary */
 
 static __always_inline __pure bool use_xsaveopt(void)
@@ -67,6 +73,11 @@ static __always_inline __pure bool use_xsave(void)
        return static_cpu_has(X86_FEATURE_XSAVE);
 }
 
+static __always_inline __pure bool use_fxsr(void)
+{
+        return static_cpu_has(X86_FEATURE_FXSR);
+}
+
 extern void __sanitize_i387_state(struct task_struct *);
 
 static inline void sanitize_i387_state(struct task_struct *tsk)
@@ -77,19 +88,11 @@ static inline void sanitize_i387_state(struct task_struct *tsk)
 }
 
 #ifdef CONFIG_X86_64
-
-/* Ignore delayed exceptions from user space */
-static inline void tolerant_fwait(void)
-{
-       asm volatile("1: fwait\n"
-                    "2:\n"
-                    _ASM_EXTABLE(1b, 2b));
-}
-
 static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
        int err;
 
+       /* See comment in fxsave() below. */
        asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
                     "2:\n"
                     ".section .fixup,\"ax\"\n"
@@ -98,44 +101,10 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
                     ".previous\n"
                     _ASM_EXTABLE(1b, 3b)
                     : [err] "=r" (err)
-#if 0 /* See comment in fxsave() below. */
-                    : [fx] "r" (fx), "m" (*fx), "0" (0));
-#else
-                    : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
-#endif
+                    : [fx] "R" (fx), "m" (*fx), "0" (0));
        return err;
 }
 
-/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
-   is pending. Clear the x87 state here by setting it to fixed
-   values. The kernel data segment can be sometimes 0 and sometimes
-   new user value. Both should be ok.
-   Use the PDA as safe address because it should be already in L1. */
-static inline void fpu_clear(struct fpu *fpu)
-{
-       struct xsave_struct *xstate = &fpu->state->xsave;
-       struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
-       /*
-        * xsave header may indicate the init state of the FP.
-        */
-       if (use_xsave() &&
-           !(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
-               return;
-
-       if (unlikely(fx->swd & X87_FSW_ES))
-               asm volatile("fnclex");
-       alternative_input(ASM_NOP8 ASM_NOP2,
-                         "    emms\n"          /* clear stack tags */
-                         "    fildl %%gs:0",   /* load to clear state */
-                         X86_FEATURE_FXSAVE_LEAK);
-}
-
-static inline void clear_fpu_state(struct task_struct *tsk)
-{
-       fpu_clear(&tsk->thread.fpu);
-}
-
 static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
 {
        int err;
@@ -149,6 +118,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
        if (unlikely(err))
                return -EFAULT;
 
+       /* See comment in fxsave() below. */
        asm volatile("1:  rex64/fxsave (%[fx])\n\t"
                     "2:\n"
                     ".section .fixup,\"ax\"\n"
@@ -157,11 +127,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
                     ".previous\n"
                     _ASM_EXTABLE(1b, 3b)
                     : [err] "=r" (err), "=m" (*fx)
-#if 0 /* See comment in fxsave() below. */
-                    : [fx] "r" (fx), "0" (0));
-#else
-                    : [fx] "cdaSDb" (fx), "0" (0));
-#endif
+                    : [fx] "R" (fx), "0" (0));
        if (unlikely(err) &&
            __clear_user(fx, sizeof(struct i387_fxsave_struct)))
                err = -EFAULT;
@@ -175,56 +141,29 @@ static inline void fpu_fxsave(struct fpu *fpu)
           uses any extended registers for addressing, a second REX prefix
           will be generated (to the assembler, rex64 followed by semicolon
           is a separate instruction), and hence the 64-bitness is lost. */
-#if 0
+
+#ifdef CONFIG_AS_FXSAVEQ
        /* Using "fxsaveq %0" would be the ideal choice, but is only supported
           starting with gas 2.16. */
        __asm__ __volatile__("fxsaveq %0"
                             : "=m" (fpu->state->fxsave));
-#elif 0
+#else
        /* Using, as a workaround, the properly prefixed form below isn't
           accepted by any binutils version so far released, complaining that
           the same type of prefix is used twice if an extended register is
-          needed for addressing (fix submitted to mainline 2005-11-21). */
-       __asm__ __volatile__("rex64/fxsave %0"
-                            : "=m" (fpu->state->fxsave));
-#else
-       /* This, however, we can work around by forcing the compiler to select
+          needed for addressing (fix submitted to mainline 2005-11-21).
+       asm volatile("rex64/fxsave %0"
+                    : "=m" (fpu->state->fxsave));
+          This, however, we can work around by forcing the compiler to select
           an addressing mode that doesn't require extended registers. */
-       __asm__ __volatile__("rex64/fxsave (%1)"
-                            : "=m" (fpu->state->fxsave)
-                            : "cdaSDb" (&fpu->state->fxsave));
+       asm volatile("rex64/fxsave (%[fx])"
+                    : "=m" (fpu->state->fxsave)
+                    : [fx] "R" (&fpu->state->fxsave));
 #endif
 }
 
-static inline void fpu_save_init(struct fpu *fpu)
-{
-       if (use_xsave())
-               fpu_xsave(fpu);
-       else
-               fpu_fxsave(fpu);
-
-       fpu_clear(fpu);
-}
-
-static inline void __save_init_fpu(struct task_struct *tsk)
-{
-       fpu_save_init(&tsk->thread.fpu);
-       task_thread_info(tsk)->status &= ~TS_USEDFPU;
-}
-
 #else  /* CONFIG_X86_32 */
 
-#ifdef CONFIG_MATH_EMULATION
-extern void finit_soft_fpu(struct i387_soft_struct *soft);
-#else
-static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
-#endif
-
-static inline void tolerant_fwait(void)
-{
-       asm volatile("fnclex ; fwait");
-}
-
 /* perform fxrstor iff the processor has extended states, otherwise frstor */
 static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
@@ -241,6 +180,14 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
        return 0;
 }
 
+static inline void fpu_fxsave(struct fpu *fpu)
+{
+       asm volatile("fxsave %[fx]"
+                    : [fx] "=m" (fpu->state->fxsave));
+}
+
+#endif /* CONFIG_X86_64 */
+
 /* We need a safe address that is cheap to find and that is already
    in L1 during context switch. The best choices are unfortunately
    different for UP and SMP */
@@ -256,47 +203,33 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 static inline void fpu_save_init(struct fpu *fpu)
 {
        if (use_xsave()) {
-               struct xsave_struct *xstate = &fpu->state->xsave;
-               struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
                fpu_xsave(fpu);
 
                /*
                 * xsave header may indicate the init state of the FP.
                 */
-               if (!(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
-                       goto end;
-
-               if (unlikely(fx->swd & X87_FSW_ES))
-                       asm volatile("fnclex");
-
-               /*
-                * we can do a simple return here or be paranoid :)
-                */
-               goto clear_state;
+               if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
+                       return;
+       } else if (use_fxsr()) {
+               fpu_fxsave(fpu);
+       } else {
+               asm volatile("fsave %[fx]; fwait"
+                            : [fx] "=m" (fpu->state->fsave));
+               return;
        }
 
-       /* Use more nops than strictly needed in case the compiler
-          varies code */
-       alternative_input(
-               "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
-               "fxsave %[fx]\n"
-               "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
-               X86_FEATURE_FXSR,
-               [fx] "m" (fpu->state->fxsave),
-               [fsw] "m" (fpu->state->fxsave.swd) : "memory");
-clear_state:
+       if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+               asm volatile("fnclex");
+
        /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
           is pending.  Clear the x87 state here by setting it to fixed
           values. safe_address is a random variable that should be in L1 */
        alternative_input(
-               GENERIC_NOP8 GENERIC_NOP2,
+               ASM_NOP8 ASM_NOP2,
                "emms\n\t"              /* clear stack tags */
-               "fildl %[addr]",        /* set F?P to defined value */
+               "fildl %P[addr]",       /* set F?P to defined value */
                X86_FEATURE_FXSAVE_LEAK,
                [addr] "m" (safe_address));
-end:
-       ;
 }
 
 static inline void __save_init_fpu(struct task_struct *tsk)
@@ -305,9 +238,6 @@ static inline void __save_init_fpu(struct task_struct *tsk)
        task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
-
-#endif /* CONFIG_X86_64 */
-
 static inline int fpu_fxrstor_checking(struct fpu *fpu)
 {
        return fxrstor_checking(&fpu->state->fxsave);
@@ -344,7 +274,10 @@ static inline void __unlazy_fpu(struct task_struct *tsk)
 static inline void __clear_fpu(struct task_struct *tsk)
 {
        if (task_thread_info(tsk)->status & TS_USEDFPU) {
-               tolerant_fwait();
+               /* Ignore delayed exceptions from user space */
+               asm volatile("1: fwait\n"
+                            "2:\n"
+                            _ASM_EXTABLE(1b, 2b));
                task_thread_info(tsk)->status &= ~TS_USEDFPU;
                stts();
        }
@@ -405,19 +338,6 @@ static inline void irq_ts_restore(int TS_state)
                stts();
 }
 
-#ifdef CONFIG_X86_64
-
-static inline void save_init_fpu(struct task_struct *tsk)
-{
-       __save_init_fpu(tsk);
-       stts();
-}
-
-#define unlazy_fpu     __unlazy_fpu
-#define clear_fpu      __clear_fpu
-
-#else  /* CONFIG_X86_32 */
-
 /*
  * These disable preemption on their own and are safe
  */
@@ -443,8 +363,6 @@ static inline void clear_fpu(struct task_struct *tsk)
        preempt_enable();
 }
 
-#endif /* CONFIG_X86_64 */
-
 /*
  * i387 state interaction
  */
@@ -508,7 +426,4 @@ extern void fpu_finit(struct fpu *fpu);
 
 #endif /* __ASSEMBLY__ */
 
-#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5
-#define PSHUFB_XMM5_XMM6 .byte 0x66, 0x0f, 0x38, 0x00, 0xf5
-
 #endif /* _ASM_X86_I387_H */
index 1655147646aa61e820ef38c76546e07a5c149e2e..a20365953bf8a7727285029f3c6d84ba56f941a0 100644 (file)
@@ -55,6 +55,8 @@ extern struct irq_chip i8259A_chip;
 struct legacy_pic {
        int nr_legacy_irqs;
        struct irq_chip *chip;
+       void (*mask)(unsigned int irq);
+       void (*unmask)(unsigned int irq);
        void (*mask_all)(void);
        void (*restore_mask)(void);
        void (*init)(int auto_eoi);
index 30a3e977612306033c9647487dde3298b31a4f73..f0203f4791a8924a94a31d92fe78c298c3f3dd64 100644 (file)
@@ -206,6 +206,7 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void set_iounmap_nonlazy(void);
 
 #ifdef __KERNEL__
 
@@ -348,6 +349,7 @@ extern void __iomem *early_memremap(resource_size_t phys_addr,
                                    unsigned long size);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void fixup_early_ioremap(void);
+extern bool is_early_ioremap_ptep(pte_t *ptep);
 
 #define IO_SPACE_LIMIT 0xffff
 
index 9cb2edb87c2f718780fb00cc61ebc1bfa5ad0228..c8be4566c3d28143af7d7868eeee0801dae0a5cf 100644 (file)
@@ -170,12 +170,6 @@ extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 
 extern void probe_nr_irqs_gsi(void);
 
-extern int setup_ioapic_entry(int apic, int irq,
-                             struct IO_APIC_route_entry *entry,
-                             unsigned int destination, int trigger,
-                             int polarity, int vector, int pin);
-extern void ioapic_write_entry(int apic, int pin,
-                              struct IO_APIC_route_entry e);
 extern void setup_ioapic_ids_from_mpc(void);
 
 struct mp_ioapic_gsi{
index f35eb45d6576258e7dba242934d76376380b531c..c4191b3b7056c6ad16563375f529d1480668a26e 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
-void *
+void __iomem *
 iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
 
 void
-iounmap_atomic(void *kvaddr, enum km_type type);
+iounmap_atomic(void __iomem *kvaddr, enum km_type type);
 
 int
 iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot);
diff --git a/arch/x86/include/asm/iommu_table.h b/arch/x86/include/asm/iommu_table.h
new file mode 100644 (file)
index 0000000..f229b13
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef _ASM_X86_IOMMU_TABLE_H
+#define _ASM_X86_IOMMU_TABLE_H
+
+#include <asm/swiotlb.h>
+
+/*
+ * History lesson:
+ * The execution chain of IOMMUs in 2.6.36 looks as so:
+ *
+ *            [xen-swiotlb]
+ *                 |
+ *         +----[swiotlb *]--+
+ *        /         |         \
+ *       /          |          \
+ *    [GART]     [Calgary]  [Intel VT-d]
+ *     /
+ *    /
+ * [AMD-Vi]
+ *
+ * *: if SWIOTLB detected 'iommu=soft'/'swiotlb=force' it would skip
+ * over the rest of IOMMUs and unconditionally initialize the SWIOTLB.
+ * Also it would surreptitiously initialize set the swiotlb=1 if there were
+ * more than 4GB and if the user did not pass in 'iommu=off'. The swiotlb
+ * flag would be turned off by all IOMMUs except the Calgary one.
+ *
+ * The IOMMU_INIT* macros allow a similar tree (or more complex if desired)
+ * to be built by defining who we depend on.
+ *
+ * And all that needs to be done is to use one of the macros in the IOMMU
+ * and the pci-dma.c will take care of the rest.
+ */
+
+struct iommu_table_entry {
+       initcall_t      detect;
+       initcall_t      depend;
+       void            (*early_init)(void); /* No memory allocate available. */
+       void            (*late_init)(void); /* Yes, can allocate memory. */
+#define IOMMU_FINISH_IF_DETECTED (1<<0)
+#define IOMMU_DETECTED          (1<<1)
+       int             flags;
+};
+/*
+ * Macro fills out an entry in the .iommu_table that is equivalent
+ * to the fields that 'struct iommu_table_entry' has. The entries
+ * that are put in the .iommu_table section are not put in any order
+ * hence during boot-time we will have to resort them based on
+ * dependency. */
+
+
+#define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\
+       static const struct iommu_table_entry const                     \
+               __iommu_entry_##_detect __used                          \
+       __attribute__ ((unused, __section__(".iommu_table"),            \
+                       aligned((sizeof(void *)))))     \
+       = {_detect, _depend, _early_init, _late_init,                   \
+          _finish ? IOMMU_FINISH_IF_DETECTED : 0}
+/*
+ * The simplest IOMMU definition. Provide the detection routine
+ * and it will be run after the SWIOTLB and the other IOMMUs
+ * that utilize this macro. If the IOMMU is detected (ie, the
+ * detect routine returns a positive value), the other IOMMUs
+ * are also checked. You can use IOMMU_INIT_POST_FINISH if you prefer
+ * to stop detecting the other IOMMUs after yours has been detected.
+ */
+#define IOMMU_INIT_POST(_detect)                                       \
+       __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 0)
+
+#define IOMMU_INIT_POST_FINISH(detect)                                 \
+       __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 1)
+
+/*
+ * A more sophisticated version of IOMMU_INIT. This variant requires:
+ *  a). A detection routine function.
+ *  b). The name of the detection routine we depend on to get called
+ *      before us.
+ *  c). The init routine which gets called if the detection routine
+ *      returns a positive value from the pci_iommu_alloc. This means
+ *      no presence of a memory allocator.
+ *  d). Similar to the 'init', except that this gets called from pci_iommu_init
+ *      where we do have a memory allocator.
+ *
+ * The standard vs the _FINISH differs in that the _FINISH variant will
+ * continue detecting other IOMMUs in the call list after the
+ * the detection routine returns a positive number. The _FINISH will
+ * stop the execution chain. Both will still call the 'init' and
+ * 'late_init' functions if they are set.
+ */
+#define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init)         \
+       __IOMMU_INIT(_detect, _depend, _init, _late_init, 1)
+
+#define IOMMU_INIT(_detect, _depend, _init, _late_init)                        \
+       __IOMMU_INIT(_detect, _depend, _init, _late_init, 0)
+
+void sort_iommu_table(struct iommu_table_entry *start,
+                     struct iommu_table_entry *finish);
+
+void check_iommu_entries(struct iommu_table_entry *start,
+                        struct iommu_table_entry *finish);
+
+#endif /* _ASM_X86_IOMMU_TABLE_H */
index 5458380b6ef8fb3cefc93077acdb8441b863ba6f..0bf5b00836502fb6512609bbad05fbc3eaa96320 100644 (file)
@@ -19,18 +19,16 @@ static inline int irq_canonicalize(int irq)
 # define ARCH_HAS_NMI_WATCHDOG
 #endif
 
-#ifdef CONFIG_4KSTACKS
-  extern void irq_ctx_init(int cpu);
-  extern void irq_ctx_exit(int cpu);
-# define __ARCH_HAS_DO_SOFTIRQ
+#ifdef CONFIG_X86_32
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
 #else
 # define irq_ctx_init(cpu) do { } while (0)
 # define irq_ctx_exit(cpu) do { } while (0)
-# ifdef CONFIG_X86_64
-#  define __ARCH_HAS_DO_SOFTIRQ
-# endif
 #endif
 
+#define __ARCH_HAS_DO_SOFTIRQ
+
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
 extern void fixup_irqs(void);
index f275e2244505b98308ca72e66e26c250d29c61a8..1c23360fb2d8effec9b2ffbba102c9b30b0f63c8 100644 (file)
@@ -3,4 +3,39 @@
 
 #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
+#ifdef CONFIG_INTR_REMAP
+static inline void prepare_irte(struct irte *irte, int vector,
+                               unsigned int dest)
+{
+       memset(irte, 0, sizeof(*irte));
+
+       irte->present = 1;
+       irte->dst_mode = apic->irq_dest_mode;
+       /*
+        * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
+        * actual level or edge trigger will be setup in the IO-APIC
+        * RTE. This will help simplify level triggered irq migration.
+        * For more details, see the comments (in io_apic.c) explainig IO-APIC
+        * irq migration in the presence of interrupt-remapping.
+       */
+       irte->trigger_mode = 0;
+       irte->dlvry_mode = apic->irq_delivery_mode;
+       irte->vector = vector;
+       irte->dest_id = IRTE_DEST(dest);
+       irte->redir_hint = 1;
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+       return cfg->irq_2_iommu.iommu != NULL;
+}
+#else
+static void prepare_irte(struct irte *irte, int vector, unsigned int dest)
+{
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+       return false;
+}
+#endif
+
 #endif /* _ASM_X86_IRQ_REMAPPING_H */
index e2ca3009255706910d1ddc407232f4d09f011f24..6af0894dafb445cdaedceb1630249c47e955633f 100644 (file)
 #define X86_PLATFORM_IPI_VECTOR                0xed
 
 /*
- * Performance monitoring pending work vector:
+ * IRQ work vector:
  */
-#define LOCAL_PENDING_VECTOR           0xec
+#define IRQ_WORK_VECTOR                        0xec
 
 #define UV_BAU_MESSAGE                 0xea
 
index 9e2b952f810a601d16125dcfb1c2764d914d960c..5745ce8bf1089cd2399415641d1a0c25f39cf6c1 100644 (file)
@@ -61,22 +61,22 @@ static inline void native_halt(void)
 #else
 #ifndef __ASSEMBLY__
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
        return native_save_fl();
 }
 
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
        native_restore_fl(flags);
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
        native_irq_disable();
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
        native_irq_enable();
 }
@@ -85,7 +85,7 @@ static inline void raw_local_irq_enable(void)
  * Used in the idle loop; sti takes one instruction cycle
  * to complete:
  */
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
 {
        native_safe_halt();
 }
@@ -102,12 +102,10 @@ static inline void halt(void)
 /*
  * For spinlocks, etc:
  */
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
-       unsigned long flags = __raw_local_save_flags();
-
-       raw_local_irq_disable();
-
+       unsigned long flags = arch_local_save_flags();
+       arch_local_irq_disable();
        return flags;
 }
 #else
@@ -153,22 +151,16 @@ static inline unsigned long __raw_local_irq_save(void)
 #endif /* CONFIG_PARAVIRT */
 
 #ifndef __ASSEMBLY__
-#define raw_local_save_flags(flags)                            \
-       do { (flags) = __raw_local_save_flags(); } while (0)
-
-#define raw_local_irq_save(flags)                              \
-       do { (flags) = __raw_local_irq_save(); } while (0)
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
        return !(flags & X86_EFLAGS_IF);
 }
 
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
 {
-       unsigned long flags = __raw_local_save_flags();
+       unsigned long flags = arch_local_save_flags();
 
-       return raw_irqs_disabled_flags(flags);
+       return arch_irqs_disabled_flags(flags);
 }
 
 #else
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..f52d42e
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ASM_X86_JUMP_LABEL_H
+#define _ASM_X86_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/nops.h>
+
+#define JUMP_LABEL_NOP_SIZE 5
+
+# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"
+
+# define JUMP_LABEL(key, label)                                        \
+       do {                                                    \
+               asm goto("1:"                                   \
+                       JUMP_LABEL_INITIAL_NOP                  \
+                       ".pushsection __jump_table,  \"a\" \n\t"\
+                       _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
+                       ".popsection \n\t"                      \
+                       : :  "i" (key) :  : label);             \
+       } while (0)
+
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_X86_64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+};
+
+#endif
index 51cfd730ac5d145ed9f184f643c254d441dbeaab..1f99ecfc48e178312860f177160b735c2655946f 100644 (file)
@@ -152,9 +152,14 @@ struct x86_emulate_ops {
 struct operand {
        enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
        unsigned int bytes;
-       unsigned long orig_val, *ptr;
+       union {
+               unsigned long orig_val;
+               u64 orig_val64;
+       };
+       unsigned long *ptr;
        union {
                unsigned long val;
+               u64 val64;
                char valptr[sizeof(unsigned long) + 2];
        };
 };
index 502e53f999cf28a25cc2b00f1766bd1ffb2f9ed2..c52e2eb40a1e254339658481621be634b427a8f0 100644 (file)
@@ -652,20 +652,6 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
        return (struct kvm_mmu_page *)page_private(page);
 }
 
-static inline u16 kvm_read_fs(void)
-{
-       u16 seg;
-       asm("mov %%fs, %0" : "=g"(seg));
-       return seg;
-}
-
-static inline u16 kvm_read_gs(void)
-{
-       u16 seg;
-       asm("mov %%gs, %0" : "=g"(seg));
-       return seg;
-}
-
 static inline u16 kvm_read_ldt(void)
 {
        u16 ldt;
@@ -673,16 +659,6 @@ static inline u16 kvm_read_ldt(void)
        return ldt;
 }
 
-static inline void kvm_load_fs(u16 sel)
-{
-       asm("mov %0, %%fs" : : "rm"(sel));
-}
-
-static inline void kvm_load_gs(u16 sel)
-{
-       asm("mov %0, %%gs" : : "rm"(sel));
-}
-
 static inline void kvm_load_ldt(u16 sel)
 {
        asm("lldt %0" : : "rm"(sel));
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h
new file mode 100644 (file)
index 0000000..19ae14b
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _X86_MEMBLOCK_H
+#define _X86_MEMBLOCK_H
+
+#define ARCH_DISCARD_MEMBLOCK
+
+u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
+void memblock_x86_to_bootmem(u64 start, u64 end);
+
+void memblock_x86_reserve_range(u64 start, u64 end, char *name);
+void memblock_x86_free_range(u64 start, u64 end);
+struct range;
+int __get_free_all_memory_range(struct range **range, int nodeid,
+                        unsigned long start_pfn, unsigned long end_pfn);
+int get_free_all_memory_range(struct range **rangep, int nodeid);
+
+void memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+                                        unsigned long last_pfn);
+u64 memblock_x86_hole_size(u64 start, u64 end);
+u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
+u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
+u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
+
+#endif
index 3e2ce58a31a37f4ef65c67762f1b0dd75eb8ae33..67763c5d8b4ecc4f2e20541bcc73640ed03a8c12 100644 (file)
 #endif
 
 #ifdef CONFIG_X86_32
-# ifdef CONFIG_4KSTACKS
-#  define MODULE_STACKSIZE "4KSTACKS "
-# else
-#  define MODULE_STACKSIZE ""
-# endif
-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
 #endif
 
 #endif /* _ASM_X86_MODULE_H */
index 16350740edf600436d4990fec8a5fc9ce62abafc..4a711a684b174435bd5aae838515a836101eb389 100644 (file)
@@ -10,6 +10,9 @@
  */
 #ifndef _ASM_X86_MRST_H
 #define _ASM_X86_MRST_H
+
+#include <linux/sfi.h>
+
 extern int pci_mrst_init(void);
 int __init sfi_parse_mrtc(struct sfi_table_header *table);
 
@@ -26,7 +29,7 @@ enum mrst_cpu_type {
 };
 
 extern enum mrst_cpu_type __mrst_cpu_chip;
-static enum mrst_cpu_type mrst_identify_cpu(void)
+static inline enum mrst_cpu_type mrst_identify_cpu(void)
 {
        return __mrst_cpu_chip;
 }
@@ -42,4 +45,9 @@ extern enum mrst_timer_options mrst_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
 
+extern struct console early_mrst_console;
+extern void mrst_early_console_init(void);
+
+extern struct console early_hsu_console;
+extern void hsu_early_console_init(void);
 #endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
new file mode 100644 (file)
index 0000000..bcdff99
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _ASM_X86_MWAIT_H
+#define _ASM_X86_MWAIT_H
+
+#define MWAIT_SUBSTATE_MASK            0xf
+#define MWAIT_CSTATE_MASK              0xf
+#define MWAIT_SUBSTATE_SIZE            4
+#define MWAIT_MAX_NUM_CSTATES          8
+
+#define CPUID_MWAIT_LEAF               5
+#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
+#define CPUID5_ECX_INTERRUPT_BREAK     0x2
+
+#define MWAIT_ECX_INTERRUPT_BREAK      0x1
+
+#endif /* _ASM_X86_MWAIT_H */
index 08fde475cb3b38fcf75e2c41ba3f14ced47dc8a9..2a8478140bb38b205e32624b7bda5118c43e8133 100644 (file)
@@ -21,10 +21,14 @@ extern void olpc_ofw_detect(void);
 /* install OFW's pde permanently into the kernel's pgtable */
 extern void setup_olpc_ofw_pgd(void);
 
+/* check if OFW was detected during boot */
+extern bool olpc_ofw_present(void);
+
 #else /* !CONFIG_OLPC_OPENFIRMWARE */
 
 static inline void olpc_ofw_detect(void) { }
 static inline void setup_olpc_ofw_pgd(void) { }
+static inline bool olpc_ofw_present(void) { return false; }
 
 #endif /* !CONFIG_OLPC_OPENFIRMWARE */
 
index 6f1b7331313f1af2744c50accfecd26e069a5bed..ade619ff9e2a414c918c7ba3c38352ee72a79254 100644 (file)
  */
 #define __PAGE_OFFSET          _AC(CONFIG_PAGE_OFFSET, UL)
 
-#ifdef CONFIG_4KSTACKS
-#define THREAD_ORDER   0
-#else
 #define THREAD_ORDER   1
-#endif
 #define THREAD_SIZE    (PAGE_SIZE << THREAD_ORDER)
 
 #define STACKFAULT_STACK 0
index a667f24c72549e6c8171892fc6fbf63ac54006d0..1df66211fd1b53d4d6233cc1e481e88009622aab 100644 (file)
@@ -8,7 +8,7 @@
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 
-#define __PHYSICAL_MASK                ((phys_addr_t)(1ULL << __PHYSICAL_MASK_SHIFT) - 1)
+#define __PHYSICAL_MASK                ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
 #define __VIRTUAL_MASK         ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
 
 /* Cast PAGE_MASK to a signed type so that it is sign-extended if
index 5653f43d90e534670974735f5d4578afdb4fc900..18e3b8a8709f9def52af32b8f27b05afbdd7a4ae 100644 (file)
@@ -105,7 +105,7 @@ static inline void write_cr8(unsigned long x)
 }
 #endif
 
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
 {
        PVOP_VCALL0(pv_irq_ops.safe_halt);
 }
@@ -416,11 +416,6 @@ static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)
        PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
 }
 
-static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
-                                           unsigned long start, unsigned long count)
-{
-       PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
-}
 static inline void paravirt_release_pmd(unsigned long pfn)
 {
        PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
@@ -829,32 +824,32 @@ static __always_inline void arch_spin_unlock(struct arch_spinlock *lock)
 #define __PV_IS_CALLEE_SAVE(func)                      \
        ((struct paravirt_callee_save) { func })
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
        return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
 }
 
-static inline void raw_local_irq_restore(unsigned long f)
+static inline void arch_local_irq_restore(unsigned long f)
 {
        PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
        PVOP_VCALLEE0(pv_irq_ops.irq_disable);
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
        PVOP_VCALLEE0(pv_irq_ops.irq_enable);
 }
 
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
        unsigned long f;
 
-       f = __raw_local_save_flags();
-       raw_local_irq_disable();
+       f = arch_local_save_flags();
+       arch_local_irq_disable();
        return f;
 }
 
index db9ef55323417812190eafd454cff45e136aec29..b82bac975250e53ac53363c2a04b724a32ea9929 100644 (file)
@@ -255,7 +255,6 @@ struct pv_mmu_ops {
         */
        void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn);
        void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn);
-       void (*alloc_pmd_clone)(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count);
        void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn);
        void (*release_pte)(unsigned long pfn);
        void (*release_pmd)(unsigned long pfn);
index 404a880ea325510ab2f659e65c02b54314948cfb..d395540ff8948f112a8de16774f2b17bfb1dd695 100644 (file)
@@ -27,6 +27,9 @@ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
                                            int node);
 extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
 
+#ifdef CONFIG_PCI
+
+#ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
        struct pci_sysdata *sd = bus->sysdata;
@@ -37,13 +40,12 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 {
        return pci_domain_nr(bus);
 }
-
+#endif
 
 /* Can be used to override the logic in pci_scan_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
-#ifdef CONFIG_PCI
 extern unsigned int pcibios_assign_all_busses(void);
 extern int pci_legacy_init(void);
 # ifdef CONFIG_ACPI
index def500776b16a3b63d34da569021722e4d82f18a..a70cd216be5d729db1f364340f911d632819f18d 100644 (file)
 #define P4_ESCR_EMASK(v)       ((v) << P4_ESCR_EVENTMASK_SHIFT)
 #define P4_ESCR_TAG(v)         ((v) << P4_ESCR_TAG_SHIFT)
 
-/* Non HT mask */
-#define P4_ESCR_MASK                   \
-       (P4_ESCR_EVENT_MASK     |       \
-       P4_ESCR_EVENTMASK_MASK  |       \
-       P4_ESCR_TAG_MASK        |       \
-       P4_ESCR_TAG_ENABLE      |       \
-       P4_ESCR_T0_OS           |       \
-       P4_ESCR_T0_USR)
-
-/* HT mask */
-#define P4_ESCR_MASK_HT                        \
-       (P4_ESCR_MASK | P4_ESCR_T1_OS | P4_ESCR_T1_USR)
-
 #define P4_CCCR_OVF                    0x80000000U
 #define P4_CCCR_CASCADE                        0x40000000U
 #define P4_CCCR_OVF_PMI_T0             0x04000000U
 #define P4_CCCR_THRESHOLD(v)           ((v) << P4_CCCR_THRESHOLD_SHIFT)
 #define P4_CCCR_ESEL(v)                        ((v) << P4_CCCR_ESCR_SELECT_SHIFT)
 
-/* Non HT mask */
-#define P4_CCCR_MASK                           \
-       (P4_CCCR_OVF                    |       \
-       P4_CCCR_CASCADE                 |       \
-       P4_CCCR_OVF_PMI_T0              |       \
-       P4_CCCR_FORCE_OVF               |       \
-       P4_CCCR_EDGE                    |       \
-       P4_CCCR_THRESHOLD_MASK          |       \
-       P4_CCCR_COMPLEMENT              |       \
-       P4_CCCR_COMPARE                 |       \
-       P4_CCCR_ESCR_SELECT_MASK        |       \
-       P4_CCCR_ENABLE)
-
-/* HT mask */
-#define P4_CCCR_MASK_HT                                \
-       (P4_CCCR_MASK | P4_CCCR_OVF_PMI_T1 | P4_CCCR_THREAD_ANY)
-
 #define P4_GEN_ESCR_EMASK(class, name, bit)    \
        class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT)
 #define P4_ESCR_EMASK_BIT(class, name)         class##__##name
 #define P4_CONFIG_HT_SHIFT             63
 #define P4_CONFIG_HT                   (1ULL << P4_CONFIG_HT_SHIFT)
 
+/*
+ * The bits we allow to pass for RAW events
+ */
+#define P4_CONFIG_MASK_ESCR            \
+       P4_ESCR_EVENT_MASK      |       \
+       P4_ESCR_EVENTMASK_MASK  |       \
+       P4_ESCR_TAG_MASK        |       \
+       P4_ESCR_TAG_ENABLE
+
+#define P4_CONFIG_MASK_CCCR            \
+       P4_CCCR_EDGE            |       \
+       P4_CCCR_THRESHOLD_MASK  |       \
+       P4_CCCR_COMPLEMENT      |       \
+       P4_CCCR_COMPARE         |       \
+       P4_CCCR_THREAD_ANY      |       \
+       P4_CCCR_RESERVED
+
+/* some dangerous bits are reserved for kernel internals */
+#define P4_CONFIG_MASK                                   \
+       (p4_config_pack_escr(P4_CONFIG_MASK_ESCR))      | \
+       (p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
+
 static inline bool p4_is_event_cascaded(u64 config)
 {
        u32 cccr = p4_config_unpack_cccr(config);
index a34c785c5a63b88ecd9fb3f07ee26c8fd3b4a7df..ada823a13c7c9460a06e330e00de2456cab9e66f 100644 (file)
@@ -28,6 +28,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 extern spinlock_t pgd_lock;
 extern struct list_head pgd_list;
 
+extern struct mm_struct *pgd_page_get_mm(struct page *page);
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else  /* !CONFIG_PARAVIRT */
@@ -603,6 +605,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm,
        pte_update(mm, addr, ptep);
 }
 
+#define flush_tlb_fix_spurious_fault(vma, address)
+
 /*
  * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
  *
index 076052cd62bef2d08af47a725ad3b187cd735be6..f96ac9bedf75db0ca247326ab580301832761d82 100644 (file)
@@ -102,6 +102,8 @@ static inline void native_pgd_clear(pgd_t *pgd)
        native_set_pgd(pgd, native_make_pgd(0));
 }
 
+extern void sync_global_pgds(unsigned long start, unsigned long end);
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
index 325b7bdbebaa9494b3e3e4c08a314aed72f88dc4..cae9c3cb95cf160e4e00f8c0b1c29fac298bb48f 100644 (file)
@@ -110,6 +110,8 @@ struct cpuinfo_x86 {
        u16                     phys_proc_id;
        /* Core id: */
        u16                     cpu_core_id;
+       /* Compute unit id */
+       u8                      compute_unit_id;
        /* Index into per_cpu list: */
        u16                     cpu_index;
 #endif
@@ -602,7 +604,7 @@ extern unsigned long                mmu_cr4_features;
 
 static inline void set_in_cr4(unsigned long mask)
 {
-       unsigned cr4;
+       unsigned long cr4;
 
        mmu_cr4_features |= mask;
        cr4 = read_cr4();
@@ -612,7 +614,7 @@ static inline void set_in_cr4(unsigned long mask)
 
 static inline void clear_in_cr4(unsigned long mask)
 {
-       unsigned cr4;
+       unsigned long cr4;
 
        mmu_cr4_features &= ~mask;
        cr4 = read_cr4();
@@ -764,29 +766,6 @@ extern unsigned long               idle_halt;
 extern unsigned long           idle_nomwait;
 extern bool                    c1e_detected;
 
-/*
- * on systems with caches, caches must be flashed as the absolute
- * last instruction before going into a suspended halt.  Otherwise,
- * dirty data can linger in the cache and become stale on resume,
- * leading to strange errors.
- *
- * perform a variety of operations to guarantee that the compiler
- * will not reorder instructions.  wbinvd itself is serializing
- * so the processor will not reorder.
- *
- * Systems without cache can just go into halt.
- */
-static inline void wbinvd_halt(void)
-{
-       mb();
-       /* check for clflush to determine if wbinvd is legal */
-       if (cpu_has_clflush)
-               asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
-       else
-               while (1)
-                       halt();
-}
-
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
index ef292c792d742cb35b1a48ac7f18f97a6546860c..d6763b139a844243b9fbb8dc620e633fe7b5825a 100644 (file)
@@ -93,6 +93,11 @@ void *extend_brk(size_t size, size_t align);
                        : : "i" (sz));                                  \
        }
 
+/* Helper for reserving space for arrays of things */
+#define RESERVE_BRK_ARRAY(type, name, entries)         \
+       type *name;                                     \
+       RESERVE_BRK(name, sizeof(type) * entries)
+
 #ifdef __i386__
 
 void __init i386_start_kernel(void);
index 8085277e1b8b62747f8d8e57dc1ce16d91214e8c..977f1761a25d51b25737d84436a3a80dd3f60810 100644 (file)
@@ -5,17 +5,26 @@
 
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
-extern int __init pci_swiotlb_detect(void);
+extern int __init pci_swiotlb_detect_override(void);
+extern int __init pci_swiotlb_detect_4gb(void);
 extern void __init pci_swiotlb_init(void);
+extern void __init pci_swiotlb_late_init(void);
 #else
 #define swiotlb 0
-static inline int pci_swiotlb_detect(void)
+static inline int pci_swiotlb_detect_override(void)
+{
+       return 0;
+}
+static inline int pci_swiotlb_detect_4gb(void)
 {
        return 0;
 }
 static inline void pci_swiotlb_init(void)
 {
 }
+static inline void pci_swiotlb_late_init(void)
+{
+}
 #endif
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
index c0427295e8f58956e32f833c78c9ad75676778d2..1ca132fc0d039cbc8c3b7f605fa4dbbd91db7291 100644 (file)
@@ -59,5 +59,7 @@ extern void check_tsc_sync_source(int cpu);
 extern void check_tsc_sync_target(void);
 
 extern int notsc_setup(char *);
+extern void save_sched_clock_state(void);
+extern void restore_sched_clock_state(void);
 
 #endif /* _ASM_X86_TSC_H */
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h
deleted file mode 100644 (file)
index 61e08c0..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * VMI interface definition
- *
- * Copyright (C) 2005, VMware, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Maintained by: Zachary Amsden zach@vmware.com
- *
- */
-#include <linux/types.h>
-
-/*
- *---------------------------------------------------------------------
- *
- *  VMI Option ROM API
- *
- *---------------------------------------------------------------------
- */
-#define VMI_SIGNATURE 0x696d5663   /* "cVmi" */
-
-#define PCI_VENDOR_ID_VMWARE            0x15AD
-#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
-
-/*
- * We use two version numbers for compatibility, with the major
- * number signifying interface breakages, and the minor number
- * interface extensions.
- */
-#define VMI_API_REV_MAJOR       3
-#define VMI_API_REV_MINOR       0
-
-#define VMI_CALL_CPUID                 0
-#define VMI_CALL_WRMSR                 1
-#define VMI_CALL_RDMSR                 2
-#define VMI_CALL_SetGDT                        3
-#define VMI_CALL_SetLDT                        4
-#define VMI_CALL_SetIDT                        5
-#define VMI_CALL_SetTR                 6
-#define VMI_CALL_GetGDT                        7
-#define VMI_CALL_GetLDT                        8
-#define VMI_CALL_GetIDT                        9
-#define VMI_CALL_GetTR                 10
-#define VMI_CALL_WriteGDTEntry         11
-#define VMI_CALL_WriteLDTEntry         12
-#define VMI_CALL_WriteIDTEntry         13
-#define VMI_CALL_UpdateKernelStack     14
-#define VMI_CALL_SetCR0                        15
-#define VMI_CALL_SetCR2                        16
-#define VMI_CALL_SetCR3                        17
-#define VMI_CALL_SetCR4                        18
-#define VMI_CALL_GetCR0                        19
-#define VMI_CALL_GetCR2                        20
-#define VMI_CALL_GetCR3                        21
-#define VMI_CALL_GetCR4                        22
-#define VMI_CALL_WBINVD                        23
-#define VMI_CALL_SetDR                 24
-#define VMI_CALL_GetDR                 25
-#define VMI_CALL_RDPMC                 26
-#define VMI_CALL_RDTSC                 27
-#define VMI_CALL_CLTS                  28
-#define VMI_CALL_EnableInterrupts      29
-#define VMI_CALL_DisableInterrupts     30
-#define VMI_CALL_GetInterruptMask      31
-#define VMI_CALL_SetInterruptMask      32
-#define VMI_CALL_IRET                  33
-#define VMI_CALL_SYSEXIT               34
-#define VMI_CALL_Halt                  35
-#define VMI_CALL_Reboot                        36
-#define VMI_CALL_Shutdown              37
-#define VMI_CALL_SetPxE                        38
-#define VMI_CALL_SetPxELong            39
-#define VMI_CALL_UpdatePxE             40
-#define VMI_CALL_UpdatePxELong         41
-#define VMI_CALL_MachineToPhysical     42
-#define VMI_CALL_PhysicalToMachine     43
-#define VMI_CALL_AllocatePage          44
-#define VMI_CALL_ReleasePage           45
-#define VMI_CALL_InvalPage             46
-#define VMI_CALL_FlushTLB              47
-#define VMI_CALL_SetLinearMapping      48
-
-#define VMI_CALL_SetIOPLMask           61
-#define VMI_CALL_SetInitialAPState     62
-#define VMI_CALL_APICWrite             63
-#define VMI_CALL_APICRead              64
-#define VMI_CALL_IODelay               65
-#define VMI_CALL_SetLazyMode           73
-
-/*
- *---------------------------------------------------------------------
- *
- * MMU operation flags
- *
- *---------------------------------------------------------------------
- */
-
-/* Flags used by VMI_{Allocate|Release}Page call */
-#define VMI_PAGE_PAE             0x10  /* Allocate PAE shadow */
-#define VMI_PAGE_CLONE           0x20  /* Clone from another shadow */
-#define VMI_PAGE_ZEROED          0x40  /* Page is pre-zeroed */
-
-
-/* Flags shared by Allocate|Release Page and PTE updates */
-#define VMI_PAGE_PT              0x01
-#define VMI_PAGE_PD              0x02
-#define VMI_PAGE_PDP             0x04
-#define VMI_PAGE_PML4            0x08
-
-#define VMI_PAGE_NORMAL          0x00 /* for debugging */
-
-/* Flags used by PTE updates */
-#define VMI_PAGE_CURRENT_AS      0x10 /* implies VMI_PAGE_VA_MASK is valid */
-#define VMI_PAGE_DEFER           0x20 /* may queue update until TLB inval */
-#define VMI_PAGE_VA_MASK         0xfffff000
-
-#ifdef CONFIG_X86_PAE
-#define VMI_PAGE_L1            (VMI_PAGE_PT | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2            (VMI_PAGE_PD | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#else
-#define VMI_PAGE_L1            (VMI_PAGE_PT | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2            (VMI_PAGE_PD | VMI_PAGE_ZEROED)
-#endif
-
-/* Flags used by VMI_FlushTLB call */
-#define VMI_FLUSH_TLB            0x01
-#define VMI_FLUSH_GLOBAL         0x02
-
-/*
- *---------------------------------------------------------------------
- *
- *  VMI relocation definitions for ROM call get_reloc
- *
- *---------------------------------------------------------------------
- */
-
-/* VMI Relocation types */
-#define VMI_RELOCATION_NONE     0
-#define VMI_RELOCATION_CALL_REL 1
-#define VMI_RELOCATION_JUMP_REL 2
-#define VMI_RELOCATION_NOP     3
-
-#ifndef __ASSEMBLY__
-struct vmi_relocation_info {
-       unsigned char           *eip;
-       unsigned char           type;
-       unsigned char           reserved[3];
-};
-#endif
-
-
-/*
- *---------------------------------------------------------------------
- *
- *  Generic ROM structures and definitions
- *
- *---------------------------------------------------------------------
- */
-
-#ifndef __ASSEMBLY__
-
-struct vrom_header {
-       u16     rom_signature;  /* option ROM signature */
-       u8      rom_length;     /* ROM length in 512 byte chunks */
-       u8      rom_entry[4];   /* 16-bit code entry point */
-       u8      rom_pad0;       /* 4-byte align pad */
-       u32     vrom_signature; /* VROM identification signature */
-       u8      api_version_min;/* Minor version of API */
-       u8      api_version_maj;/* Major version of API */
-       u8      jump_slots;     /* Number of jump slots */
-       u8      reserved1;      /* Reserved for expansion */
-       u32     virtual_top;    /* Hypervisor virtual address start */
-       u16     reserved2;      /* Reserved for expansion */
-       u16     license_offs;   /* Offset to License string */
-       u16     pci_header_offs;/* Offset to PCI OPROM header */
-       u16     pnp_header_offs;/* Offset to PnP OPROM header */
-       u32     rom_pad3;       /* PnP reserverd / VMI reserved */
-       u8      reserved[96];   /* Reserved for headers */
-       char    vmi_init[8];    /* VMI_Init jump point */
-       char    get_reloc[8];   /* VMI_GetRelocationInfo jump point */
-} __attribute__((packed));
-
-struct pnp_header {
-       char sig[4];
-       char rev;
-       char size;
-       short next;
-       short res;
-       long devID;
-       unsigned short manufacturer_offset;
-       unsigned short product_offset;
-} __attribute__((packed));
-
-struct pci_header {
-       char sig[4];
-       short vendorID;
-       short deviceID;
-       short vpdData;
-       short size;
-       char rev;
-       char class;
-       char subclass;
-       char interface;
-       short chunks;
-       char rom_version_min;
-       char rom_version_maj;
-       char codetype;
-       char lastRom;
-       short reserved;
-} __attribute__((packed));
-
-/* Function prototypes for bootstrapping */
-#ifdef CONFIG_VMI
-extern void vmi_init(void);
-extern void vmi_activate(void);
-extern void vmi_bringup(void);
-#else
-static inline void vmi_init(void) {}
-static inline void vmi_activate(void) {}
-static inline void vmi_bringup(void) {}
-#endif
-
-/* State needed to start an application processor in an SMP system. */
-struct vmi_ap_state {
-       u32 cr0;
-       u32 cr2;
-       u32 cr3;
-       u32 cr4;
-
-       u64 efer;
-
-       u32 eip;
-       u32 eflags;
-       u32 eax;
-       u32 ebx;
-       u32 ecx;
-       u32 edx;
-       u32 esp;
-       u32 ebp;
-       u32 esi;
-       u32 edi;
-       u16 cs;
-       u16 ss;
-       u16 ds;
-       u16 es;
-       u16 fs;
-       u16 gs;
-       u16 ldtr;
-
-       u16 gdtr_limit;
-       u32 gdtr_base;
-       u32 idtr_base;
-       u16 idtr_limit;
-};
-
-#endif
diff --git a/arch/x86/include/asm/vmi_time.h b/arch/x86/include/asm/vmi_time.h
deleted file mode 100644 (file)
index c6e0bee..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * VMI Time wrappers
- *
- * Copyright (C) 2006, VMware, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to dhecht@vmware.com
- *
- */
-
-#ifndef _ASM_X86_VMI_TIME_H
-#define _ASM_X86_VMI_TIME_H
-
-/*
- * Raw VMI call indices for timer functions
- */
-#define VMI_CALL_GetCycleFrequency     66
-#define VMI_CALL_GetCycleCounter       67
-#define VMI_CALL_SetAlarm              68
-#define VMI_CALL_CancelAlarm           69
-#define VMI_CALL_GetWallclockTime      70
-#define VMI_CALL_WallclockUpdated      71
-
-/* Cached VMI timer operations */
-extern struct vmi_timer_ops {
-       u64 (*get_cycle_frequency)(void);
-       u64 (*get_cycle_counter)(int);
-       u64 (*get_wallclock)(void);
-       int (*wallclock_updated)(void);
-       void (*set_alarm)(u32 flags, u64 expiry, u64 period);
-       void (*cancel_alarm)(u32 flags);
-} vmi_timer_ops;
-
-/* Prototypes */
-extern void __init vmi_time_init(void);
-extern unsigned long vmi_get_wallclock(void);
-extern int vmi_set_wallclock(unsigned long now);
-extern unsigned long long vmi_sched_clock(void);
-extern unsigned long vmi_tsc_khz(void);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-extern void __devinit vmi_time_bsp_init(void);
-extern void __devinit vmi_time_ap_init(void);
-#endif
-
-/*
- * When run under a hypervisor, a vcpu is always in one of three states:
- * running, halted, or ready.  The vcpu is in the 'running' state if it
- * is executing.  When the vcpu executes the halt interface, the vcpu
- * enters the 'halted' state and remains halted until there is some work
- * pending for the vcpu (e.g. an alarm expires, host I/O completes on
- * behalf of virtual I/O).  At this point, the vcpu enters the 'ready'
- * state (waiting for the hypervisor to reschedule it).  Finally, at any
- * time when the vcpu is not in the 'running' state nor the 'halted'
- * state, it is in the 'ready' state.
- *
- * Real time is advances while the vcpu is 'running', 'ready', or
- * 'halted'.  Stolen time is the time in which the vcpu is in the
- * 'ready' state.  Available time is the remaining time -- the vcpu is
- * either 'running' or 'halted'.
- *
- * All three views of time are accessible through the VMI cycle
- * counters.
- */
-
-/* The cycle counters. */
-#define VMI_CYCLES_REAL         0
-#define VMI_CYCLES_AVAILABLE    1
-#define VMI_CYCLES_STOLEN       2
-
-/* The alarm interface 'flags' bits */
-#define VMI_ALARM_COUNTERS      2
-
-#define VMI_ALARM_COUNTER_MASK  0x000000ff
-
-#define VMI_ALARM_WIRED_IRQ0    0x00000000
-#define VMI_ALARM_WIRED_LVTT    0x00010000
-
-#define VMI_ALARM_IS_ONESHOT    0x00000000
-#define VMI_ALARM_IS_PERIODIC   0x00000100
-
-#define CONFIG_VMI_ALARM_HZ    100
-
-#endif /* _ASM_X86_VMI_TIME_H */
index 0925676266bdbc9cbcf03811916b9f8b9b9e627e..2c833d8c41418c0583ee2da48231918dd1a6c176 100644 (file)
@@ -11,6 +11,8 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_tsc.o = -pg
 CFLAGS_REMOVE_rtc.o = -pg
 CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
+CFLAGS_REMOVE_pvclock.o = -pg
+CFLAGS_REMOVE_kvmclock.o = -pg
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
@@ -32,7 +34,8 @@ GCOV_PROFILE_paravirt.o               := n
 obj-y                  := process_$(BITS).o signal.o entry_$(BITS).o
 obj-y                  += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y                  += time.o ioport.o ldt.o dumpstack.o
-obj-y                  += setup.o x86_init.o i8259.o irqinit.o
+obj-y                  += setup.o x86_init.o i8259.o irqinit.o jump_label.o
+obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-$(CONFIG_X86_VISWS)        += visws_quirks.o
 obj-$(CONFIG_X86_32)   += probe_roms_32.o
 obj-$(CONFIG_X86_32)   += sys_i386_32.o i386_ksyms_32.o
@@ -42,6 +45,7 @@ obj-y                 += bootflag.o e820.o
 obj-y                  += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y                  += tsc.o io_delay.o rtc.o
+obj-y                  += pci-iommu_table.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
@@ -83,15 +87,15 @@ obj-$(CONFIG_DOUBLEFAULT)   += doublefault_32.o
 obj-$(CONFIG_KGDB)             += kgdb.o
 obj-$(CONFIG_VM86)             += vm86_32.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_MRST)        += early_printk_mrst.o
 
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
 obj-$(CONFIG_APB_TIMER)                += apb_timer.o
 
-obj-$(CONFIG_K8_NB)            += k8.o
+obj-$(CONFIG_AMD_NB)           += amd_nb.o
 obj-$(CONFIG_DEBUG_RODATA_TEST)        += test_rodata.o
 obj-$(CONFIG_DEBUG_NX_TEST)    += test_nx.o
 
-obj-$(CONFIG_VMI)              += vmi_32.o vmiclock_32.o
 obj-$(CONFIG_KVM_GUEST)                += kvm.o
 obj-$(CONFIG_KVM_CLOCK)                += kvmclock.o
 obj-$(CONFIG_PARAVIRT)         += paravirt.o paravirt_patch_$(BITS).o
@@ -104,6 +108,7 @@ obj-$(CONFIG_SCx200)                += scx200.o
 scx200-y                       += scx200_32.o
 
 obj-$(CONFIG_OLPC)             += olpc.o
+obj-$(CONFIG_OLPC_XO1)         += olpc-xo1.o
 obj-$(CONFIG_OLPC_OPENFIRMWARE)        += olpc_ofw.o
 obj-$(CONFIG_X86_MRST)         += mrst.o
 
@@ -120,7 +125,6 @@ obj-$(CONFIG_SWIOTLB)                       += pci-swiotlb.o
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
        obj-$(CONFIG_X86_UV)            += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
-       obj-$(CONFIG_X86_PM_TIMER)      += pmtimer_64.o
        obj-$(CONFIG_AUDIT)             += audit_64.o
 
        obj-$(CONFIG_GART_IOMMU)        += pci-gart_64.o aperture_64.o
index fb7a5f052e2b8766d11115e3f7fc174fadf6ac2f..5812404a0d4ce5e3eb815675f591f18b95762329 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <acpi/processor.h>
 #include <asm/acpi.h>
+#include <asm/mwait.h>
 
 /*
  * Initialize bm_flags based on the CPU cache properties
@@ -61,20 +62,10 @@ struct cstate_entry {
                unsigned int ecx;
        } states[ACPI_PROCESSOR_MAX_POWER];
 };
-static struct cstate_entry *cpu_cstate_entry;  /* per CPU ptr */
+static struct cstate_entry __percpu *cpu_cstate_entry; /* per CPU ptr */
 
 static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
 
-#define MWAIT_SUBSTATE_MASK    (0xf)
-#define MWAIT_CSTATE_MASK      (0xf)
-#define MWAIT_SUBSTATE_SIZE    (4)
-
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK     (0x2)
-
-#define MWAIT_ECX_INTERRUPT_BREAK      (0x1)
-
 #define NATIVE_CSTATE_BEYOND_HALT      (2)
 
 static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
index 33cec152070df4f9c5dc30d47a6274524d097225..e1252074ea4077306d5673c41eed846daabec90c 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/dmi.h>
 #include <linux/cpumask.h>
 #include <asm/segment.h>
@@ -125,7 +126,7 @@ void acpi_restore_state_mem(void)
  */
 void __init acpi_reserve_wakeup_memory(void)
 {
-       unsigned long mem;
+       phys_addr_t mem;
 
        if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
                printk(KERN_ERR
@@ -133,15 +134,15 @@ void __init acpi_reserve_wakeup_memory(void)
                return;
        }
 
-       mem = find_e820_area(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
+       mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
 
-       if (mem == -1L) {
+       if (mem == MEMBLOCK_ERROR) {
                printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
                return;
        }
        acpi_realmode = (unsigned long) phys_to_virt(mem);
        acpi_wakeup_address = mem;
-       reserve_early(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
+       memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
 }
 
 
index f65ab8b014c4f42421d77200243c39c7fd252165..a36bb90aef5383d68bcf4af0b0c33749d572163a 100644 (file)
@@ -195,7 +195,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern s32 __smp_locks[], __smp_locks_end[];
-static void *text_poke_early(void *addr, const void *opcode, size_t len);
+void *text_poke_early(void *addr, const void *opcode, size_t len);
 
 /* Replace instructions with better alternatives for this CPU type.
    This runs before SMP is initialized to avoid SMP problems with
@@ -522,7 +522,7 @@ void __init alternative_instructions(void)
  * instructions. And on the local CPU you need to be protected again NMI or MCE
  * handlers seeing an inconsistent instruction while you patch.
  */
-static void *__init_or_module text_poke_early(void *addr, const void *opcode,
+void *__init_or_module text_poke_early(void *addr, const void *opcode,
                                              size_t len)
 {
        unsigned long flags;
@@ -637,7 +637,72 @@ void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
        tpp.len = len;
        atomic_set(&stop_machine_first, 1);
        wrote_text = 0;
-       stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+       /* Use __stop_machine() because the caller already got online_cpus. */
+       __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
        return addr;
 }
 
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+
+unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+
+void __init arch_init_ideal_nop5(void)
+{
+       extern const unsigned char ftrace_test_p6nop[];
+       extern const unsigned char ftrace_test_nop5[];
+       extern const unsigned char ftrace_test_jmp[];
+       int faulted = 0;
+
+       /*
+        * There is no good nop for all x86 archs.
+        * We will default to using the P6_NOP5, but first we
+        * will test to make sure that the nop will actually
+        * work on this CPU. If it faults, we will then
+        * go to a lesser efficient 5 byte nop. If that fails
+        * we then just use a jmp as our nop. This isn't the most
+        * efficient nop, but we can not use a multi part nop
+        * since we would then risk being preempted in the middle
+        * of that nop, and if we enabled tracing then, it might
+        * cause a system crash.
+        *
+        * TODO: check the cpuid to determine the best nop.
+        */
+       asm volatile (
+               "ftrace_test_jmp:"
+               "jmp ftrace_test_p6nop\n"
+               "nop\n"
+               "nop\n"
+               "nop\n"  /* 2 byte jmp + 3 bytes */
+               "ftrace_test_p6nop:"
+               P6_NOP5
+               "jmp 1f\n"
+               "ftrace_test_nop5:"
+               ".byte 0x66,0x66,0x66,0x66,0x90\n"
+               "1:"
+               ".section .fixup, \"ax\"\n"
+               "2:     movl $1, %0\n"
+               "       jmp ftrace_test_nop5\n"
+               "3:     movl $2, %0\n"
+               "       jmp 1b\n"
+               ".previous\n"
+               _ASM_EXTABLE(ftrace_test_p6nop, 2b)
+               _ASM_EXTABLE(ftrace_test_nop5, 3b)
+               : "=r"(faulted) : "0" (faulted));
+
+       switch (faulted) {
+       case 0:
+               pr_info("converting mcount calls to 0f 1f 44 00 00\n");
+               memcpy(ideal_nop5, ftrace_test_p6nop, IDEAL_NOP_SIZE_5);
+               break;
+       case 1:
+               pr_info("converting mcount calls to 66 66 66 66 90\n");
+               memcpy(ideal_nop5, ftrace_test_nop5, IDEAL_NOP_SIZE_5);
+               break;
+       case 2:
+               pr_info("converting mcount calls to jmp . + 5\n");
+               memcpy(ideal_nop5, ftrace_test_jmp, IDEAL_NOP_SIZE_5);
+               break;
+       }
+
+}
+#endif
index fa044e1e30a2ed081175480dccec352a7e381392..d2fdb0826df25654fa94cc7ee307c23e235c5c91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
                           size_t size,
                           int dir)
 {
+       dma_addr_t flush_addr;
        dma_addr_t i, start;
        unsigned int pages;
 
@@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
            (dma_addr + size > dma_dom->aperture_size))
                return;
 
+       flush_addr = dma_addr;
        pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
        dma_addr &= PAGE_MASK;
        start = dma_addr;
@@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-               iommu_flush_pages(&dma_dom->domain, dma_addr, size);
+               iommu_flush_pages(&dma_dom->domain, flush_addr, size);
                dma_dom->need_flush = false;
        }
 }
index 3cc63e2b8dd4c4acc4ee7f77c3ad432d97beb169..6e11c8134158e62837deab38e350037e462730f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -31,7 +31,7 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/x86_init.h>
-
+#include <asm/iommu_table.h>
 /*
  * definitions for the ACPI scanning code
  */
@@ -194,6 +194,39 @@ static inline unsigned long tbl_size(int entry_size)
        return 1UL << shift;
 }
 
+/* Access to l1 and l2 indexed register spaces */
+
+static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
+{
+       u32 val;
+
+       pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+       pci_read_config_dword(iommu->dev, 0xfc, &val);
+       return val;
+}
+
+static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
+{
+       pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
+       pci_write_config_dword(iommu->dev, 0xfc, val);
+       pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+}
+
+static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
+{
+       u32 val;
+
+       pci_write_config_dword(iommu->dev, 0xf0, address);
+       pci_read_config_dword(iommu->dev, 0xf4, &val);
+       return val;
+}
+
+static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
+{
+       pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
+       pci_write_config_dword(iommu->dev, 0xf4, val);
+}
+
 /****************************************************************************
  *
  * AMD IOMMU MMIO register space handling functions
@@ -619,6 +652,7 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
 {
        int cap_ptr = iommu->cap_ptr;
        u32 range, misc;
+       int i, j;
 
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
                              &iommu->cap);
@@ -632,6 +666,30 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
        iommu->last_device = calc_devid(MMIO_GET_BUS(range),
                                        MMIO_GET_LD(range));
        iommu->evt_msi_num = MMIO_MSI_NUM(misc);
+
+       if (!is_rd890_iommu(iommu->dev))
+               return;
+
+       /*
+        * Some rd890 systems may not be fully reconfigured by the BIOS, so
+        * it's necessary for us to store this information so it can be
+        * reprogrammed on resume
+        */
+
+       pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
+                             &iommu->stored_addr_lo);
+       pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
+                             &iommu->stored_addr_hi);
+
+       /* Low bit locks writes to configuration space */
+       iommu->stored_addr_lo &= ~1;
+
+       for (i = 0; i < 6; i++)
+               for (j = 0; j < 0x12; j++)
+                       iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
+
+       for (i = 0; i < 0x83; i++)
+               iommu->stored_l2[i] = iommu_read_l2(iommu, i);
 }
 
 /*
@@ -649,29 +707,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
        struct ivhd_entry *e;
 
        /*
-        * First set the recommended feature enable bits from ACPI
-        * into the IOMMU control registers
-        */
-       h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
-               iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
-               iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
-
-       h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
-               iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
-               iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
-
-       h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
-               iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
-               iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
-
-       h->flags & IVHD_FLAG_ISOC_EN_MASK ?
-               iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
-               iommu_feature_disable(iommu, CONTROL_ISOC_EN);
-
-       /*
-        * make IOMMU memory accesses cache coherent
+        * First save the recommended feature enable bits from ACPI
         */
-       iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+       iommu->acpi_flags = h->flags;
 
        /*
         * Done. Now parse the device entries
@@ -1116,6 +1154,79 @@ static void init_device_table(void)
        }
 }
 
+static void iommu_init_flags(struct amd_iommu *iommu)
+{
+       iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
+               iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
+               iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
+
+       iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
+               iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
+               iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
+
+       iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
+               iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
+               iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
+
+       iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
+               iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
+               iommu_feature_disable(iommu, CONTROL_ISOC_EN);
+
+       /*
+        * make IOMMU memory accesses cache coherent
+        */
+       iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+}
+
+static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
+{
+       int i, j;
+       u32 ioc_feature_control;
+       struct pci_dev *pdev = NULL;
+
+       /* RD890 BIOSes may not have completely reconfigured the iommu */
+       if (!is_rd890_iommu(iommu->dev))
+               return;
+
+       /*
+        * First, we need to ensure that the iommu is enabled. This is
+        * controlled by a register in the northbridge
+        */
+       pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
+
+       if (!pdev)
+               return;
+
+       /* Select Northbridge indirect register 0x75 and enable writing */
+       pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
+       pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
+
+       /* Enable the iommu */
+       if (!(ioc_feature_control & 0x1))
+               pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
+
+       pci_dev_put(pdev);
+
+       /* Restore the iommu BAR */
+       pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+                              iommu->stored_addr_lo);
+       pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
+                              iommu->stored_addr_hi);
+
+       /* Restore the l1 indirect regs for each of the 6 l1s */
+       for (i = 0; i < 6; i++)
+               for (j = 0; j < 0x12; j++)
+                       iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
+
+       /* Restore the l2 indirect regs */
+       for (i = 0; i < 0x83; i++)
+               iommu_write_l2(iommu, i, iommu->stored_l2[i]);
+
+       /* Lock PCI setup registers */
+       pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+                              iommu->stored_addr_lo | 1);
+}
+
 /*
  * This function finally enables all IOMMUs found in the system after
  * they have been initialized
@@ -1126,6 +1237,7 @@ static void enable_iommus(void)
 
        for_each_iommu(iommu) {
                iommu_disable(iommu);
+               iommu_init_flags(iommu);
                iommu_set_device_table(iommu);
                iommu_enable_command_buffer(iommu);
                iommu_enable_event_buffer(iommu);
@@ -1150,6 +1262,11 @@ static void disable_iommus(void)
 
 static int amd_iommu_resume(struct sys_device *dev)
 {
+       struct amd_iommu *iommu;
+
+       for_each_iommu(iommu)
+               iommu_apply_resume_quirks(iommu);
+
        /* re-load the hardware */
        enable_iommus();
 
@@ -1382,13 +1499,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)
        return 0;
 }
 
-void __init amd_iommu_detect(void)
+int __init amd_iommu_detect(void)
 {
        if (no_iommu || (iommu_detected && !gart_iommu_aperture))
-               return;
+               return -ENODEV;
 
        if (amd_iommu_disabled)
-               return;
+               return -ENODEV;
 
        if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
                iommu_detected = 1;
@@ -1397,7 +1514,9 @@ void __init amd_iommu_detect(void)
 
                /* Make sure ACS will be enabled */
                pci_request_acs();
+               return 1;
        }
+       return -ENODEV;
 }
 
 /****************************************************************************
@@ -1428,3 +1547,8 @@ static int __init parse_amd_iommu_options(char *str)
 
 __setup("amd_iommu_dump", parse_amd_iommu_dump);
 __setup("amd_iommu=", parse_amd_iommu_options);
+
+IOMMU_INIT_FINISH(amd_iommu_detect,
+                 gart_iommu_hole_init,
+                 0,
+                 0);
similarity index 66%
rename from arch/x86/kernel/k8.c
rename to arch/x86/kernel/amd_nb.c
index 0f7bc20cfcdedd58f66b6b036bfb7d824e599e37..8f6463d8ed0de1ebfece6cb1138a15697f657197 100644 (file)
@@ -8,21 +8,19 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/k8.h>
-
-int num_k8_northbridges;
-EXPORT_SYMBOL(num_k8_northbridges);
+#include <asm/amd_nb.h>
 
 static u32 *flush_words;
 
 struct pci_device_id k8_nb_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) },
        {}
 };
 EXPORT_SYMBOL(k8_nb_ids);
 
-struct pci_dev **k8_northbridges;
+struct k8_northbridge_info k8_northbridges;
 EXPORT_SYMBOL(k8_northbridges);
 
 static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
@@ -40,36 +38,45 @@ int cache_k8_northbridges(void)
        int i;
        struct pci_dev *dev;
 
-       if (num_k8_northbridges)
+       if (k8_northbridges.num)
                return 0;
 
        dev = NULL;
        while ((dev = next_k8_northbridge(dev)) != NULL)
-               num_k8_northbridges++;
+               k8_northbridges.num++;
+
+       /* some CPU families (e.g. family 0x11) do not support GART */
+       if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
+           boot_cpu_data.x86 == 0x15)
+               k8_northbridges.gart_supported = 1;
 
-       k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
-                                 GFP_KERNEL);
-       if (!k8_northbridges)
+       k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) *
+                                         sizeof(void *), GFP_KERNEL);
+       if (!k8_northbridges.nb_misc)
                return -ENOMEM;
 
-       if (!num_k8_northbridges) {
-               k8_northbridges[0] = NULL;
+       if (!k8_northbridges.num) {
+               k8_northbridges.nb_misc[0] = NULL;
                return 0;
        }
 
-       flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
-       if (!flush_words) {
-               kfree(k8_northbridges);
-               return -ENOMEM;
+       if (k8_northbridges.gart_supported) {
+               flush_words = kmalloc(k8_northbridges.num * sizeof(u32),
+                                     GFP_KERNEL);
+               if (!flush_words) {
+                       kfree(k8_northbridges.nb_misc);
+                       return -ENOMEM;
+               }
        }
 
        dev = NULL;
        i = 0;
        while ((dev = next_k8_northbridge(dev)) != NULL) {
-               k8_northbridges[i] = dev;
-               pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
+               k8_northbridges.nb_misc[i] = dev;
+               if (k8_northbridges.gart_supported)
+                       pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
        }
-       k8_northbridges[i] = NULL;
+       k8_northbridges.nb_misc[i] = NULL;
        return 0;
 }
 EXPORT_SYMBOL_GPL(cache_k8_northbridges);
@@ -93,22 +100,25 @@ void k8_flush_garts(void)
        unsigned long flags;
        static DEFINE_SPINLOCK(gart_lock);
 
+       if (!k8_northbridges.gart_supported)
+               return;
+
        /* Avoid races between AGP and IOMMU. In theory it's not needed
           but I'm not sure if the hardware won't lose flush requests
           when another is pending. This whole thing is so expensive anyways
           that it doesn't matter to serialize more. -AK */
        spin_lock_irqsave(&gart_lock, flags);
        flushed = 0;
-       for (i = 0; i < num_k8_northbridges; i++) {
-               pci_write_config_dword(k8_northbridges[i], 0x9c,
+       for (i = 0; i < k8_northbridges.num; i++) {
+               pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c,
                                       flush_words[i]|1);
                flushed++;
        }
-       for (i = 0; i < num_k8_northbridges; i++) {
+       for (i = 0; i < k8_northbridges.num; i++) {
                u32 w;
                /* Make sure the hardware actually executed the flush*/
                for (;;) {
-                       pci_read_config_dword(k8_northbridges[i],
+                       pci_read_config_dword(k8_northbridges.nb_misc[i],
                                              0x9c, &w);
                        if (!(w & 1))
                                break;
index 8dd77800ff5d7b444742ae02cc5168ccf8855fcd..92543c73cf8ed8d085dc581fe8171b3bbb6f939e 100644 (file)
@@ -231,34 +231,6 @@ static void apbt_restart_clocksource(struct clocksource *cs)
        apbt_start_counter(phy_cs_timer_id);
 }
 
-/* Setup IRQ routing via IOAPIC */
-#ifdef CONFIG_SMP
-static void apbt_setup_irq(struct apbt_dev *adev)
-{
-       struct irq_chip *chip;
-       struct irq_desc *desc;
-
-       /* timer0 irq has been setup early */
-       if (adev->irq == 0)
-               return;
-       desc = irq_to_desc(adev->irq);
-       chip = get_irq_chip(adev->irq);
-       disable_irq(adev->irq);
-       desc->status |= IRQ_MOVE_PCNTXT;
-       irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-       /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
-       set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
-       enable_irq(adev->irq);
-       if (system_state == SYSTEM_BOOTING)
-               if (request_irq(adev->irq, apbt_interrupt_handler,
-                               IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
-                               adev->name, adev)) {
-                       printk(KERN_ERR "Failed request IRQ for APBT%d\n",
-                              adev->num);
-               }
-}
-#endif
-
 static void apbt_enable_int(int n)
 {
        unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
@@ -334,6 +306,27 @@ static int __init apbt_clockevent_register(void)
 }
 
 #ifdef CONFIG_SMP
+
+static void apbt_setup_irq(struct apbt_dev *adev)
+{
+       /* timer0 irq has been setup early */
+       if (adev->irq == 0)
+               return;
+
+       if (system_state == SYSTEM_BOOTING) {
+               irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
+               /* APB timer irqs are set up as mp_irqs, timer is edge type */
+               __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
+               if (request_irq(adev->irq, apbt_interrupt_handler,
+                               IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+                               adev->name, adev)) {
+                       printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+                              adev->num);
+               }
+       } else
+               enable_irq(adev->irq);
+}
+
 /* Should be called with per cpu */
 void apbt_setup_secondary_clock(void)
 {
@@ -343,7 +336,7 @@ void apbt_setup_secondary_clock(void)
 
        /* Don't register boot CPU clockevent */
        cpu = smp_processor_id();
-       if (cpu == boot_cpu_id)
+       if (!cpu)
                return;
        /*
         * We need to calculate the scaled math multiplication factor for
@@ -389,16 +382,17 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
 
        switch (action & 0xf) {
        case CPU_DEAD:
+               disable_irq(adev->irq);
                apbt_disable_int(cpu);
-               if (system_state == SYSTEM_RUNNING)
+               if (system_state == SYSTEM_RUNNING) {
                        pr_debug("skipping APBT CPU %lu offline\n", cpu);
-               else if (adev) {
+               else if (adev) {
                        pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
                        free_irq(adev->irq, adev);
                }
                break;
        default:
-               pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+               pr_debug("APBT notified %lu, no action\n", action);
        }
        return NOTIFY_OK;
 }
@@ -552,7 +546,7 @@ bad_count:
                pr_debug("APB CS going back %lx:%lx:%lx ",
                         t2, last_read, t2 - last_read);
 bad_count_x3:
-               pr_debug(KERN_INFO "tripple check enforced\n");
+               pr_debug("triple check enforced\n");
                t0 = apbt_readl(phy_cs_timer_id,
                                APBTMR_N_CURRENT_VALUE);
                udelay(1);
index a2e0caf26e172c8f7b18231e4f4a072161ed66fe..b3a16e8f0703d47f50a354223bfe8c6e9382126e 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/gart.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/x86_init.h>
 
 int gart_iommu_aperture;
@@ -307,7 +307,7 @@ void __init early_gart_iommu_check(void)
                                continue;
 
                        ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
-                       aper_enabled = ctl & AMD64_GARTEN;
+                       aper_enabled = ctl & GARTEN;
                        aper_order = (ctl >> 1) & 7;
                        aper_size = (32 * 1024 * 1024) << aper_order;
                        aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;
@@ -362,7 +362,7 @@ void __init early_gart_iommu_check(void)
                                continue;
 
                        ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
-                       ctl &= ~AMD64_GARTEN;
+                       ctl &= ~GARTEN;
                        write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
                }
        }
@@ -371,7 +371,7 @@ void __init early_gart_iommu_check(void)
 
 static int __initdata printed_gart_size_msg;
 
-void __init gart_iommu_hole_init(void)
+int __init gart_iommu_hole_init(void)
 {
        u32 agp_aper_base = 0, agp_aper_order = 0;
        u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
@@ -381,7 +381,7 @@ void __init gart_iommu_hole_init(void)
 
        if (gart_iommu_aperture_disabled || !fix_aperture ||
            !early_pci_allowed())
-               return;
+               return -ENODEV;
 
        printk(KERN_INFO  "Checking aperture...\n");
 
@@ -463,8 +463,9 @@ out:
                        unsigned long n = (32 * 1024 * 1024) << last_aper_order;
 
                        insert_aperture_resource((u32)last_aper_base, n);
+                       return 1;
                }
-               return;
+               return 0;
        }
 
        if (!fallback_aper_force) {
@@ -500,13 +501,18 @@ out:
                        panic("Not enough memory for aperture");
                }
        } else {
-               return;
+               return 0;
        }
 
        /* Fix up the north bridges */
        for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
-               int bus;
-               int dev_base, dev_limit;
+               int bus, dev_base, dev_limit;
+
+               /*
+                * Don't enable translation yet but enable GART IO and CPU
+                * accesses and set DISTLBWALKPRB since GART table memory is UC.
+                */
+               u32 ctl = DISTLBWALKPRB | aper_order << 1;
 
                bus = bus_dev_ranges[i].bus;
                dev_base = bus_dev_ranges[i].dev_base;
@@ -515,13 +521,12 @@ out:
                        if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
                                continue;
 
-                       /* Don't enable translation yet. That is done later.
-                          Assume this BIOS didn't initialise the GART so
-                          just overwrite all previous bits */
-                       write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, aper_order << 1);
+                       write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
                        write_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE, aper_alloc >> 25);
                }
        }
 
        set_up_gart_resume(aper_order, aper_alloc);
+
+       return 1;
 }
index e3b534cda49a8097dde55400083d7eeb8f9c694c..850657d1b0ed573e23552913d7aae230df30fe9a 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
 #include <asm/tsc.h>
+#include <asm/atomic.h>
 
 unsigned int num_processors;
 
@@ -370,38 +371,87 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 }
 
 /*
- * Setup extended LVT, AMD specific (K8, family 10h)
+ * Setup extended LVT, AMD specific
  *
- * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
- * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ * Software should use the LVT offsets the BIOS provides.  The offsets
+ * are determined by the subsystems using it like those for MCE
+ * threshold or IBS.  On K8 only offset 0 (APIC500) and MCE interrupts
+ * are supported. Beginning with family 10h at least 4 offsets are
+ * available.
  *
- * If mask=1, the LVT entry does not generate interrupts while mask=0
- * enables the vector. See also the BKDGs.
+ * Since the offsets must be consistent for all cores, we keep track
+ * of the LVT offsets in software and reserve the offset for the same
+ * vector also to be used on other cores. An offset is freed by
+ * setting the entry to APIC_EILVT_MASKED.
+ *
+ * If the BIOS is right, there should be no conflicts. Otherwise a
+ * "[Firmware Bug]: ..." error message is generated. However, if
+ * software does not properly determines the offsets, it is not
+ * necessarily a BIOS bug.
  */
 
-#define APIC_EILVT_LVTOFF_MCE 0
-#define APIC_EILVT_LVTOFF_IBS 1
+static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX];
 
-static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
+static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
 {
-       unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
-       unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
-
-       apic_write(reg, v);
+       return (old & APIC_EILVT_MASKED)
+               || (new == APIC_EILVT_MASKED)
+               || ((new & ~APIC_EILVT_MASKED) == old);
 }
 
-u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
+static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
 {
-       setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
-       return APIC_EILVT_LVTOFF_MCE;
+       unsigned int rsvd;                      /* 0: uninitialized */
+
+       if (offset >= APIC_EILVT_NR_MAX)
+               return ~0;
+
+       rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED;
+       do {
+               if (rsvd &&
+                   !eilvt_entry_is_changeable(rsvd, new))
+                       /* may not change if vectors are different */
+                       return rsvd;
+               rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
+       } while (rsvd != new);
+
+       return new;
 }
 
-u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
+/*
+ * If mask=1, the LVT entry does not generate interrupts while mask=0
+ * enables the vector. See also the BKDGs.
+ */
+
+int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
 {
-       setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
-       return APIC_EILVT_LVTOFF_IBS;
+       unsigned long reg = APIC_EILVTn(offset);
+       unsigned int new, old, reserved;
+
+       new = (mask << 16) | (msg_type << 8) | vector;
+       old = apic_read(reg);
+       reserved = reserve_eilvt_offset(offset, new);
+
+       if (reserved != new) {
+               pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
+                      "vector 0x%x was already reserved by another core, "
+                      "APIC%lX=0x%x\n",
+                      smp_processor_id(), new, reserved, reg, old);
+               return -EINVAL;
+       }
+
+       if (!eilvt_entry_is_changeable(old, new)) {
+               pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
+                      "register already in use, APIC%lX=0x%x\n",
+                      smp_processor_id(), new, reg, old);
+               return -EBUSY;
+       }
+
+       apic_write(reg, new);
+
+       return 0;
 }
-EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt);
 
 /*
  * Program the next event, relative to now
@@ -1665,10 +1715,7 @@ int __init APIC_init_uniprocessor(void)
        }
 #endif
 
-#ifndef CONFIG_SMP
-       enable_IR_x2apic();
        default_setup_apic_routing();
-#endif
 
        verify_local_APIC();
        connect_bsp_APIC();
index f1efebaf55105fa835ac7938c1654295fdd81562..8ae808d110f445f352ca686faf3a29d9d93bfa50 100644 (file)
@@ -131,13 +131,9 @@ struct irq_pin_list {
        struct irq_pin_list *next;
 };
 
-static struct irq_pin_list *get_one_free_irq_2_pin(int node)
+static struct irq_pin_list *alloc_irq_pin_list(int node)
 {
-       struct irq_pin_list *pin;
-
-       pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
-
-       return pin;
+       return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -150,10 +146,7 @@ static struct irq_cfg irq_cfgx[NR_IRQS];
 int __init arch_early_irq_init(void)
 {
        struct irq_cfg *cfg;
-       struct irq_desc *desc;
-       int count;
-       int node;
-       int i;
+       int count, node, i;
 
        if (!legacy_pic->nr_legacy_irqs) {
                nr_irqs_gsi = 0;
@@ -162,13 +155,15 @@ int __init arch_early_irq_init(void)
 
        cfg = irq_cfgx;
        count = ARRAY_SIZE(irq_cfgx);
-       node= cpu_to_node(boot_cpu_id);
+       node = cpu_to_node(0);
+
+       /* Make sure the legacy interrupts are marked in the bitmap */
+       irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
 
        for (i = 0; i < count; i++) {
-               desc = irq_to_desc(i);
-               desc->chip_data = &cfg[i];
-               zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
-               zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+               set_irq_chip_data(i, &cfg[i]);
+               zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
+               zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
                /*
                 * For legacy IRQ's, start with assigning irq0 to irq15 to
                 * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
@@ -183,165 +178,88 @@ int __init arch_early_irq_init(void)
 }
 
 #ifdef CONFIG_SPARSE_IRQ
-struct irq_cfg *irq_cfg(unsigned int irq)
+static struct irq_cfg *irq_cfg(unsigned int irq)
 {
-       struct irq_cfg *cfg = NULL;
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       if (desc)
-               cfg = desc->chip_data;
-
-       return cfg;
+       return get_irq_chip_data(irq);
 }
 
-static struct irq_cfg *get_one_free_irq_cfg(int node)
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
 {
        struct irq_cfg *cfg;
 
-       cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
-       if (cfg) {
-               if (!zalloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
-                       kfree(cfg);
-                       cfg = NULL;
-               } else if (!zalloc_cpumask_var_node(&cfg->old_domain,
-                                                         GFP_ATOMIC, node)) {
-                       free_cpumask_var(cfg->domain);
-                       kfree(cfg);
-                       cfg = NULL;
-               }
-       }
-
+       cfg = kzalloc_node(sizeof(*cfg), GFP_KERNEL, node);
+       if (!cfg)
+               return NULL;
+       if (!zalloc_cpumask_var_node(&cfg->domain, GFP_KERNEL, node))
+               goto out_cfg;
+       if (!zalloc_cpumask_var_node(&cfg->old_domain, GFP_KERNEL, node))
+               goto out_domain;
        return cfg;
+out_domain:
+       free_cpumask_var(cfg->domain);
+out_cfg:
+       kfree(cfg);
+       return NULL;
 }
 
-int arch_init_chip_data(struct irq_desc *desc, int node)
-{
-       struct irq_cfg *cfg;
-
-       cfg = desc->chip_data;
-       if (!cfg) {
-               desc->chip_data = get_one_free_irq_cfg(node);
-               if (!desc->chip_data) {
-                       printk(KERN_ERR "can not alloc irq_cfg\n");
-                       BUG_ON(1);
-               }
-       }
-
-       return 0;
-}
-
-/* for move_irq_desc */
-static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
+static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
 {
-       struct irq_pin_list *old_entry, *head, *tail, *entry;
-
-       cfg->irq_2_pin = NULL;
-       old_entry = old_cfg->irq_2_pin;
-       if (!old_entry)
-               return;
-
-       entry = get_one_free_irq_2_pin(node);
-       if (!entry)
+       if (!cfg)
                return;
+       set_irq_chip_data(at, NULL);
+       free_cpumask_var(cfg->domain);
+       free_cpumask_var(cfg->old_domain);
+       kfree(cfg);
+}
 
-       entry->apic     = old_entry->apic;
-       entry->pin      = old_entry->pin;
-       head            = entry;
-       tail            = entry;
-       old_entry       = old_entry->next;
-       while (old_entry) {
-               entry = get_one_free_irq_2_pin(node);
-               if (!entry) {
-                       entry = head;
-                       while (entry) {
-                               head = entry->next;
-                               kfree(entry);
-                               entry = head;
-                       }
-                       /* still use the old one */
-                       return;
-               }
-               entry->apic     = old_entry->apic;
-               entry->pin      = old_entry->pin;
-               tail->next      = entry;
-               tail            = entry;
-               old_entry       = old_entry->next;
-       }
+#else
 
-       tail->next = NULL;
-       cfg->irq_2_pin = head;
+struct irq_cfg *irq_cfg(unsigned int irq)
+{
+       return irq < nr_irqs ? irq_cfgx + irq : NULL;
 }
 
-static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
 {
-       struct irq_pin_list *entry, *next;
-
-       if (old_cfg->irq_2_pin == cfg->irq_2_pin)
-               return;
+       return irq_cfgx + irq;
+}
 
-       entry = old_cfg->irq_2_pin;
+static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
 
-       while (entry) {
-               next = entry->next;
-               kfree(entry);
-               entry = next;
-       }
-       old_cfg->irq_2_pin = NULL;
-}
+#endif
 
-void arch_init_copy_chip_data(struct irq_desc *old_desc,
-                                struct irq_desc *desc, int node)
+static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
 {
+       int res = irq_alloc_desc_at(at, node);
        struct irq_cfg *cfg;
-       struct irq_cfg *old_cfg;
-
-       cfg = get_one_free_irq_cfg(node);
-
-       if (!cfg)
-               return;
 
-       desc->chip_data = cfg;
-
-       old_cfg = old_desc->chip_data;
-
-       memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
-
-       init_copy_irq_2_pin(old_cfg, cfg, node);
-}
+       if (res < 0) {
+               if (res != -EEXIST)
+                       return NULL;
+               cfg = get_irq_chip_data(at);
+               if (cfg)
+                       return cfg;
+       }
 
-static void free_irq_cfg(struct irq_cfg *old_cfg)
-{
-       kfree(old_cfg);
+       cfg = alloc_irq_cfg(at, node);
+       if (cfg)
+               set_irq_chip_data(at, cfg);
+       else
+               irq_free_desc(at);
+       return cfg;
 }
 
-void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+static int alloc_irq_from(unsigned int from, int node)
 {
-       struct irq_cfg *old_cfg, *cfg;
-
-       old_cfg = old_desc->chip_data;
-       cfg = desc->chip_data;
-
-       if (old_cfg == cfg)
-               return;
-
-       if (old_cfg) {
-               free_irq_2_pin(old_cfg, cfg);
-               free_irq_cfg(old_cfg);
-               old_desc->chip_data = NULL;
-       }
+       return irq_alloc_desc_from(from, node);
 }
-/* end for move_irq_desc */
 
-#else
-struct irq_cfg *irq_cfg(unsigned int irq)
+static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
 {
-       return irq < nr_irqs ? irq_cfgx + irq : NULL;
+       free_irq_cfg(at, cfg);
+       irq_free_desc(at);
 }
 
-#endif
-
 struct io_apic {
        unsigned int index;
        unsigned int unused[3];
@@ -446,7 +364,7 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
        io_apic_write(apic, 0x10 + 2*pin, eu.w1);
 }
 
-void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
        unsigned long flags;
        raw_spin_lock_irqsave(&ioapic_lock, flags);
@@ -476,7 +394,7 @@ static void ioapic_mask_entry(int apic, int pin)
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
 static int
-add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
+__add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
        struct irq_pin_list **last, *entry;
 
@@ -488,7 +406,7 @@ add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
                last = &entry->next;
        }
 
-       entry = get_one_free_irq_2_pin(node);
+       entry = alloc_irq_pin_list(node);
        if (!entry) {
                printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
                                node, apic, pin);
@@ -503,7 +421,7 @@ add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
 
 static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
-       if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
+       if (__add_pin_to_irq_node(cfg, node, apic, pin))
                panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
 }
 
@@ -566,11 +484,6 @@ static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
                             IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
 }
 
-static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
-{
-       io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
-}
-
 static void io_apic_sync(struct irq_pin_list *entry)
 {
        /*
@@ -582,44 +495,37 @@ static void io_apic_sync(struct irq_pin_list *entry)
        readl(&io_apic->data);
 }
 
-static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+static void mask_ioapic(struct irq_cfg *cfg)
 {
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
+static void mask_ioapic_irq(struct irq_data *data)
 {
-       struct irq_cfg *cfg = desc->chip_data;
-       unsigned long flags;
-
-       BUG_ON(!cfg);
+       mask_ioapic(data->chip_data);
+}
 
-       raw_spin_lock_irqsave(&ioapic_lock, flags);
-       __mask_IO_APIC_irq(cfg);
-       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+static void __unmask_ioapic(struct irq_cfg *cfg)
+{
+       io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
 }
 
-static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
+static void unmask_ioapic(struct irq_cfg *cfg)
 {
-       struct irq_cfg *cfg = desc->chip_data;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
-       __unmask_IO_APIC_irq(cfg);
+       __unmask_ioapic(cfg);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void mask_IO_APIC_irq(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       mask_IO_APIC_irq_desc(desc);
-}
-static void unmask_IO_APIC_irq(unsigned int irq)
+static void unmask_ioapic_irq(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       unmask_IO_APIC_irq_desc(desc);
+       unmask_ioapic(data->chip_data);
 }
 
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
@@ -689,14 +595,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)
        struct IO_APIC_route_entry **ioapic_entries;
 
        ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
-                               GFP_ATOMIC);
+                               GFP_KERNEL);
        if (!ioapic_entries)
                return 0;
 
        for (apic = 0; apic < nr_ioapics; apic++) {
                ioapic_entries[apic] =
                        kzalloc(sizeof(struct IO_APIC_route_entry) *
-                               nr_ioapic_registers[apic], GFP_ATOMIC);
+                               nr_ioapic_registers[apic], GFP_KERNEL);
                if (!ioapic_entries[apic])
                        goto nomem;
        }
@@ -1254,7 +1160,6 @@ void __setup_vector_irq(int cpu)
        /* Initialize vector_irq on a new cpu */
        int irq, vector;
        struct irq_cfg *cfg;
-       struct irq_desc *desc;
 
        /*
         * vector_lock will make sure that we don't run into irq vector
@@ -1263,9 +1168,10 @@ void __setup_vector_irq(int cpu)
         */
        raw_spin_lock(&vector_lock);
        /* Mark the inuse vectors */
-       for_each_irq_desc(irq, desc) {
-               cfg = desc->chip_data;
-
+       for_each_active_irq(irq) {
+               cfg = get_irq_chip_data(irq);
+               if (!cfg)
+                       continue;
                /*
                 * If it is a legacy IRQ handled by the legacy PIC, this cpu
                 * will be part of the irq_cfg's domain.
@@ -1322,17 +1228,17 @@ static inline int IO_APIC_irq_trigger(int irq)
 }
 #endif
 
-static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+static void ioapic_register_intr(unsigned int irq, unsigned long trigger)
 {
 
        if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
            trigger == IOAPIC_LEVEL)
-               desc->status |= IRQ_LEVEL;
+               irq_set_status_flags(irq, IRQ_LEVEL);
        else
-               desc->status &= ~IRQ_LEVEL;
+               irq_clear_status_flags(irq, IRQ_LEVEL);
 
-       if (irq_remapped(irq)) {
-               desc->status |= IRQ_MOVE_PCNTXT;
+       if (irq_remapped(get_irq_chip_data(irq))) {
+               irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
                if (trigger)
                        set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
                                                      handle_fasteoi_irq,
@@ -1353,10 +1259,10 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t
                                              handle_edge_irq, "edge");
 }
 
-int setup_ioapic_entry(int apic_id, int irq,
-                      struct IO_APIC_route_entry *entry,
-                      unsigned int destination, int trigger,
-                      int polarity, int vector, int pin)
+static int setup_ioapic_entry(int apic_id, int irq,
+                             struct IO_APIC_route_entry *entry,
+                             unsigned int destination, int trigger,
+                             int polarity, int vector, int pin)
 {
        /*
         * add it to the IO-APIC irq-routing table:
@@ -1377,21 +1283,7 @@ int setup_ioapic_entry(int apic_id, int irq,
                if (index < 0)
                        panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
 
-               memset(&irte, 0, sizeof(irte));
-
-               irte.present = 1;
-               irte.dst_mode = apic->irq_dest_mode;
-               /*
-                * Trigger mode in the IRTE will always be edge, and the
-                * actual level or edge trigger will be setup in the IO-APIC
-                * RTE. This will help simplify level triggered irq migration.
-                * For more details, see the comments above explainig IO-APIC
-                * irq migration in the presence of interrupt-remapping.
-                */
-               irte.trigger_mode = 0;
-               irte.dlvry_mode = apic->irq_delivery_mode;
-               irte.vector = vector;
-               irte.dest_id = IRTE_DEST(destination);
+               prepare_irte(&irte, vector, destination);
 
                /* Set source-id of interrupt request */
                set_ioapic_sid(&irte, apic_id);
@@ -1426,18 +1318,14 @@ int setup_ioapic_entry(int apic_id, int irq,
        return 0;
 }
 
-static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc,
-                             int trigger, int polarity)
+static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
+                            struct irq_cfg *cfg, int trigger, int polarity)
 {
-       struct irq_cfg *cfg;
        struct IO_APIC_route_entry entry;
        unsigned int dest;
 
        if (!IO_APIC_IRQ(irq))
                return;
-
-       cfg = desc->chip_data;
-
        /*
         * For legacy irqs, cfg->domain starts with cpu 0 for legacy
         * controllers like 8259. Now that IO-APIC can handle this irq, update
@@ -1466,9 +1354,9 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
                return;
        }
 
-       ioapic_register_intr(irq, desc, trigger);
+       ioapic_register_intr(irq, trigger);
        if (irq < legacy_pic->nr_legacy_irqs)
-               legacy_pic->chip->mask(irq);
+               legacy_pic->mask(irq);
 
        ioapic_write_entry(apic_id, pin, entry);
 }
@@ -1479,11 +1367,9 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-       int apic_id, pin, idx, irq;
-       int notcon = 0;
-       struct irq_desc *desc;
+       int apic_id, pin, idx, irq, notcon = 0;
+       int node = cpu_to_node(0);
        struct irq_cfg *cfg;
-       int node = cpu_to_node(boot_cpu_id);
 
        apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
@@ -1520,19 +1406,17 @@ static void __init setup_IO_APIC_irqs(void)
                                apic->multi_timer_check(apic_id, irq))
                        continue;
 
-               desc = irq_to_desc_alloc_node(irq, node);
-               if (!desc) {
-                       printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+               cfg = alloc_irq_and_cfg_at(irq, node);
+               if (!cfg)
                        continue;
-               }
-               cfg = desc->chip_data;
+
                add_pin_to_irq_node(cfg, node, apic_id, pin);
                /*
                 * don't mark it in pin_programmed, so later acpi could
                 * set it correctly when irq < 16
                 */
-               setup_IO_APIC_irq(apic_id, pin, irq, desc,
-                               irq_trigger(idx), irq_polarity(idx));
+               setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
+                                 irq_polarity(idx));
        }
 
        if (notcon)
@@ -1547,9 +1431,7 @@ static void __init setup_IO_APIC_irqs(void)
  */
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
-       int apic_id = 0, pin, idx, irq;
-       int node = cpu_to_node(boot_cpu_id);
-       struct irq_desc *desc;
+       int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
        struct irq_cfg *cfg;
 
        /*
@@ -1565,18 +1447,15 @@ void setup_IO_APIC_irq_extra(u32 gsi)
                return;
 
        irq = pin_2_irq(idx, apic_id, pin);
-#ifdef CONFIG_SPARSE_IRQ
-       desc = irq_to_desc(irq);
-       if (desc)
+
+       /* Only handle the non legacy irqs on secondary ioapics */
+       if (apic_id == 0 || irq < NR_IRQS_LEGACY)
                return;
-#endif
-       desc = irq_to_desc_alloc_node(irq, node);
-       if (!desc) {
-               printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+
+       cfg = alloc_irq_and_cfg_at(irq, node);
+       if (!cfg)
                return;
-       }
 
-       cfg = desc->chip_data;
        add_pin_to_irq_node(cfg, node, apic_id, pin);
 
        if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
@@ -1586,7 +1465,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
        }
        set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
 
-       setup_IO_APIC_irq(apic_id, pin, irq, desc,
+       setup_ioapic_irq(apic_id, pin, irq, cfg,
                        irq_trigger(idx), irq_polarity(idx));
 }
 
@@ -1637,7 +1516,6 @@ __apicdebuginit(void) print_IO_APIC(void)
        union IO_APIC_reg_03 reg_03;
        unsigned long flags;
        struct irq_cfg *cfg;
-       struct irq_desc *desc;
        unsigned int irq;
 
        printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1724,10 +1602,10 @@ __apicdebuginit(void) print_IO_APIC(void)
        }
        }
        printk(KERN_DEBUG "IRQ to pin mappings:\n");
-       for_each_irq_desc(irq, desc) {
+       for_each_active_irq(irq) {
                struct irq_pin_list *entry;
 
-               cfg = desc->chip_data;
+               cfg = get_irq_chip_data(irq);
                if (!cfg)
                        continue;
                entry = cfg->irq_2_pin;
@@ -2234,29 +2112,26 @@ static int __init timer_irq_works(void)
  * an edge even if it isn't on the 8259A...
  */
 
-static unsigned int startup_ioapic_irq(unsigned int irq)
+static unsigned int startup_ioapic_irq(struct irq_data *data)
 {
-       int was_pending = 0;
+       int was_pending = 0, irq = data->irq;
        unsigned long flags;
-       struct irq_cfg *cfg;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        if (irq < legacy_pic->nr_legacy_irqs) {
-               legacy_pic->chip->mask(irq);
+               legacy_pic->mask(irq);
                if (legacy_pic->irq_pending(irq))
                        was_pending = 1;
        }
-       cfg = irq_cfg(irq);
-       __unmask_IO_APIC_irq(cfg);
+       __unmask_ioapic(data->chip_data);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
        return was_pending;
 }
 
-static int ioapic_retrigger_irq(unsigned int irq)
+static int ioapic_retrigger_irq(struct irq_data *data)
 {
-
-       struct irq_cfg *cfg = irq_cfg(irq);
+       struct irq_cfg *cfg = data->chip_data;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&vector_lock, flags);
@@ -2307,7 +2182,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
                 * With interrupt-remapping, destination information comes
                 * from interrupt-remapping table entry.
                 */
-               if (!irq_remapped(irq))
+               if (!irq_remapped(cfg))
                        io_apic_write(apic, 0x11 + pin*2, dest);
                reg = io_apic_read(apic, 0x10 + pin*2);
                reg &= ~IO_APIC_REDIR_VECTOR_MASK;
@@ -2317,65 +2192,46 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
 }
 
 /*
- * Either sets desc->affinity to a valid value, and returns
+ * Either sets data->affinity to a valid value, and returns
  * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
- * leaves desc->affinity untouched.
+ * leaves data->affinity untouched.
  */
-unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask,
-                 unsigned int *dest_id)
+int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                         unsigned int *dest_id)
 {
-       struct irq_cfg *cfg;
-       unsigned int irq;
+       struct irq_cfg *cfg = data->chip_data;
 
        if (!cpumask_intersects(mask, cpu_online_mask))
                return -1;
 
-       irq = desc->irq;
-       cfg = desc->chip_data;
-       if (assign_irq_vector(irq, cfg, mask))
+       if (assign_irq_vector(data->irq, data->chip_data, mask))
                return -1;
 
-       cpumask_copy(desc->affinity, mask);
+       cpumask_copy(data->affinity, mask);
 
-       *dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+       *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain);
        return 0;
 }
 
 static int
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                   bool force)
 {
-       struct irq_cfg *cfg;
+       unsigned int dest, irq = data->irq;
        unsigned long flags;
-       unsigned int dest;
-       unsigned int irq;
-       int ret = -1;
-
-       irq = desc->irq;
-       cfg = desc->chip_data;
+       int ret;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
-       ret = set_desc_affinity(desc, mask, &dest);
+       ret = __ioapic_set_affinity(data, mask, &dest);
        if (!ret) {
                /* Only the high 8 bits are valid. */
                dest = SET_APIC_LOGICAL_ID(dest);
-               __target_IO_APIC_irq(irq, dest, cfg);
+               __target_IO_APIC_irq(irq, dest, data->chip_data);
        }
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-
        return ret;
 }
 
-static int
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-
-       return set_ioapic_affinity_irq_desc(desc, mask);
-}
-
 #ifdef CONFIG_INTR_REMAP
 
 /*
@@ -2390,24 +2246,21 @@ set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
  * the interrupt-remapping table entry.
  */
 static int
-migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                      bool force)
 {
-       struct irq_cfg *cfg;
+       struct irq_cfg *cfg = data->chip_data;
+       unsigned int dest, irq = data->irq;
        struct irte irte;
-       unsigned int dest;
-       unsigned int irq;
-       int ret = -1;
 
        if (!cpumask_intersects(mask, cpu_online_mask))
-               return ret;
+               return -EINVAL;
 
-       irq = desc->irq;
        if (get_irte(irq, &irte))
-               return ret;
+               return -EBUSY;
 
-       cfg = desc->chip_data;
        if (assign_irq_vector(irq, cfg, mask))
-               return ret;
+               return -EBUSY;
 
        dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
 
@@ -2422,29 +2275,14 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
        if (cfg->move_in_progress)
                send_cleanup_vector(cfg);
 
-       cpumask_copy(desc->affinity, mask);
-
+       cpumask_copy(data->affinity, mask);
        return 0;
 }
 
-/*
- * Migrates the IRQ destination in the process context.
- */
-static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
-                                           const struct cpumask *mask)
-{
-       return migrate_ioapic_irq_desc(desc, mask);
-}
-static int set_ir_ioapic_affinity_irq(unsigned int irq,
-                                      const struct cpumask *mask)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       return set_ir_ioapic_affinity_irq_desc(desc, mask);
-}
 #else
-static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
-                                                  const struct cpumask *mask)
+static inline int
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                      bool force)
 {
        return 0;
 }
@@ -2506,10 +2344,8 @@ unlock:
        irq_exit();
 }
 
-static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
+static void __irq_complete_move(struct irq_cfg *cfg, unsigned vector)
 {
-       struct irq_desc *desc = *descp;
-       struct irq_cfg *cfg = desc->chip_data;
        unsigned me;
 
        if (likely(!cfg->move_in_progress))
@@ -2521,31 +2357,28 @@ static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
                send_cleanup_vector(cfg);
 }
 
-static void irq_complete_move(struct irq_desc **descp)
+static void irq_complete_move(struct irq_cfg *cfg)
 {
-       __irq_complete_move(descp, ~get_irq_regs()->orig_ax);
+       __irq_complete_move(cfg, ~get_irq_regs()->orig_ax);
 }
 
 void irq_force_complete_move(int irq)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg = desc->chip_data;
+       struct irq_cfg *cfg = get_irq_chip_data(irq);
 
        if (!cfg)
                return;
 
-       __irq_complete_move(&desc, cfg->vector);
+       __irq_complete_move(cfg, cfg->vector);
 }
 #else
-static inline void irq_complete_move(struct irq_desc **descp) {}
+static inline void irq_complete_move(struct irq_cfg *cfg) { }
 #endif
 
-static void ack_apic_edge(unsigned int irq)
+static void ack_apic_edge(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       irq_complete_move(&desc);
-       move_native_irq(irq);
+       irq_complete_move(data->chip_data);
+       move_native_irq(data->irq);
        ack_APIC_irq();
 }
 
@@ -2567,10 +2400,12 @@ atomic_t irq_mis_count;
  * Otherwise, we simulate the EOI message manually by changing the trigger
  * mode to edge and then back to level, with RTE being masked during this.
 */
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 {
        struct irq_pin_list *entry;
+       unsigned long flags;
 
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        for_each_irq_pin(entry, cfg->irq_2_pin) {
                if (mp_ioapics[entry->apic].apicver >= 0x20) {
                        /*
@@ -2579,7 +2414,7 @@ static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
                         * intr-remapping table entry. Hence for the io-apic
                         * EOI we use the pin number.
                         */
-                       if (irq_remapped(irq))
+                       if (irq_remapped(cfg))
                                io_apic_eoi(entry->apic, entry->pin);
                        else
                                io_apic_eoi(entry->apic, cfg->vector);
@@ -2588,36 +2423,22 @@ static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
                        __unmask_and_level_IO_APIC_irq(entry);
                }
        }
-}
-
-static void eoi_ioapic_irq(struct irq_desc *desc)
-{
-       struct irq_cfg *cfg;
-       unsigned long flags;
-       unsigned int irq;
-
-       irq = desc->irq;
-       cfg = desc->chip_data;
-
-       raw_spin_lock_irqsave(&ioapic_lock, flags);
-       __eoi_ioapic_irq(irq, cfg);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void ack_apic_level(unsigned int irq)
+static void ack_apic_level(struct irq_data *data)
 {
+       struct irq_cfg *cfg = data->chip_data;
+       int i, do_unmask_irq = 0, irq = data->irq;
        struct irq_desc *desc = irq_to_desc(irq);
        unsigned long v;
-       int i;
-       struct irq_cfg *cfg;
-       int do_unmask_irq = 0;
 
-       irq_complete_move(&desc);
+       irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        /* If we are moving the irq we need to mask it */
        if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
                do_unmask_irq = 1;
-               mask_IO_APIC_irq_desc(desc);
+               mask_ioapic(cfg);
        }
 #endif
 
@@ -2653,7 +2474,6 @@ static void ack_apic_level(unsigned int irq)
         * we use the above logic (mask+edge followed by unmask+level) from
         * Manfred Spraul to clear the remote IRR.
         */
-       cfg = desc->chip_data;
        i = cfg->vector;
        v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
@@ -2673,7 +2493,7 @@ static void ack_apic_level(unsigned int irq)
        if (!(v & (1 << (i & 0x1f)))) {
                atomic_inc(&irq_mis_count);
 
-               eoi_ioapic_irq(desc);
+               eoi_ioapic_irq(irq, cfg);
        }
 
        /* Now we can move and renable the irq */
@@ -2704,61 +2524,57 @@ static void ack_apic_level(unsigned int irq)
                 * accurate and is causing problems then it is a hardware bug
                 * and you can go talk to the chipset vendor about it.
                 */
-               cfg = desc->chip_data;
                if (!io_apic_level_ack_pending(cfg))
                        move_masked_irq(irq);
-               unmask_IO_APIC_irq_desc(desc);
+               unmask_ioapic(cfg);
        }
 }
 
 #ifdef CONFIG_INTR_REMAP
-static void ir_ack_apic_edge(unsigned int irq)
+static void ir_ack_apic_edge(struct irq_data *data)
 {
        ack_APIC_irq();
 }
 
-static void ir_ack_apic_level(unsigned int irq)
+static void ir_ack_apic_level(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-
        ack_APIC_irq();
-       eoi_ioapic_irq(desc);
+       eoi_ioapic_irq(data->irq, data->chip_data);
 }
 #endif /* CONFIG_INTR_REMAP */
 
 static struct irq_chip ioapic_chip __read_mostly = {
-       .name           = "IO-APIC",
-       .startup        = startup_ioapic_irq,
-       .mask           = mask_IO_APIC_irq,
-       .unmask         = unmask_IO_APIC_irq,
-       .ack            = ack_apic_edge,
-       .eoi            = ack_apic_level,
+       .name                   = "IO-APIC",
+       .irq_startup            = startup_ioapic_irq,
+       .irq_mask               = mask_ioapic_irq,
+       .irq_unmask             = unmask_ioapic_irq,
+       .irq_ack                = ack_apic_edge,
+       .irq_eoi                = ack_apic_level,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_ioapic_affinity_irq,
+       .irq_set_affinity       = ioapic_set_affinity,
 #endif
-       .retrigger      = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 static struct irq_chip ir_ioapic_chip __read_mostly = {
-       .name           = "IR-IO-APIC",
-       .startup        = startup_ioapic_irq,
-       .mask           = mask_IO_APIC_irq,
-       .unmask         = unmask_IO_APIC_irq,
+       .name                   = "IR-IO-APIC",
+       .irq_startup            = startup_ioapic_irq,
+       .irq_mask               = mask_ioapic_irq,
+       .irq_unmask             = unmask_ioapic_irq,
 #ifdef CONFIG_INTR_REMAP
-       .ack            = ir_ack_apic_edge,
-       .eoi            = ir_ack_apic_level,
+       .irq_ack                = ir_ack_apic_edge,
+       .irq_eoi                = ir_ack_apic_level,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_ir_ioapic_affinity_irq,
+       .irq_set_affinity       = ir_ioapic_set_affinity,
 #endif
 #endif
-       .retrigger      = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 static inline void init_IO_APIC_traps(void)
 {
-       int irq;
-       struct irq_desc *desc;
        struct irq_cfg *cfg;
+       unsigned int irq;
 
        /*
         * NOTE! The local APIC isn't very good at handling
@@ -2771,8 +2587,8 @@ static inline void init_IO_APIC_traps(void)
         * Also, we've got to be careful not to trash gate
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
-       for_each_irq_desc(irq, desc) {
-               cfg = desc->chip_data;
+       for_each_active_irq(irq) {
+               cfg = get_irq_chip_data(irq);
                if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
                        /*
                         * Hmm.. We don't have an entry for this,
@@ -2783,7 +2599,7 @@ static inline void init_IO_APIC_traps(void)
                                legacy_pic->make_irq(irq);
                        else
                                /* Strange. Oh, well.. */
-                               desc->chip = &no_irq_chip;
+                               set_irq_chip(irq, &no_irq_chip);
                }
        }
 }
@@ -2792,7 +2608,7 @@ static inline void init_IO_APIC_traps(void)
  * The local APIC irq-chip implementation:
  */
 
-static void mask_lapic_irq(unsigned int irq)
+static void mask_lapic_irq(struct irq_data *data)
 {
        unsigned long v;
 
@@ -2800,7 +2616,7 @@ static void mask_lapic_irq(unsigned int irq)
        apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 }
 
-static void unmask_lapic_irq(unsigned int irq)
+static void unmask_lapic_irq(struct irq_data *data)
 {
        unsigned long v;
 
@@ -2808,21 +2624,21 @@ static void unmask_lapic_irq(unsigned int irq)
        apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
-static void ack_lapic_irq(unsigned int irq)
+static void ack_lapic_irq(struct irq_data *data)
 {
        ack_APIC_irq();
 }
 
 static struct irq_chip lapic_chip __read_mostly = {
        .name           = "local-APIC",
-       .mask           = mask_lapic_irq,
-       .unmask         = unmask_lapic_irq,
-       .ack            = ack_lapic_irq,
+       .irq_mask       = mask_lapic_irq,
+       .irq_unmask     = unmask_lapic_irq,
+       .irq_ack        = ack_lapic_irq,
 };
 
-static void lapic_register_intr(int irq, struct irq_desc *desc)
+static void lapic_register_intr(int irq)
 {
-       desc->status &= ~IRQ_LEVEL;
+       irq_clear_status_flags(irq, IRQ_LEVEL);
        set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
                                      "edge");
 }
@@ -2925,9 +2741,8 @@ int timer_through_8259 __initdata;
  */
 static inline void __init check_timer(void)
 {
-       struct irq_desc *desc = irq_to_desc(0);
-       struct irq_cfg *cfg = desc->chip_data;
-       int node = cpu_to_node(boot_cpu_id);
+       struct irq_cfg *cfg = get_irq_chip_data(0);
+       int node = cpu_to_node(0);
        int apic1, pin1, apic2, pin2;
        unsigned long flags;
        int no_pin1 = 0;
@@ -2937,7 +2752,7 @@ static inline void __init check_timer(void)
        /*
         * get/set the timer IRQ vector:
         */
-       legacy_pic->chip->mask(0);
+       legacy_pic->mask(0);
        assign_irq_vector(0, cfg, apic->target_cpus());
 
        /*
@@ -2996,7 +2811,7 @@ static inline void __init check_timer(void)
                        add_pin_to_irq_node(cfg, node, apic1, pin1);
                        setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
                } else {
-                       /* for edge trigger, setup_IO_APIC_irq already
+                       /* for edge trigger, setup_ioapic_irq already
                         * leave it unmasked.
                         * so only need to unmask if it is level-trigger
                         * do we really have level trigger timer?
@@ -3004,12 +2819,12 @@ static inline void __init check_timer(void)
                        int idx;
                        idx = find_irq_entry(apic1, pin1, mp_INT);
                        if (idx != -1 && irq_trigger(idx))
-                               unmask_IO_APIC_irq_desc(desc);
+                               unmask_ioapic(cfg);
                }
                if (timer_irq_works()) {
                        if (nmi_watchdog == NMI_IO_APIC) {
                                setup_nmi();
-                               legacy_pic->chip->unmask(0);
+                               legacy_pic->unmask(0);
                        }
                        if (disable_timer_pin_1 > 0)
                                clear_IO_APIC_pin(0, pin1);
@@ -3032,14 +2847,14 @@ static inline void __init check_timer(void)
                 */
                replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
                setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-               legacy_pic->chip->unmask(0);
+               legacy_pic->unmask(0);
                if (timer_irq_works()) {
                        apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
                        timer_through_8259 = 1;
                        if (nmi_watchdog == NMI_IO_APIC) {
-                               legacy_pic->chip->mask(0);
+                               legacy_pic->mask(0);
                                setup_nmi();
-                               legacy_pic->chip->unmask(0);
+                               legacy_pic->unmask(0);
                        }
                        goto out;
                }
@@ -3047,7 +2862,7 @@ static inline void __init check_timer(void)
                 * Cleanup, just in case ...
                 */
                local_irq_disable();
-               legacy_pic->chip->mask(0);
+               legacy_pic->mask(0);
                clear_IO_APIC_pin(apic2, pin2);
                apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
        }
@@ -3064,16 +2879,16 @@ static inline void __init check_timer(void)
        apic_printk(APIC_QUIET, KERN_INFO
                    "...trying to set up timer as Virtual Wire IRQ...\n");
 
-       lapic_register_intr(0, desc);
+       lapic_register_intr(0);
        apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);     /* Fixed mode */
-       legacy_pic->chip->unmask(0);
+       legacy_pic->unmask(0);
 
        if (timer_irq_works()) {
                apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
                goto out;
        }
        local_irq_disable();
-       legacy_pic->chip->mask(0);
+       legacy_pic->mask(0);
        apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
        apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
@@ -3239,49 +3054,42 @@ device_initcall(ioapic_init_sysfs);
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq_nr(unsigned int irq_want, int node)
+unsigned int create_irq_nr(unsigned int from, int node)
 {
-       /* Allocate an unused irq */
-       unsigned int irq;
-       unsigned int new;
+       struct irq_cfg *cfg;
        unsigned long flags;
-       struct irq_cfg *cfg_new = NULL;
-       struct irq_desc *desc_new = NULL;
-
-       irq = 0;
-       if (irq_want < nr_irqs_gsi)
-               irq_want = nr_irqs_gsi;
-
-       raw_spin_lock_irqsave(&vector_lock, flags);
-       for (new = irq_want; new < nr_irqs; new++) {
-               desc_new = irq_to_desc_alloc_node(new, node);
-               if (!desc_new) {
-                       printk(KERN_INFO "can not get irq_desc for %d\n", new);
-                       continue;
-               }
-               cfg_new = desc_new->chip_data;
-
-               if (cfg_new->vector != 0)
-                       continue;
+       unsigned int ret = 0;
+       int irq;
 
-               desc_new = move_irq_desc(desc_new, node);
-               cfg_new = desc_new->chip_data;
+       if (from < nr_irqs_gsi)
+               from = nr_irqs_gsi;
 
-               if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
-                       irq = new;
-               break;
+       irq = alloc_irq_from(from, node);
+       if (irq < 0)
+               return 0;
+       cfg = alloc_irq_cfg(irq, node);
+       if (!cfg) {
+               free_irq_at(irq, NULL);
+               return 0;
        }
-       raw_spin_unlock_irqrestore(&vector_lock, flags);
 
-       if (irq > 0)
-               dynamic_irq_init_keep_chip_data(irq);
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       if (!__assign_irq_vector(irq, cfg, apic->target_cpus()))
+               ret = irq;
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
 
-       return irq;
+       if (ret) {
+               set_irq_chip_data(irq, cfg);
+               irq_clear_status_flags(irq, IRQ_NOREQUEST);
+       } else {
+               free_irq_at(irq, cfg);
+       }
+       return ret;
 }
 
 int create_irq(void)
 {
-       int node = cpu_to_node(boot_cpu_id);
+       int node = cpu_to_node(0);
        unsigned int irq_want;
        int irq;
 
@@ -3296,14 +3104,17 @@ int create_irq(void)
 
 void destroy_irq(unsigned int irq)
 {
+       struct irq_cfg *cfg = get_irq_chip_data(irq);
        unsigned long flags;
 
-       dynamic_irq_cleanup_keep_chip_data(irq);
+       irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
 
-       free_irte(irq);
+       if (intr_remapping_enabled)
+               free_irte(irq);
        raw_spin_lock_irqsave(&vector_lock, flags);
-       __clear_irq_vector(irq, get_irq_chip_data(irq));
+       __clear_irq_vector(irq, cfg);
        raw_spin_unlock_irqrestore(&vector_lock, flags);
+       free_irq_at(irq, cfg);
 }
 
 /*
@@ -3327,7 +3138,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
 
        dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
-       if (irq_remapped(irq)) {
+       if (irq_remapped(get_irq_chip_data(irq))) {
                struct irte irte;
                int ir_index;
                u16 sub_handle;
@@ -3335,14 +3146,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
                ir_index = map_irq_to_irte_handle(irq, &sub_handle);
                BUG_ON(ir_index == -1);
 
-               memset (&irte, 0, sizeof(irte));
-
-               irte.present = 1;
-               irte.dst_mode = apic->irq_dest_mode;
-               irte.trigger_mode = 0; /* edge */
-               irte.dlvry_mode = apic->irq_delivery_mode;
-               irte.vector = cfg->vector;
-               irte.dest_id = IRTE_DEST(dest);
+               prepare_irte(&irte, cfg->vector, dest);
 
                /* Set source-id of interrupt request */
                if (pdev)
@@ -3387,26 +3191,24 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
 }
 
 #ifdef CONFIG_SMP
-static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg;
+       struct irq_cfg *cfg = data->chip_data;
        struct msi_msg msg;
        unsigned int dest;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
-       cfg = desc->chip_data;
-
-       get_cached_msi_msg_desc(desc, &msg);
+       __get_cached_msi_msg(data->msi_desc, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
-       write_msi_msg_desc(desc, &msg);
+       __write_msi_msg(data->msi_desc, &msg);
 
        return 0;
 }
@@ -3416,17 +3218,17 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
  * done in the process context using interrupt-remapping hardware.
  */
 static int
-ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                   bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg = desc->chip_data;
-       unsigned int dest;
+       struct irq_cfg *cfg = data->chip_data;
+       unsigned int dest, irq = data->irq;
        struct irte irte;
 
        if (get_irte(irq, &irte))
                return -1;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
        irte.vector = cfg->vector;
@@ -3456,27 +3258,27 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
  * which implement the MSI or MSI-X Capability Structure.
  */
 static struct irq_chip msi_chip = {
-       .name           = "PCI-MSI",
-       .unmask         = unmask_msi_irq,
-       .mask           = mask_msi_irq,
-       .ack            = ack_apic_edge,
+       .name                   = "PCI-MSI",
+       .irq_unmask             = unmask_msi_irq,
+       .irq_mask               = mask_msi_irq,
+       .irq_ack                = ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_msi_irq_affinity,
+       .irq_set_affinity       = msi_set_affinity,
 #endif
-       .retrigger      = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 static struct irq_chip msi_ir_chip = {
-       .name           = "IR-PCI-MSI",
-       .unmask         = unmask_msi_irq,
-       .mask           = mask_msi_irq,
+       .name                   = "IR-PCI-MSI",
+       .irq_unmask             = unmask_msi_irq,
+       .irq_mask               = mask_msi_irq,
 #ifdef CONFIG_INTR_REMAP
-       .ack            = ir_ack_apic_edge,
+       .irq_ack                = ir_ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity   = ir_set_msi_irq_affinity,
+       .irq_set_affinity       = ir_msi_set_affinity,
 #endif
 #endif
-       .retrigger      = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 /*
@@ -3508,8 +3310,8 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
-       int ret;
        struct msi_msg msg;
+       int ret;
 
        ret = msi_compose_msg(dev, irq, &msg, -1);
        if (ret < 0)
@@ -3518,12 +3320,8 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
        set_irq_msi(irq, msidesc);
        write_msi_msg(irq, &msg);
 
-       if (irq_remapped(irq)) {
-               struct irq_desc *desc = irq_to_desc(irq);
-               /*
-                * irq migration in process context
-                */
-               desc->status |= IRQ_MOVE_PCNTXT;
+       if (irq_remapped(get_irq_chip_data(irq))) {
+               irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
                set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
        } else
                set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
@@ -3535,13 +3333,10 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-       unsigned int irq;
-       int ret, sub_handle;
+       int node, ret, sub_handle, index = 0;
+       unsigned int irq, irq_want;
        struct msi_desc *msidesc;
-       unsigned int irq_want;
        struct intel_iommu *iommu = NULL;
-       int index = 0;
-       int node;
 
        /* x86 doesn't support multiple MSI yet */
        if (type == PCI_CAP_ID_MSI && nvec > 1)
@@ -3601,18 +3396,17 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
 #ifdef CONFIG_SMP
-static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                     bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg;
+       struct irq_cfg *cfg = data->chip_data;
+       unsigned int dest, irq = data->irq;
        struct msi_msg msg;
-       unsigned int dest;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
-       cfg = desc->chip_data;
-
        dmar_msi_read(irq, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
@@ -3628,14 +3422,14 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 #endif /* CONFIG_SMP */
 
 static struct irq_chip dmar_msi_type = {
-       .name = "DMAR_MSI",
-       .unmask = dmar_msi_unmask,
-       .mask = dmar_msi_mask,
-       .ack = ack_apic_edge,
+       .name                   = "DMAR_MSI",
+       .irq_unmask             = dmar_msi_unmask,
+       .irq_mask               = dmar_msi_mask,
+       .irq_ack                = ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity = dmar_msi_set_affinity,
+       .irq_set_affinity       = dmar_msi_set_affinity,
 #endif
-       .retrigger = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 int arch_setup_dmar_msi(unsigned int irq)
@@ -3656,26 +3450,24 @@ int arch_setup_dmar_msi(unsigned int irq)
 #ifdef CONFIG_HPET_TIMER
 
 #ifdef CONFIG_SMP
-static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(struct irq_data *data,
+                                const struct cpumask *mask, bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg;
+       struct irq_cfg *cfg = data->chip_data;
        struct msi_msg msg;
        unsigned int dest;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
-       cfg = desc->chip_data;
-
-       hpet_msi_read(irq, &msg);
+       hpet_msi_read(data->handler_data, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
-       hpet_msi_write(irq, &msg);
+       hpet_msi_write(data->handler_data, &msg);
 
        return 0;
 }
@@ -3683,34 +3475,33 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 #endif /* CONFIG_SMP */
 
 static struct irq_chip ir_hpet_msi_type = {
-       .name = "IR-HPET_MSI",
-       .unmask = hpet_msi_unmask,
-       .mask = hpet_msi_mask,
+       .name                   = "IR-HPET_MSI",
+       .irq_unmask             = hpet_msi_unmask,
+       .irq_mask               = hpet_msi_mask,
 #ifdef CONFIG_INTR_REMAP
-       .ack = ir_ack_apic_edge,
+       .irq_ack                = ir_ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity = ir_set_msi_irq_affinity,
+       .irq_set_affinity       = ir_msi_set_affinity,
 #endif
 #endif
-       .retrigger = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 static struct irq_chip hpet_msi_type = {
        .name = "HPET_MSI",
-       .unmask = hpet_msi_unmask,
-       .mask = hpet_msi_mask,
-       .ack = ack_apic_edge,
+       .irq_unmask = hpet_msi_unmask,
+       .irq_mask = hpet_msi_mask,
+       .irq_ack = ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity = hpet_msi_set_affinity,
+       .irq_set_affinity = hpet_msi_set_affinity,
 #endif
-       .retrigger = ioapic_retrigger_irq,
+       .irq_retrigger = ioapic_retrigger_irq,
 };
 
 int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
-       int ret;
        struct msi_msg msg;
-       struct irq_desc *desc = irq_to_desc(irq);
+       int ret;
 
        if (intr_remapping_enabled) {
                struct intel_iommu *iommu = map_hpet_to_ir(id);
@@ -3728,9 +3519,9 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
        if (ret < 0)
                return ret;
 
-       hpet_msi_write(irq, &msg);
-       desc->status |= IRQ_MOVE_PCNTXT;
-       if (irq_remapped(irq))
+       hpet_msi_write(get_irq_data(irq), &msg);
+       irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
+       if (irq_remapped(get_irq_chip_data(irq)))
                set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type,
                                              handle_edge_irq, "edge");
        else
@@ -3763,33 +3554,30 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
        write_ht_irq_msg(irq, &msg);
 }
 
-static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg;
+       struct irq_cfg *cfg = data->chip_data;
        unsigned int dest;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
-       cfg = desc->chip_data;
-
-       target_ht_irq(irq, dest, cfg->vector);
-
+       target_ht_irq(data->irq, dest, cfg->vector);
        return 0;
 }
 
 #endif
 
 static struct irq_chip ht_irq_chip = {
-       .name           = "PCI-HT",
-       .mask           = mask_ht_irq,
-       .unmask         = unmask_ht_irq,
-       .ack            = ack_apic_edge,
+       .name                   = "PCI-HT",
+       .irq_mask               = mask_ht_irq,
+       .irq_unmask             = unmask_ht_irq,
+       .irq_ack                = ack_apic_edge,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_ht_irq_affinity,
+       .irq_set_affinity       = ht_set_affinity,
 #endif
-       .retrigger      = ioapic_retrigger_irq,
+       .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
@@ -3880,14 +3668,13 @@ int __init arch_probe_nr_irqs(void)
        if (nr < nr_irqs)
                nr_irqs = nr;
 
-       return 0;
+       return NR_IRQS_LEGACY;
 }
 #endif
 
 static int __io_apic_set_pci_routing(struct device *dev, int irq,
                                struct io_apic_irq_attr *irq_attr)
 {
-       struct irq_desc *desc;
        struct irq_cfg *cfg;
        int node;
        int ioapic, pin;
@@ -3903,13 +3690,11 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
        if (dev)
                node = dev_to_node(dev);
        else
-               node = cpu_to_node(boot_cpu_id);
+               node = cpu_to_node(0);
 
-       desc = irq_to_desc_alloc_node(irq, node);
-       if (!desc) {
-               printk(KERN_INFO "can not get irq_desc %d\n", irq);
+       cfg = alloc_irq_and_cfg_at(irq, node);
+       if (!cfg)
                return 0;
-       }
 
        pin = irq_attr->ioapic_pin;
        trigger = irq_attr->trigger;
@@ -3919,15 +3704,14 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
         * IRQs < 16 are already in the irq_2_pin[] map
         */
        if (irq >= legacy_pic->nr_legacy_irqs) {
-               cfg = desc->chip_data;
-               if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
+               if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
                        printk(KERN_INFO "can not add pin %d for irq %d\n",
                                pin, irq);
                        return 0;
                }
        }
 
-       setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+       setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
 
        return 0;
 }
@@ -4120,14 +3904,14 @@ void __init setup_ioapic_dest(void)
                 */
                if (desc->status &
                    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
-                       mask = desc->affinity;
+                       mask = desc->irq_data.affinity;
                else
                        mask = apic->target_cpus();
 
                if (intr_remapping_enabled)
-                       set_ir_ioapic_affinity_irq_desc(desc, mask);
+                       ir_ioapic_set_affinity(&desc->irq_data, mask, false);
                else
-                       set_ioapic_affinity_irq_desc(desc, mask);
+                       ioapic_set_affinity(&desc->irq_data, mask, false);
        }
 
 }
@@ -4311,19 +4095,18 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 void __init pre_init_apic_IRQ0(void)
 {
        struct irq_cfg *cfg;
-       struct irq_desc *desc;
 
        printk(KERN_INFO "Early APIC setup for system timer0\n");
 #ifndef CONFIG_SMP
        phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
 #endif
-       desc = irq_to_desc_alloc_node(0, 0);
+       /* Make sure the irq descriptor is set up */
+       cfg = alloc_irq_and_cfg_at(0, 0);
 
        setup_local_APIC();
 
-       cfg = irq_cfg(0);
        add_pin_to_irq_node(cfg, 0, 0, 0);
        set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
 
-       setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+       setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
 }
index a43f71cb30f8709595fe77c80be19d36c24aae29..c90041ccb74239cd471a5d334f16d93b28a46b62 100644 (file)
@@ -178,7 +178,7 @@ int __init check_nmi_watchdog(void)
 error:
        if (nmi_watchdog == NMI_IO_APIC) {
                if (!timer_through_8259)
-                       legacy_pic->chip->mask(0);
+                       legacy_pic->mask(0);
                on_each_cpu(__acpi_nmi_disable, NULL, 1);
        }
 
index 3e28401f161c768193e784cc013814cadf190078..960f26ab5c9f24ed2f4587107faa2fcd457d782c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/nodemask.h>
 #include <linux/topology.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/kernel.h>
@@ -88,7 +89,7 @@ static inline void numaq_register_node(int node, struct sys_cfg_data *scd)
        node_end_pfn[node] =
                 MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
 
-       e820_register_active_regions(node, node_start_pfn[node],
+       memblock_x86_register_active_regions(node, node_start_pfn[node],
                                                node_end_pfn[node]);
 
        memory_present(node, node_start_pfn[node], node_end_pfn[node]);
index 83e9be4778e2b597791306a85ca9ca527003e2c2..f9e4e6a54073e3d901d0475da9c5deceb21d55d8 100644 (file)
@@ -54,6 +54,9 @@ static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
  */
 void __init default_setup_apic_routing(void)
 {
+
+       enable_IR_x2apic();
+
 #ifdef CONFIG_X86_X2APIC
        if (x2apic_mode
 #ifdef CONFIG_X86_UV
index 7b598b84c902e62f9f852d78c896acb03d4ba318..f744f54cb248e7ac0cd6defaa84a8e673468b30a 100644 (file)
@@ -698,9 +698,11 @@ void __init uv_system_init(void)
                for (j = 0; j < 64; j++) {
                        if (!test_bit(j, &present))
                                continue;
-                       uv_blade_info[blade].pnode = (i * 64 + j);
+                       pnode = (i * 64 + j);
+                       uv_blade_info[blade].pnode = pnode;
                        uv_blade_info[blade].nr_possible_cpus = 0;
                        uv_blade_info[blade].nr_online_cpus = 0;
+                       max_pnode = max(pnode, max_pnode);
                        blade++;
                }
        }
@@ -738,7 +740,6 @@ void __init uv_system_init(void)
                uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid);
                uv_node_to_blade[nid] = blade;
                uv_cpu_to_blade[cpu] = blade;
-               max_pnode = max(pnode, max_pnode);
        }
 
        /* Add blade/pnode info for nodes without cpus */
@@ -750,7 +751,6 @@ void __init uv_system_init(void)
                pnode = (paddr >> m_val) & pnode_mask;
                blade = boot_pnode_to_blade(pnode);
                uv_node_to_blade[nid] = blade;
-               max_pnode = max(pnode, max_pnode);
        }
 
        map_gru_high(max_pnode);
index 4c9c67bf09b70e093e784c579b4e95a88e3acac8..fbbc4dadecc4566968d26dbaed45173c15516e3e 100644 (file)
@@ -1926,6 +1926,7 @@ static const struct file_operations apm_bios_fops = {
        .unlocked_ioctl = do_ioctl,
        .open           = do_open,
        .release        = do_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice apm_device = {
index fc999e6fc46a34cf1417cd600c11a0e07af1acfd..13a389179514eb4b17c7d5fc6d5100e1996d0770 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/workqueue.h>
-#include <asm/e820.h>
+#include <linux/memblock.h>
+
 #include <asm/proto.h>
 
 /*
@@ -18,10 +19,12 @@ static int __read_mostly memory_corruption_check = -1;
 static unsigned __read_mostly corruption_check_size = 64*1024;
 static unsigned __read_mostly corruption_check_period = 60; /* seconds */
 
-static struct e820entry scan_areas[MAX_SCAN_AREAS];
+static struct scan_area {
+       u64 addr;
+       u64 size;
+} scan_areas[MAX_SCAN_AREAS];
 static int num_scan_areas;
 
-
 static __init int set_corruption_check(char *arg)
 {
        char *end;
@@ -81,9 +84,9 @@ void __init setup_bios_corruption_check(void)
 
        while (addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
                u64 size;
-               addr = find_e820_area_size(addr, &size, PAGE_SIZE);
+               addr = memblock_x86_find_in_range_size(addr, &size, PAGE_SIZE);
 
-               if (!(addr + 1))
+               if (addr == MEMBLOCK_ERROR)
                        break;
 
                if (addr >= corruption_check_size)
@@ -92,7 +95,7 @@ void __init setup_bios_corruption_check(void)
                if ((addr + size) > corruption_check_size)
                        size = corruption_check_size - addr;
 
-               e820_update_range(addr, size, E820_RAM, E820_RESERVED);
+               memblock_x86_reserve_range(addr, addr + size, "SCAN RAM");
                scan_areas[num_scan_areas].addr = addr;
                scan_areas[num_scan_areas].size = size;
                num_scan_areas++;
@@ -105,7 +108,6 @@ void __init setup_bios_corruption_check(void)
 
        printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
               num_scan_areas);
-       update_e820();
 }
 
 
index ba5f62f45f01e136e849894076917684ffcd8c40..9e093f8fe78c4713aec4f91a62394eb0efa1f6c0 100644 (file)
@@ -148,7 +148,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        /* calling is from identify_secondary_cpu() ? */
-       if (c->cpu_index == boot_cpu_id)
+       if (!c->cpu_index)
                return;
 
        /*
@@ -253,37 +253,51 @@ static int __cpuinit nearby_node(int apicid)
 #endif
 
 /*
- * Fixup core topology information for AMD multi-node processors.
- * Assumption: Number of cores in each internal node is the same.
+ * Fixup core topology information for
+ * (1) AMD multi-node processors
+ *     Assumption: Number of cores in each internal node is the same.
+ * (2) AMD processors supporting compute units
  */
 #ifdef CONFIG_X86_HT
-static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
+static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 {
-       unsigned long long value;
-       u32 nodes, cores_per_node;
+       u32 nodes;
+       u8 node_id;
        int cpu = smp_processor_id();
 
-       if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
-               return;
+       /* get information required for multi-node processors */
+       if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+               u32 eax, ebx, ecx, edx;
 
-       /* fixup topology information only once for a core */
-       if (cpu_has(c, X86_FEATURE_AMD_DCM))
-               return;
+               cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+               nodes = ((ecx >> 8) & 7) + 1;
+               node_id = ecx & 7;
 
-       rdmsrl(MSR_FAM10H_NODE_ID, value);
+               /* get compute unit information */
+               smp_num_siblings = ((ebx >> 8) & 3) + 1;
+               c->compute_unit_id = ebx & 0xff;
+       } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
+               u64 value;
 
-       nodes = ((value >> 3) & 7) + 1;
-       if (nodes == 1)
+               rdmsrl(MSR_FAM10H_NODE_ID, value);
+               nodes = ((value >> 3) & 7) + 1;
+               node_id = value & 7;
+       } else
                return;
 
-       set_cpu_cap(c, X86_FEATURE_AMD_DCM);
-       cores_per_node = c->x86_max_cores / nodes;
+       /* fixup multi-node processor information */
+       if (nodes > 1) {
+               u32 cores_per_node;
+
+               set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+               cores_per_node = c->x86_max_cores / nodes;
 
-       /* store NodeID, use llc_shared_map to store sibling info */
-       per_cpu(cpu_llc_id, cpu) = value & 7;
+               /* store NodeID, use llc_shared_map to store sibling info */
+               per_cpu(cpu_llc_id, cpu) = node_id;
 
-       /* fixup core id to be in range from 0 to (cores_per_node - 1) */
-       c->cpu_core_id = c->cpu_core_id % cores_per_node;
+               /* core id to be in range from 0 to (cores_per_node - 1) */
+               c->cpu_core_id = c->cpu_core_id % cores_per_node;
+       }
 }
 #endif
 
@@ -304,9 +318,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
        c->phys_proc_id = c->initial_apicid >> bits;
        /* use socket ID also for last level cache */
        per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
-       /* fixup topology information on multi-node processors */
-       if ((c->x86 == 0x10) && (c->x86_model == 9))
-               amd_fixup_dcm(c);
+       amd_get_topology(c);
 #endif
 }
 
@@ -412,6 +424,23 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
        }
 #endif
+
+       /* We need to do the following only once */
+       if (c != &boot_cpu_data)
+               return;
+
+       if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+               if (c->x86 > 0x10 ||
+                   (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+                       u64 val;
+
+                       rdmsrl(MSR_K7_HWCR, val);
+                       if (!(val & BIT(24)))
+                               printk(KERN_WARNING FW_BUG "TSC doesn't count "
+                                       "with P0 frequency!\n");
+               }
+       }
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -523,7 +552,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 #endif
 
        if (c->extended_cpuid_level >= 0x80000006) {
-               if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
+               if (cpuid_edx(0x80000006) & 0xf000)
                        num_cache_leaves = 4;
                else
                        num_cache_leaves = 3;
index 490dac63c2d21e90ab3af70c543b012f1c3f43b5..4b68bda30938d0a55ed39eeaeff68157266a9ea0 100644 (file)
@@ -545,7 +545,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
        }
 }
 
-static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
 {
        u32 tfms, xlvl;
        u32 ebx;
@@ -665,7 +665,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
                this_cpu->c_early_init(c);
 
 #ifdef CONFIG_SMP
-       c->cpu_index = boot_cpu_id;
+       c->cpu_index = 0;
 #endif
        filter_cpuid_features(c, false);
 }
@@ -704,16 +704,21 @@ void __init early_cpu_init(void)
 }
 
 /*
- * The NOPL instruction is supposed to exist on all CPUs with
- * family >= 6; unfortunately, that's not true in practice because
- * of early VIA chips and (more importantly) broken virtualizers that
- * are not easy to detect.  In the latter case it doesn't even *fail*
- * reliably, so probing for it doesn't even work.  Disable it completely
+ * The NOPL instruction is supposed to exist on all CPUs of family >= 6;
+ * unfortunately, that's not true in practice because of early VIA
+ * chips and (more importantly) broken virtualizers that are not easy
+ * to detect. In the latter case it doesn't even *fail* reliably, so
+ * probing for it doesn't even work. Disable it completely on 32-bit
  * unless we can find a reliable way to detect all the broken cases.
+ * Enable it explicitly on 64-bit for non-constant inputs of cpu_has().
  */
 static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
 {
+#ifdef CONFIG_X86_32
        clear_cpu_cap(c, X86_FEATURE_NOPL);
+#else
+       set_cpu_cap(c, X86_FEATURE_NOPL);
+#endif
 }
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -1264,13 +1269,6 @@ void __cpuinit cpu_init(void)
        clear_all_debug_regs();
        dbg_restore_debug_regs();
 
-       /*
-        * Force FPU initialization:
-        */
-       current_thread_info()->status = 0;
-       clear_used_math();
-       mxcsr_feature_mask_init();
-
        fpu_init();
        xsave_init();
 }
index 3624e8a0f71bf72e4c3cd86abcedfbb1c53d9b4d..e765633f210ed893f56bc23ba26e6cfea6c074fd 100644 (file)
@@ -32,6 +32,8 @@ struct cpu_dev {
 extern const struct cpu_dev *const __x86_cpu_dev_start[],
                            *const __x86_cpu_dev_end[];
 
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
 extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
 
 #endif
index 994230d4dc4e545986a8c982629589905f0f224d..4f6f679f27990198640f9a1e139ea3a838b05eb8 100644 (file)
@@ -368,16 +368,22 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
                return -ENODEV;
 
        out_obj = output.pointer;
-       if (out_obj->type != ACPI_TYPE_BUFFER)
-               return -ENODEV;
+       if (out_obj->type != ACPI_TYPE_BUFFER) {
+               ret = -ENODEV;
+               goto out_free;
+       }
 
        errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
-       if (errors)
-               return -ENODEV;
+       if (errors) {
+               ret = -ENODEV;
+               goto out_free;
+       }
 
        supported = *((u32 *)(out_obj->buffer.pointer + 4));
-       if (!(supported & 0x1))
-               return -ENODEV;
+       if (!(supported & 0x1)) {
+               ret = -ENODEV;
+               goto out_free;
+       }
 
 out_free:
        kfree(output.pointer);
index 85f69cdeae1020a18e1c9097c8da276a8e50b992..695f17731e2382ce63bbbb4a9caaf2ec7e16e29e 100644 (file)
@@ -39,6 +39,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
                        misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
                        wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
                        c->cpuid_level = cpuid_eax(0);
+                       get_cpu_cap(c);
                }
        }
 
@@ -169,7 +170,7 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        /* calling is from identify_secondary_cpu() ? */
-       if (c->cpu_index == boot_cpu_id)
+       if (!c->cpu_index)
                return;
 
        /*
index 898c2f4eab88b28cb74719b943cad01ec06efa29..12cd823c8d038008f8abe77785b4bb475dd3cf20 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <asm/processor.h>
 #include <linux/smp.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/smp.h>
 
 #define LVL_1_INST     1
@@ -306,7 +306,7 @@ struct _cache_attr {
        ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
 };
 
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
 
 /*
  * L3 cache descriptors
@@ -369,7 +369,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
                        return;
 
        /* not in virtualized environments */
-       if (num_k8_northbridges == 0)
+       if (k8_northbridges.num == 0)
                return;
 
        /*
@@ -377,7 +377,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
         * never freed but this is done only on shutdown so it doesn't matter.
         */
        if (!l3_caches) {
-               int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+               int size = k8_northbridges.num * sizeof(struct amd_l3_cache *);
 
                l3_caches = kzalloc(size, GFP_ATOMIC);
                if (!l3_caches)
@@ -556,12 +556,12 @@ static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
 static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
                show_cache_disable_1, store_cache_disable_1);
 
-#else  /* CONFIG_CPU_SUP_AMD */
+#else  /* CONFIG_AMD_NB */
 static void __cpuinit
 amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
 {
 };
-#endif /* CONFIG_CPU_SUP_AMD */
+#endif /* CONFIG_AMD_NB */
 
 static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
@@ -1000,7 +1000,7 @@ static struct attribute *default_attrs[] = {
 
 static struct attribute *default_l3_attrs[] = {
        DEFAULT_SYSFS_CACHE_ATTRS,
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
        &cache_disable_0.attr,
        &cache_disable_1.attr,
 #endif
index 8a85dd1b1aa1d515e76b1e1cd9fdb213b27a6bcd..1e8d66c1336a177a717a3fa1a1772f0cc5bd31aa 100644 (file)
@@ -192,6 +192,7 @@ static const struct file_operations severities_coverage_fops = {
        .release        = seq_release,
        .read           = seq_read,
        .write          = severities_coverage_write,
+       .llseek         = seq_lseek,
 };
 
 static int __init severities_debugfs_init(void)
index ed41562909fe6d368f9f2c50a6c3000c6d9c9f5e..7a35b72d7c039d633bd8a4c9179eb4e4a5b7a549 100644 (file)
@@ -1665,6 +1665,7 @@ struct file_operations mce_chrdev_ops = {
        .read                   = mce_read,
        .poll                   = mce_poll,
        .unlocked_ioctl         = mce_ioctl,
+       .llseek         = no_llseek,
 };
 EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
index 224392d8fe8c095390439a10ea45af2e21bc0930..80c482382d5c95e06b71ffdf91b6f5d362bf2b45 100644 (file)
@@ -131,7 +131,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
        u32 low = 0, high = 0, address = 0;
        unsigned int bank, block;
        struct thresh_restart tr;
-       u8 lvt_off;
+       int lvt_off = -1;
+       u8 offset;
 
        for (bank = 0; bank < NR_BANKS; ++bank) {
                for (block = 0; block < NR_BLOCKS; ++block) {
@@ -141,6 +142,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                                address = (low & MASK_BLKPTR_LO) >> 21;
                                if (!address)
                                        break;
+
                                address += MCG_XBLK_ADDR;
                        } else
                                ++address;
@@ -148,12 +150,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                        if (rdmsr_safe(address, &low, &high))
                                break;
 
-                       if (!(high & MASK_VALID_HI)) {
-                               if (block)
-                                       continue;
-                               else
-                                       break;
-                       }
+                       if (!(high & MASK_VALID_HI))
+                               continue;
 
                        if (!(high & MASK_CNTP_HI)  ||
                             (high & MASK_LOCKED_HI))
@@ -165,8 +163,28 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                        if (shared_bank[bank] && c->cpu_core_id)
                                break;
 #endif
-                       lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
-                                                      APIC_EILVT_MSG_FIX, 0);
+                       offset = (high & MASK_LVTOFF_HI) >> 20;
+                       if (lvt_off < 0) {
+                               if (setup_APIC_eilvt(offset,
+                                                    THRESHOLD_APIC_VECTOR,
+                                                    APIC_EILVT_MSG_FIX, 0)) {
+                                       pr_err(FW_BUG "cpu %d, failed to "
+                                              "setup threshold interrupt "
+                                              "for bank %d, block %d "
+                                              "(MSR%08X=0x%x%08x)",
+                                              smp_processor_id(), bank, block,
+                                              address, high, low);
+                                       continue;
+                               }
+                               lvt_off = offset;
+                       } else if (lvt_off != offset) {
+                               pr_err(FW_BUG "cpu %d, invalid threshold "
+                                      "interrupt offset %d for bank %d,"
+                                      "block %d (MSR%08X=0x%x%08x)",
+                                      smp_processor_id(), lvt_off, bank,
+                                      block, address, high, low);
+                               continue;
+                       }
 
                        high &= ~MASK_LVTOFF_HI;
                        high |= lvt_off << 20;
@@ -530,7 +548,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                err = -ENOMEM;
                goto out;
        }
-       if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
+       if (!zalloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
                kfree(b);
                err = -ENOMEM;
                goto out;
@@ -543,7 +561,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 #ifndef CONFIG_SMP
        cpumask_setall(b->cpus);
 #else
-       cpumask_copy(b->cpus, c->llc_shared_map);
+       cpumask_set_cpu(cpu, b->cpus);
 #endif
 
        per_cpu(threshold_banks, cpu)[bank] = b;
index c2a8b26d4feacf4ac6b6b022c0a9c590fbbcef85..4b683267eca5fb982111375ab9e000d7eda3b437 100644 (file)
@@ -202,10 +202,11 @@ static int therm_throt_process(bool new_event, int event, int level)
 
 #ifdef CONFIG_SYSFS
 /* Add/Remove thermal_throttle interface for CPU device: */
-static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
+static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev,
+                               unsigned int cpu)
 {
        int err;
-       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
 
        err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group);
        if (err)
@@ -215,7 +216,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
                err = sysfs_add_file_to_group(&sys_dev->kobj,
                                              &attr_core_power_limit_count.attr,
                                              thermal_attr_group.name);
-       if (cpu_has(c, X86_FEATURE_PTS))
+       if (cpu_has(c, X86_FEATURE_PTS)) {
                err = sysfs_add_file_to_group(&sys_dev->kobj,
                                              &attr_package_throttle_count.attr,
                                              thermal_attr_group.name);
@@ -223,6 +224,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
                        err = sysfs_add_file_to_group(&sys_dev->kobj,
                                        &attr_package_power_limit_count.attr,
                                        thermal_attr_group.name);
+       }
 
        return err;
 }
@@ -251,7 +253,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb,
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
                mutex_lock(&therm_cpu_lock);
-               err = thermal_throttle_add_dev(sys_dev);
+               err = thermal_throttle_add_dev(sys_dev, cpu);
                mutex_unlock(&therm_cpu_lock);
                WARN_ON(err);
                break;
@@ -287,7 +289,7 @@ static __init int thermal_throttle_init_device(void)
 #endif
        /* connect live CPUs to sysfs */
        for_each_online_cpu(cpu) {
-               err = thermal_throttle_add_dev(get_cpu_sysdev(cpu));
+               err = thermal_throttle_add_dev(get_cpu_sysdev(cpu), cpu);
                WARN_ON(err);
        }
 #ifdef CONFIG_HOTPLUG_CPU
@@ -348,7 +350,7 @@ static void intel_thermal_interrupt(void)
 
 static void unexpected_thermal_interrupt(void)
 {
-       printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+       printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n",
                        smp_processor_id());
        add_taint(TAINT_MACHINE_CHECK);
 }
index c5f59d07142562e9c673572970ae79fca1e3622e..ac140c7be396b6f55c97521ddcd572df664e95b6 100644 (file)
@@ -827,7 +827,7 @@ int __init amd_special_default_mtrr(void)
 
        if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
                return 0;
-       if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+       if (boot_cpu_data.x86 < 0xf)
                return 0;
        /* In case some hypervisor doesn't pass SYSCFG through: */
        if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
index 7d28d7d03885a1d28e0785221f8e0197b89f957f..9f27228ceffd4e90da9467498e409e451187ee99 100644 (file)
@@ -64,18 +64,59 @@ static inline void k8_check_syscfg_dram_mod_en(void)
        }
 }
 
+/* Get the size of contiguous MTRR range */
+static u64 get_mtrr_size(u64 mask)
+{
+       u64 size;
+
+       mask >>= PAGE_SHIFT;
+       mask |= size_or_mask;
+       size = -mask;
+       size <<= PAGE_SHIFT;
+       return size;
+}
+
 /*
- * Returns the effective MTRR type for the region
- * Error returns:
- * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
- * - 0xFF - when MTRR is not enabled
+ * Check and return the effective type for MTRR-MTRR type overlap.
+ * Returns 1 if the effective type is UNCACHEABLE, else returns 0
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+static int check_type_overlap(u8 *prev, u8 *curr)
+{
+       if (*prev == MTRR_TYPE_UNCACHABLE || *curr == MTRR_TYPE_UNCACHABLE) {
+               *prev = MTRR_TYPE_UNCACHABLE;
+               *curr = MTRR_TYPE_UNCACHABLE;
+               return 1;
+       }
+
+       if ((*prev == MTRR_TYPE_WRBACK && *curr == MTRR_TYPE_WRTHROUGH) ||
+           (*prev == MTRR_TYPE_WRTHROUGH && *curr == MTRR_TYPE_WRBACK)) {
+               *prev = MTRR_TYPE_WRTHROUGH;
+               *curr = MTRR_TYPE_WRTHROUGH;
+       }
+
+       if (*prev != *curr) {
+               *prev = MTRR_TYPE_UNCACHABLE;
+               *curr = MTRR_TYPE_UNCACHABLE;
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Error/Semi-error returns:
+ * 0xFF - when MTRR is not enabled
+ * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
+ *             corresponds only to [start:*partial_end].
+ *             Caller has to lookup again for [*partial_end:end].
+ */
+static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 {
        int i;
        u64 base, mask;
        u8 prev_match, curr_match;
 
+       *repeat = 0;
        if (!mtrr_state_set)
                return 0xFF;
 
@@ -126,8 +167,34 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 
                start_state = ((start & mask) == (base & mask));
                end_state = ((end & mask) == (base & mask));
-               if (start_state != end_state)
-                       return 0xFE;
+
+               if (start_state != end_state) {
+                       /*
+                        * We have start:end spanning across an MTRR.
+                        * We split the region into
+                        * either
+                        * (start:mtrr_end) (mtrr_end:end)
+                        * or
+                        * (start:mtrr_start) (mtrr_start:end)
+                        * depending on kind of overlap.
+                        * Return the type for first region and a pointer to
+                        * the start of second region so that caller will
+                        * lookup again on the second region.
+                        * Note: This way we handle multiple overlaps as well.
+                        */
+                       if (start_state)
+                               *partial_end = base + get_mtrr_size(mask);
+                       else
+                               *partial_end = base;
+
+                       if (unlikely(*partial_end <= start)) {
+                               WARN_ON(1);
+                               *partial_end = start + PAGE_SIZE;
+                       }
+
+                       end = *partial_end - 1; /* end is inclusive */
+                       *repeat = 1;
+               }
 
                if ((start & mask) != (base & mask))
                        continue;
@@ -138,21 +205,8 @@ u8 mtrr_type_lookup(u64 start, u64 end)
                        continue;
                }
 
-               if (prev_match == MTRR_TYPE_UNCACHABLE ||
-                   curr_match == MTRR_TYPE_UNCACHABLE) {
-                       return MTRR_TYPE_UNCACHABLE;
-               }
-
-               if ((prev_match == MTRR_TYPE_WRBACK &&
-                    curr_match == MTRR_TYPE_WRTHROUGH) ||
-                   (prev_match == MTRR_TYPE_WRTHROUGH &&
-                    curr_match == MTRR_TYPE_WRBACK)) {
-                       prev_match = MTRR_TYPE_WRTHROUGH;
-                       curr_match = MTRR_TYPE_WRTHROUGH;
-               }
-
-               if (prev_match != curr_match)
-                       return MTRR_TYPE_UNCACHABLE;
+               if (check_type_overlap(&prev_match, &curr_match))
+                       return curr_match;
        }
 
        if (mtrr_tom2) {
@@ -166,6 +220,36 @@ u8 mtrr_type_lookup(u64 start, u64 end)
        return mtrr_state.def_type;
 }
 
+/*
+ * Returns the effective MTRR type for the region
+ * Error return:
+ * 0xFF - when MTRR is not enabled
+ */
+u8 mtrr_type_lookup(u64 start, u64 end)
+{
+       u8 type, prev_type;
+       int repeat;
+       u64 partial_end;
+
+       type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+       /*
+        * Common path is with repeat = 0.
+        * However, we can have cases where [start:end] spans across some
+        * MTRR range. Do repeated lookups for that case here.
+        */
+       while (repeat) {
+               prev_type = type;
+               start = partial_end;
+               type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+               if (check_type_overlap(&prev_type, &type))
+                       return type;
+       }
+
+       return type;
+}
+
 /* Get the MSR pair relating to a var range */
 static void
 get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
index f2da20fda02ddf6fcd449a88ba399fe4ed44af2a..fe73c1844a9a5b7c9a0c902bef0b9f993207acee 100644 (file)
@@ -102,6 +102,7 @@ struct cpu_hw_events {
         */
        struct perf_event       *events[X86_PMC_IDX_MAX]; /* in counter order */
        unsigned long           active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+       unsigned long           running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
        int                     enabled;
 
        int                     n_events;
@@ -530,7 +531,7 @@ static int x86_pmu_hw_config(struct perf_event *event)
 /*
  * Setup the hardware configuration for a given attr_type
  */
-static int __hw_perf_event_init(struct perf_event *event)
+static int __x86_pmu_event_init(struct perf_event *event)
 {
        int err;
 
@@ -583,7 +584,7 @@ static void x86_pmu_disable_all(void)
        }
 }
 
-void hw_perf_disable(void)
+static void x86_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -618,7 +619,7 @@ static void x86_pmu_enable_all(int added)
        }
 }
 
-static const struct pmu pmu;
+static struct pmu pmu;
 
 static inline int is_x86_event(struct perf_event *event)
 {
@@ -800,10 +801,10 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc,
                hwc->last_tag == cpuc->tags[i];
 }
 
-static int x86_pmu_start(struct perf_event *event);
-static void x86_pmu_stop(struct perf_event *event);
+static void x86_pmu_start(struct perf_event *event, int flags);
+static void x86_pmu_stop(struct perf_event *event, int flags);
 
-void hw_perf_enable(void)
+static void x86_pmu_enable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct perf_event *event;
@@ -839,7 +840,14 @@ void hw_perf_enable(void)
                            match_prev_assignment(hwc, cpuc, i))
                                continue;
 
-                       x86_pmu_stop(event);
+                       /*
+                        * Ensure we don't accidentally enable a stopped
+                        * counter simply because we rescheduled.
+                        */
+                       if (hwc->state & PERF_HES_STOPPED)
+                               hwc->state |= PERF_HES_ARCH;
+
+                       x86_pmu_stop(event, PERF_EF_UPDATE);
                }
 
                for (i = 0; i < cpuc->n_events; i++) {
@@ -851,7 +859,10 @@ void hw_perf_enable(void)
                        else if (i < n_running)
                                continue;
 
-                       x86_pmu_start(event);
+                       if (hwc->state & PERF_HES_ARCH)
+                               continue;
+
+                       x86_pmu_start(event, PERF_EF_RELOAD);
                }
                cpuc->n_added = 0;
                perf_events_lapic_init();
@@ -952,15 +963,12 @@ static void x86_pmu_enable_event(struct perf_event *event)
 }
 
 /*
- * activate a single event
+ * Add a single event to the PMU.
  *
  * The event is added to the group of enabled events
  * but only if it can be scehduled with existing events.
- *
- * Called with PMU disabled. If successful and return value 1,
- * then guaranteed to call perf_enable() and hw_perf_enable()
  */
-static int x86_pmu_enable(struct perf_event *event)
+static int x86_pmu_add(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc;
@@ -969,57 +977,67 @@ static int x86_pmu_enable(struct perf_event *event)
 
        hwc = &event->hw;
 
+       perf_pmu_disable(event->pmu);
        n0 = cpuc->n_events;
-       n = collect_events(cpuc, event, false);
-       if (n < 0)
-               return n;
+       ret = n = collect_events(cpuc, event, false);
+       if (ret < 0)
+               goto out;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
 
        /*
         * If group events scheduling transaction was started,
         * skip the schedulability test here, it will be peformed
-        * at commit time(->commit_txn) as a whole
+        * at commit time (->commit_txn) as a whole
         */
        if (cpuc->group_flag & PERF_EVENT_TXN)
-               goto out;
+               goto done_collect;
 
        ret = x86_pmu.schedule_events(cpuc, n, assign);
        if (ret)
-               return ret;
+               goto out;
        /*
         * copy new assignment, now we know it is possible
         * will be used by hw_perf_enable()
         */
        memcpy(cpuc->assign, assign, n*sizeof(int));
 
-out:
+done_collect:
        cpuc->n_events = n;
        cpuc->n_added += n - n0;
        cpuc->n_txn += n - n0;
 
-       return 0;
+       ret = 0;
+out:
+       perf_pmu_enable(event->pmu);
+       return ret;
 }
 
-static int x86_pmu_start(struct perf_event *event)
+static void x86_pmu_start(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int idx = event->hw.idx;
 
-       if (idx == -1)
-               return -EAGAIN;
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (WARN_ON_ONCE(idx == -1))
+               return;
+
+       if (flags & PERF_EF_RELOAD) {
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+               x86_perf_event_set_period(event);
+       }
+
+       event->hw.state = 0;
 
-       x86_perf_event_set_period(event);
        cpuc->events[idx] = event;
        __set_bit(idx, cpuc->active_mask);
+       __set_bit(idx, cpuc->running);
        x86_pmu.enable(event);
        perf_event_update_userpage(event);
-
-       return 0;
-}
-
-static void x86_pmu_unthrottle(struct perf_event *event)
-{
-       int ret = x86_pmu_start(event);
-       WARN_ON_ONCE(ret);
 }
 
 void perf_event_print_debug(void)
@@ -1076,27 +1094,29 @@ void perf_event_print_debug(void)
        local_irq_restore(flags);
 }
 
-static void x86_pmu_stop(struct perf_event *event)
+static void x86_pmu_stop(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       int idx = hwc->idx;
-
-       if (!__test_and_clear_bit(idx, cpuc->active_mask))
-               return;
-
-       x86_pmu.disable(event);
 
-       /*
-        * Drain the remaining delta count out of a event
-        * that we are disabling:
-        */
-       x86_perf_event_update(event);
+       if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
+               x86_pmu.disable(event);
+               cpuc->events[hwc->idx] = NULL;
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
 
-       cpuc->events[idx] = NULL;
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               x86_perf_event_update(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
 }
 
-static void x86_pmu_disable(struct perf_event *event)
+static void x86_pmu_del(struct perf_event *event, int flags)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int i;
@@ -1109,7 +1129,7 @@ static void x86_pmu_disable(struct perf_event *event)
        if (cpuc->group_flag & PERF_EVENT_TXN)
                return;
 
-       x86_pmu_stop(event);
+       x86_pmu_stop(event, PERF_EF_UPDATE);
 
        for (i = 0; i < cpuc->n_events; i++) {
                if (event == cpuc->event_list[i]) {
@@ -1132,7 +1152,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
        struct perf_sample_data data;
        struct cpu_hw_events *cpuc;
        struct perf_event *event;
-       struct hw_perf_event *hwc;
        int idx, handled = 0;
        u64 val;
 
@@ -1141,11 +1160,18 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
        cpuc = &__get_cpu_var(cpu_hw_events);
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               if (!test_bit(idx, cpuc->active_mask))
+               if (!test_bit(idx, cpuc->active_mask)) {
+                       /*
+                        * Though we deactivated the counter some cpus
+                        * might still deliver spurious interrupts still
+                        * in flight. Catch them:
+                        */
+                       if (__test_and_clear_bit(idx, cpuc->running))
+                               handled++;
                        continue;
+               }
 
                event = cpuc->events[idx];
-               hwc = &event->hw;
 
                val = x86_perf_event_update(event);
                if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
@@ -1154,14 +1180,14 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
                /*
                 * event overflow
                 */
-               handled         = 1;
+               handled++;
                data.period     = event->hw.last_period;
 
                if (!x86_perf_event_set_period(event))
                        continue;
 
                if (perf_event_overflow(event, 1, &data, regs))
-                       x86_pmu_stop(event);
+                       x86_pmu_stop(event, 0);
        }
 
        if (handled)
@@ -1170,25 +1196,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
        return handled;
 }
 
-void smp_perf_pending_interrupt(struct pt_regs *regs)
-{
-       irq_enter();
-       ack_APIC_irq();
-       inc_irq_stat(apic_pending_irqs);
-       perf_event_do_pending();
-       irq_exit();
-}
-
-void set_perf_event_pending(void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-       if (!x86_pmu.apic || !x86_pmu_initialized())
-               return;
-
-       apic->send_IPI_self(LOCAL_PENDING_VECTOR);
-#endif
-}
-
 void perf_events_lapic_init(void)
 {
        if (!x86_pmu.apic || !x86_pmu_initialized())
@@ -1200,12 +1207,20 @@ void perf_events_lapic_init(void)
        apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
+struct pmu_nmi_state {
+       unsigned int    marked;
+       int             handled;
+};
+
+static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi);
+
 static int __kprobes
 perf_event_nmi_handler(struct notifier_block *self,
                         unsigned long cmd, void *__args)
 {
        struct die_args *args = __args;
-       struct pt_regs *regs;
+       unsigned int this_nmi;
+       int handled;
 
        if (!atomic_read(&active_events))
                return NOTIFY_DONE;
@@ -1214,22 +1229,47 @@ perf_event_nmi_handler(struct notifier_block *self,
        case DIE_NMI:
        case DIE_NMI_IPI:
                break;
-
+       case DIE_NMIUNKNOWN:
+               this_nmi = percpu_read(irq_stat.__nmi_count);
+               if (this_nmi != __get_cpu_var(pmu_nmi).marked)
+                       /* let the kernel handle the unknown nmi */
+                       return NOTIFY_DONE;
+               /*
+                * This one is a PMU back-to-back nmi. Two events
+                * trigger 'simultaneously' raising two back-to-back
+                * NMIs. If the first NMI handles both, the latter
+                * will be empty and daze the CPU. So, we drop it to
+                * avoid false-positive 'unknown nmi' messages.
+                */
+               return NOTIFY_STOP;
        default:
                return NOTIFY_DONE;
        }
 
-       regs = args->regs;
-
        apic_write(APIC_LVTPC, APIC_DM_NMI);
-       /*
-        * Can't rely on the handled return value to say it was our NMI, two
-        * events could trigger 'simultaneously' raising two back-to-back NMIs.
-        *
-        * If the first NMI handles both, the latter will be empty and daze
-        * the CPU.
-        */
-       x86_pmu.handle_irq(regs);
+
+       handled = x86_pmu.handle_irq(args->regs);
+       if (!handled)
+               return NOTIFY_DONE;
+
+       this_nmi = percpu_read(irq_stat.__nmi_count);
+       if ((handled > 1) ||
+               /* the next nmi could be a back-to-back nmi */
+           ((__get_cpu_var(pmu_nmi).marked == this_nmi) &&
+            (__get_cpu_var(pmu_nmi).handled > 1))) {
+               /*
+                * We could have two subsequent back-to-back nmis: The
+                * first handles more than one counter, the 2nd
+                * handles only one counter and the 3rd handles no
+                * counter.
+                *
+                * This is the 2nd nmi because the previous was
+                * handling more than one counter. We will mark the
+                * next (3rd) and then drop it if unhandled.
+                */
+               __get_cpu_var(pmu_nmi).marked   = this_nmi + 1;
+               __get_cpu_var(pmu_nmi).handled  = handled;
+       }
 
        return NOTIFY_STOP;
 }
@@ -1345,7 +1385,6 @@ void __init init_hw_perf_events(void)
                x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
        }
        x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-       perf_max_events = x86_pmu.num_counters;
 
        if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
                WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
@@ -1381,6 +1420,7 @@ void __init init_hw_perf_events(void)
        pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
        pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
 
+       perf_pmu_register(&pmu);
        perf_cpu_notifier(x86_pmu_notifier);
 }
 
@@ -1394,10 +1434,11 @@ static inline void x86_pmu_read(struct perf_event *event)
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-static void x86_pmu_start_txn(const struct pmu *pmu)
+static void x86_pmu_start_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
+       perf_pmu_disable(pmu);
        cpuc->group_flag |= PERF_EVENT_TXN;
        cpuc->n_txn = 0;
 }
@@ -1407,7 +1448,7 @@ static void x86_pmu_start_txn(const struct pmu *pmu)
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-static void x86_pmu_cancel_txn(const struct pmu *pmu)
+static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -1417,6 +1458,7 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu)
         */
        cpuc->n_added -= cpuc->n_txn;
        cpuc->n_events -= cpuc->n_txn;
+       perf_pmu_enable(pmu);
 }
 
 /*
@@ -1424,7 +1466,7 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu)
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-static int x86_pmu_commit_txn(const struct pmu *pmu)
+static int x86_pmu_commit_txn(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int assign[X86_PMC_IDX_MAX];
@@ -1446,22 +1488,10 @@ static int x86_pmu_commit_txn(const struct pmu *pmu)
        memcpy(cpuc->assign, assign, n*sizeof(int));
 
        cpuc->group_flag &= ~PERF_EVENT_TXN;
-
+       perf_pmu_enable(pmu);
        return 0;
 }
 
-static const struct pmu pmu = {
-       .enable         = x86_pmu_enable,
-       .disable        = x86_pmu_disable,
-       .start          = x86_pmu_start,
-       .stop           = x86_pmu_stop,
-       .read           = x86_pmu_read,
-       .unthrottle     = x86_pmu_unthrottle,
-       .start_txn      = x86_pmu_start_txn,
-       .cancel_txn     = x86_pmu_cancel_txn,
-       .commit_txn     = x86_pmu_commit_txn,
-};
-
 /*
  * validate that we can schedule this event
  */
@@ -1536,12 +1566,22 @@ out:
        return ret;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+int x86_pmu_event_init(struct perf_event *event)
 {
-       const struct pmu *tmp;
+       struct pmu *tmp;
        int err;
 
-       err = __hw_perf_event_init(event);
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+       case PERF_TYPE_HARDWARE:
+       case PERF_TYPE_HW_CACHE:
+               break;
+
+       default:
+               return -ENOENT;
+       }
+
+       err = __x86_pmu_event_init(event);
        if (!err) {
                /*
                 * we temporarily connect event to its pmu
@@ -1561,26 +1601,31 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
        if (err) {
                if (event->destroy)
                        event->destroy(event);
-               return ERR_PTR(err);
        }
 
-       return &pmu;
+       return err;
 }
 
-/*
- * callchain support
- */
+static struct pmu pmu = {
+       .pmu_enable     = x86_pmu_enable,
+       .pmu_disable    = x86_pmu_disable,
 
-static inline
-void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-       if (entry->nr < PERF_MAX_STACK_DEPTH)
-               entry->ip[entry->nr++] = ip;
-}
+       .event_init     = x86_pmu_event_init,
 
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry);
+       .add            = x86_pmu_add,
+       .del            = x86_pmu_del,
+       .start          = x86_pmu_start,
+       .stop           = x86_pmu_stop,
+       .read           = x86_pmu_read,
 
+       .start_txn      = x86_pmu_start_txn,
+       .cancel_txn     = x86_pmu_cancel_txn,
+       .commit_txn     = x86_pmu_commit_txn,
+};
+
+/*
+ * callchain support
+ */
 
 static void
 backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
@@ -1602,7 +1647,7 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
 {
        struct perf_callchain_entry *entry = data;
 
-       callchain_store(entry, addr);
+       perf_callchain_store(entry, addr);
 }
 
 static const struct stacktrace_ops backtrace_ops = {
@@ -1613,11 +1658,15 @@ static const struct stacktrace_ops backtrace_ops = {
        .walk_stack             = print_context_stack_bp,
 };
 
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-       callchain_store(entry, PERF_CONTEXT_KERNEL);
-       callchain_store(entry, regs->ip);
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* TODO: We don't support guest os callchain now */
+               return;
+       }
+
+       perf_callchain_store(entry, regs->ip);
 
        dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
 }
@@ -1646,7 +1695,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
                if (fp < compat_ptr(regs->sp))
                        break;
 
-               callchain_store(entry, frame.return_address);
+               perf_callchain_store(entry, frame.return_address);
                fp = compat_ptr(frame.next_frame);
        }
        return 1;
@@ -1659,19 +1708,20 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
 }
 #endif
 
-static void
-perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        struct stack_frame frame;
        const void __user *fp;
 
-       if (!user_mode(regs))
-               regs = task_pt_regs(current);
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* TODO: We don't support guest os callchain now */
+               return;
+       }
 
        fp = (void __user *)regs->bp;
 
-       callchain_store(entry, PERF_CONTEXT_USER);
-       callchain_store(entry, regs->ip);
+       perf_callchain_store(entry, regs->ip);
 
        if (perf_callchain_user32(regs, entry))
                return;
@@ -1688,52 +1738,11 @@ perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
                if ((unsigned long)fp < regs->sp)
                        break;
 
-               callchain_store(entry, frame.return_address);
+               perf_callchain_store(entry, frame.return_address);
                fp = frame.next_frame;
        }
 }
 
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-       int is_user;
-
-       if (!regs)
-               return;
-
-       is_user = user_mode(regs);
-
-       if (is_user && current->state != TASK_RUNNING)
-               return;
-
-       if (!is_user)
-               perf_callchain_kernel(regs, entry);
-
-       if (current->mm)
-               perf_callchain_user(regs, entry);
-}
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-       struct perf_callchain_entry *entry;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               /* TODO: We don't support guest os callchain now */
-               return NULL;
-       }
-
-       if (in_nmi())
-               entry = &__get_cpu_var(pmc_nmi_entry);
-       else
-               entry = &__get_cpu_var(pmc_irq_entry);
-
-       entry->nr = 0;
-
-       perf_do_callchain(regs, entry);
-
-       return entry;
-}
-
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
        unsigned long ip;
index c2897b7b4a3b1c7a6cfe4fe7e70b3d7378432d4c..46d58448c3aff9039fdf0b909d069d00d80ef75e 100644 (file)
@@ -52,7 +52,7 @@ static __initconst const u64 amd_hw_cache_event_ids
  [ C(DTLB) ] = {
        [ C(OP_READ) ] = {
                [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-               [ C(RESULT_MISS)   ] = 0x0046, /* L1 DTLB and L2 DLTB Miss   */
+               [ C(RESULT_MISS)   ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */
        },
        [ C(OP_WRITE) ] = {
                [ C(RESULT_ACCESS) ] = 0,
@@ -66,7 +66,7 @@ static __initconst const u64 amd_hw_cache_event_ids
  [ C(ITLB) ] = {
        [ C(OP_READ) ] = {
                [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes        */
-               [ C(RESULT_MISS)   ] = 0x0085, /* Instr. fetch ITLB misses   */
+               [ C(RESULT_MISS)   ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */
        },
        [ C(OP_WRITE) ] = {
                [ C(RESULT_ACCESS) ] = -1,
index d8d86d01400866c6320001fb715301276747cd52..c8f5c088cad11ae3f245e1e7374bb43c915170d6 100644 (file)
@@ -712,22 +712,24 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
        struct perf_sample_data data;
        struct cpu_hw_events *cpuc;
        int bit, loops;
-       u64 ack, status;
+       u64 status;
+       int handled;
 
        perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
        intel_pmu_disable_all();
-       intel_pmu_drain_bts_buffer();
+       handled = intel_pmu_drain_bts_buffer();
        status = intel_pmu_get_status();
        if (!status) {
                intel_pmu_enable_all(0);
-               return 0;
+               return handled;
        }
 
        loops = 0;
 again:
+       intel_pmu_ack_status(status);
        if (++loops > 100) {
                WARN_ONCE(1, "perfevents: irq loop stuck!\n");
                perf_event_print_debug();
@@ -736,19 +738,22 @@ again:
        }
 
        inc_irq_stat(apic_perf_irqs);
-       ack = status;
 
        intel_pmu_lbr_read();
 
        /*
         * PEBS overflow sets bit 62 in the global status register
         */
-       if (__test_and_clear_bit(62, (unsigned long *)&status))
+       if (__test_and_clear_bit(62, (unsigned long *)&status)) {
+               handled++;
                x86_pmu.drain_pebs(regs);
+       }
 
        for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
                struct perf_event *event = cpuc->events[bit];
 
+               handled++;
+
                if (!test_bit(bit, cpuc->active_mask))
                        continue;
 
@@ -758,11 +763,9 @@ again:
                data.period = event->hw.last_period;
 
                if (perf_event_overflow(event, 1, &data, regs))
-                       x86_pmu_stop(event);
+                       x86_pmu_stop(event, 0);
        }
 
-       intel_pmu_ack_status(ack);
-
        /*
         * Repeat if there is more work to be done:
         */
@@ -772,7 +775,7 @@ again:
 
 done:
        intel_pmu_enable_all(0);
-       return 1;
+       return handled;
 }
 
 static struct event_constraint *
index 18018d1311cdf3fa7f550b2fd7894c278505afe6..4977f9c400e5738cb668efc937c69cde22a2772d 100644 (file)
@@ -214,7 +214,7 @@ static void intel_pmu_disable_bts(void)
        update_debugctlmsr(debugctlmsr);
 }
 
-static void intel_pmu_drain_bts_buffer(void)
+static int intel_pmu_drain_bts_buffer(void)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct debug_store *ds = cpuc->ds;
@@ -231,16 +231,16 @@ static void intel_pmu_drain_bts_buffer(void)
        struct pt_regs regs;
 
        if (!event)
-               return;
+               return 0;
 
        if (!ds)
-               return;
+               return 0;
 
        at  = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
        top = (struct bts_record *)(unsigned long)ds->bts_index;
 
        if (top <= at)
-               return;
+               return 0;
 
        ds->bts_index = ds->bts_buffer_base;
 
@@ -256,7 +256,7 @@ static void intel_pmu_drain_bts_buffer(void)
        perf_prepare_sample(&header, &data, event, &regs);
 
        if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1))
-               return;
+               return 1;
 
        for (; at < top; at++) {
                data.ip         = at->from;
@@ -270,6 +270,7 @@ static void intel_pmu_drain_bts_buffer(void)
        /* There's new data available. */
        event->hw.interrupts++;
        event->pending_kill = POLL_IN;
+       return 1;
 }
 
 /*
@@ -491,7 +492,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
                regs.flags &= ~PERF_EFLAGS_EXACT;
 
        if (perf_event_overflow(event, 1, &data, &regs))
-               x86_pmu_stop(event);
+               x86_pmu_stop(event, 0);
 }
 
 static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
index febb12cea795268f224a9d39937e3f27bb86bf67..81400b93e69483e18bedf1c541753e2f915910cd 100644 (file)
@@ -18,6 +18,8 @@
 struct p4_event_bind {
        unsigned int opcode;                    /* Event code and ESCR selector */
        unsigned int escr_msr[2];               /* ESCR MSR for this event */
+       unsigned int escr_emask;                /* valid ESCR EventMask bits */
+       unsigned int shared;                    /* event is shared across threads */
        char cntr[2][P4_CNTR_LIMIT];            /* counter index (offset), -1 on abscence */
 };
 
@@ -66,231 +68,435 @@ static struct p4_event_bind p4_event_bind_map[] = {
        [P4_EVENT_TC_DELIVER_MODE] = {
                .opcode         = P4_OPCODE(P4_EVENT_TC_DELIVER_MODE),
                .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DB)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DI)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BD)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BB)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BI)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, ID),
+               .shared         = 1,
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_BPU_FETCH_REQUEST] = {
                .opcode         = P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST),
                .escr_msr       = { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BPU_FETCH_REQUEST, TCMISS),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_ITLB_REFERENCE] = {
                .opcode         = P4_OPCODE(P4_EVENT_ITLB_REFERENCE),
                .escr_msr       = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, MISS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT_UK),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_MEMORY_CANCEL] = {
                .opcode         = P4_OPCODE(P4_EVENT_MEMORY_CANCEL),
                .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, 64K_CONF),
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_MEMORY_COMPLETE] = {
                .opcode         = P4_OPCODE(P4_EVENT_MEMORY_COMPLETE),
                .escr_msr       = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, LSC)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, SSC),
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_LOAD_PORT_REPLAY] = {
                .opcode         = P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY),
                .escr_msr       = { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD),
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_STORE_PORT_REPLAY] = {
                .opcode         = P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY),
                .escr_msr       = { MSR_P4_SAAT_ESCR0 ,  MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST),
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_MOB_LOAD_REPLAY] = {
                .opcode         = P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY),
                .escr_msr       = { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STA)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STD)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_PAGE_WALK_TYPE] = {
                .opcode         = P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE),
                .escr_msr       = { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, DTMISS)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, ITMISS),
+               .shared         = 1,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_BSQ_CACHE_REFERENCE] = {
                .opcode         = P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE),
                .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_IOQ_ALLOCATION] = {
                .opcode         = P4_OPCODE(P4_EVENT_IOQ_ALLOCATION),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, DEFAULT)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_READ)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_UC)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WC)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WT)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WP)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WB)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OWN)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OTHER)               |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, PREFETCH),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_IOQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
                .opcode         = P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES),
                .escr_msr       = { MSR_P4_FSB_ESCR1,  MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH),
                .cntr           = { {2, -1, -1}, {3, -1, -1} },
        },
        [P4_EVENT_FSB_DATA_ACTIVITY] = {
                .opcode         = P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER),
+               .shared         = 1,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_BSQ_ALLOCATION] = {           /* shared ESCR, broken CCCR1 */
                .opcode         = P4_OPCODE(P4_EVENT_BSQ_ALLOCATION),
                .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE)      |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE)      |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2),
                .cntr           = { {0, -1, -1}, {1, -1, -1} },
        },
        [P4_EVENT_BSQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
                .opcode         = P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES),
                .escr_msr       = { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE)     |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE)  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE)  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2),
                .cntr           = { {2, -1, -1}, {3, -1, -1} },
        },
        [P4_EVENT_SSE_INPUT_ASSIST] = {
                .opcode         = P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SSE_INPUT_ASSIST, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_PACKED_SP_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_PACKED_SP_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_SP_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_PACKED_DP_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_PACKED_DP_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_DP_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_SCALAR_SP_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_SCALAR_SP_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_SP_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_SCALAR_DP_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_SCALAR_DP_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_DP_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_64BIT_MMX_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_64BIT_MMX_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_64BIT_MMX_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_128BIT_MMX_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_128BIT_MMX_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_128BIT_MMX_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_X87_FP_UOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_X87_FP_UOP),
                .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_FP_UOP, ALL),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_TC_MISC] = {
                .opcode         = P4_OPCODE(P4_EVENT_TC_MISC),
                .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MISC, FLUSH),
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_GLOBAL_POWER_EVENTS] = {
                .opcode         = P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING),
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_TC_MS_XFER] = {
                .opcode         = P4_OPCODE(P4_EVENT_TC_MS_XFER),
                .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MS_XFER, CISC),
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_UOP_QUEUE_WRITES] = {
                .opcode         = P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES),
                .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD)     |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM),
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = {
                .opcode         = P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE),
                .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT),
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_RETIRED_BRANCH_TYPE] = {
                .opcode         = P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE),
                .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT),
                .cntr           = { {4, 5, -1}, {6, 7, -1} },
        },
        [P4_EVENT_RESOURCE_STALL] = {
                .opcode         = P4_OPCODE(P4_EVENT_RESOURCE_STALL),
                .escr_msr       = { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RESOURCE_STALL, SBFULL),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_WC_BUFFER] = {
                .opcode         = P4_OPCODE(P4_EVENT_WC_BUFFER),
                .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_EVICTS)               |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS),
+               .shared         = 1,
                .cntr           = { {8, 9, -1}, {10, 11, -1} },
        },
        [P4_EVENT_B2B_CYCLES] = {
                .opcode         = P4_OPCODE(P4_EVENT_B2B_CYCLES),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_BNR] = {
                .opcode         = P4_OPCODE(P4_EVENT_BNR),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_SNOOP] = {
                .opcode         = P4_OPCODE(P4_EVENT_SNOOP),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_RESPONSE] = {
                .opcode         = P4_OPCODE(P4_EVENT_RESPONSE),
                .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
                .cntr           = { {0, -1, -1}, {2, -1, -1} },
        },
        [P4_EVENT_FRONT_END_EVENT] = {
                .opcode         = P4_OPCODE(P4_EVENT_FRONT_END_EVENT),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, NBOGUS)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, BOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_EXECUTION_EVENT] = {
                .opcode         = P4_OPCODE(P4_EVENT_EXECUTION_EVENT),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_REPLAY_EVENT] = {
                .opcode         = P4_OPCODE(P4_EVENT_REPLAY_EVENT),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, NBOGUS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, BOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_INSTR_RETIRED] = {
                .opcode         = P4_OPCODE(P4_EVENT_INSTR_RETIRED),
                .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSTAG)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSTAG),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_UOPS_RETIRED] = {
                .opcode         = P4_OPCODE(P4_EVENT_UOPS_RETIRED),
                .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, NBOGUS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, BOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_UOP_TYPE] = {
                .opcode         = P4_OPCODE(P4_EVENT_UOP_TYPE),
                .escr_msr       = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGLOADS)                  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGSTORES),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_BRANCH_RETIRED] = {
                .opcode         = P4_OPCODE(P4_EVENT_BRANCH_RETIRED),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNP)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNM)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTP)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTM),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_MISPRED_BRANCH_RETIRED] = {
                .opcode         = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
                .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+               P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_X87_ASSIST] = {
                .opcode         = P4_OPCODE(P4_EVENT_X87_ASSIST),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSU)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSO)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAO)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAU)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, PREA),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_MACHINE_CLEAR] = {
                .opcode         = P4_OPCODE(P4_EVENT_MACHINE_CLEAR),
                .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, CLEAR)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, MOCLEAR)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, SMCLEAR),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
        [P4_EVENT_INSTR_COMPLETED] = {
                .opcode         = P4_OPCODE(P4_EVENT_INSTR_COMPLETED),
                .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, NBOGUS)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, BOGUS),
                .cntr           = { {12, 13, 16}, {14, 15, 17} },
        },
 };
@@ -428,29 +634,73 @@ static u64 p4_pmu_event_map(int hw_event)
        return config;
 }
 
+/* check cpu model specifics */
+static bool p4_event_match_cpu_model(unsigned int event_idx)
+{
+       /* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */
+       if (event_idx == P4_EVENT_INSTR_COMPLETED) {
+               if (boot_cpu_data.x86_model != 3 &&
+                       boot_cpu_data.x86_model != 4 &&
+                       boot_cpu_data.x86_model != 6)
+                       return false;
+       }
+
+       /*
+        * For info
+        * - IQ_ESCR0, IQ_ESCR1 only for models 1 and 2
+        */
+
+       return true;
+}
+
 static int p4_validate_raw_event(struct perf_event *event)
 {
-       unsigned int v;
+       unsigned int v, emask;
 
-       /* user data may have out-of-bound event index */
+       /* User data may have out-of-bound event index */
        v = p4_config_unpack_event(event->attr.config);
-       if (v >= ARRAY_SIZE(p4_event_bind_map)) {
-               pr_warning("P4 PMU: Unknown event code: %d\n", v);
+       if (v >= ARRAY_SIZE(p4_event_bind_map))
+               return -EINVAL;
+
+       /* It may be unsupported: */
+       if (!p4_event_match_cpu_model(v))
                return -EINVAL;
+
+       /*
+        * NOTE: P4_CCCR_THREAD_ANY has not the same meaning as
+        * in Architectural Performance Monitoring, it means not
+        * on _which_ logical cpu to count but rather _when_, ie it
+        * depends on logical cpu state -- count event if one cpu active,
+        * none, both or any, so we just allow user to pass any value
+        * desired.
+        *
+        * In turn we always set Tx_OS/Tx_USR bits bound to logical
+        * cpu without their propagation to another cpu
+        */
+
+       /*
+        * if an event is shared accross the logical threads
+        * the user needs special permissions to be able to use it
+        */
+       if (p4_event_bind_map[v].shared) {
+               if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+                       return -EACCES;
        }
 
+       /* ESCR EventMask bits may be invalid */
+       emask = p4_config_unpack_escr(event->attr.config) & P4_ESCR_EVENTMASK_MASK;
+       if (emask & ~p4_event_bind_map[v].escr_emask)
+               return -EINVAL;
+
        /*
-        * it may have some screwed PEBS bits
+        * it may have some invalid PEBS bits
         */
-       if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE)) {
-               pr_warning("P4 PMU: PEBS are not supported yet\n");
+       if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE))
                return -EINVAL;
-       }
+
        v = p4_config_unpack_metric(event->attr.config);
-       if (v >= ARRAY_SIZE(p4_pebs_bind_map)) {
-               pr_warning("P4 PMU: Unknown metric code: %d\n", v);
+       if (v >= ARRAY_SIZE(p4_pebs_bind_map))
                return -EINVAL;
-       }
 
        return 0;
 }
@@ -478,25 +728,21 @@ static int p4_hw_config(struct perf_event *event)
 
        if (event->attr.type == PERF_TYPE_RAW) {
 
+               /*
+                * Clear bits we reserve to be managed by kernel itself
+                * and never allowed from a user space
+                */
+                event->attr.config &= P4_CONFIG_MASK;
+
                rc = p4_validate_raw_event(event);
                if (rc)
                        goto out;
 
                /*
-                * We don't control raw events so it's up to the caller
-                * to pass sane values (and we don't count the thread number
-                * on HT machine but allow HT-compatible specifics to be
-                * passed on)
-                *
                 * Note that for RAW events we allow user to use P4_CCCR_RESERVED
                 * bits since we keep additional info here (for cache events and etc)
-                *
-                * XXX: HT wide things should check perf_paranoid_cpu() &&
-                *      CAP_SYS_ADMIN
                 */
-               event->hw.config |= event->attr.config &
-                       (p4_config_pack_escr(P4_ESCR_MASK_HT) |
-                        p4_config_pack_cccr(P4_CCCR_MASK_HT | P4_CCCR_RESERVED));
+               event->hw.config |= event->attr.config;
        }
 
        rc = x86_setup_perfctr(event);
@@ -658,8 +904,12 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
                int overflow;
 
-               if (!test_bit(idx, cpuc->active_mask))
+               if (!test_bit(idx, cpuc->active_mask)) {
+                       /* catch in-flight IRQs */
+                       if (__test_and_clear_bit(idx, cpuc->running))
+                               handled++;
                        continue;
+               }
 
                event = cpuc->events[idx];
                hwc = &event->hw;
@@ -690,7 +940,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
                inc_irq_stat(apic_perf_irqs);
        }
 
-       return handled > 0;
+       return handled;
 }
 
 /*
index fb329e9f849443315e19c8db38c01161f5edf73b..d9f4ff8fcd693c509b2d079b381a8e8683d10d9c 100644 (file)
@@ -700,11 +700,10 @@ static void probe_nmi_watchdog(void)
 {
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
-               if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
-                   boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17)
-                       return;
-               wd_ops = &k7_wd_ops;
-               break;
+               if (boot_cpu_data.x86 == 6 ||
+                   (boot_cpu_data.x86 >= 0xf && boot_cpu_data.x86 <= 0x15))
+                       wd_ops = &k7_wd_ops;
+               return;
        case X86_VENDOR_INTEL:
                /* Work around where perfctr1 doesn't have a working enable
                 * bit as described in the following errata:
index 34b4dad6f0b8e35a0fe80d01f8708c230592144d..c7f64e6f537a8dc5195e6d37082b205d6df5cfbd 100644 (file)
@@ -31,6 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
        const struct cpuid_bit *cb;
 
        static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
+               { X86_FEATURE_DTS,              CR_EAX, 0, 0x00000006, 0 },
                { X86_FEATURE_IDA,              CR_EAX, 1, 0x00000006, 0 },
                { X86_FEATURE_ARAT,             CR_EAX, 2, 0x00000006, 0 },
                { X86_FEATURE_PLN,              CR_EAX, 4, 0x00000006, 0 },
@@ -43,6 +44,12 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
                { X86_FEATURE_LBRV,             CR_EDX, 1, 0x8000000a, 0 },
                { X86_FEATURE_SVML,             CR_EDX, 2, 0x8000000a, 0 },
                { X86_FEATURE_NRIPS,            CR_EDX, 3, 0x8000000a, 0 },
+               { X86_FEATURE_TSCRATEMSR,       CR_EDX, 4, 0x8000000a, 0 },
+               { X86_FEATURE_VMCBCLEAN,        CR_EDX, 5, 0x8000000a, 0 },
+               { X86_FEATURE_FLUSHBYASID,      CR_EDX, 6, 0x8000000a, 0 },
+               { X86_FEATURE_DECODEASSISTS,    CR_EDX, 7, 0x8000000a, 0 },
+               { X86_FEATURE_PAUSEFILTER,      CR_EDX,10, 0x8000000a, 0 },
+               { X86_FEATURE_PFTHRESHOLD,      CR_EDX,12, 0x8000000a, 0 },
                { 0, 0, 0, 0, 0 }
        };
 
index 045b36cada655370382231cb186d45d5d8820d95..994828899e098350d12ca73217235af843b0d497 100644 (file)
@@ -34,7 +34,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
        if (!csize)
                return 0;
 
-       vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+       vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
        if (!vaddr)
                return -ENOMEM;
 
@@ -46,6 +46,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
        } else
                memcpy(buf, vaddr + offset, csize);
 
+       set_iounmap_nonlazy();
        iounmap(vaddr);
        return csize;
 }
index 0d6fc71bedb152802401b49eb801696cb5ee460d..0c2b7ef7a34d5453d510ba3a598e5b15c2af6b53 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/firmware-map.h>
+#include <linux/memblock.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -738,73 +739,7 @@ core_initcall(e820_mark_nvs_memory);
 #endif
 
 /*
- * Find a free area with specified alignment in a specific range.
- */
-u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
-{
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i];
-               u64 addr;
-               u64 ei_start, ei_last;
-
-               if (ei->type != E820_RAM)
-                       continue;
-
-               ei_last = ei->addr + ei->size;
-               ei_start = ei->addr;
-               addr = find_early_area(ei_start, ei_last, start, end,
-                                        size, align);
-
-               if (addr != -1ULL)
-                       return addr;
-       }
-       return -1ULL;
-}
-
-u64 __init find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align)
-{
-       return find_e820_area(start, end, size, align);
-}
-
-u64 __init get_max_mapped(void)
-{
-       u64 end = max_pfn_mapped;
-
-       end <<= PAGE_SHIFT;
-
-       return end;
-}
-/*
- * Find next free range after *start
- */
-u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
-{
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i];
-               u64 addr;
-               u64 ei_start, ei_last;
-
-               if (ei->type != E820_RAM)
-                       continue;
-
-               ei_last = ei->addr + ei->size;
-               ei_start = ei->addr;
-               addr = find_early_area_size(ei_start, ei_last, start,
-                                        sizep, align);
-
-               if (addr != -1ULL)
-                       return addr;
-       }
-
-       return -1ULL;
-}
-
-/*
- * pre allocated 4k and reserved it in e820
+ * pre allocated 4k and reserved it in memblock and e820_saved
  */
 u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
 {
@@ -813,8 +748,8 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
        u64 start;
 
        for (start = startt; ; start += size) {
-               start = find_e820_area_size(start, &size, align);
-               if (!(start + 1))
+               start = memblock_x86_find_in_range_size(start, &size, align);
+               if (start == MEMBLOCK_ERROR)
                        return 0;
                if (size >= sizet)
                        break;
@@ -830,10 +765,9 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
        addr = round_down(start + size - sizet, align);
        if (addr < start)
                return 0;
-       e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
+       memblock_x86_reserve_range(addr, addr + sizet, "new next");
        e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
-       printk(KERN_INFO "update e820 for early_reserve_e820\n");
-       update_e820();
+       printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
        update_e820_saved();
 
        return addr;
@@ -895,74 +829,6 @@ unsigned long __init e820_end_of_low_ram_pfn(void)
 {
        return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
 }
-/*
- * Finds an active region in the address range from start_pfn to last_pfn and
- * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
- */
-int __init e820_find_active_region(const struct e820entry *ei,
-                                 unsigned long start_pfn,
-                                 unsigned long last_pfn,
-                                 unsigned long *ei_startpfn,
-                                 unsigned long *ei_endpfn)
-{
-       u64 align = PAGE_SIZE;
-
-       *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
-       *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
-
-       /* Skip map entries smaller than a page */
-       if (*ei_startpfn >= *ei_endpfn)
-               return 0;
-
-       /* Skip if map is outside the node */
-       if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
-                                   *ei_startpfn >= last_pfn)
-               return 0;
-
-       /* Check for overlaps */
-       if (*ei_startpfn < start_pfn)
-               *ei_startpfn = start_pfn;
-       if (*ei_endpfn > last_pfn)
-               *ei_endpfn = last_pfn;
-
-       return 1;
-}
-
-/* Walk the e820 map and register active regions within a node */
-void __init e820_register_active_regions(int nid, unsigned long start_pfn,
-                                        unsigned long last_pfn)
-{
-       unsigned long ei_startpfn;
-       unsigned long ei_endpfn;
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++)
-               if (e820_find_active_region(&e820.map[i],
-                                           start_pfn, last_pfn,
-                                           &ei_startpfn, &ei_endpfn))
-                       add_active_range(nid, ei_startpfn, ei_endpfn);
-}
-
-/*
- * Find the hole size (in bytes) in the memory range.
- * @start: starting address of the memory range to scan
- * @end: ending address of the memory range to scan
- */
-u64 __init e820_hole_size(u64 start, u64 end)
-{
-       unsigned long start_pfn = start >> PAGE_SHIFT;
-       unsigned long last_pfn = end >> PAGE_SHIFT;
-       unsigned long ei_startpfn, ei_endpfn, ram = 0;
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               if (e820_find_active_region(&e820.map[i],
-                                           start_pfn, last_pfn,
-                                           &ei_startpfn, &ei_endpfn))
-                       ram += ei_endpfn - ei_startpfn;
-       }
-       return end - start - ((u64)ram << PAGE_SHIFT);
-}
 
 static void early_panic(char *msg)
 {
@@ -1210,3 +1076,48 @@ void __init setup_memory_map(void)
        printk(KERN_INFO "BIOS-provided physical RAM map:\n");
        e820_print_map(who);
 }
+
+void __init memblock_x86_fill(void)
+{
+       int i;
+       u64 end;
+
+       /*
+        * EFI may have more than 128 entries
+        * We are safe to enable resizing, beause memblock_x86_fill()
+        * is rather later for x86
+        */
+       memblock_can_resize = 1;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+
+               end = ei->addr + ei->size;
+               if (end != (resource_size_t)end)
+                       continue;
+
+               if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
+                       continue;
+
+               memblock_add(ei->addr, ei->size);
+       }
+
+       memblock_analyze();
+       memblock_dump_all();
+}
+
+void __init memblock_find_dma_reserve(void)
+{
+#ifdef CONFIG_X86_64
+       u64 free_size_pfn;
+       u64 mem_size_pfn;
+       /*
+        * need to find out used area below MAX_DMA_PFN
+        * need to use memblock to get free size in [0, MAX_DMA_PFN]
+        * at first, and assume boot_mem will not take below MAX_DMA_PFN
+        */
+       mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+       free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+       set_dma_reserve(mem_size_pfn - free_size_pfn);
+#endif
+}
index e5cc7e82e60ddbf1bd1ca2871fdb7d7fc7628e34..76b8cd953deed9f8a50d572cdc52b5edb68bc3b7 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/apic.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
-#include <asm/hpet.h>
 
 static void __init fix_hypertransport_config(int num, int slot, int func)
 {
@@ -97,7 +96,6 @@ static void __init nvidia_bugs(int num, int slot, int func)
 
 }
 
-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
 #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
 static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
 {
@@ -116,7 +114,6 @@ static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
        d &= 0xff;
        return d;
 }
-#endif
 
 static void __init ati_bugs(int num, int slot, int func)
 {
@@ -192,21 +189,6 @@ static void __init ati_bugs_contd(int num, int slot, int func)
 }
 #endif
 
-/*
- * Force the read back of the CMP register in hpet_next_event()
- * to work around the problem that the CMP register write seems to be
- * delayed. See hpet_next_event() for details.
- *
- * We do this on all SMBUS incarnations for now until we have more
- * information about the affected chipsets.
- */
-static void __init ati_hpet_bugs(int num, int slot, int func)
-{
-#ifdef CONFIG_HPET_TIMER
-       hpet_readback_cmp = 1;
-#endif
-}
-
 #define QFLAG_APPLY_ONCE       0x1
 #define QFLAG_APPLIED          0x2
 #define QFLAG_DONE             (QFLAG_APPLY_ONCE|QFLAG_APPLIED)
@@ -236,8 +218,6 @@ static struct chipset early_qrk[] __initdata = {
          PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs },
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
          PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd },
-       { PCI_VENDOR_ID_ATI, PCI_ANY_ID,
-         PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_hpet_bugs },
        {}
 };
 
index fa99bae75acee4d1efb12b141a24d97019e03b5f..4572f25f93255f8bb4a5e5158d3c9949f912b657 100644 (file)
@@ -14,6 +14,7 @@
 #include <xen/hvc-console.h>
 #include <asm/pci-direct.h>
 #include <asm/fixmap.h>
+#include <asm/mrst.h>
 #include <asm/pgtable.h>
 #include <linux/usb/ehci_def.h>
 
@@ -238,6 +239,18 @@ static int __init setup_early_printk(char *buf)
 #ifdef CONFIG_HVC_XEN
                if (!strncmp(buf, "xen", 3))
                        early_console_register(&xenboot_console, keep);
+#endif
+#ifdef CONFIG_X86_MRST_EARLY_PRINTK
+               if (!strncmp(buf, "mrst", 4)) {
+                       mrst_early_console_init();
+                       early_console_register(&early_mrst_console, keep);
+               }
+
+               if (!strncmp(buf, "hsu", 3)) {
+                       hsu_early_console_init();
+                       early_console_register(&early_hsu_console, keep);
+               }
+
 #endif
                buf++;
        }
diff --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/kernel/early_printk_mrst.c
new file mode 100644 (file)
index 0000000..65df603
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * early_printk_mrst.c - early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2010, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * This file implements two early consoles named mrst and hsu.
+ * mrst is based on Maxim3110 spi-uart device, it exists in both
+ * Moorestown and Medfield platforms, while hsu is based on a High
+ * Speed UART device which only exists in the Medfield platform
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kmsg_dump.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/mrst.h>
+
+#define MRST_SPI_TIMEOUT               0x200000
+#define MRST_REGBASE_SPI0              0xff128000
+#define MRST_REGBASE_SPI1              0xff128400
+#define MRST_CLK_SPI0_REG              0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET                 0
+
+#define SPI_FRF_OFFSET                 4
+#define SPI_FRF_SPI                    0x0
+#define SPI_FRF_SSP                    0x1
+#define SPI_FRF_MICROWIRE              0x2
+#define SPI_FRF_RESV                   0x3
+
+#define SPI_MODE_OFFSET                        6
+#define SPI_SCPH_OFFSET                        6
+#define SPI_SCOL_OFFSET                        7
+#define SPI_TMOD_OFFSET                        8
+#define        SPI_TMOD_TR                     0x0             /* xmit & recv */
+#define SPI_TMOD_TO                    0x1             /* xmit only */
+#define SPI_TMOD_RO                    0x2             /* recv only */
+#define SPI_TMOD_EPROMREAD             0x3             /* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET               10
+#define SPI_SRL_OFFSET                 11
+#define SPI_CFS_OFFSET                 12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK                                0x7f            /* cover 7 bits */
+#define SR_BUSY                                (1 << 0)
+#define SR_TF_NOT_FULL                 (1 << 1)
+#define SR_TF_EMPT                     (1 << 2)
+#define SR_RF_NOT_EMPT                 (1 << 3)
+#define SR_RF_FULL                     (1 << 4)
+#define SR_TX_ERR                      (1 << 5)
+#define SR_DCOL                                (1 << 6)
+
+struct dw_spi_reg {
+       u32     ctrl0;
+       u32     ctrl1;
+       u32     ssienr;
+       u32     mwcr;
+       u32     ser;
+       u32     baudr;
+       u32     txfltr;
+       u32     rxfltr;
+       u32     txflr;
+       u32     rxflr;
+       u32     sr;
+       u32     imr;
+       u32     isr;
+       u32     risr;
+       u32     txoicr;
+       u32     rxoicr;
+       u32     rxuicr;
+       u32     msticr;
+       u32     icr;
+       u32     dmacr;
+       u32     dmatdlr;
+       u32     dmardlr;
+       u32     idr;
+       u32     version;
+
+       /* Currently operates as 32 bits, though only the low 16 bits matter */
+       u32     dr;
+} __packed;
+
+#define dw_readl(dw, name)             __raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)       __raw_writel((val), &(dw)->name)
+
+/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
+static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
+
+static u32 *pclk_spi0;
+/* Always contains an accessable address, start with 0 */
+static struct dw_spi_reg *pspi;
+
+static struct kmsg_dumper dw_dumper;
+static int dumper_registered;
+
+static void dw_kmsg_dump(struct kmsg_dumper *dumper,
+                       enum kmsg_dump_reason reason,
+                       const char *s1, unsigned long l1,
+                       const char *s2, unsigned long l2)
+{
+       int i;
+
+       /* When run to this, we'd better re-init the HW */
+       mrst_early_console_init();
+
+       for (i = 0; i < l1; i++)
+               early_mrst_console.write(&early_mrst_console, s1 + i, 1);
+       for (i = 0; i < l2; i++)
+               early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+       u16 config;
+
+       config = 0xc001;
+       dw_writel(pspi, dr, config);
+}
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+       u16 data;
+
+       data = 0x8000 | c;
+       dw_writel(pspi, dr, data);
+}
+
+void mrst_early_console_init(void)
+{
+       u32 ctrlr0 = 0;
+       u32 spi0_cdiv;
+       u32 freq; /* Freqency info only need be searched once */
+
+       /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+       pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+                                                       MRST_CLK_SPI0_REG);
+       spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+       freq = 100000000 / (spi0_cdiv + 1);
+
+       if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
+               mrst_spi_paddr = MRST_REGBASE_SPI1;
+
+       pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+                                               mrst_spi_paddr);
+
+       /* Disable SPI controller */
+       dw_writel(pspi, ssienr, 0);
+
+       /* Set control param, 8 bits, transmit only mode */
+       ctrlr0 = dw_readl(pspi, ctrl0);
+
+       ctrlr0 &= 0xfcc0;
+       ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+                     | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+       dw_writel(pspi, ctrl0, ctrlr0);
+
+       /*
+        * Change the spi0 clk to comply with 115200 bps, use 100000 to
+        * calculate the clk dividor to make the clock a little slower
+        * than real baud rate.
+        */
+       dw_writel(pspi, baudr, freq/100000);
+
+       /* Disable all INT for early phase */
+       dw_writel(pspi, imr, 0x0);
+
+       /* Set the cs to spi-uart */
+       dw_writel(pspi, ser, 0x2);
+
+       /* Enable the HW, the last step for HW init */
+       dw_writel(pspi, ssienr, 0x1);
+
+       /* Set the default configuration */
+       max3110_write_config();
+
+       /* Register the kmsg dumper */
+       if (!dumper_registered) {
+               dw_dumper.dump = dw_kmsg_dump;
+               kmsg_dump_register(&dw_dumper);
+               dumper_registered = 1;
+       }
+}
+
+/* Slave select should be called in the read/write function */
+static void early_mrst_spi_putc(char c)
+{
+       unsigned int timeout;
+       u32 sr;
+
+       timeout = MRST_SPI_TIMEOUT;
+       /* Early putc needs to make sure the TX FIFO is not full */
+       while (--timeout) {
+               sr = dw_readl(pspi, sr);
+               if (!(sr & SR_TF_NOT_FULL))
+                       cpu_relax();
+               else
+                       break;
+       }
+
+       if (!timeout)
+               pr_warning("MRST earlycon: timed out\n");
+       else
+               max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
+{
+       int i;
+
+       for (i = 0; i < n && *str; i++) {
+               if (*str == '\n')
+                       early_mrst_spi_putc('\r');
+               early_mrst_spi_putc(*str);
+               str++;
+       }
+}
+
+struct console early_mrst_console = {
+       .name =         "earlymrst",
+       .write =        early_mrst_spi_write,
+       .flags =        CON_PRINTBUFFER,
+       .index =        -1,
+};
+
+/*
+ * Following is the early console based on Medfield HSU (High
+ * Speed UART) device.
+ */
+#define HSU_PORT2_PADDR                0xffa28180
+
+static void __iomem *phsu;
+
+void hsu_early_console_init(void)
+{
+       u8 lcr;
+
+       phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+                                                       HSU_PORT2_PADDR);
+
+       /* Disable FIFO */
+       writeb(0x0, phsu + UART_FCR);
+
+       /* Set to default 115200 bps, 8n1 */
+       lcr = readb(phsu + UART_LCR);
+       writeb((0x80 | lcr), phsu + UART_LCR);
+       writeb(0x18, phsu + UART_DLL);
+       writeb(lcr,  phsu + UART_LCR);
+       writel(0x3600, phsu + UART_MUL*4);
+
+       writeb(0x8, phsu + UART_MCR);
+       writeb(0x7, phsu + UART_FCR);
+       writeb(0x3, phsu + UART_LCR);
+
+       /* Clear IRQ status */
+       readb(phsu + UART_LSR);
+       readb(phsu + UART_RX);
+       readb(phsu + UART_IIR);
+       readb(phsu + UART_MSR);
+
+       /* Enable FIFO */
+       writeb(0x7, phsu + UART_FCR);
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void early_hsu_putc(char ch)
+{
+       unsigned int timeout = 10000; /* 10ms */
+       u8 status;
+
+       while (--timeout) {
+               status = readb(phsu + UART_LSR);
+               if (status & BOTH_EMPTY)
+                       break;
+               udelay(1);
+       }
+
+       /* Only write the char when there was no timeout */
+       if (timeout)
+               writeb(ch, phsu + UART_TX);
+}
+
+static void early_hsu_write(struct console *con, const char *str, unsigned n)
+{
+       int i;
+
+       for (i = 0; i < n && *str; i++) {
+               if (*str == '\n')
+                       early_hsu_putc('\r');
+               early_hsu_putc(*str);
+               str++;
+       }
+}
+
+struct console early_hsu_console = {
+       .name =         "earlyhsu",
+       .write =        early_hsu_write,
+       .flags =        CON_PRINTBUFFER,
+       .index =        -1,
+};
index c2fa9b8b497e082cd703f2e2e0f9b03319bdd2e6..0fe27d7c6258e8e22b8918c0fbf14d088ecd9380 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/efi.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/time.h>
@@ -275,7 +276,7 @@ static void __init do_add_efi_memmap(void)
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
-void __init efi_reserve_early(void)
+void __init efi_memblock_x86_reserve_range(void)
 {
        unsigned long pmap;
 
@@ -290,7 +291,7 @@ void __init efi_reserve_early(void)
                boot_params.efi_info.efi_memdesc_size;
        memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
        memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
-       reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size,
+       memblock_x86_reserve_range(pmap, pmap + memmap.nr_map * memmap.desc_size,
                      "EFI memmap");
 }
 
index 227d00920d2f8eaa1d90340ced0261ffe0a8f859..9fb188d7bc762a8101bffde7d32f8e4851512360 100644 (file)
 
  /* unfortunately push/pop can't be no-op */
 .macro PUSH_GS
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
 .endm
 .macro POP_GS pop=0
        addl $(4 + \pop), %esp
 #else  /* CONFIG_X86_32_LAZY_GS */
 
 .macro PUSH_GS
-       pushl %gs
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %gs
        /*CFI_REL_OFFSET gs, 0*/
 .endm
 
 .macro POP_GS pop=0
-98:    popl %gs
-       CFI_ADJUST_CFA_OFFSET -4
+98:    popl_cfi %gs
        /*CFI_RESTORE gs*/
   .if \pop <> 0
        add $\pop, %esp
 .macro SAVE_ALL
        cld
        PUSH_GS
-       pushl %fs
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %fs
        /*CFI_REL_OFFSET fs, 0;*/
-       pushl %es
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %es
        /*CFI_REL_OFFSET es, 0;*/
-       pushl %ds
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ds
        /*CFI_REL_OFFSET ds, 0;*/
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        CFI_REL_OFFSET eax, 0
-       pushl %ebp
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebp
        CFI_REL_OFFSET ebp, 0
-       pushl %edi
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %edi
        CFI_REL_OFFSET edi, 0
-       pushl %esi
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %esi
        CFI_REL_OFFSET esi, 0
-       pushl %edx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %edx
        CFI_REL_OFFSET edx, 0
-       pushl %ecx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ecx
        CFI_REL_OFFSET ecx, 0
-       pushl %ebx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebx
        CFI_REL_OFFSET ebx, 0
        movl $(__USER_DS), %edx
        movl %edx, %ds
 .endm
 
 .macro RESTORE_INT_REGS
-       popl %ebx
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %ebx
        CFI_RESTORE ebx
-       popl %ecx
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %ecx
        CFI_RESTORE ecx
-       popl %edx
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %edx
        CFI_RESTORE edx
-       popl %esi
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %esi
        CFI_RESTORE esi
-       popl %edi
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %edi
        CFI_RESTORE edi
-       popl %ebp
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %ebp
        CFI_RESTORE ebp
-       popl %eax
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %eax
        CFI_RESTORE eax
 .endm
 
 .macro RESTORE_REGS pop=0
        RESTORE_INT_REGS
-1:     popl %ds
-       CFI_ADJUST_CFA_OFFSET -4
+1:     popl_cfi %ds
        /*CFI_RESTORE ds;*/
-2:     popl %es
-       CFI_ADJUST_CFA_OFFSET -4
+2:     popl_cfi %es
        /*CFI_RESTORE es;*/
-3:     popl %fs
-       CFI_ADJUST_CFA_OFFSET -4
+3:     popl_cfi %fs
        /*CFI_RESTORE fs;*/
        POP_GS \pop
 .pushsection .fixup, "ax"
 
 ENTRY(ret_from_fork)
        CFI_STARTPROC
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        call schedule_tail
        GET_THREAD_INFO(%ebp)
-       popl %eax
-       CFI_ADJUST_CFA_OFFSET -4
-       pushl $0x0202                   # Reset kernel eflags
-       CFI_ADJUST_CFA_OFFSET 4
-       popfl
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %eax
+       pushl_cfi $0x0202               # Reset kernel eflags
+       popfl_cfi
        jmp syscall_exit
        CFI_ENDPROC
 END(ret_from_fork)
@@ -409,29 +382,23 @@ sysenter_past_esp:
         * enough kernel state to call TRACE_IRQS_OFF can be called - but
         * we immediately enable interrupts at that point anyway.
         */
-       pushl $(__USER_DS)
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $(__USER_DS)
        /*CFI_REL_OFFSET ss, 0*/
-       pushl %ebp
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebp
        CFI_REL_OFFSET esp, 0
-       pushfl
+       pushfl_cfi
        orl $X86_EFLAGS_IF, (%esp)
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $(__USER_CS)
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $(__USER_CS)
        /*CFI_REL_OFFSET cs, 0*/
        /*
         * Push current_thread_info()->sysenter_return to the stack.
         * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
         * pushed above; +8 corresponds to copy_thread's esp0 setting.
         */
-       pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
        CFI_REL_OFFSET eip, 0
 
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        SAVE_ALL
        ENABLE_INTERRUPTS(CLBR_NONE)
 
@@ -486,8 +453,7 @@ sysenter_audit:
        movl %eax,%edx                  /* 2nd arg: syscall number */
        movl $AUDIT_ARCH_I386,%eax      /* 1st arg: audit arch */
        call audit_syscall_entry
-       pushl %ebx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebx
        movl PT_EAX(%esp),%eax          /* reload syscall number */
        jmp sysenter_do_call
 
@@ -529,8 +495,7 @@ ENDPROC(ia32_sysenter_target)
        # system call handler stub
 ENTRY(system_call)
        RING0_INT_FRAME                 # can't unwind into user space anyway
-       pushl %eax                      # save orig_eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax                  # save orig_eax
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
                                        # system call tracing in operation / emulation
@@ -566,7 +531,6 @@ restore_all_notrace:
        je ldt_ss                       # returning to user-space with LDT SS
 restore_nocheck:
        RESTORE_REGS 4                  # skip orig_eax/error_code
-       CFI_ADJUST_CFA_OFFSET -4
 irq_return:
        INTERRUPT_RETURN
 .section .fixup,"ax"
@@ -619,10 +583,8 @@ ldt_ss:
        shr $16, %edx
        mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
        mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
-       pushl $__ESPFIX_SS
-       CFI_ADJUST_CFA_OFFSET 4
-       push %eax                       /* new kernel esp */
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $__ESPFIX_SS
+       pushl_cfi %eax                  /* new kernel esp */
        /* Disable interrupts, but do not irqtrace this section: we
         * will soon execute iret and the tracer was already set to
         * the irqstate after the iret */
@@ -666,11 +628,9 @@ work_notifysig:                            # deal with pending signals and
 
        ALIGN
 work_notifysig_v86:
-       pushl %ecx                      # save ti_flags for do_notify_resume
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ecx                  # save ti_flags for do_notify_resume
        call save_v86_state             # %eax contains pt_regs pointer
-       popl %ecx
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %ecx
        movl %eax, %esp
 #else
        movl %esp, %eax
@@ -750,14 +710,18 @@ ptregs_##name: \
 #define PTREGSCALL3(name) \
        ALIGN; \
 ptregs_##name: \
+       CFI_STARTPROC; \
        leal 4(%esp),%eax; \
-       pushl %eax; \
+       pushl_cfi %eax; \
        movl PT_EDX(%eax),%ecx; \
        movl PT_ECX(%eax),%edx; \
        movl PT_EBX(%eax),%eax; \
        call sys_##name; \
        addl $4,%esp; \
-       ret
+       CFI_ADJUST_CFA_OFFSET -4; \
+       ret; \
+       CFI_ENDPROC; \
+ENDPROC(ptregs_##name)
 
 PTREGSCALL1(iopl)
 PTREGSCALL0(fork)
@@ -772,15 +736,19 @@ PTREGSCALL1(vm86old)
 /* Clone is an oddball.  The 4th arg is in %edi */
        ALIGN;
 ptregs_clone:
+       CFI_STARTPROC
        leal 4(%esp),%eax
-       pushl %eax
-       pushl PT_EDI(%eax)
+       pushl_cfi %eax
+       pushl_cfi PT_EDI(%eax)
        movl PT_EDX(%eax),%ecx
        movl PT_ECX(%eax),%edx
        movl PT_EBX(%eax),%eax
        call sys_clone
        addl $8,%esp
+       CFI_ADJUST_CFA_OFFSET -8
        ret
+       CFI_ENDPROC
+ENDPROC(ptregs_clone)
 
 .macro FIXUP_ESPFIX_STACK
 /*
@@ -795,10 +763,8 @@ ptregs_clone:
        mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
        shl $16, %eax
        addl %esp, %eax                 /* the adjusted stack pointer */
-       pushl $__KERNEL_DS
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $__KERNEL_DS
+       pushl_cfi %eax
        lss (%esp), %esp                /* switch to the normal stack segment */
        CFI_ADJUST_CFA_OFFSET -8
 .endm
@@ -835,8 +801,7 @@ vector=FIRST_EXTERNAL_VECTOR
       .if vector <> FIRST_EXTERNAL_VECTOR
        CFI_ADJUST_CFA_OFFSET -4
       .endif
-1:     pushl $(~vector+0x80)   /* Note: always in signed byte range */
-       CFI_ADJUST_CFA_OFFSET 4
+1:     pushl_cfi $(~vector+0x80)       /* Note: always in signed byte range */
       .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
        jmp 2f
       .endif
@@ -876,8 +841,7 @@ ENDPROC(common_interrupt)
 #define BUILD_INTERRUPT3(name, nr, fn) \
 ENTRY(name)                            \
        RING0_INT_FRAME;                \
-       pushl $~(nr);                   \
-       CFI_ADJUST_CFA_OFFSET 4;        \
+       pushl_cfi $~(nr);               \
        SAVE_ALL;                       \
        TRACE_IRQS_OFF                  \
        movl %esp,%eax;                 \
@@ -893,21 +857,18 @@ ENDPROC(name)
 
 ENTRY(coprocessor_error)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_coprocessor_error
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_coprocessor_error
        jmp error_code
        CFI_ENDPROC
 END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
 #ifdef CONFIG_X86_INVD_BUG
        /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
-661:   pushl $do_general_protection
+661:   pushl_cfi $do_general_protection
 662:
 .section .altinstructions,"a"
        .balign 4
@@ -922,19 +883,16 @@ ENTRY(simd_coprocessor_error)
 664:
 .previous
 #else
-       pushl $do_simd_coprocessor_error
+       pushl_cfi $do_simd_coprocessor_error
 #endif
-       CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
 END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
        RING0_INT_FRAME
-       pushl $-1                       # mark this as an int
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_device_not_available
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $-1                   # mark this as an int
+       pushl_cfi $do_device_not_available
        jmp error_code
        CFI_ENDPROC
 END(device_not_available)
@@ -956,82 +914,68 @@ END(native_irq_enable_sysexit)
 
 ENTRY(overflow)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_overflow
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_overflow
        jmp error_code
        CFI_ENDPROC
 END(overflow)
 
 ENTRY(bounds)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_bounds
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_bounds
        jmp error_code
        CFI_ENDPROC
 END(bounds)
 
 ENTRY(invalid_op)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_invalid_op
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_invalid_op
        jmp error_code
        CFI_ENDPROC
 END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_coprocessor_segment_overrun
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_coprocessor_segment_overrun
        jmp error_code
        CFI_ENDPROC
 END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
        RING0_EC_FRAME
-       pushl $do_invalid_TSS
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_invalid_TSS
        jmp error_code
        CFI_ENDPROC
 END(invalid_TSS)
 
 ENTRY(segment_not_present)
        RING0_EC_FRAME
-       pushl $do_segment_not_present
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_segment_not_present
        jmp error_code
        CFI_ENDPROC
 END(segment_not_present)
 
 ENTRY(stack_segment)
        RING0_EC_FRAME
-       pushl $do_stack_segment
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_stack_segment
        jmp error_code
        CFI_ENDPROC
 END(stack_segment)
 
 ENTRY(alignment_check)
        RING0_EC_FRAME
-       pushl $do_alignment_check
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_alignment_check
        jmp error_code
        CFI_ENDPROC
 END(alignment_check)
 
 ENTRY(divide_error)
        RING0_INT_FRAME
-       pushl $0                        # no error code
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_divide_error
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0                    # no error code
+       pushl_cfi $do_divide_error
        jmp error_code
        CFI_ENDPROC
 END(divide_error)
@@ -1039,10 +983,8 @@ END(divide_error)
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl machine_check_vector
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi machine_check_vector
        jmp error_code
        CFI_ENDPROC
 END(machine_check)
@@ -1050,10 +992,8 @@ END(machine_check)
 
 ENTRY(spurious_interrupt_bug)
        RING0_INT_FRAME
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_spurious_interrupt_bug
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
+       pushl_cfi $do_spurious_interrupt_bug
        jmp error_code
        CFI_ENDPROC
 END(spurious_interrupt_bug)
@@ -1084,8 +1024,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
-       pushl $0
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $0
        SAVE_ALL
        TRACE_IRQS_OFF
 
@@ -1121,23 +1060,20 @@ ENDPROC(xen_hypervisor_callback)
 # We distinguish between categories by maintaining a status value in EAX.
 ENTRY(xen_failsafe_callback)
        CFI_STARTPROC
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        movl $1,%eax
 1:     mov 4(%esp),%ds
 2:     mov 8(%esp),%es
 3:     mov 12(%esp),%fs
 4:     mov 16(%esp),%gs
        testl %eax,%eax
-       popl %eax
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %eax
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
        addl $16,%esp
        jmp iret_exc            # EAX != 0 => Category 2 (Bad IRET)
-5:     pushl $0                # EAX == 0 => Category 1 (Bad segment)
-       CFI_ADJUST_CFA_OFFSET 4
+5:     pushl_cfi $0            # EAX == 0 => Category 1 (Bad segment)
        SAVE_ALL
        jmp ret_from_exception
        CFI_ENDPROC
@@ -1287,40 +1223,29 @@ syscall_table_size=(.-sys_call_table)
 
 ENTRY(page_fault)
        RING0_EC_FRAME
-       pushl $do_page_fault
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_page_fault
        ALIGN
 error_code:
        /* the function address is in %gs's slot on the stack */
-       pushl %fs
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %fs
        /*CFI_REL_OFFSET fs, 0*/
-       pushl %es
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %es
        /*CFI_REL_OFFSET es, 0*/
-       pushl %ds
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ds
        /*CFI_REL_OFFSET ds, 0*/
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        CFI_REL_OFFSET eax, 0
-       pushl %ebp
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebp
        CFI_REL_OFFSET ebp, 0
-       pushl %edi
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %edi
        CFI_REL_OFFSET edi, 0
-       pushl %esi
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %esi
        CFI_REL_OFFSET esi, 0
-       pushl %edx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %edx
        CFI_REL_OFFSET edx, 0
-       pushl %ecx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ecx
        CFI_REL_OFFSET ecx, 0
-       pushl %ebx
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ebx
        CFI_REL_OFFSET ebx, 0
        cld
        movl $(__KERNEL_PERCPU), %ecx
@@ -1362,12 +1287,9 @@ END(page_fault)
        movl TSS_sysenter_sp0 + \offset(%esp), %esp
        CFI_DEF_CFA esp, 0
        CFI_UNDEFINED eip
-       pushfl
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $__KERNEL_CS
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $sysenter_past_esp
-       CFI_ADJUST_CFA_OFFSET 4
+       pushfl_cfi
+       pushl_cfi $__KERNEL_CS
+       pushl_cfi $sysenter_past_esp
        CFI_REL_OFFSET eip, 0
 .endm
 
@@ -1377,8 +1299,7 @@ ENTRY(debug)
        jne debug_stack_correct
        FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
 debug_stack_correct:
-       pushl $-1                       # mark this as an int
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $-1                   # mark this as an int
        SAVE_ALL
        TRACE_IRQS_OFF
        xorl %edx,%edx                  # error code 0
@@ -1398,32 +1319,27 @@ END(debug)
  */
 ENTRY(nmi)
        RING0_INT_FRAME
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        movl %ss, %eax
        cmpw $__ESPFIX_SS, %ax
-       popl %eax
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %eax
        je nmi_espfix_stack
        cmpl $ia32_sysenter_target,(%esp)
        je nmi_stack_fixup
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        movl %esp,%eax
        /* Do not access memory above the end of our stack page,
         * it might not exist.
         */
        andl $(THREAD_SIZE-1),%eax
        cmpl $(THREAD_SIZE-20),%eax
-       popl %eax
-       CFI_ADJUST_CFA_OFFSET -4
+       popl_cfi %eax
        jae nmi_stack_correct
        cmpl $ia32_sysenter_target,12(%esp)
        je nmi_debug_stack_check
 nmi_stack_correct:
        /* We have a RING0_INT_FRAME here */
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        SAVE_ALL
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
@@ -1452,18 +1368,14 @@ nmi_espfix_stack:
         *
         * create the pointer to lss back
         */
-       pushl %ss
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl %esp
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %ss
+       pushl_cfi %esp
        addl $4, (%esp)
        /* copy the iret frame of 12 bytes */
        .rept 3
-       pushl 16(%esp)
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi 16(%esp)
        .endr
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi %eax
        SAVE_ALL
        FIXUP_ESPFIX_STACK              # %eax == %esp
        xorl %edx,%edx                  # zero error code
@@ -1477,8 +1389,7 @@ END(nmi)
 
 ENTRY(int3)
        RING0_INT_FRAME
-       pushl $-1                       # mark this as an int
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $-1                   # mark this as an int
        SAVE_ALL
        TRACE_IRQS_OFF
        xorl %edx,%edx          # zero error code
@@ -1490,8 +1401,7 @@ END(int3)
 
 ENTRY(general_protection)
        RING0_EC_FRAME
-       pushl $do_general_protection
-       CFI_ADJUST_CFA_OFFSET 4
+       pushl_cfi $do_general_protection
        jmp error_code
        CFI_ENDPROC
 END(general_protection)
index 17be5ec7cbbad332973b6b46a79cdb3db2832f74..a7ae7fd1010fdbddcd596aa0aae01ee160b7bb66 100644 (file)
@@ -213,23 +213,17 @@ ENDPROC(native_usergs_sysret64)
        .macro FAKE_STACK_FRAME child_rip
        /* push in order ss, rsp, eflags, cs, rip */
        xorl %eax, %eax
-       pushq $__KERNEL_DS /* ss */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi $__KERNEL_DS /* ss */
        /*CFI_REL_OFFSET        ss,0*/
-       pushq %rax /* rsp */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi %rax /* rsp */
        CFI_REL_OFFSET  rsp,0
-       pushq $X86_EFLAGS_IF /* eflags - interrupts on */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi $X86_EFLAGS_IF /* eflags - interrupts on */
        /*CFI_REL_OFFSET        rflags,0*/
-       pushq $__KERNEL_CS /* cs */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi $__KERNEL_CS /* cs */
        /*CFI_REL_OFFSET        cs,0*/
-       pushq \child_rip /* rip */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi \child_rip /* rip */
        CFI_REL_OFFSET  rip,0
-       pushq   %rax /* orig rax */
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi %rax /* orig rax */
        .endm
 
        .macro UNFAKE_STACK_FRAME
@@ -398,10 +392,8 @@ ENTRY(ret_from_fork)
 
        LOCK ; btr $TIF_FORK,TI_flags(%r8)
 
-       push kernel_eflags(%rip)
-       CFI_ADJUST_CFA_OFFSET 8
-       popf                                    # reset kernel eflags
-       CFI_ADJUST_CFA_OFFSET -8
+       pushq_cfi kernel_eflags(%rip)
+       popfq_cfi                               # reset kernel eflags
 
        call schedule_tail                      # rdi: 'prev' task parameter
 
@@ -521,11 +513,9 @@ sysret_careful:
        jnc sysret_signal
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       pushq %rdi
-       CFI_ADJUST_CFA_OFFSET 8
+       pushq_cfi %rdi
        call schedule
-       popq  %rdi
-       CFI_ADJUST_CFA_OFFSET -8
+       popq_cfi %rdi
        jmp sysret_check
 
        /* Handle a signal */
@@ -634,11 +624,9 @@ int_careful:
        jnc  int_very_careful
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       pushq %rdi
-       CFI_ADJUST_CFA_OFFSET 8
+       pushq_cfi %rdi
        call schedule
-       popq %rdi
-       CFI_ADJUST_CFA_OFFSET -8
+       popq_cfi %rdi
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        jmp int_with_check
@@ -652,12 +640,10 @@ int_check_syscall_exit_work:
        /* Check for syscall exit trace */
        testl $_TIF_WORK_SYSCALL_EXIT,%edx
        jz int_signal
-       pushq %rdi
-       CFI_ADJUST_CFA_OFFSET 8
+       pushq_cfi %rdi
        leaq 8(%rsp),%rdi       # &ptregs -> arg1
        call syscall_trace_leave
-       popq %rdi
-       CFI_ADJUST_CFA_OFFSET -8
+       popq_cfi %rdi
        andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
        jmp int_restore_rest
 
@@ -714,9 +700,8 @@ END(ptregscall_common)
 
 ENTRY(stub_execve)
        CFI_STARTPROC
-       popq %r11
-       CFI_ADJUST_CFA_OFFSET -8
-       CFI_REGISTER rip, r11
+       addq $8, %rsp
+       PARTIAL_FRAME 0
        SAVE_REST
        FIXUP_TOP_OF_STACK %r11
        movq %rsp, %rcx
@@ -735,7 +720,7 @@ END(stub_execve)
 ENTRY(stub_rt_sigreturn)
        CFI_STARTPROC
        addq $8, %rsp
-       CFI_ADJUST_CFA_OFFSET   -8
+       PARTIAL_FRAME 0
        SAVE_REST
        movq %rsp,%rdi
        FIXUP_TOP_OF_STACK %r11
@@ -766,8 +751,7 @@ vector=FIRST_EXTERNAL_VECTOR
       .if vector <> FIRST_EXTERNAL_VECTOR
        CFI_ADJUST_CFA_OFFSET -8
       .endif
-1:     pushq $(~vector+0x80)   /* Note: always in signed byte range */
-       CFI_ADJUST_CFA_OFFSET 8
+1:     pushq_cfi $(~vector+0x80)       /* Note: always in signed byte range */
       .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
        jmp 2f
       .endif
@@ -796,8 +780,8 @@ END(interrupt)
 
 /* 0(%rsp): ~(interrupt number) */
        .macro interrupt func
-       subq $10*8, %rsp
-       CFI_ADJUST_CFA_OFFSET 10*8
+       subq $ORIG_RAX-ARGOFFSET+8, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-ARGOFFSET+8
        call save_args
        PARTIAL_FRAME 0
        call \func
@@ -822,6 +806,7 @@ ret_from_intr:
        TRACE_IRQS_OFF
        decl PER_CPU_VAR(irq_count)
        leaveq
+       CFI_RESTORE             rbp
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   -8
 exit_intr:
@@ -903,11 +888,9 @@ retint_careful:
        jnc   retint_signal
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       pushq %rdi
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi %rdi
        call  schedule
-       popq %rdi
-       CFI_ADJUST_CFA_OFFSET   -8
+       popq_cfi %rdi
        GET_THREAD_INFO(%rcx)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
@@ -956,8 +939,7 @@ END(common_interrupt)
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
        INTR_FRAME
-       pushq $~(\num)
-       CFI_ADJUST_CFA_OFFSET 8
+       pushq_cfi $~(\num)
        interrupt \do_sym
        jmp ret_from_intr
        CFI_ENDPROC
@@ -1023,9 +1005,9 @@ apicinterrupt ERROR_APIC_VECTOR \
 apicinterrupt SPURIOUS_APIC_VECTOR \
        spurious_interrupt smp_spurious_interrupt
 
-#ifdef CONFIG_PERF_EVENTS
-apicinterrupt LOCAL_PENDING_VECTOR \
-       perf_pending_interrupt smp_perf_pending_interrupt
+#ifdef CONFIG_IRQ_WORK
+apicinterrupt IRQ_WORK_VECTOR \
+       irq_work_interrupt smp_irq_work_interrupt
 #endif
 
 /*
@@ -1036,8 +1018,8 @@ ENTRY(\sym)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
-       subq $15*8,%rsp
-       CFI_ADJUST_CFA_OFFSET 15*8
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call error_entry
        DEFAULT_FRAME 0
        movq %rsp,%rdi          /* pt_regs pointer */
@@ -1052,9 +1034,9 @@ END(\sym)
 ENTRY(\sym)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
-       pushq $-1               /* ORIG_RAX: no syscall to restart */
-       CFI_ADJUST_CFA_OFFSET 8
-       subq $15*8, %rsp
+       pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call save_paranoid
        TRACE_IRQS_OFF
        movq %rsp,%rdi          /* pt_regs pointer */
@@ -1070,9 +1052,9 @@ END(\sym)
 ENTRY(\sym)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
-       pushq $-1               /* ORIG_RAX: no syscall to restart */
-       CFI_ADJUST_CFA_OFFSET 8
-       subq $15*8, %rsp
+       pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call save_paranoid
        TRACE_IRQS_OFF
        movq %rsp,%rdi          /* pt_regs pointer */
@@ -1089,8 +1071,8 @@ END(\sym)
 ENTRY(\sym)
        XCPT_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
-       subq $15*8,%rsp
-       CFI_ADJUST_CFA_OFFSET 15*8
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call error_entry
        DEFAULT_FRAME 0
        movq %rsp,%rdi                  /* pt_regs pointer */
@@ -1107,8 +1089,8 @@ END(\sym)
 ENTRY(\sym)
        XCPT_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
-       subq $15*8,%rsp
-       CFI_ADJUST_CFA_OFFSET 15*8
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call save_paranoid
        DEFAULT_FRAME 0
        TRACE_IRQS_OFF
@@ -1139,16 +1121,14 @@ zeroentry simd_coprocessor_error do_simd_coprocessor_error
        /* edi:  new selector */
 ENTRY(native_load_gs_index)
        CFI_STARTPROC
-       pushf
-       CFI_ADJUST_CFA_OFFSET 8
+       pushfq_cfi
        DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
        SWAPGS
 gs_change:
        movl %edi,%gs
 2:     mfence          /* workaround */
        SWAPGS
-       popf
-       CFI_ADJUST_CFA_OFFSET -8
+       popfq_cfi
        ret
        CFI_ENDPROC
 END(native_load_gs_index)
@@ -1215,8 +1195,7 @@ END(kernel_execve)
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
        CFI_STARTPROC
-       push %rbp
-       CFI_ADJUST_CFA_OFFSET   8
+       pushq_cfi %rbp
        CFI_REL_OFFSET rbp,0
        mov  %rsp,%rbp
        CFI_DEF_CFA_REGISTER rbp
@@ -1225,6 +1204,7 @@ ENTRY(call_softirq)
        push  %rbp                      # backlink for old unwinder
        call __do_softirq
        leaveq
+       CFI_RESTORE             rbp
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   -8
        decl PER_CPU_VAR(irq_count)
@@ -1368,7 +1348,7 @@ paranoidzeroentry machine_check *machine_check_vector(%rip)
 
        /* ebx: no swapgs flag */
 ENTRY(paranoid_exit)
-       INTR_FRAME
+       DEFAULT_FRAME
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl %ebx,%ebx                         /* swapgs needed? */
@@ -1445,7 +1425,6 @@ error_swapgs:
 error_sti:
        TRACE_IRQS_OFF
        ret
-       CFI_ENDPROC
 
 /*
  * There are two places in the kernel that can potentially fault with
@@ -1470,6 +1449,7 @@ bstep_iret:
        /* Fix truncated RIP */
        movq %rcx,RIP+8(%rsp)
        jmp error_swapgs
+       CFI_ENDPROC
 END(error_entry)
 
 
@@ -1498,8 +1478,8 @@ ENTRY(nmi)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1
-       subq $15*8, %rsp
-       CFI_ADJUST_CFA_OFFSET 15*8
+       subq $ORIG_RAX-R15, %rsp
+       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
        call save_paranoid
        DEFAULT_FRAME 0
        /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
index cd37469b54eeed3fc479d2c931d8d2ed933ea411..3afb33f14d2d2c86a3c961d87aaae531d2631ac8 100644 (file)
@@ -257,14 +257,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code)
        return mod_code_status;
 }
 
-
-
-
-static unsigned char ftrace_nop[MCOUNT_INSN_SIZE];
-
 static unsigned char *ftrace_nop_replace(void)
 {
-       return ftrace_nop;
+       return ideal_nop5;
 }
 
 static int
@@ -338,62 +333,6 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
 
 int __init ftrace_dyn_arch_init(void *data)
 {
-       extern const unsigned char ftrace_test_p6nop[];
-       extern const unsigned char ftrace_test_nop5[];
-       extern const unsigned char ftrace_test_jmp[];
-       int faulted = 0;
-
-       /*
-        * There is no good nop for all x86 archs.
-        * We will default to using the P6_NOP5, but first we
-        * will test to make sure that the nop will actually
-        * work on this CPU. If it faults, we will then
-        * go to a lesser efficient 5 byte nop. If that fails
-        * we then just use a jmp as our nop. This isn't the most
-        * efficient nop, but we can not use a multi part nop
-        * since we would then risk being preempted in the middle
-        * of that nop, and if we enabled tracing then, it might
-        * cause a system crash.
-        *
-        * TODO: check the cpuid to determine the best nop.
-        */
-       asm volatile (
-               "ftrace_test_jmp:"
-               "jmp ftrace_test_p6nop\n"
-               "nop\n"
-               "nop\n"
-               "nop\n"  /* 2 byte jmp + 3 bytes */
-               "ftrace_test_p6nop:"
-               P6_NOP5
-               "jmp 1f\n"
-               "ftrace_test_nop5:"
-               ".byte 0x66,0x66,0x66,0x66,0x90\n"
-               "1:"
-               ".section .fixup, \"ax\"\n"
-               "2:     movl $1, %0\n"
-               "       jmp ftrace_test_nop5\n"
-               "3:     movl $2, %0\n"
-               "       jmp 1b\n"
-               ".previous\n"
-               _ASM_EXTABLE(ftrace_test_p6nop, 2b)
-               _ASM_EXTABLE(ftrace_test_nop5, 3b)
-               : "=r"(faulted) : "0" (faulted));
-
-       switch (faulted) {
-       case 0:
-               pr_info("converting mcount calls to 0f 1f 44 00 00\n");
-               memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
-               break;
-       case 1:
-               pr_info("converting mcount calls to 66 66 66 66 90\n");
-               memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
-               break;
-       case 2:
-               pr_info("converting mcount calls to jmp . + 5\n");
-               memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
-               break;
-       }
-
        /* The return code is retured via data */
        *(unsigned long *)data = 0;
 
index 3e66bd364a9db3cf8f3fb624f96eeb7075364d78..af0699ba48cfb7efebb03bc5bc57af750b73f9ef 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/memblock.h>
 
 #include <asm/setup.h>
 #include <asm/bios_ebda.h>
@@ -51,5 +52,5 @@ void __init reserve_ebda_region(void)
                lowmem = 0x9f000;
 
        /* reserve all memory between lowmem and the 1MB mark */
-       reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
+       memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved");
 }
index 784360c0625c04edbcee49e13f5fe471add070ec..9a6ca23921705ee4122e8d90aec48a7bdc350f0e 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/start_kernel.h>
 #include <linux/mm.h>
+#include <linux/memblock.h>
 
 #include <asm/setup.h>
 #include <asm/sections.h>
@@ -30,17 +31,18 @@ static void __init i386_default_early_setup(void)
 
 void __init i386_start_kernel(void)
 {
+       memblock_init();
+
 #ifdef CONFIG_X86_TRAMPOLINE
        /*
         * But first pinch a few for the stack/trampoline stuff
         * FIXME: Don't need the extra page at 4K, but need to fix
         * trampoline before removing it. (see the GDT stuff)
         */
-       reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE,
-                                        "EX TRAMPOLINE");
+       memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
 #endif
 
-       reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+       memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
@@ -49,7 +51,7 @@ void __init i386_start_kernel(void)
                u64 ramdisk_image = boot_params.hdr.ramdisk_image;
                u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
                u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-               reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+               memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
        }
 #endif
 
index 7147143fd614e429392741ae13ce5577c7be5364..2d2673c28aff2754af1e6e8848e9068ab1a6cca5 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/percpu.h>
 #include <linux/start_kernel.h>
 #include <linux/io.h>
+#include <linux/memblock.h>
 
 #include <asm/processor.h>
 #include <asm/proto.h>
@@ -79,6 +80,8 @@ void __init x86_64_start_kernel(char * real_mode_data)
        /* Cleanup the over mapped high alias */
        cleanup_highmap();
 
+       max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
+
        for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
 #ifdef CONFIG_EARLY_PRINTK
                set_intr_gate(i, &early_idt_handlers[i]);
@@ -98,7 +101,9 @@ void __init x86_64_start_reservations(char *real_mode_data)
 {
        copy_bootdata(__va(real_mode_data));
 
-       reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+       memblock_init();
+
+       memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
@@ -107,7 +112,7 @@ void __init x86_64_start_reservations(char *real_mode_data)
                unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
                unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
                unsigned long ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-               reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+               memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
        }
 #endif
 
index 351f9c0fea1f20714321d01260003173faf548dc..aff0b3c2750929aff9f36ccf946f4a7ae31b1afa 100644 (file)
@@ -35,7 +35,6 @@
 unsigned long                          hpet_address;
 u8                                     hpet_blockid; /* OS timer block num */
 u8                                     hpet_msi_disable;
-u8                                     hpet_readback_cmp;
 
 #ifdef CONFIG_PCI_MSI
 static unsigned long                   hpet_num_timers;
@@ -381,40 +380,35 @@ static int hpet_next_event(unsigned long delta,
                           struct clock_event_device *evt, int timer)
 {
        u32 cnt;
+       s32 res;
 
        cnt = hpet_readl(HPET_COUNTER);
        cnt += (u32) delta;
        hpet_writel(cnt, HPET_Tn_CMP(timer));
 
        /*
-        * We need to read back the CMP register on certain HPET
-        * implementations (ATI chipsets) which seem to delay the
-        * transfer of the compare register into the internal compare
-        * logic. With small deltas this might actually be too late as
-        * the counter could already be higher than the compare value
-        * at that point and we would wait for the next hpet interrupt
-        * forever. We found out that reading the CMP register back
-        * forces the transfer so we can rely on the comparison with
-        * the counter register below.
-        *
-        * That works fine on those ATI chipsets, but on newer Intel
-        * chipsets (ICH9...) this triggers due to an erratum: Reading
-        * the comparator immediately following a write is returning
-        * the old value.
-        *
-        * We restrict the read back to the affected ATI chipsets (set
-        * by quirks) and also run it with hpet=verbose for debugging
-        * purposes.
+        * HPETs are a complete disaster. The compare register is
+        * based on a equal comparison and neither provides a less
+        * than or equal functionality (which would require to take
+        * the wraparound into account) nor a simple count down event
+        * mode. Further the write to the comparator register is
+        * delayed internally up to two HPET clock cycles in certain
+        * chipsets (ATI, ICH9,10). We worked around that by reading
+        * back the compare register, but that required another
+        * workaround for ICH9,10 chips where the first readout after
+        * write can return the old stale value. We already have a
+        * minimum delta of 5us enforced, but a NMI or SMI hitting
+        * between the counter readout and the comparator write can
+        * move us behind that point easily. Now instead of reading
+        * the compare register back several times, we make the ETIME
+        * decision based on the following: Return ETIME if the
+        * counter value after the write is less than 8 HPET cycles
+        * away from the event or if the counter is already ahead of
+        * the event.
         */
-       if (hpet_readback_cmp || hpet_verbose) {
-               u32 cmp = hpet_readl(HPET_Tn_CMP(timer));
-
-               if (cmp != cnt)
-                       printk_once(KERN_WARNING
-                           "hpet: compare register read back failed.\n");
-       }
+       res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-       return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+       return res < 8 ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
@@ -437,9 +431,9 @@ static int hpet_legacy_next_event(unsigned long delta,
 static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
 static struct hpet_dev *hpet_devs;
 
-void hpet_msi_unmask(unsigned int irq)
+void hpet_msi_unmask(struct irq_data *data)
 {
-       struct hpet_dev *hdev = get_irq_data(irq);
+       struct hpet_dev *hdev = data->handler_data;
        unsigned int cfg;
 
        /* unmask it */
@@ -448,10 +442,10 @@ void hpet_msi_unmask(unsigned int irq)
        hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
-void hpet_msi_mask(unsigned int irq)
+void hpet_msi_mask(struct irq_data *data)
 {
+       struct hpet_dev *hdev = data->handler_data;
        unsigned int cfg;
-       struct hpet_dev *hdev = get_irq_data(irq);
 
        /* mask it */
        cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
@@ -459,18 +453,14 @@ void hpet_msi_mask(unsigned int irq)
        hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
-void hpet_msi_write(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
 {
-       struct hpet_dev *hdev = get_irq_data(irq);
-
        hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
        hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
 }
 
-void hpet_msi_read(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
 {
-       struct hpet_dev *hdev = get_irq_data(irq);
-
        msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
        msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
        msg->address_hi = 0;
@@ -503,7 +493,7 @@ static int hpet_assign_irq(struct hpet_dev *dev)
 {
        unsigned int irq;
 
-       irq = create_irq();
+       irq = create_irq_nr(0, -1);
        if (!irq)
                return -EINVAL;
 
index a474ec37c32f84df372d39eac5730532d60d0228..ff15c9dcc25de8be8144fd4d15f1dfd3069314e4 100644 (file)
@@ -206,11 +206,27 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
 int arch_bp_generic_fields(int x86_len, int x86_type,
                           int *gen_len, int *gen_type)
 {
-       /* Len */
-       switch (x86_len) {
-       case X86_BREAKPOINT_LEN_X:
+       /* Type */
+       switch (x86_type) {
+       case X86_BREAKPOINT_EXECUTE:
+               if (x86_len != X86_BREAKPOINT_LEN_X)
+                       return -EINVAL;
+
+               *gen_type = HW_BREAKPOINT_X;
                *gen_len = sizeof(long);
+               return 0;
+       case X86_BREAKPOINT_WRITE:
+               *gen_type = HW_BREAKPOINT_W;
                break;
+       case X86_BREAKPOINT_RW:
+               *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Len */
+       switch (x86_len) {
        case X86_BREAKPOINT_LEN_1:
                *gen_len = HW_BREAKPOINT_LEN_1;
                break;
@@ -229,21 +245,6 @@ int arch_bp_generic_fields(int x86_len, int x86_type,
                return -EINVAL;
        }
 
-       /* Type */
-       switch (x86_type) {
-       case X86_BREAKPOINT_EXECUTE:
-               *gen_type = HW_BREAKPOINT_X;
-               break;
-       case X86_BREAKPOINT_WRITE:
-               *gen_type = HW_BREAKPOINT_W;
-               break;
-       case X86_BREAKPOINT_RW:
-               *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
-               break;
-       default:
-               return -EINVAL;
-       }
-
        return 0;
 }
 
@@ -316,9 +317,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        ret = -EINVAL;
 
        switch (info->len) {
-       case X86_BREAKPOINT_LEN_X:
-               align = sizeof(long) -1;
-               break;
        case X86_BREAKPOINT_LEN_1:
                align = 0;
                break;
index a46cb3522c0c19d67f2d474c6e1f09fb616004ff..58bb239a2fd76d67121bd1c25e48512bad529825 100644 (file)
@@ -68,19 +68,22 @@ static void __cpuinit init_thread_xstate(void)
         */
 
        if (!HAVE_HWFP) {
+               /*
+                * Disable xsave as we do not support it if i387
+                * emulation is enabled.
+                */
+               setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+               setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
                xstate_size = sizeof(struct i387_soft_struct);
                return;
        }
 
        if (cpu_has_fxsr)
                xstate_size = sizeof(struct i387_fxsave_struct);
-#ifdef CONFIG_X86_32
        else
                xstate_size = sizeof(struct i387_fsave_struct);
-#endif
 }
 
-#ifdef CONFIG_X86_64
 /*
  * Called at bootup to set up the initial FPU state that is later cloned
  * into all processes.
@@ -88,12 +91,21 @@ static void __cpuinit init_thread_xstate(void)
 
 void __cpuinit fpu_init(void)
 {
-       unsigned long oldcr0 = read_cr0();
-
-       set_in_cr4(X86_CR4_OSFXSR);
-       set_in_cr4(X86_CR4_OSXMMEXCPT);
+       unsigned long cr0;
+       unsigned long cr4_mask = 0;
 
-       write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
+       if (cpu_has_fxsr)
+               cr4_mask |= X86_CR4_OSFXSR;
+       if (cpu_has_xmm)
+               cr4_mask |= X86_CR4_OSXMMEXCPT;
+       if (cr4_mask)
+               set_in_cr4(cr4_mask);
+
+       cr0 = read_cr0();
+       cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
+       if (!HAVE_HWFP)
+               cr0 |= X86_CR0_EM;
+       write_cr0(cr0);
 
        if (!smp_processor_id())
                init_thread_xstate();
@@ -104,24 +116,12 @@ void __cpuinit fpu_init(void)
        clear_used_math();
 }
 
-#else  /* CONFIG_X86_64 */
-
-void __cpuinit fpu_init(void)
-{
-       if (!smp_processor_id())
-               init_thread_xstate();
-}
-
-#endif /* CONFIG_X86_32 */
-
 void fpu_finit(struct fpu *fpu)
 {
-#ifdef CONFIG_X86_32
        if (!HAVE_HWFP) {
                finit_soft_fpu(&fpu->state->soft);
                return;
        }
-#endif
 
        if (cpu_has_fxsr) {
                struct i387_fxsave_struct *fx = &fpu->state->fxsave;
@@ -386,19 +386,17 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
 #ifdef CONFIG_X86_64
        env->fip = fxsave->rip;
        env->foo = fxsave->rdp;
+       /*
+        * should be actually ds/cs at fpu exception time, but
+        * that information is not available in 64bit mode.
+        */
+       env->fcs = task_pt_regs(tsk)->cs;
        if (tsk == current) {
-               /*
-                * should be actually ds/cs at fpu exception time, but
-                * that information is not available in 64bit mode.
-                */
-               asm("mov %%ds, %[fos]" : [fos] "=r" (env->fos));
-               asm("mov %%cs, %[fcs]" : [fcs] "=r" (env->fcs));
+               savesegment(ds, env->fos);
        } else {
-               struct pt_regs *regs = task_pt_regs(tsk);
-
-               env->fos = 0xffff0000 | tsk->thread.ds;
-               env->fcs = regs->cs;
+               env->fos = tsk->thread.ds;
        }
+       env->fos |= 0xffff0000;
 #else
        env->fip = fxsave->fip;
        env->fcs = (u16) fxsave->fcs | ((u32) fxsave->fop << 16);
index cafa7c80ac95714e7097ba06ff195cd6f285417f..20757cb2efa3121841f89bcbcd2f5e0ae0a6006c 100644 (file)
  * plus some generic x86 specific things if generic specifics makes
  * any sense at all.
  */
+static void init_8259A(int auto_eoi);
 
 static int i8259A_auto_eoi;
 DEFINE_RAW_SPINLOCK(i8259A_lock);
-static void mask_and_ack_8259A(unsigned int);
-static void mask_8259A(void);
-static void unmask_8259A(void);
-static void disable_8259A_irq(unsigned int irq);
-static void enable_8259A_irq(unsigned int irq);
-static void init_8259A(int auto_eoi);
-static int i8259A_irq_pending(unsigned int irq);
-
-struct irq_chip i8259A_chip = {
-       .name           = "XT-PIC",
-       .mask           = disable_8259A_irq,
-       .disable        = disable_8259A_irq,
-       .unmask         = enable_8259A_irq,
-       .mask_ack       = mask_and_ack_8259A,
-};
 
 /*
  * 8259A PIC functions to handle ISA devices:
@@ -68,7 +54,7 @@ unsigned int cached_irq_mask = 0xffff;
  */
 unsigned long io_apic_irqs;
 
-static void disable_8259A_irq(unsigned int irq)
+static void mask_8259A_irq(unsigned int irq)
 {
        unsigned int mask = 1 << irq;
        unsigned long flags;
@@ -82,7 +68,12 @@ static void disable_8259A_irq(unsigned int irq)
        raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-static void enable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(struct irq_data *data)
+{
+       mask_8259A_irq(data->irq);
+}
+
+static void unmask_8259A_irq(unsigned int irq)
 {
        unsigned int mask = ~(1 << irq);
        unsigned long flags;
@@ -96,6 +87,11 @@ static void enable_8259A_irq(unsigned int irq)
        raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
+static void enable_8259A_irq(struct irq_data *data)
+{
+       unmask_8259A_irq(data->irq);
+}
+
 static int i8259A_irq_pending(unsigned int irq)
 {
        unsigned int mask = 1<<irq;
@@ -117,7 +113,7 @@ static void make_8259A_irq(unsigned int irq)
        disable_irq_nosync(irq);
        io_apic_irqs &= ~(1<<irq);
        set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
-                                     "XT");
+                                     i8259A_chip.name);
        enable_irq(irq);
 }
 
@@ -150,8 +146,9 @@ static inline int i8259A_irq_real(unsigned int irq)
  * first, _then_ send the EOI, and the order of EOI
  * to the two 8259s is important!
  */
-static void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        unsigned int irqmask = 1 << irq;
        unsigned long flags;
 
@@ -223,6 +220,14 @@ spurious_8259A_irq:
        }
 }
 
+struct irq_chip i8259A_chip = {
+       .name           = "XT-PIC",
+       .irq_mask       = disable_8259A_irq,
+       .irq_disable    = disable_8259A_irq,
+       .irq_unmask     = enable_8259A_irq,
+       .irq_mask_ack   = mask_and_ack_8259A,
+};
+
 static char irq_trigger[2];
 /**
  * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
@@ -342,9 +347,9 @@ static void init_8259A(int auto_eoi)
                 * In AEOI mode we just have to mask the interrupt
                 * when acking.
                 */
-               i8259A_chip.mask_ack = disable_8259A_irq;
+               i8259A_chip.irq_mask_ack = disable_8259A_irq;
        else
-               i8259A_chip.mask_ack = mask_and_ack_8259A;
+               i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
 
        udelay(100);            /* wait for 8259A to initialize */
 
@@ -363,14 +368,6 @@ static void init_8259A(int auto_eoi)
 static void legacy_pic_noop(void) { };
 static void legacy_pic_uint_noop(unsigned int unused) { };
 static void legacy_pic_int_noop(int unused) { };
-
-static struct irq_chip dummy_pic_chip  = {
-       .name = "dummy pic",
-       .mask = legacy_pic_uint_noop,
-       .unmask = legacy_pic_uint_noop,
-       .disable = legacy_pic_uint_noop,
-       .mask_ack = legacy_pic_uint_noop,
-};
 static int legacy_pic_irq_pending_noop(unsigned int irq)
 {
        return 0;
@@ -378,7 +375,9 @@ static int legacy_pic_irq_pending_noop(unsigned int irq)
 
 struct legacy_pic null_legacy_pic = {
        .nr_legacy_irqs = 0,
-       .chip = &dummy_pic_chip,
+       .chip = &dummy_irq_chip,
+       .mask = legacy_pic_uint_noop,
+       .unmask = legacy_pic_uint_noop,
        .mask_all = legacy_pic_noop,
        .restore_mask = legacy_pic_noop,
        .init = legacy_pic_int_noop,
@@ -389,7 +388,9 @@ struct legacy_pic null_legacy_pic = {
 struct legacy_pic default_legacy_pic = {
        .nr_legacy_irqs = NR_IRQS_LEGACY,
        .chip  = &i8259A_chip,
-       .mask_all  = mask_8259A,
+       .mask = mask_8259A_irq,
+       .unmask = unmask_8259A_irq,
+       .mask_all = mask_8259A,
        .restore_mask = unmask_8259A,
        .init = init_8259A,
        .irq_pending = i8259A_irq_pending,
index 91fd0c70a18abddc28eff75e287c70dd5d37af7d..83ec0175f986a5742c2ef85eff69d24100cd44b6 100644 (file)
@@ -67,10 +67,10 @@ static int show_other_interrupts(struct seq_file *p, int prec)
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
        seq_printf(p, "  Performance monitoring interrupts\n");
-       seq_printf(p, "%*s: ", prec, "PND");
+       seq_printf(p, "%*s: ", prec, "IWI");
        for_each_online_cpu(j)
-               seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
-       seq_printf(p, "  Performance pending work\n");
+               seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs);
+       seq_printf(p, "  IRQ work interrupts\n");
 #endif
        if (x86_platform_ipi_callback) {
                seq_printf(p, "%*s: ", prec, "PLT");
@@ -159,7 +159,7 @@ int show_interrupts(struct seq_file *p, void *v)
        seq_printf(p, "%*d: ", prec, i);
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-       seq_printf(p, " %8s", desc->chip->name);
+       seq_printf(p, " %8s", desc->irq_data.chip->name);
        seq_printf(p, "-%-8s", desc->name);
 
        if (action) {
@@ -185,7 +185,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
        sum += irq_stats(cpu)->apic_timer_irqs;
        sum += irq_stats(cpu)->irq_spurious_count;
        sum += irq_stats(cpu)->apic_perf_irqs;
-       sum += irq_stats(cpu)->apic_pending_irqs;
+       sum += irq_stats(cpu)->apic_irq_work_irqs;
 #endif
        if (x86_platform_ipi_callback)
                sum += irq_stats(cpu)->x86_platform_ipis;
@@ -282,6 +282,7 @@ void fixup_irqs(void)
        unsigned int irq, vector;
        static int warned;
        struct irq_desc *desc;
+       struct irq_data *data;
 
        for_each_irq_desc(irq, desc) {
                int break_affinity = 0;
@@ -296,7 +297,8 @@ void fixup_irqs(void)
                /* interrupt's are disabled at this point */
                raw_spin_lock(&desc->lock);
 
-               affinity = desc->affinity;
+               data = &desc->irq_data;
+               affinity = data->affinity;
                if (!irq_has_action(irq) ||
                    cpumask_equal(affinity, cpu_online_mask)) {
                        raw_spin_unlock(&desc->lock);
@@ -315,16 +317,16 @@ void fixup_irqs(void)
                        affinity = cpu_all_mask;
                }
 
-               if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask)
-                       desc->chip->mask(irq);
+               if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_mask)
+                       data->chip->irq_mask(data);
 
-               if (desc->chip->set_affinity)
-                       desc->chip->set_affinity(irq, affinity);
+               if (data->chip->irq_set_affinity)
+                       data->chip->irq_set_affinity(data, affinity, true);
                else if (!(warned++))
                        set_affinity = 0;
 
-               if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask)
-                       desc->chip->unmask(irq);
+               if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_unmask)
+                       data->chip->irq_unmask(data);
 
                raw_spin_unlock(&desc->lock);
 
@@ -355,10 +357,10 @@ void fixup_irqs(void)
                if (irr  & (1 << (vector % 32))) {
                        irq = __get_cpu_var(vector_irq)[vector];
 
-                       desc = irq_to_desc(irq);
+                       data = irq_get_irq_data(irq);
                        raw_spin_lock(&desc->lock);
-                       if (desc->chip->retrigger)
-                               desc->chip->retrigger(irq);
+                       if (data->chip->irq_retrigger)
+                               data->chip->irq_retrigger(data);
                        raw_spin_unlock(&desc->lock);
                }
        }
index 10709f29d16610933c3bf7a860e43bac4740dcd0..50fbbe60e5074efcc11600616e32e21e3ca31551 100644 (file)
@@ -49,20 +49,19 @@ static inline int check_stack_overflow(void) { return 0; }
 static inline void print_stack_overflow(void) { }
 #endif
 
-#ifdef CONFIG_4KSTACKS
 /*
  * per-CPU IRQ handling contexts (thread information and stack)
  */
 union irq_ctx {
        struct thread_info      tinfo;
        u32                     stack[THREAD_SIZE/sizeof(u32)];
-} __attribute__((aligned(PAGE_SIZE)));
+} __attribute__((aligned(THREAD_SIZE)));
 
 static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
 static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
 
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, hardirq_stack, THREAD_SIZE);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, softirq_stack, THREAD_SIZE);
 
 static void call_on_stack(void *func, void *stack)
 {
@@ -187,11 +186,6 @@ asmlinkage void do_softirq(void)
        local_irq_restore(flags);
 }
 
-#else
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
-#endif
-
 bool handle_irq(unsigned irq, struct pt_regs *regs)
 {
        struct irq_desc *desc;
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
new file mode 100644 (file)
index 0000000..ca8f703
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * x86 specific code for irq_work
+ *
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq_work.h>
+#include <linux/hardirq.h>
+#include <asm/apic.h>
+
+void smp_irq_work_interrupt(struct pt_regs *regs)
+{
+       irq_enter();
+       ack_APIC_irq();
+       inc_irq_stat(apic_irq_work_irqs);
+       irq_work_run();
+       irq_exit();
+}
+
+void arch_irq_work_raise(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+       if (!cpu_has_apic)
+               return;
+
+       apic->send_IPI_self(IRQ_WORK_VECTOR);
+       apic_wait_icr_idle();
+#endif
+}
index 990ae7cfc5783f131df476506bc9341574a466c2..c752e973958d447ca2d34179df67a7af04c8a0bb 100644 (file)
@@ -100,6 +100,8 @@ int vector_used_by_percpu_irq(unsigned int vector)
 
 void __init init_ISA_irqs(void)
 {
+       struct irq_chip *chip = legacy_pic->chip;
+       const char *name = chip->name;
        int i;
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
@@ -107,19 +109,8 @@ void __init init_ISA_irqs(void)
 #endif
        legacy_pic->init(0);
 
-       /*
-        * 16 old-style INTA-cycle interrupts:
-        */
-       for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {
-               struct irq_desc *desc = irq_to_desc(i);
-
-               desc->status = IRQ_DISABLED;
-               desc->action = NULL;
-               desc->depth = 1;
-
-               set_irq_chip_and_handler_name(i, &i8259A_chip,
-                                             handle_level_irq, "XT");
-       }
+       for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+               set_irq_chip_and_handler_name(i, chip, handle_level_irq, name);
 }
 
 void __init init_IRQ(void)
@@ -224,9 +215,9 @@ static void __init apic_intr_init(void)
        alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
        alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 
-       /* Performance monitoring interrupts: */
-# ifdef CONFIG_PERF_EVENTS
-       alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+       /* IRQ work interrupts: */
+# ifdef CONFIG_IRQ_WORK
+       alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt);
 # endif
 
 #endif
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..961b6b3
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * jump label x86 support
+ *
+ * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ *
+ */
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/cpu.h>
+#include <asm/kprobes.h>
+#include <asm/alternative.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+union jump_code_union {
+       char code[JUMP_LABEL_NOP_SIZE];
+       struct {
+               char jump;
+               int offset;
+       } __attribute__((packed));
+};
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       union jump_code_union code;
+
+       if (type == JUMP_LABEL_ENABLE) {
+               code.jump = 0xe9;
+               code.offset = entry->target -
+                               (entry->code + JUMP_LABEL_NOP_SIZE);
+       } else
+               memcpy(&code, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+       get_online_cpus();
+       mutex_lock(&text_mutex);
+       text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+       mutex_unlock(&text_mutex);
+       put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+       text_poke_early((void *)addr, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+}
+
+#endif
index 8afd9f321f100de0a8ddc236f1f411d4d98680ad..90fcf62854bbac679eec40879db54df2ed6d09b5 100644 (file)
@@ -78,6 +78,7 @@ static int setup_data_open(struct inode *inode, struct file *file)
 static const struct file_operations fops_setup_data = {
        .read           = setup_data_read,
        .open           = setup_data_open,
+       .llseek         = default_llseek,
 };
 
 static int __init
index 770ebfb349e93efe3367cf0c6caff93b61b8b884..1cbd54c0df99189548a3a03f40fbb75a1703475a 100644 (file)
@@ -230,9 +230,6 @@ static int recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
        return 0;
 }
 
-/* Dummy buffers for kallsyms_lookup */
-static char __dummy_buf[KSYM_NAME_LEN];
-
 /* Check if paddr is at an instruction boundary */
 static int __kprobes can_probe(unsigned long paddr)
 {
@@ -241,7 +238,7 @@ static int __kprobes can_probe(unsigned long paddr)
        struct insn insn;
        kprobe_opcode_t buf[MAX_INSN_SIZE];
 
-       if (!kallsyms_lookup(paddr, NULL, &offset, NULL, __dummy_buf))
+       if (!kallsyms_lookup_size_offset(paddr, NULL, &offset))
                return 0;
 
        /* Decode instructions */
@@ -1129,7 +1126,7 @@ static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr,
        *(unsigned long *)addr = val;
 }
 
-void __kprobes kprobes_optinsn_template_holder(void)
+static void __used __kprobes kprobes_optinsn_template_holder(void)
 {
        asm volatile (
                        ".global optprobe_template_entry\n"
@@ -1221,7 +1218,8 @@ static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
        }
        /* Check whether the address range is reserved */
        if (ftrace_text_reserved(src, src + len - 1) ||
-           alternatives_text_reserved(src, src + len - 1))
+           alternatives_text_reserved(src, src + len - 1) ||
+           jump_label_text_reserved(src, src + len - 1))
                return -EBUSY;
 
        return len;
@@ -1269,11 +1267,9 @@ static int __kprobes can_optimize(unsigned long paddr)
        unsigned long addr, size = 0, offset = 0;
        struct insn insn;
        kprobe_opcode_t buf[MAX_INSN_SIZE];
-       /* Dummy buffers for lookup_symbol_attrs */
-       static char __dummy_buf[KSYM_NAME_LEN];
 
        /* Lookup symbol including addr */
-       if (!kallsyms_lookup(paddr, &size, &offset, NULL, __dummy_buf))
+       if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
                return 0;
 
        /* Check there is enough space for a relative jump. */
index 035c8c529181fa351c042f8d6a5b8ec3240dec8f..b3ea9db39db6f7ee9f9dab00632f754d8a75827d 100644 (file)
@@ -36,7 +36,7 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
                if (!page)
                        goto out;
                pud = (pud_t *)page_address(page);
-               memset(pud, 0, PAGE_SIZE);
+               clear_page(pud);
                set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
        }
        pud = pud_offset(pgd, addr);
@@ -45,7 +45,7 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
                if (!page)
                        goto out;
                pmd = (pmd_t *)page_address(page);
-               memset(pmd, 0, PAGE_SIZE);
+               clear_page(pmd);
                set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
        }
        pmd = pmd_offset(pud, addr);
index fa6551d36c102105c8654c7d4f60f82e65990822..0b3d37e83606b441f69a913a4f919e617b020920 100644 (file)
@@ -232,6 +232,7 @@ static const struct file_operations microcode_fops = {
        .owner                  = THIS_MODULE,
        .write                  = microcode_write,
        .open                   = microcode_open,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice microcode_dev = {
index e0bc186d7501f123265ae288ae071e772016e89b..8f295609173524cdf06a20c6c0ad4fbe1de12263 100644 (file)
@@ -239,11 +239,13 @@ int module_finalize(const Elf_Ehdr *hdr,
                apply_paravirt(pseg, pseg + para->sh_size);
        }
 
-       return module_bug_finalize(hdr, sechdrs, me);
+       /* make jump label nops */
+       jump_label_apply_nops(me);
+
+       return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
        alternatives_smp_module_del(mod);
-       module_bug_cleanup(mod);
 }
index d7b6f7fb4fecfd44205d63ab6cfebfb400e8b21a..9af64d9c4b6770c4fea928f6b2a9533c1f4620e8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/bitops.h>
@@ -657,7 +658,7 @@ static void __init smp_reserve_memory(struct mpf_intel *mpf)
 {
        unsigned long size = get_mpc_size(mpf->physptr);
 
-       reserve_early_overlap_ok(mpf->physptr, mpf->physptr+size, "MP-table mpc");
+       memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc");
 }
 
 static int __init smp_scan_config(unsigned long base, unsigned long length)
@@ -686,7 +687,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
                               mpf, (u64)virt_to_phys(mpf));
 
                        mem = virt_to_phys(mpf);
-                       reserve_early_overlap_ok(mem, mem + sizeof(*mpf), "MP-table mpf");
+                       memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf");
                        if (mpf->physptr)
                                smp_reserve_memory(mpf);
 
diff --git a/arch/x86/kernel/olpc-xo1.c b/arch/x86/kernel/olpc-xo1.c
new file mode 100644 (file)
index 0000000..f5442c0
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Support for features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1"
+
+#define PMS_BAR                4
+#define ACPI_BAR       5
+
+/* PMC registers (PMS block) */
+#define PM_SCLK                0x10
+#define PM_IN_SLPCTL   0x20
+#define PM_WKXD                0x34
+#define PM_WKD         0x30
+#define PM_SSC         0x54
+
+/* PM registers (ACPI block) */
+#define PM1_CNT                0x08
+#define PM_GPE0_STS    0x18
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static void xo1_power_off(void)
+{
+       printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+       /* Enable all of these controls with 0 delay */
+       outl(0x40000000, pms_base + PM_SCLK);
+       outl(0x40000000, pms_base + PM_IN_SLPCTL);
+       outl(0x40000000, pms_base + PM_WKXD);
+       outl(0x40000000, pms_base + PM_WKD);
+
+       /* Clear status bits (possibly unnecessary) */
+       outl(0x0002ffff, pms_base  + PM_SSC);
+       outl(0xffffffff, acpi_base + PM_GPE0_STS);
+
+       /* Write SLP_EN bit to start the machinery */
+       outl(0x00002000, acpi_base + PM1_CNT);
+}
+
+/* Read the base addresses from the PCI BAR info */
+static int __devinit setup_bases(struct pci_dev *pdev)
+{
+       int r;
+
+       r = pci_enable_device_io(pdev);
+       if (r) {
+               dev_err(&pdev->dev, "can't enable device IO\n");
+               return r;
+       }
+
+       r = pci_request_region(pdev, ACPI_BAR, DRV_NAME);
+       if (r) {
+               dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR);
+               return r;
+       }
+
+       r = pci_request_region(pdev, PMS_BAR, DRV_NAME);
+       if (r) {
+               dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR);
+               pci_release_region(pdev, ACPI_BAR);
+               return r;
+       }
+
+       acpi_base = pci_resource_start(pdev, ACPI_BAR);
+       pms_base = pci_resource_start(pdev, PMS_BAR);
+
+       return 0;
+}
+
+static int __devinit olpc_xo1_probe(struct platform_device *pdev)
+{
+       struct pci_dev *pcidev;
+       int r;
+
+       pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+                               NULL);
+       if (!pdev)
+               return -ENODEV;
+
+       r = setup_bases(pcidev);
+       if (r)
+               return r;
+
+       pm_power_off = xo1_power_off;
+
+       printk(KERN_INFO "OLPC XO-1 support registered\n");
+       return 0;
+}
+
+static int __devexit olpc_xo1_remove(struct platform_device *pdev)
+{
+       pm_power_off = NULL;
+       return 0;
+}
+
+static struct platform_driver olpc_xo1_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = olpc_xo1_probe,
+       .remove = __devexit_p(olpc_xo1_remove),
+};
+
+static int __init olpc_xo1_init(void)
+{
+       return platform_driver_register(&olpc_xo1_driver);
+}
+
+static void __exit olpc_xo1_exit(void)
+{
+       platform_driver_unregister(&olpc_xo1_driver);
+}
+
+MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:olpc-xo1");
+
+module_init(olpc_xo1_init);
+module_exit(olpc_xo1_exit);
index 0e0cdde519be93a3cda8bab4ba6d8637632171ef..edaf3fe8dc5e4b0326c0280042b868cd3400bf4c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/string.h>
+#include <linux/platform_device.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -114,6 +115,7 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
        unsigned long flags;
        int ret = -EIO;
        int i;
+       int restarts = 0;
 
        spin_lock_irqsave(&ec_lock, flags);
 
@@ -169,7 +171,9 @@ restart:
                        if (wait_on_obf(0x6c, 1)) {
                                printk(KERN_ERR "olpc-ec:  timeout waiting for"
                                                " EC to provide data!\n");
-                               goto restart;
+                               if (restarts++ < 10)
+                                       goto restart;
+                               goto err;
                        }
                        outbuf[i] = inb(0x68);
                        pr_devel("olpc-ec:  received 0x%x\n", outbuf[i]);
@@ -183,8 +187,21 @@ err:
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
-static void __init platform_detect(void)
+static bool __init check_ofw_architecture(void)
+{
+       size_t propsize;
+       char olpc_arch[5];
+       const void *args[] = { NULL, "architecture", olpc_arch, (void *)5 };
+       void *res[] = { &propsize };
+
+       if (olpc_ofw("getprop", args, res)) {
+               printk(KERN_ERR "ofw: getprop call failed!\n");
+               return false;
+       }
+       return propsize == 5 && strncmp("OLPC", olpc_arch, 5) == 0;
+}
+
+static u32 __init get_board_revision(void)
 {
        size_t propsize;
        __be32 rev;
@@ -193,45 +210,43 @@ static void __init platform_detect(void)
 
        if (olpc_ofw("getprop", args, res) || propsize != 4) {
                printk(KERN_ERR "ofw: getprop call failed!\n");
-               rev = cpu_to_be32(0);
+               return cpu_to_be32(0);
        }
-       olpc_platform_info.boardrev = be32_to_cpu(rev);
+       return be32_to_cpu(rev);
 }
-#else
-static void __init platform_detect(void)
+
+static bool __init platform_detect(void)
 {
-       /* stopgap until OFW support is added to the kernel */
-       olpc_platform_info.boardrev = olpc_board(0xc2);
+       if (!check_ofw_architecture())
+               return false;
+       olpc_platform_info.flags |= OLPC_F_PRESENT;
+       olpc_platform_info.boardrev = get_board_revision();
+       return true;
 }
-#endif
 
-static int __init olpc_init(void)
+static int __init add_xo1_platform_devices(void)
 {
-       unsigned char *romsig;
+       struct platform_device *pdev;
 
-       /* The ioremap check is dangerous; limit what we run it on */
-       if (!is_geode() || cs5535_has_vsa2())
-               return 0;
+       pdev = platform_device_register_simple("xo1-rfkill", -1, NULL, 0);
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
 
-       spin_lock_init(&ec_lock);
+       pdev = platform_device_register_simple("olpc-xo1", -1, NULL, 0);
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
 
-       romsig = ioremap(0xffffffc0, 16);
-       if (!romsig)
-               return 0;
+       return 0;
+}
 
-       if (strncmp(romsig, "CL1   Q", 7))
-               goto unmap;
-       if (strncmp(romsig+6, romsig+13, 3)) {
-               printk(KERN_INFO "OLPC BIOS signature looks invalid.  "
-                               "Assuming not OLPC\n");
-               goto unmap;
-       }
+static int __init olpc_init(void)
+{
+       int r = 0;
 
-       printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig);
-       olpc_platform_info.flags |= OLPC_F_PRESENT;
+       if (!olpc_ofw_present() || !platform_detect())
+               return 0;
 
-       /* get the platform revision */
-       platform_detect();
+       spin_lock_init(&ec_lock);
 
        /* assume B1 and above models always have a DCON */
        if (olpc_board_at_least(olpc_board(0xb1)))
@@ -242,8 +257,10 @@ static int __init olpc_init(void)
                        (unsigned char *) &olpc_platform_info.ecver, 1);
 
 #ifdef CONFIG_PCI_OLPC
-       /* If the VSA exists let it emulate PCI, if not emulate in kernel */
-       if (!cs5535_has_vsa2())
+       /* If the VSA exists let it emulate PCI, if not emulate in kernel.
+        * XO-1 only. */
+       if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) &&
+                       !cs5535_has_vsa2())
                x86_init.pci.arch_init = pci_olpc_init;
 #endif
 
@@ -252,8 +269,12 @@ static int __init olpc_init(void)
                        olpc_platform_info.boardrev >> 4,
                        olpc_platform_info.ecver);
 
-unmap:
-       iounmap(romsig);
+       if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */
+               r = add_xo1_platform_devices();
+               if (r)
+                       return r;
+       }
+
        return 0;
 }
 
index 3218aa71ab5ebb7dd20a7d1dd94cfd88dcb3d755..787320464379f976626e22fb2d62a83730ccbf52 100644 (file)
@@ -74,6 +74,12 @@ int __olpc_ofw(const char *name, int nr_args, const void **args, int nr_res,
 }
 EXPORT_SYMBOL_GPL(__olpc_ofw);
 
+bool olpc_ofw_present(void)
+{
+       return olpc_ofw_cif != NULL;
+}
+EXPORT_SYMBOL_GPL(olpc_ofw_present);
+
 /* OFW cif _should_ be above this address */
 #define OFW_MIN 0xff000000
 
index 1db183ed7c01cb929cef9dc3fc6e1f1153841e59..c5b250011fd479aa8ecc8f8348ade0b096a7aa08 100644 (file)
@@ -413,7 +413,6 @@ struct pv_mmu_ops pv_mmu_ops = {
 
        .alloc_pte = paravirt_nop,
        .alloc_pmd = paravirt_nop,
-       .alloc_pmd_clone = paravirt_nop,
        .alloc_pud = paravirt_nop,
        .release_pte = paravirt_nop,
        .release_pmd = paravirt_nop,
index 078d4ec1a9d92d462c27e0cd6f7bb095b2838526..f56a117cef68999ceeab576e2ef2b116a4fa9db2 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/rio.h>
 #include <asm/bios_ebda.h>
 #include <asm/x86_init.h>
+#include <asm/iommu_table.h>
 
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
@@ -1364,7 +1365,7 @@ static int __init calgary_iommu_init(void)
        return 0;
 }
 
-void __init detect_calgary(void)
+int __init detect_calgary(void)
 {
        int bus;
        void *tbl;
@@ -1378,13 +1379,13 @@ void __init detect_calgary(void)
         * another HW IOMMU already, bail out.
         */
        if (no_iommu || iommu_detected)
-               return;
+               return -ENODEV;
 
        if (!use_calgary)
-               return;
+               return -ENODEV;
 
        if (!early_pci_allowed())
-               return;
+               return -ENODEV;
 
        printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");
 
@@ -1410,13 +1411,13 @@ void __init detect_calgary(void)
        if (!rio_table_hdr) {
                printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
                       "in EBDA - bailing!\n");
-               return;
+               return -ENODEV;
        }
 
        ret = build_detail_arrays();
        if (ret) {
                printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
-               return;
+               return -ENOMEM;
        }
 
        specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
@@ -1464,7 +1465,7 @@ void __init detect_calgary(void)
 
                x86_init.iommu.iommu_init = calgary_iommu_init;
        }
-       return;
+       return calgary_found;
 
 cleanup:
        for (--bus; bus >= 0; --bus) {
@@ -1473,6 +1474,7 @@ cleanup:
                if (info->tce_space)
                        free_tce_table(info->tce_space);
        }
+       return -ENOMEM;
 }
 
 static int __init calgary_parse_options(char *p)
@@ -1594,3 +1596,5 @@ static int __init calgary_fixup_tce_spaces(void)
  * and before device_initcall.
  */
 rootfs_initcall(calgary_fixup_tce_spaces);
+
+IOMMU_INIT_POST(detect_calgary);
index 9f07cfcbd3a5e60db651c952c9a66fa21dd68d87..9ea999a4dcc178ce4e27dd069a957ff050d1dee7 100644 (file)
@@ -11,9 +11,8 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/calgary.h>
-#include <asm/amd_iommu.h>
 #include <asm/x86_init.h>
-#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
 
 static int forbid_dac __read_mostly;
 
@@ -45,6 +44,8 @@ int iommu_detected __read_mostly = 0;
  */
 int iommu_pass_through __read_mostly;
 
+extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
+
 /* Dummy device used for NULL arguments (normally ISA). */
 struct device x86_dma_fallback_dev = {
        .init_name = "fallback device",
@@ -130,26 +131,24 @@ static void __init dma32_free_bootmem(void)
 
 void __init pci_iommu_alloc(void)
 {
+       struct iommu_table_entry *p;
+
        /* free the range so iommu could get some range less than 4G */
        dma32_free_bootmem();
 
-       if (pci_xen_swiotlb_detect() || pci_swiotlb_detect())
-               goto out;
-
-       gart_iommu_hole_init();
-
-       detect_calgary();
-
-       detect_intel_iommu();
+       sort_iommu_table(__iommu_table, __iommu_table_end);
+       check_iommu_entries(__iommu_table, __iommu_table_end);
 
-       /* needs to be called after gart_iommu_hole_init */
-       amd_iommu_detect();
-out:
-       pci_xen_swiotlb_init();
-
-       pci_swiotlb_init();
+       for (p = __iommu_table; p < __iommu_table_end; p++) {
+               if (p && p->detect && p->detect() > 0) {
+                       p->flags |= IOMMU_DETECTED;
+                       if (p->early_init)
+                               p->early_init();
+                       if (p->flags & IOMMU_FINISH_IF_DETECTED)
+                               break;
+               }
+       }
 }
-
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
                                 dma_addr_t *dma_addr, gfp_t flag)
 {
@@ -292,6 +291,7 @@ EXPORT_SYMBOL(dma_supported);
 
 static int __init pci_iommu_init(void)
 {
+       struct iommu_table_entry *p;
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
 
 #ifdef CONFIG_PCI
@@ -299,12 +299,10 @@ static int __init pci_iommu_init(void)
 #endif
        x86_init.iommu.iommu_init();
 
-       if (swiotlb || xen_swiotlb) {
-               printk(KERN_INFO "PCI-DMA: "
-                      "Using software bounce buffering for IO (SWIOTLB)\n");
-               swiotlb_print_info();
-       } else
-               swiotlb_free();
+       for (p = __iommu_table; p < __iommu_table_end; p++) {
+               if (p && (p->flags & IOMMU_DETECTED) && p->late_init)
+                       p->late_init();
+       }
 
        return 0;
 }
index 0f7f130caa6778d6077868e6e768b88f1439fc24..ba0f0ca9f280bb0473470fdb71a3fa04faec00f0 100644 (file)
@@ -39,8 +39,9 @@
 #include <asm/cacheflush.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/x86_init.h>
+#include <asm/iommu_table.h>
 
 static unsigned long iommu_bus_base;   /* GART remapping area (physical) */
 static unsigned long iommu_size;       /* size of remapping area bytes */
@@ -560,8 +561,11 @@ static void enable_gart_translations(void)
 {
        int i;
 
-       for (i = 0; i < num_k8_northbridges; i++) {
-               struct pci_dev *dev = k8_northbridges[i];
+       if (!k8_northbridges.gart_supported)
+               return;
+
+       for (i = 0; i < k8_northbridges.num; i++) {
+               struct pci_dev *dev = k8_northbridges.nb_misc[i];
 
                enable_gart_translation(dev, __pa(agp_gatt_table));
        }
@@ -592,16 +596,19 @@ static void gart_fixup_northbridges(struct sys_device *dev)
        if (!fix_up_north_bridges)
                return;
 
+       if (!k8_northbridges.gart_supported)
+               return;
+
        pr_info("PCI-DMA: Restoring GART aperture settings\n");
 
-       for (i = 0; i < num_k8_northbridges; i++) {
-               struct pci_dev *dev = k8_northbridges[i];
+       for (i = 0; i < k8_northbridges.num; i++) {
+               struct pci_dev *dev = k8_northbridges.nb_misc[i];
 
                /*
                 * Don't enable translations just yet.  That is the next
                 * step.  Restore the pre-suspend aperture settings.
                 */
-               pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1);
+               gart_set_size_and_enable(dev, aperture_order);
                pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);
        }
 }
@@ -649,8 +656,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
 
        aper_size = aper_base = info->aper_size = 0;
        dev = NULL;
-       for (i = 0; i < num_k8_northbridges; i++) {
-               dev = k8_northbridges[i];
+       for (i = 0; i < k8_northbridges.num; i++) {
+               dev = k8_northbridges.nb_misc[i];
                new_aper_base = read_aperture(dev, &new_aper_size);
                if (!new_aper_base)
                        goto nommu;
@@ -718,10 +725,13 @@ static void gart_iommu_shutdown(void)
        if (!no_agp)
                return;
 
-       for (i = 0; i < num_k8_northbridges; i++) {
+       if (!k8_northbridges.gart_supported)
+               return;
+
+       for (i = 0; i < k8_northbridges.num; i++) {
                u32 ctl;
 
-               dev = k8_northbridges[i];
+               dev = k8_northbridges.nb_misc[i];
                pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
 
                ctl &= ~GARTEN;
@@ -739,7 +749,7 @@ int __init gart_iommu_init(void)
        unsigned long scratch;
        long i;
 
-       if (num_k8_northbridges == 0)
+       if (!k8_northbridges.gart_supported)
                return 0;
 
 #ifndef CONFIG_AGP_AMD64
@@ -896,3 +906,4 @@ void __init gart_parse_options(char *p)
                }
        }
 }
+IOMMU_INIT_POST(gart_iommu_hole_init);
diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c
new file mode 100644 (file)
index 0000000..55d745e
--- /dev/null
@@ -0,0 +1,89 @@
+#include <linux/dma-mapping.h>
+#include <asm/iommu_table.h>
+#include <linux/string.h>
+#include <linux/kallsyms.h>
+
+
+#define DEBUG 1
+
+static struct iommu_table_entry * __init
+find_dependents_of(struct iommu_table_entry *start,
+                  struct iommu_table_entry *finish,
+                  struct iommu_table_entry *q)
+{
+       struct iommu_table_entry *p;
+
+       if (!q)
+               return NULL;
+
+       for (p = start; p < finish; p++)
+               if (p->detect == q->depend)
+                       return p;
+
+       return NULL;
+}
+
+
+void __init sort_iommu_table(struct iommu_table_entry *start,
+                            struct iommu_table_entry *finish) {
+
+       struct iommu_table_entry *p, *q, tmp;
+
+       for (p = start; p < finish; p++) {
+again:
+               q = find_dependents_of(start, finish, p);
+               /* We are bit sneaky here. We use the memory address to figure
+                * out if the node we depend on is past our point, if so, swap.
+                */
+               if (q > p) {
+                       tmp = *p;
+                       memmove(p, q, sizeof(*p));
+                       *q = tmp;
+                       goto again;
+               }
+       }
+
+}
+
+#ifdef DEBUG
+void __init check_iommu_entries(struct iommu_table_entry *start,
+                               struct iommu_table_entry *finish)
+{
+       struct iommu_table_entry *p, *q, *x;
+       char sym_p[KSYM_SYMBOL_LEN];
+       char sym_q[KSYM_SYMBOL_LEN];
+
+       /* Simple cyclic dependency checker. */
+       for (p = start; p < finish; p++) {
+               q = find_dependents_of(start, finish, p);
+               x = find_dependents_of(start, finish, q);
+               if (p == x) {
+                       sprint_symbol(sym_p, (unsigned long)p->detect);
+                       sprint_symbol(sym_q, (unsigned long)q->detect);
+
+                       printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %s depends" \
+                                       " on %s and vice-versa. BREAKING IT.\n",
+                                       sym_p, sym_q);
+                       /* Heavy handed way..*/
+                       x->depend = 0;
+               }
+       }
+
+       for (p = start; p < finish; p++) {
+               q = find_dependents_of(p, finish, p);
+               if (q && q > p) {
+                       sprint_symbol(sym_p, (unsigned long)p->detect);
+                       sprint_symbol(sym_q, (unsigned long)q->detect);
+
+                       printk(KERN_ERR "EXECUTION ORDER INVALID! %s "\
+                                       "should be called before %s!\n",
+                                       sym_p, sym_q);
+               }
+       }
+}
+#else
+inline void check_iommu_entries(struct iommu_table_entry *start,
+                                      struct iommu_table_entry *finish)
+{
+}
+#endif
index a5bc528d43282a344936922328d2b5bf59b187ae..8f972cbddef0c390df0a386ff4d08a8c20865ea1 100644 (file)
@@ -10,7 +10,8 @@
 #include <asm/iommu.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-
+#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
 int swiotlb __read_mostly;
 
 static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -41,25 +42,42 @@ static struct dma_map_ops swiotlb_dma_ops = {
 };
 
 /*
- * pci_swiotlb_detect - set swiotlb to 1 if necessary
+ * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
  * option).
  */
-int __init pci_swiotlb_detect(void)
+int __init pci_swiotlb_detect_override(void)
 {
        int use_swiotlb = swiotlb | swiotlb_force;
 
+       if (swiotlb_force)
+               swiotlb = 1;
+
+       return use_swiotlb;
+}
+IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
+                 pci_xen_swiotlb_detect,
+                 pci_swiotlb_init,
+                 pci_swiotlb_late_init);
+
+/*
+ * if 4GB or more detected (and iommu=off not set) return 1
+ * and set swiotlb to 1.
+ */
+int __init pci_swiotlb_detect_4gb(void)
+{
        /* don't initialize swiotlb if iommu=off (no_iommu=1) */
 #ifdef CONFIG_X86_64
        if (!no_iommu && max_pfn > MAX_DMA32_PFN)
                swiotlb = 1;
 #endif
-       if (swiotlb_force)
-               swiotlb = 1;
-
-       return use_swiotlb;
+       return swiotlb;
 }
+IOMMU_INIT(pci_swiotlb_detect_4gb,
+          pci_swiotlb_detect_override,
+          pci_swiotlb_init,
+          pci_swiotlb_late_init);
 
 void __init pci_swiotlb_init(void)
 {
@@ -68,3 +86,15 @@ void __init pci_swiotlb_init(void)
                dma_ops = &swiotlb_dma_ops;
        }
 }
+
+void __init pci_swiotlb_late_init(void)
+{
+       /* An IOMMU turned us off. */
+       if (!swiotlb)
+               swiotlb_free();
+       else {
+               printk(KERN_INFO "PCI-DMA: "
+                      "Using software bounce buffering for IO (SWIOTLB)\n");
+               swiotlb_print_info();
+       }
+}
diff --git a/arch/x86/kernel/pmtimer_64.c b/arch/x86/kernel/pmtimer_64.c
deleted file mode 100644 (file)
index b112406..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Ported over from i386 by AK, original copyright was:
- *
- * (C) Dominik Brodowski <linux@brodo.de> 2003
- *
- * Driver to use the Power Management Timer (PMTMR) available in some
- * southbridges as primary timing source for the Linux kernel.
- *
- * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
- * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
- *
- * This file is licensed under the GPL v2.
- *
- * Dropped all the hardware bug workarounds for now. Hopefully they
- * are not needed on 64bit chipsets.
- */
-
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/cpumask.h>
-#include <linux/acpi_pmtmr.h>
-
-#include <asm/io.h>
-#include <asm/proto.h>
-#include <asm/msr.h>
-#include <asm/vsyscall.h>
-
-static inline u32 cyc2us(u32 cycles)
-{
-       /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
-        * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
-        *
-        * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
-        * easily be multiplied with 286 (=0x11E) without having to fear
-        * u32 overflows.
-        */
-       cycles *= 286;
-       return (cycles >> 10);
-}
-
-static unsigned pmtimer_wait_tick(void)
-{
-       u32 a, b;
-       for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
-            a == b;
-            b = inl(pmtmr_ioport) & ACPI_PM_MASK)
-               cpu_relax();
-       return b;
-}
-
-/* note: wait time is rounded up to one tick */
-void pmtimer_wait(unsigned us)
-{
-       u32 a, b;
-       a = pmtimer_wait_tick();
-       do {
-               b = inl(pmtmr_ioport);
-               cpu_relax();
-       } while (cyc2us(b - a) < us);
-}
-
-static int __init nopmtimer_setup(char *s)
-{
-       pmtmr_ioport = 0;
-       return 1;
-}
-
-__setup("nopmtimer", nopmtimer_setup);
index 3d9ea531ddd1bfa8cc9e2e28fbfa8a22f461bc20..b3d7a3a04f389d9626837a1e776c5106e821f7dc 100644 (file)
@@ -424,7 +424,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        load_TLS(next, cpu);
 
        /* Must be after DS reload */
-       unlazy_fpu(prev_p);
+       __unlazy_fpu(prev_p);
 
        /* Make sure cpu is ready for new context */
        if (preload_fpu)
index e3af342fe83ae7a57b8f6db6de4fb9541c4ab15e..7a4cf14223ba3288384909657d49edff7371623e 100644 (file)
@@ -84,7 +84,7 @@ static int __init reboot_setup(char *str)
                        }
                                /* we will leave sorting out the final value
                                   when we are ready to reboot, since we might not
-                                  have set up boot_cpu_id or smp_num_cpu */
+                                  have detected BSP APIC ID or smp_num_cpu */
                        break;
 #endif /* CONFIG_SMP */
 
index c3a4fbb2b996d00277d6523cb76b74e2c5944621..420e6419785025f39c1e4095a9d7e6f558c8a1db 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/apm_bios.h>
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
 #include <linux/mca.h>
@@ -83,7 +84,6 @@
 #include <asm/dmi.h>
 #include <asm/io_apic.h>
 #include <asm/ist.h>
-#include <asm/vmi.h>
 #include <asm/setup_arch.h>
 #include <asm/bios_ebda.h>
 #include <asm/cacheflush.h>
 #include <asm/percpu.h>
 #include <asm/topology.h>
 #include <asm/apicdef.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #ifdef CONFIG_X86_64
 #include <asm/numa_64.h>
 #endif
 #include <asm/mce.h>
+#include <asm/alternative.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -125,7 +126,6 @@ unsigned long max_pfn_mapped;
 RESERVE_BRK(dmi_alloc, 65536);
 #endif
 
-unsigned int boot_cpu_id __read_mostly;
 
 static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
 unsigned long _brk_end = (unsigned long)__brk_base;
@@ -302,7 +302,7 @@ static inline void init_gbpages(void)
 static void __init reserve_brk(void)
 {
        if (_brk_end > _brk_start)
-               reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
+               memblock_x86_reserve_range(__pa(_brk_start), __pa(_brk_end), "BRK");
 
        /* Mark brk area as locked down and no longer taking any
           new allocations */
@@ -324,17 +324,16 @@ static void __init relocate_initrd(void)
        char *p, *q;
 
        /* We need to move the initrd down into lowmem */
-       ramdisk_here = find_e820_area(0, end_of_lowmem, area_size,
+       ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size,
                                         PAGE_SIZE);
 
-       if (ramdisk_here == -1ULL)
+       if (ramdisk_here == MEMBLOCK_ERROR)
                panic("Cannot find place for new RAMDISK of size %lld\n",
                         ramdisk_size);
 
        /* Note: this includes all the lowmem currently occupied by
           the initrd, we rely on that fact to keep the data intact. */
-       reserve_early(ramdisk_here, ramdisk_here + area_size,
-                        "NEW RAMDISK");
+       memblock_x86_reserve_range(ramdisk_here, ramdisk_here + area_size, "NEW RAMDISK");
        initrd_start = ramdisk_here + PAGE_OFFSET;
        initrd_end   = initrd_start + ramdisk_size;
        printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
@@ -390,7 +389,7 @@ static void __init reserve_initrd(void)
        initrd_start = 0;
 
        if (ramdisk_size >= (end_of_lowmem>>1)) {
-               free_early(ramdisk_image, ramdisk_end);
+               memblock_x86_free_range(ramdisk_image, ramdisk_end);
                printk(KERN_ERR "initrd too large to handle, "
                       "disabling initrd\n");
                return;
@@ -413,7 +412,7 @@ static void __init reserve_initrd(void)
 
        relocate_initrd();
 
-       free_early(ramdisk_image, ramdisk_end);
+       memblock_x86_free_range(ramdisk_image, ramdisk_end);
 }
 #else
 static void __init reserve_initrd(void)
@@ -469,7 +468,7 @@ static void __init e820_reserve_setup_data(void)
        e820_print_map("reserve setup_data");
 }
 
-static void __init reserve_early_setup_data(void)
+static void __init memblock_x86_reserve_range_setup_data(void)
 {
        struct setup_data *data;
        u64 pa_data;
@@ -481,7 +480,7 @@ static void __init reserve_early_setup_data(void)
        while (pa_data) {
                data = early_memremap(pa_data, sizeof(*data));
                sprintf(buf, "setup data %x", data->type);
-               reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+               memblock_x86_reserve_range(pa_data, pa_data+sizeof(*data)+data->len, buf);
                pa_data = data->next;
                early_iounmap(data, sizeof(*data));
        }
@@ -502,6 +501,7 @@ static inline unsigned long long get_total_mem(void)
        return total << PAGE_SHIFT;
 }
 
+#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
 static void __init reserve_crashkernel(void)
 {
        unsigned long long total_mem;
@@ -519,23 +519,27 @@ static void __init reserve_crashkernel(void)
        if (crash_base <= 0) {
                const unsigned long long alignment = 16<<20;    /* 16M */
 
-               crash_base = find_e820_area(alignment, ULONG_MAX, crash_size,
-                                alignment);
-               if (crash_base == -1ULL) {
+               /*
+                *  kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX
+                */
+               crash_base = memblock_find_in_range(alignment,
+                              DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment);
+
+               if (crash_base == MEMBLOCK_ERROR) {
                        pr_info("crashkernel reservation failed - No suitable area found.\n");
                        return;
                }
        } else {
                unsigned long long start;
 
-               start = find_e820_area(crash_base, ULONG_MAX, crash_size,
-                                1<<20);
+               start = memblock_find_in_range(crash_base,
+                                crash_base + crash_size, crash_size, 1<<20);
                if (start != crash_base) {
                        pr_info("crashkernel reservation failed - memory is in use.\n");
                        return;
                }
        }
-       reserve_early(crash_base, crash_base + crash_size, "CRASH KERNEL");
+       memblock_x86_reserve_range(crash_base, crash_base + crash_size, "CRASH KERNEL");
 
        printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
                        "for crashkernel (System RAM: %ldMB)\n",
@@ -615,82 +619,10 @@ static __init void reserve_ibft_region(void)
        addr = find_ibft_region(&size);
 
        if (size)
-               reserve_early_overlap_ok(addr, addr + size, "ibft");
-}
-
-#ifdef CONFIG_X86_RESERVE_LOW_64K
-static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
-{
-       printk(KERN_NOTICE
-               "%s detected: BIOS may corrupt low RAM, working around it.\n",
-               d->ident);
-
-       e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
-       sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
-       return 0;
+               memblock_x86_reserve_range(addr, addr + size, "* ibft");
 }
-#endif
 
-/* List of systems that have known low memory corruption BIOS problems */
-static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
-#ifdef CONFIG_X86_RESERVE_LOW_64K
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "AMI BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-               },
-       },
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "Phoenix BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
-               },
-       },
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "Phoenix/MSC BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
-               },
-       },
-       /*
-        * AMI BIOS with low memory corruption was found on Intel DG45ID and
-        * DG45FC boards.
-        * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
-        * match only DMI_BOARD_NAME and see if there is more bad products
-        * with this vendor.
-        */
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "AMI BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
-               },
-       },
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "AMI BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
-               },
-       },
-       /*
-        * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
-        * match on the product name.
-        */
-       {
-               .callback = dmi_low_memory_corruption,
-               .ident = "Phoenix BIOS",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
-               },
-       },
-#endif
-       {}
-};
+static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
 
 static void __init trim_bios_range(void)
 {
@@ -698,8 +630,14 @@ static void __init trim_bios_range(void)
         * A special case is the first 4Kb of memory;
         * This is a BIOS owned area, not kernel ram, but generally
         * not listed as such in the E820 table.
+        *
+        * This typically reserves additional memory (64KiB by default)
+        * since some BIOSes are known to corrupt low memory.  See the
+        * Kconfig help text for X86_RESERVE_LOW.
         */
-       e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED);
+       e820_update_range(0, ALIGN(reserve_low, PAGE_SIZE),
+                         E820_RAM, E820_RESERVED);
+
        /*
         * special case: Some BIOSen report the PC BIOS
         * area (640->1Mb) as ram even though it is not.
@@ -709,6 +647,37 @@ static void __init trim_bios_range(void)
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
+static int __init parse_reservelow(char *p)
+{
+       unsigned long long size;
+
+       if (!p)
+               return -EINVAL;
+
+       size = memparse(p, &p);
+
+       if (size < 4096)
+               size = 4096;
+
+       if (size > 640*1024)
+               size = 640*1024;
+
+       reserve_low = size;
+
+       return 0;
+}
+
+early_param("reservelow", parse_reservelow);
+
+static u64 __init get_max_mapped(void)
+{
+       u64 end = max_pfn_mapped;
+
+       end <<= PAGE_SHIFT;
+
+       return end;
+}
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -726,6 +695,7 @@ void __init setup_arch(char **cmdline_p)
 {
        int acpi = 0;
        int k8 = 0;
+       unsigned long flags;
 
 #ifdef CONFIG_X86_32
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
@@ -734,10 +704,10 @@ void __init setup_arch(char **cmdline_p)
        printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
 
-       /* VMI may relocate the fixmap; do this before touching ioremap area */
-       vmi_init();
-
-       /* OFW also may relocate the fixmap */
+       /*
+        * If we have OLPC OFW, we might end up relocating the fixmap due to
+        * reserve_top(), so do this before touching the ioremap area.
+        */
        olpc_ofw_detect();
 
        early_trap_init();
@@ -782,7 +752,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
         4)) {
                efi_enabled = 1;
-               efi_reserve_early();
+               efi_memblock_x86_reserve_range();
        }
 #endif
 
@@ -838,11 +808,8 @@ void __init setup_arch(char **cmdline_p)
 
        x86_report_nx();
 
-       /* Must be before kernel pagetables are setup */
-       vmi_activate();
-
        /* after early param, so could get panic from serial */
-       reserve_early_setup_data();
+       memblock_x86_reserve_range_setup_data();
 
        if (acpi_mps_check()) {
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -863,8 +830,6 @@ void __init setup_arch(char **cmdline_p)
 
        dmi_scan_machine();
 
-       dmi_check_system(bad_bios_dmi_table);
-
        /*
         * VMware detection requires dmi to be available, so this
         * needs to be done after dmi_scan_machine, for the BP.
@@ -897,8 +862,6 @@ void __init setup_arch(char **cmdline_p)
         */
        max_pfn = e820_end_of_ram_pfn();
 
-       /* preallocate 4k for mptable mpc */
-       early_reserve_e820_mpc_new();
        /* update e820 for memory not covered by WB MTRRs */
        mtrr_bp_init();
        if (mtrr_trim_uncached_memory(max_pfn))
@@ -920,18 +883,8 @@ void __init setup_arch(char **cmdline_p)
                max_low_pfn = max_pfn;
 
        high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
-       max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
 #endif
 
-#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
-       setup_bios_corruption_check();
-#endif
-
-       printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
-                       max_pfn_mapped<<PAGE_SHIFT);
-
-       reserve_brk();
-
        /*
         * Find and reserve possible boot-time SMP configuration:
         */
@@ -939,6 +892,26 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_ibft_region();
 
+       /*
+        * Need to conclude brk, before memblock_x86_fill()
+        *  it could use memblock_find_in_range, could overlap with
+        *  brk area.
+        */
+       reserve_brk();
+
+       memblock.current_limit = get_max_mapped();
+       memblock_x86_fill();
+
+       /* preallocate 4k for mptable mpc */
+       early_reserve_e820_mpc_new();
+
+#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+       setup_bios_corruption_check();
+#endif
+
+       printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+                       max_pfn_mapped<<PAGE_SHIFT);
+
        reserve_trampoline_memory();
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -962,6 +935,7 @@ void __init setup_arch(char **cmdline_p)
                max_low_pfn = max_pfn;
        }
 #endif
+       memblock.current_limit = get_max_mapped();
 
        /*
         * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
@@ -1000,10 +974,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        initmem_init(0, max_pfn, acpi, k8);
-#ifndef CONFIG_NO_BOOTMEM
-       early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
-#endif
-
+       memblock_find_dma_reserve();
        dma32_reserve_bootmem();
 
 #ifdef CONFIG_KVM_CLOCK
@@ -1071,6 +1042,10 @@ void __init setup_arch(char **cmdline_p)
        x86_init.oem.banner();
 
        mcheck_init();
+
+       local_irq_save(flags);
+       arch_init_ideal_nop5();
+       local_irq_restore(flags);
 }
 
 #ifdef CONFIG_X86_32
index a60df9ae645440789181acd318e12bd4c450aeff..002b79685f738014a8cf9127f804851459a6216b 100644 (file)
@@ -131,13 +131,7 @@ static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
 
 static void __init pcpu_fc_free(void *ptr, size_t size)
 {
-#ifdef CONFIG_NO_BOOTMEM
-       u64 start = __pa(ptr);
-       u64 end = start + size;
-       free_early_partial(start, end);
-#else
        free_bootmem(__pa(ptr), size);
-#endif
 }
 
 static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
@@ -253,7 +247,7 @@ void __init setup_per_cpu_areas(void)
                 * Up to this point, the boot CPU has been using .init.data
                 * area.  Reload any changed state for the boot CPU.
                 */
-               if (cpu == boot_cpu_id)
+               if (!cpu)
                        switch_to_new_gdt(cpu);
        }
 
index cb22acf3ed099de3a256f2f482ae1cdcd5338320..dd4c281ffe5720c3ff15f1eceaa09759e17df7d1 100644 (file)
@@ -34,7 +34,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 
-void __init mp_sfi_register_lapic_address(unsigned long address)
+static void __init mp_sfi_register_lapic_address(unsigned long address)
 {
        mp_lapic_addr = address;
 
@@ -46,7 +46,7 @@ void __init mp_sfi_register_lapic_address(unsigned long address)
 }
 
 /* All CPUs enumerated by SFI must be present and enabled */
-void __cpuinit mp_sfi_register_lapic(u8 id)
+static void __cpuinit mp_sfi_register_lapic(u8 id)
 {
        if (MAX_APICS - id <= 0) {
                pr_warning("Processor #%d invalid (max %d)\n",
index 8b3bfc4dd70872680ff4b451a8b03903bd68727b..dfb50890b5b78b59f3843e6087ebc0a7540cc578 100644 (file)
@@ -62,7 +62,7 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/mtrr.h>
-#include <asm/vmi.h>
+#include <asm/mwait.h>
 #include <asm/apic.h>
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
@@ -311,7 +311,6 @@ notrace static void __cpuinit start_secondary(void *unused)
        __flush_tlb_all();
 #endif
 
-       vmi_bringup();
        cpu_init();
        preempt_disable();
        smp_callin();
@@ -324,9 +323,9 @@ notrace static void __cpuinit start_secondary(void *unused)
        check_tsc_sync_target();
 
        if (nmi_watchdog == NMI_IO_APIC) {
-               legacy_pic->chip->mask(0);
+               legacy_pic->mask(0);
                enable_NMI_through_LVT0();
-               legacy_pic->chip->unmask(0);
+               legacy_pic->unmask(0);
        }
 
        /* This must be done before setting cpu_online_mask */
@@ -397,6 +396,19 @@ void __cpuinit smp_store_cpu_info(int id)
                identify_secondary_cpu(c);
 }
 
+static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
+{
+       struct cpuinfo_x86 *c1 = &cpu_data(cpu1);
+       struct cpuinfo_x86 *c2 = &cpu_data(cpu2);
+
+       cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
+       cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1));
+       cpumask_set_cpu(cpu1, cpu_core_mask(cpu2));
+       cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
+       cpumask_set_cpu(cpu1, c2->llc_shared_map);
+       cpumask_set_cpu(cpu2, c1->llc_shared_map);
+}
+
 
 void __cpuinit set_cpu_sibling_map(int cpu)
 {
@@ -409,14 +421,13 @@ void __cpuinit set_cpu_sibling_map(int cpu)
                for_each_cpu(i, cpu_sibling_setup_mask) {
                        struct cpuinfo_x86 *o = &cpu_data(i);
 
-                       if (c->phys_proc_id == o->phys_proc_id &&
-                           c->cpu_core_id == o->cpu_core_id) {
-                               cpumask_set_cpu(i, cpu_sibling_mask(cpu));
-                               cpumask_set_cpu(cpu, cpu_sibling_mask(i));
-                               cpumask_set_cpu(i, cpu_core_mask(cpu));
-                               cpumask_set_cpu(cpu, cpu_core_mask(i));
-                               cpumask_set_cpu(i, c->llc_shared_map);
-                               cpumask_set_cpu(cpu, o->llc_shared_map);
+                       if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+                               if (c->phys_proc_id == o->phys_proc_id &&
+                                   c->compute_unit_id == o->compute_unit_id)
+                                       link_thread_siblings(cpu, i);
+                       } else if (c->phys_proc_id == o->phys_proc_id &&
+                                  c->cpu_core_id == o->cpu_core_id) {
+                               link_thread_siblings(cpu, i);
                        }
                }
        } else {
@@ -1109,8 +1120,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        }
        set_cpu_sibling_map(0);
 
-       enable_IR_x2apic();
-       default_setup_apic_routing();
 
        if (smp_sanity_check(max_cpus) < 0) {
                printk(KERN_INFO "SMP disabled\n");
@@ -1118,6 +1127,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
                goto out;
        }
 
+       default_setup_apic_routing();
+
        preempt_disable();
        if (read_apic_id() != boot_cpu_physical_apicid) {
                panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
@@ -1383,11 +1394,88 @@ void play_dead_common(void)
        local_irq_disable();
 }
 
+/*
+ * We need to flush the caches before going to sleep, lest we have
+ * dirty data in our caches when we come back up.
+ */
+static inline void mwait_play_dead(void)
+{
+       unsigned int eax, ebx, ecx, edx;
+       unsigned int highest_cstate = 0;
+       unsigned int highest_subcstate = 0;
+       int i;
+       void *mwait_ptr;
+
+       if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+               return;
+       if (!cpu_has(&current_cpu_data, X86_FEATURE_CLFLSH))
+               return;
+       if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+               return;
+
+       eax = CPUID_MWAIT_LEAF;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       /*
+        * eax will be 0 if EDX enumeration is not valid.
+        * Initialized below to cstate, sub_cstate value when EDX is valid.
+        */
+       if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
+               eax = 0;
+       } else {
+               edx >>= MWAIT_SUBSTATE_SIZE;
+               for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
+                       if (edx & MWAIT_SUBSTATE_MASK) {
+                               highest_cstate = i;
+                               highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
+                       }
+               }
+               eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
+                       (highest_subcstate - 1);
+       }
+
+       /*
+        * This should be a memory location in a cache line which is
+        * unlikely to be touched by other processors.  The actual
+        * content is immaterial as it is not actually modified in any way.
+        */
+       mwait_ptr = &current_thread_info()->flags;
+
+       wbinvd();
+
+       while (1) {
+               /*
+                * The CLFLUSH is a workaround for erratum AAI65 for
+                * the Xeon 7400 series.  It's not clear it is actually
+                * needed, but it should be harmless in either case.
+                * The WBINVD is insufficient due to the spurious-wakeup
+                * case where we return around the loop.
+                */
+               clflush(mwait_ptr);
+               __monitor(mwait_ptr, 0, 0);
+               mb();
+               __mwait(eax, 0);
+       }
+}
+
+static inline void hlt_play_dead(void)
+{
+       if (current_cpu_data.x86 >= 4)
+               wbinvd();
+
+       while (1) {
+               native_halt();
+       }
+}
+
 void native_play_dead(void)
 {
        play_dead_common();
        tboot_shutdown(TB_SHUTDOWN_WFS);
-       wbinvd_halt();
+
+       mwait_play_dead();      /* Only returns on failure */
+       hlt_play_dead();
 }
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
index d5e06624e34a556552585690b4532509fe21552f..0b0cb5fede1993d8dc45b54ffcf27ff8732c3082 100644 (file)
@@ -33,8 +33,8 @@ int kernel_execve(const char *filename,
                  const char *const envp[])
 {
        long __res;
-       asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
+       asm volatile ("int $0x80"
        : "=a" (__res)
-       : "0" (__NR_execve), "ri" (filename), "c" (argv), "d" (envp) : "memory");
+       : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
        return __res;
 }
index 312ef0292815f1a3a757c10d3f994d67702b3531..50ac949c7f1c5ee85381bd5ade1a37244a2f98d6 100644 (file)
@@ -1285,6 +1285,7 @@ static const struct file_operations tunables_fops = {
        .open           = tunables_open,
        .read           = tunables_read,
        .write          = tunables_write,
+       .llseek         = default_llseek,
 };
 
 static int __init uv_ptc_init(void)
index a874495b3673baeb27467d144995d885f2f94ebc..4c3da5674e677a14f67990959b1060381bad66f3 100644 (file)
@@ -1,8 +1,8 @@
 #include <linux/io.h>
+#include <linux/memblock.h>
 
 #include <asm/trampoline.h>
 #include <asm/pgtable.h>
-#include <asm/e820.h>
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
 #define __trampinit
@@ -17,15 +17,15 @@ unsigned char *__trampinitdata trampoline_base;
 
 void __init reserve_trampoline_memory(void)
 {
-       unsigned long mem;
+       phys_addr_t mem;
 
        /* Has to be in very low memory so we can execute real-mode AP code. */
-       mem = find_e820_area(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
-       if (mem == -1L)
+       mem = memblock_find_in_range(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
+       if (mem == MEMBLOCK_ERROR)
                panic("Cannot allocate trampoline\n");
 
        trampoline_base = __va(mem);
-       reserve_early(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
+       memblock_x86_reserve_range(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
 }
 
 /*
@@ -45,8 +45,7 @@ void __init setup_trampoline_page_table(void)
        /* Copy kernel address range */
        clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
                        swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-                       min_t(unsigned long, KERNEL_PGD_PTRS,
-                             KERNEL_PGD_BOUNDARY));
+                       KERNEL_PGD_PTRS);
 
        /* Initialize low mappings */
        clone_pgd_range(trampoline_pg_dir,
index 60788dee0f8a74f53d547c462d5694201b6d609d..d43968503dd22fc67a35570fcf0b92b337637c09 100644 (file)
@@ -776,21 +776,10 @@ asmlinkage void math_state_restore(void)
 }
 EXPORT_SYMBOL_GPL(math_state_restore);
 
-#ifndef CONFIG_MATH_EMULATION
-void math_emulate(struct math_emu_info *info)
-{
-       printk(KERN_EMERG
-               "math-emulation not enabled and no coprocessor found.\n");
-       printk(KERN_EMERG "killing %s.\n", current->comm);
-       force_sig(SIGFPE, current);
-       schedule();
-}
-#endif /* CONFIG_MATH_EMULATION */
-
 dotraplinkage void __kprobes
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_MATH_EMULATION
        if (read_cr0() & X86_CR0_EM) {
                struct math_emu_info info = { };
 
@@ -798,12 +787,12 @@ do_device_not_available(struct pt_regs *regs, long error_code)
 
                info.regs = regs;
                math_emulate(&info);
-       } else {
-               math_state_restore(); /* interrupts still off */
-               conditional_sti(regs);
+               return;
        }
-#else
-       math_state_restore();
+#endif
+       math_state_restore(); /* interrupts still off */
+#ifdef CONFIG_X86_32
+       conditional_sti(regs);
 #endif
 }
 
@@ -881,18 +870,6 @@ void __init trap_init(void)
 #endif
 
 #ifdef CONFIG_X86_32
-       if (cpu_has_fxsr) {
-               printk(KERN_INFO "Enabling fast FPU save and restore... ");
-               set_in_cr4(X86_CR4_OSFXSR);
-               printk("done.\n");
-       }
-       if (cpu_has_xmm) {
-               printk(KERN_INFO
-                       "Enabling unmasked SIMD FPU exception support... ");
-               set_in_cr4(X86_CR4_OSXMMEXCPT);
-               printk("done.\n");
-       }
-
        set_system_trap_gate(SYSCALL_VECTOR, &system_call);
        set_bit(SYSCALL_VECTOR, used_vectors);
 #endif
index ce8e50239332470ba329dd3045692fee42f69a16..0c40d8b72416ba2ef7e86bfd812b7bf6f1db2f8f 100644 (file)
@@ -104,10 +104,14 @@ int __init notsc_setup(char *str)
 
 __setup("notsc", notsc_setup);
 
+static int no_sched_irq_time;
+
 static int __init tsc_setup(char *str)
 {
        if (!strcmp(str, "reliable"))
                tsc_clocksource_reliable = 1;
+       if (!strncmp(str, "noirqtime", 9))
+               no_sched_irq_time = 1;
        return 1;
 }
 
@@ -626,6 +630,44 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
        local_irq_restore(flags);
 }
 
+static unsigned long long cyc2ns_suspend;
+
+void save_sched_clock_state(void)
+{
+       if (!sched_clock_stable)
+               return;
+
+       cyc2ns_suspend = sched_clock();
+}
+
+/*
+ * Even on processors with invariant TSC, TSC gets reset in some the
+ * ACPI system sleep states. And in some systems BIOS seem to reinit TSC to
+ * arbitrary value (still sync'd across cpu's) during resume from such sleep
+ * states. To cope up with this, recompute the cyc2ns_offset for each cpu so
+ * that sched_clock() continues from the point where it was left off during
+ * suspend.
+ */
+void restore_sched_clock_state(void)
+{
+       unsigned long long offset;
+       unsigned long flags;
+       int cpu;
+
+       if (!sched_clock_stable)
+               return;
+
+       local_irq_save(flags);
+
+       __get_cpu_var(cyc2ns_offset) = 0;
+       offset = cyc2ns_suspend - sched_clock();
+
+       for_each_possible_cpu(cpu)
+               per_cpu(cyc2ns_offset, cpu) = offset;
+
+       local_irq_restore(flags);
+}
+
 #ifdef CONFIG_CPU_FREQ
 
 /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
@@ -763,6 +805,7 @@ void mark_tsc_unstable(char *reason)
        if (!tsc_unstable) {
                tsc_unstable = 1;
                sched_clock_stable = 0;
+               disable_sched_clock_irqtime();
                printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
                if (clocksource_tsc.mult)
@@ -854,60 +897,6 @@ static void __init init_tsc_clocksource(void)
        clocksource_register_khz(&clocksource_tsc, tsc_khz);
 }
 
-#ifdef CONFIG_X86_64
-/*
- * calibrate_cpu is used on systems with fixed rate TSCs to determine
- * processor frequency
- */
-#define TICK_COUNT 100000000
-static unsigned long __init calibrate_cpu(void)
-{
-       int tsc_start, tsc_now;
-       int i, no_ctr_free;
-       unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
-       unsigned long flags;
-
-       for (i = 0; i < 4; i++)
-               if (avail_to_resrv_perfctr_nmi_bit(i))
-                       break;
-       no_ctr_free = (i == 4);
-       if (no_ctr_free) {
-               WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... "
-                    "cpu_khz value may be incorrect.\n");
-               i = 3;
-               rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
-               wrmsrl(MSR_K7_EVNTSEL3, 0);
-               rdmsrl(MSR_K7_PERFCTR3, pmc3);
-       } else {
-               reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-               reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
-       }
-       local_irq_save(flags);
-       /* start measuring cycles, incrementing from 0 */
-       wrmsrl(MSR_K7_PERFCTR0 + i, 0);
-       wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
-       rdtscl(tsc_start);
-       do {
-               rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
-               tsc_now = get_cycles();
-       } while ((tsc_now - tsc_start) < TICK_COUNT);
-
-       local_irq_restore(flags);
-       if (no_ctr_free) {
-               wrmsrl(MSR_K7_EVNTSEL3, 0);
-               wrmsrl(MSR_K7_PERFCTR3, pmc3);
-               wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
-       } else {
-               release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-               release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
-       }
-
-       return pmc_now * tsc_khz / (tsc_now - tsc_start);
-}
-#else
-static inline unsigned long calibrate_cpu(void) { return cpu_khz; }
-#endif
-
 void __init tsc_init(void)
 {
        u64 lpj;
@@ -926,10 +915,6 @@ void __init tsc_init(void)
                return;
        }
 
-       if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
-                       (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))
-               cpu_khz = calibrate_cpu();
-
        printk("Detected %lu.%03lu MHz processor.\n",
                        (unsigned long)cpu_khz / 1000,
                        (unsigned long)cpu_khz % 1000);
@@ -949,6 +934,9 @@ void __init tsc_init(void)
        /* now allow native_sched_clock() to use rdtsc */
        tsc_disabled = 0;
 
+       if (!no_sched_irq_time)
+               enable_sched_clock_irqtime();
+
        lpj = ((u64)tsc_khz * 1000);
        do_div(lpj, HZ);
        lpj_fine = lpj;
index 1132129db792b704fe14f4adaf02fda8ffafaa24..7b24460917d551b540a337a0f7c74dbe4f65e297 100644 (file)
@@ -28,34 +28,21 @@ struct uv_irq_2_mmr_pnode{
 static spinlock_t              uv_irq_lock;
 static struct rb_root          uv_irq_root;
 
-static int uv_set_irq_affinity(unsigned int, const struct cpumask *);
+static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
 
-static void uv_noop(unsigned int irq)
-{
-}
-
-static unsigned int uv_noop_ret(unsigned int irq)
-{
-       return 0;
-}
+static void uv_noop(struct irq_data *data) { }
 
-static void uv_ack_apic(unsigned int irq)
+static void uv_ack_apic(struct irq_data *data)
 {
        ack_APIC_irq();
 }
 
 static struct irq_chip uv_irq_chip = {
-       .name           = "UV-CORE",
-       .startup        = uv_noop_ret,
-       .shutdown       = uv_noop,
-       .enable         = uv_noop,
-       .disable        = uv_noop,
-       .ack            = uv_noop,
-       .mask           = uv_noop,
-       .unmask         = uv_noop,
-       .eoi            = uv_ack_apic,
-       .end            = uv_noop,
-       .set_affinity   = uv_set_irq_affinity,
+       .name                   = "UV-CORE",
+       .irq_mask               = uv_noop,
+       .irq_unmask             = uv_noop,
+       .irq_eoi                = uv_ack_apic,
+       .irq_set_affinity       = uv_set_irq_affinity,
 };
 
 /*
@@ -144,26 +131,22 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
                       unsigned long mmr_offset, int limit)
 {
        const struct cpumask *eligible_cpu = cpumask_of(cpu);
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg;
-       int mmr_pnode;
+       struct irq_cfg *cfg = get_irq_chip_data(irq);
        unsigned long mmr_value;
        struct uv_IO_APIC_route_entry *entry;
-       int err;
+       int mmr_pnode, err;
 
        BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
                        sizeof(unsigned long));
 
-       cfg = irq_cfg(irq);
-
        err = assign_irq_vector(irq, cfg, eligible_cpu);
        if (err != 0)
                return err;
 
        if (limit == UV_AFFINITY_CPU)
-               desc->status |= IRQ_NO_BALANCING;
+               irq_set_status_flags(irq, IRQ_NO_BALANCING);
        else
-               desc->status |= IRQ_MOVE_PCNTXT;
+               irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 
        set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
                                      irq_name);
@@ -206,17 +189,17 @@ static void arch_disable_uv_irq(int mmr_pnode, unsigned long mmr_offset)
        uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
 }
 
-static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+                   bool force)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct irq_cfg *cfg = desc->chip_data;
+       struct irq_cfg *cfg = data->chip_data;
        unsigned int dest;
-       unsigned long mmr_value;
+       unsigned long mmr_value, mmr_offset;
        struct uv_IO_APIC_route_entry *entry;
-       unsigned long mmr_offset;
        int mmr_pnode;
 
-       if (set_desc_affinity(desc, mask, &dest))
+       if (__ioapic_set_affinity(data, mask, &dest))
                return -1;
 
        mmr_value = 0;
@@ -231,7 +214,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
        entry->dest             = dest;
 
        /* Get previously stored MMR and pnode of hub sourcing interrupts */
-       if (uv_irq_2_mmr_info(irq, &mmr_offset, &mmr_pnode))
+       if (uv_irq_2_mmr_info(data->irq, &mmr_offset, &mmr_pnode))
                return -1;
 
        uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
index e680ea52db9b372fdd83b4954dd1774ad733f66c..3371bd053b89f29e14e5f55d88929d2427f123b2 100644 (file)
@@ -66,10 +66,7 @@ static void __init visws_time_init(void)
 }
 
 /* Replaces the default init_ISA_irqs in the generic setup */
-static void __init visws_pre_intr_init(void)
-{
-       init_VISWS_APIC_irqs();
-}
+static void __init visws_pre_intr_init(void);
 
 /* Quirk for machine specific memory setup. */
 
@@ -429,67 +426,34 @@ static int is_co_apic(unsigned int irq)
 /*
  * This is the SGI Cobalt (IO-)APIC:
  */
-
-static void enable_cobalt_irq(unsigned int irq)
+static void enable_cobalt_irq(struct irq_data *data)
 {
-       co_apic_set(is_co_apic(irq), irq);
+       co_apic_set(is_co_apic(data->irq), data->irq);
 }
 
-static void disable_cobalt_irq(unsigned int irq)
+static void disable_cobalt_irq(struct irq_data *data)
 {
-       int entry = is_co_apic(irq);
+       int entry = is_co_apic(data->irq);
 
        co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
        co_apic_read(CO_APIC_LO(entry));
 }
 
-/*
- * "irq" really just serves to identify the device.  Here is where we
- * map this to the Cobalt APIC entry where it's physically wired.
- * This is called via request_irq -> setup_irq -> irq_desc->startup()
- */
-static unsigned int startup_cobalt_irq(unsigned int irq)
+static void ack_cobalt_irq(struct irq_data *data)
 {
        unsigned long flags;
-       struct irq_desc *desc = irq_to_desc(irq);
 
        spin_lock_irqsave(&cobalt_lock, flags);
-       if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
-               desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
-       enable_cobalt_irq(irq);
-       spin_unlock_irqrestore(&cobalt_lock, flags);
-       return 0;
-}
-
-static void ack_cobalt_irq(unsigned int irq)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cobalt_lock, flags);
-       disable_cobalt_irq(irq);
+       disable_cobalt_irq(data);
        apic_write(APIC_EOI, APIC_EIO_ACK);
        spin_unlock_irqrestore(&cobalt_lock, flags);
 }
 
-static void end_cobalt_irq(unsigned int irq)
-{
-       unsigned long flags;
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       spin_lock_irqsave(&cobalt_lock, flags);
-       if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               enable_cobalt_irq(irq);
-       spin_unlock_irqrestore(&cobalt_lock, flags);
-}
-
 static struct irq_chip cobalt_irq_type = {
-       .name =         "Cobalt-APIC",
-       .startup =      startup_cobalt_irq,
-       .shutdown =     disable_cobalt_irq,
-       .enable =       enable_cobalt_irq,
-       .disable =      disable_cobalt_irq,
-       .ack =          ack_cobalt_irq,
-       .end =          end_cobalt_irq,
+       .name           = "Cobalt-APIC",
+       .irq_enable     = enable_cobalt_irq,
+       .irq_disable    = disable_cobalt_irq,
+       .irq_ack        = ack_cobalt_irq,
 };
 
 
@@ -503,35 +467,34 @@ static struct irq_chip cobalt_irq_type = {
  * interrupt controller type, and through a special virtual interrupt-
  * controller. Device drivers only see the virtual interrupt sources.
  */
-static unsigned int startup_piix4_master_irq(unsigned int irq)
+static unsigned int startup_piix4_master_irq(struct irq_data *data)
 {
        legacy_pic->init(0);
-
-       return startup_cobalt_irq(irq);
+       enable_cobalt_irq(data);
 }
 
-static void end_piix4_master_irq(unsigned int irq)
+static void end_piix4_master_irq(struct irq_data *data)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&cobalt_lock, flags);
-       enable_cobalt_irq(irq);
+       enable_cobalt_irq(data);
        spin_unlock_irqrestore(&cobalt_lock, flags);
 }
 
 static struct irq_chip piix4_master_irq_type = {
-       .name =         "PIIX4-master",
-       .startup =      startup_piix4_master_irq,
-       .ack =          ack_cobalt_irq,
-       .end =          end_piix4_master_irq,
+       .name           = "PIIX4-master",
+       .irq_startup    = startup_piix4_master_irq,
+       .irq_ack        = ack_cobalt_irq,
 };
 
+static void pii4_mask(struct irq_data *data) { }
 
 static struct irq_chip piix4_virtual_irq_type = {
-       .name =         "PIIX4-virtual",
+       .name           = "PIIX4-virtual",
+       .mask           = pii4_mask,
 };
 
-
 /*
  * PIIX4-8259 master/virtual functions to handle interrupt requests
  * from legacy devices: floppy, parallel, serial, rtc.
@@ -549,9 +512,8 @@ static struct irq_chip piix4_virtual_irq_type = {
  */
 static irqreturn_t piix4_master_intr(int irq, void *dev_id)
 {
-       int realirq;
-       struct irq_desc *desc;
        unsigned long flags;
+       int realirq;
 
        raw_spin_lock_irqsave(&i8259A_lock, flags);
 
@@ -592,18 +554,10 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id)
 
        raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 
-       desc = irq_to_desc(realirq);
-
        /*
         * handle this 'virtual interrupt' as a Cobalt one now.
         */
-       kstat_incr_irqs_this_cpu(realirq, desc);
-
-       if (likely(desc->action != NULL))
-               handle_IRQ_event(realirq, desc->action);
-
-       if (!(desc->status & IRQ_DISABLED))
-               legacy_pic->chip->unmask(realirq);
+       generic_handle_irq(realirq);
 
        return IRQ_HANDLED;
 
@@ -624,41 +578,35 @@ static struct irqaction cascade_action = {
 
 static inline void set_piix4_virtual_irq_type(void)
 {
-       piix4_virtual_irq_type.shutdown = i8259A_chip.mask;
        piix4_virtual_irq_type.enable = i8259A_chip.unmask;
        piix4_virtual_irq_type.disable = i8259A_chip.mask;
+       piix4_virtual_irq_type.unmask = i8259A_chip.unmask;
 }
 
-void init_VISWS_APIC_irqs(void)
+static void __init visws_pre_intr_init(void)
 {
        int i;
 
-       for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
-               struct irq_desc *desc = irq_to_desc(i);
-
-               desc->status = IRQ_DISABLED;
-               desc->action = 0;
-               desc->depth = 1;
+       set_piix4_virtual_irq_type();
 
-               if (i == 0) {
-                       desc->chip = &cobalt_irq_type;
-               }
-               else if (i == CO_IRQ_IDE0) {
-                       desc->chip = &cobalt_irq_type;
-               }
-               else if (i == CO_IRQ_IDE1) {
-                       desc->chip = &cobalt_irq_type;
-               }
-               else if (i == CO_IRQ_8259) {
-                       desc->chip = &piix4_master_irq_type;
-               }
-               else if (i < CO_IRQ_APIC0) {
-                       set_piix4_virtual_irq_type();
-                       desc->chip = &piix4_virtual_irq_type;
-               }
-               else if (IS_CO_APIC(i)) {
-                       desc->chip = &cobalt_irq_type;
-               }
+       for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
+               struct irq_chip *chip = NULL;
+
+               if (i == 0)
+                       chip = &cobalt_irq_type;
+               else if (i == CO_IRQ_IDE0)
+                       chip = &cobalt_irq_type;
+               else if (i == CO_IRQ_IDE1)
+                       >chip = &cobalt_irq_type;
+               else if (i == CO_IRQ_8259)
+                       chip = &piix4_master_irq_type;
+               else if (i < CO_IRQ_APIC0)
+                       chip = &piix4_virtual_irq_type;
+               else if (IS_CO_APIC(i))
+                       chip = &cobalt_irq_type;
+
+               if (chip)
+                       set_irq_chip(i, chip);
        }
 
        setup_irq(CO_IRQ_8259, &master_action);
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
deleted file mode 100644 (file)
index ce9fbac..0000000
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * VMI specific paravirt-ops implementation
- *
- * Copyright (C) 2005, VMware, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to zach@vmware.com
- *
- */
-
-#include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <asm/vmi.h>
-#include <asm/io.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/pgalloc.h>
-#include <asm/processor.h>
-#include <asm/timer.h>
-#include <asm/vmi_time.h>
-#include <asm/kmap_types.h>
-#include <asm/setup.h>
-
-/* Convenient for calling VMI functions indirectly in the ROM */
-typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
-typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
-
-#define call_vrom_func(rom,func) \
-   (((VROMFUNC *)(rom->func))())
-
-#define call_vrom_long_func(rom,func,arg) \
-   (((VROMLONGFUNC *)(rom->func)) (arg))
-
-static struct vrom_header *vmi_rom;
-static int disable_pge;
-static int disable_pse;
-static int disable_sep;
-static int disable_tsc;
-static int disable_mtrr;
-static int disable_noidle;
-static int disable_vmi_timer;
-
-/* Cached VMI operations */
-static struct {
-       void (*cpuid)(void /* non-c */);
-       void (*_set_ldt)(u32 selector);
-       void (*set_tr)(u32 selector);
-       void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
-       void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
-       void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
-       void (*set_kernel_stack)(u32 selector, u32 sp0);
-       void (*allocate_page)(u32, u32, u32, u32, u32);
-       void (*release_page)(u32, u32);
-       void (*set_pte)(pte_t, pte_t *, unsigned);
-       void (*update_pte)(pte_t *, unsigned);
-       void (*set_linear_mapping)(int, void *, u32, u32);
-       void (*_flush_tlb)(int);
-       void (*set_initial_ap_state)(int, int);
-       void (*halt)(void);
-       void (*set_lazy_mode)(int mode);
-} vmi_ops;
-
-/* Cached VMI operations */
-struct vmi_timer_ops vmi_timer_ops;
-
-/*
- * VMI patching routines.
- */
-#define MNEM_CALL 0xe8
-#define MNEM_JMP  0xe9
-#define MNEM_RET  0xc3
-
-#define IRQ_PATCH_INT_MASK 0
-#define IRQ_PATCH_DISABLE  5
-
-static inline void patch_offset(void *insnbuf,
-                               unsigned long ip, unsigned long dest)
-{
-        *(unsigned long *)(insnbuf+1) = dest-ip-5;
-}
-
-static unsigned patch_internal(int call, unsigned len, void *insnbuf,
-                              unsigned long ip)
-{
-       u64 reloc;
-       struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc;
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, call);
-       switch(rel->type) {
-               case VMI_RELOCATION_CALL_REL:
-                       BUG_ON(len < 5);
-                       *(char *)insnbuf = MNEM_CALL;
-                       patch_offset(insnbuf, ip, (unsigned long)rel->eip);
-                       return 5;
-
-               case VMI_RELOCATION_JUMP_REL:
-                       BUG_ON(len < 5);
-                       *(char *)insnbuf = MNEM_JMP;
-                       patch_offset(insnbuf, ip, (unsigned long)rel->eip);
-                       return 5;
-
-               case VMI_RELOCATION_NOP:
-                       /* obliterate the whole thing */
-                       return 0;
-
-               case VMI_RELOCATION_NONE:
-                       /* leave native code in place */
-                       break;
-
-               default:
-                       BUG();
-       }
-       return len;
-}
-
-/*
- * Apply patch if appropriate, return length of new instruction
- * sequence.  The callee does nop padding for us.
- */
-static unsigned vmi_patch(u8 type, u16 clobbers, void *insns,
-                         unsigned long ip, unsigned len)
-{
-       switch (type) {
-               case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
-                       return patch_internal(VMI_CALL_DisableInterrupts, len,
-                                             insns, ip);
-               case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
-                       return patch_internal(VMI_CALL_EnableInterrupts, len,
-                                             insns, ip);
-               case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
-                       return patch_internal(VMI_CALL_SetInterruptMask, len,
-                                             insns, ip);
-               case PARAVIRT_PATCH(pv_irq_ops.save_fl):
-                       return patch_internal(VMI_CALL_GetInterruptMask, len,
-                                             insns, ip);
-               case PARAVIRT_PATCH(pv_cpu_ops.iret):
-                       return patch_internal(VMI_CALL_IRET, len, insns, ip);
-               case PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit):
-                       return patch_internal(VMI_CALL_SYSEXIT, len, insns, ip);
-               default:
-                       break;
-       }
-       return len;
-}
-
-/* CPUID has non-C semantics, and paravirt-ops API doesn't match hardware ISA */
-static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
-                               unsigned int *cx, unsigned int *dx)
-{
-       int override = 0;
-       if (*ax == 1)
-               override = 1;
-        asm volatile ("call *%6"
-                      : "=a" (*ax),
-                        "=b" (*bx),
-                        "=c" (*cx),
-                        "=d" (*dx)
-                      : "0" (*ax), "2" (*cx), "r" (vmi_ops.cpuid));
-       if (override) {
-               if (disable_pse)
-                       *dx &= ~X86_FEATURE_PSE;
-               if (disable_pge)
-                       *dx &= ~X86_FEATURE_PGE;
-               if (disable_sep)
-                       *dx &= ~X86_FEATURE_SEP;
-               if (disable_tsc)
-                       *dx &= ~X86_FEATURE_TSC;
-               if (disable_mtrr)
-                       *dx &= ~X86_FEATURE_MTRR;
-       }
-}
-
-static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
-{
-       if (gdt[nr].a != new->a || gdt[nr].b != new->b)
-               write_gdt_entry(gdt, nr, new, 0);
-}
-
-static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
-{
-       struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0]);
-       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1]);
-       vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2]);
-}
-
-static void vmi_set_ldt(const void *addr, unsigned entries)
-{
-       unsigned cpu = smp_processor_id();
-       struct desc_struct desc;
-
-       pack_descriptor(&desc, (unsigned long)addr,
-                       entries * sizeof(struct desc_struct) - 1,
-                       DESC_LDT, 0);
-       write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
-       vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
-}
-
-static void vmi_set_tr(void)
-{
-       vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
-}
-
-static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
-{
-       u32 *idt_entry = (u32 *)g;
-       vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[1]);
-}
-
-static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
-                               const void *desc, int type)
-{
-       u32 *gdt_entry = (u32 *)desc;
-       vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[1]);
-}
-
-static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
-                               const void *desc)
-{
-       u32 *ldt_entry = (u32 *)desc;
-       vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
-}
-
-static void vmi_load_sp0(struct tss_struct *tss,
-                                  struct thread_struct *thread)
-{
-       tss->x86_tss.sp0 = thread->sp0;
-
-       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
-       if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
-               tss->x86_tss.ss1 = thread->sysenter_cs;
-               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
-       }
-       vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.sp0);
-}
-
-static void vmi_flush_tlb_user(void)
-{
-       vmi_ops._flush_tlb(VMI_FLUSH_TLB);
-}
-
-static void vmi_flush_tlb_kernel(void)
-{
-       vmi_ops._flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
-}
-
-/* Stub to do nothing at all; used for delays and unimplemented calls */
-static void vmi_nop(void)
-{
-}
-
-static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn)
-{
-       vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn)
-{
-       /*
-        * This call comes in very early, before mem_map is setup.
-        * It is called only for swapper_pg_dir, which already has
-        * data on it.
-        */
-       vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count)
-{
-       vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
-}
-
-static void vmi_release_pte(unsigned long pfn)
-{
-       vmi_ops.release_page(pfn, VMI_PAGE_L1);
-}
-
-static void vmi_release_pmd(unsigned long pfn)
-{
-       vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * We use the pgd_free hook for releasing the pgd page:
- */
-static void vmi_pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-       unsigned long pfn = __pa(pgd) >> PAGE_SHIFT;
-
-       vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * Helper macros for MMU update flags.  We can defer updates until a flush
- * or page invalidation only if the update is to the current address space
- * (otherwise, there is no flush).  We must check against init_mm, since
- * this could be a kernel update, which usually passes init_mm, although
- * sometimes this check can be skipped if we know the particular function
- * is only called on user mode PTEs.  We could change the kernel to pass
- * current->active_mm here, but in particular, I was unsure if changing
- * mm/highmem.c to do this would still be correct on other architectures.
- */
-#define is_current_as(mm, mustbeuser) ((mm) == current->active_mm ||    \
-                                       (!mustbeuser && (mm) == &init_mm))
-#define vmi_flags_addr(mm, addr, level, user)                           \
-        ((level) | (is_current_as(mm, user) ?                           \
-                (VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-#define vmi_flags_addr_defer(mm, addr, level, user)                     \
-        ((level) | (is_current_as(mm, user) ?                           \
-                (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-
-static void vmi_update_pte(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_update_pte_defer(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pte(pte_t *ptep, pte_t pte)
-{
-       /* XXX because of set_pmd_pte, this can be called on PT or PD layers */
-       vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
-       vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
-#ifdef CONFIG_X86_PAE
-       const pte_t pte = { .pte = pmdval.pmd };
-#else
-       const pte_t pte = { pmdval.pud.pgd.pgd };
-#endif
-       vmi_ops.set_pte(pte, (pte_t *)pmdp, VMI_PAGE_PD);
-}
-
-#ifdef CONFIG_X86_PAE
-
-static void vmi_set_pte_atomic(pte_t *ptep, pte_t pteval)
-{
-       /*
-        * XXX This is called from set_pmd_pte, but at both PT
-        * and PD layers so the VMI_PAGE_PT flag is wrong.  But
-        * it is only called for large page mapping changes,
-        * the Xen backend, doesn't support large pages, and the
-        * ESX backend doesn't depend on the flag.
-        */
-       set_64bit((unsigned long long *)ptep,pte_val(pteval));
-       vmi_ops.update_pte(ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pud(pud_t *pudp, pud_t pudval)
-{
-       /* Um, eww */
-       const pte_t pte = { .pte = pudval.pgd.pgd };
-       vmi_ops.set_pte(pte, (pte_t *)pudp, VMI_PAGE_PDP);
-}
-
-static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       const pte_t pte = { .pte = 0 };
-       vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_pmd_clear(pmd_t *pmd)
-{
-       const pte_t pte = { .pte = 0 };
-       vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
-}
-#endif
-
-#ifdef CONFIG_SMP
-static void __devinit
-vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
-                    unsigned long start_esp)
-{
-       struct vmi_ap_state ap;
-
-       /* Default everything to zero.  This is fine for most GPRs. */
-       memset(&ap, 0, sizeof(struct vmi_ap_state));
-
-       ap.gdtr_limit = GDT_SIZE - 1;
-       ap.gdtr_base = (unsigned long) get_cpu_gdt_table(phys_apicid);
-
-       ap.idtr_limit = IDT_ENTRIES * 8 - 1;
-       ap.idtr_base = (unsigned long) idt_table;
-
-       ap.ldtr = 0;
-
-       ap.cs = __KERNEL_CS;
-       ap.eip = (unsigned long) start_eip;
-       ap.ss = __KERNEL_DS;
-       ap.esp = (unsigned long) start_esp;
-
-       ap.ds = __USER_DS;
-       ap.es = __USER_DS;
-       ap.fs = __KERNEL_PERCPU;
-       ap.gs = __KERNEL_STACK_CANARY;
-
-       ap.eflags = 0;
-
-#ifdef CONFIG_X86_PAE
-       /* efer should match BSP efer. */
-       if (cpu_has_nx) {
-               unsigned l, h;
-               rdmsr(MSR_EFER, l, h);
-               ap.efer = (unsigned long long) h << 32 | l;
-       }
-#endif
-
-       ap.cr3 = __pa(swapper_pg_dir);
-       /* Protected mode, paging, AM, WP, NE, MP. */
-       ap.cr0 = 0x80050023;
-       ap.cr4 = mmu_cr4_features;
-       vmi_ops.set_initial_ap_state((u32)&ap, phys_apicid);
-}
-#endif
-
-static void vmi_start_context_switch(struct task_struct *prev)
-{
-       paravirt_start_context_switch(prev);
-       vmi_ops.set_lazy_mode(2);
-}
-
-static void vmi_end_context_switch(struct task_struct *next)
-{
-       vmi_ops.set_lazy_mode(0);
-       paravirt_end_context_switch(next);
-}
-
-static void vmi_enter_lazy_mmu(void)
-{
-       paravirt_enter_lazy_mmu();
-       vmi_ops.set_lazy_mode(1);
-}
-
-static void vmi_leave_lazy_mmu(void)
-{
-       vmi_ops.set_lazy_mode(0);
-       paravirt_leave_lazy_mmu();
-}
-
-static inline int __init check_vmi_rom(struct vrom_header *rom)
-{
-       struct pci_header *pci;
-       struct pnp_header *pnp;
-       const char *manufacturer = "UNKNOWN";
-       const char *product = "UNKNOWN";
-       const char *license = "unspecified";
-
-       if (rom->rom_signature != 0xaa55)
-               return 0;
-       if (rom->vrom_signature != VMI_SIGNATURE)
-               return 0;
-       if (rom->api_version_maj != VMI_API_REV_MAJOR ||
-           rom->api_version_min+1 < VMI_API_REV_MINOR+1) {
-               printk(KERN_WARNING "VMI: Found mismatched rom version %d.%d\n",
-                               rom->api_version_maj,
-                               rom->api_version_min);
-               return 0;
-       }
-
-       /*
-        * Relying on the VMI_SIGNATURE field is not 100% safe, so check
-        * the PCI header and device type to make sure this is really a
-        * VMI device.
-        */
-       if (!rom->pci_header_offs) {
-               printk(KERN_WARNING "VMI: ROM does not contain PCI header.\n");
-               return 0;
-       }
-
-       pci = (struct pci_header *)((char *)rom+rom->pci_header_offs);
-       if (pci->vendorID != PCI_VENDOR_ID_VMWARE ||
-           pci->deviceID != PCI_DEVICE_ID_VMWARE_VMI) {
-               /* Allow it to run... anyways, but warn */
-               printk(KERN_WARNING "VMI: ROM from unknown manufacturer\n");
-       }
-
-       if (rom->pnp_header_offs) {
-               pnp = (struct pnp_header *)((char *)rom+rom->pnp_header_offs);
-               if (pnp->manufacturer_offset)
-                       manufacturer = (const char *)rom+pnp->manufacturer_offset;
-               if (pnp->product_offset)
-                       product = (const char *)rom+pnp->product_offset;
-       }
-
-       if (rom->license_offs)
-               license = (char *)rom+rom->license_offs;
-
-       printk(KERN_INFO "VMI: Found %s %s, API version %d.%d, ROM version %d.%d\n",
-               manufacturer, product,
-               rom->api_version_maj, rom->api_version_min,
-               pci->rom_version_maj, pci->rom_version_min);
-
-       /* Don't allow BSD/MIT here for now because we don't want to end up
-          with any binary only shim layers */
-       if (strcmp(license, "GPL") && strcmp(license, "GPL v2")) {
-               printk(KERN_WARNING "VMI: Non GPL license `%s' found for ROM. Not used.\n",
-                       license);
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * Probe for the VMI option ROM
- */
-static inline int __init probe_vmi_rom(void)
-{
-       unsigned long base;
-
-       /* VMI ROM is in option ROM area, check signature */
-       for (base = 0xC0000; base < 0xE0000; base += 2048) {
-               struct vrom_header *romstart;
-               romstart = (struct vrom_header *)isa_bus_to_virt(base);
-               if (check_vmi_rom(romstart)) {
-                       vmi_rom = romstart;
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * VMI setup common to all processors
- */
-void vmi_bringup(void)
-{
-       /* We must establish the lowmem mapping for MMU ops to work */
-       if (vmi_ops.set_linear_mapping)
-               vmi_ops.set_linear_mapping(0, (void *)__PAGE_OFFSET, MAXMEM_PFN, 0);
-}
-
-/*
- * Return a pointer to a VMI function or NULL if unimplemented
- */
-static void *vmi_get_function(int vmicall)
-{
-       u64 reloc;
-       const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, vmicall);
-       BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);
-       if (rel->type == VMI_RELOCATION_CALL_REL)
-               return (void *)rel->eip;
-       else
-               return NULL;
-}
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For unimplemented operations, fall back to default, unless nop
- * is returned by the ROM.
- */
-#define para_fill(opname, vmicall)                             \
-do {                                                           \
-       reloc = call_vrom_long_func(vmi_rom, get_reloc,         \
-                                   VMI_CALL_##vmicall);        \
-       if (rel->type == VMI_RELOCATION_CALL_REL)               \
-               opname = (void *)rel->eip;                      \
-       else if (rel->type == VMI_RELOCATION_NOP)               \
-               opname = (void *)vmi_nop;                       \
-       else if (rel->type != VMI_RELOCATION_NONE)              \
-               printk(KERN_WARNING "VMI: Unknown relocation "  \
-                                   "type %d for " #vmicall"\n",\
-                                       rel->type);             \
-} while (0)
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For cached operations which do not match the VMI ROM ABI and must
- * go through a tranlation stub.  Ignore NOPs, since it is not clear
- * a NOP * VMI function corresponds to a NOP paravirt-op when the
- * functions are not in 1-1 correspondence.
- */
-#define para_wrap(opname, wrapper, cache, vmicall)             \
-do {                                                           \
-       reloc = call_vrom_long_func(vmi_rom, get_reloc,         \
-                                   VMI_CALL_##vmicall);        \
-       BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);           \
-       if (rel->type == VMI_RELOCATION_CALL_REL) {             \
-               opname = wrapper;                               \
-               vmi_ops.cache = (void *)rel->eip;               \
-       }                                                       \
-} while (0)
-
-/*
- * Activate the VMI interface and switch into paravirtualized mode
- */
-static inline int __init activate_vmi(void)
-{
-       short kernel_cs;
-       u64 reloc;
-       const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
-
-       /*
-        * Prevent page tables from being allocated in highmem, even if
-        * CONFIG_HIGHPTE is enabled.
-        */
-       __userpte_alloc_gfp &= ~__GFP_HIGHMEM;
-
-       if (call_vrom_func(vmi_rom, vmi_init) != 0) {
-               printk(KERN_ERR "VMI ROM failed to initialize!");
-               return 0;
-       }
-       savesegment(cs, kernel_cs);
-
-       pv_info.paravirt_enabled = 1;
-       pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
-       pv_info.name = "vmi [deprecated]";
-
-       pv_init_ops.patch = vmi_patch;
-
-       /*
-        * Many of these operations are ABI compatible with VMI.
-        * This means we can fill in the paravirt-ops with direct
-        * pointers into the VMI ROM.  If the calling convention for
-        * these operations changes, this code needs to be updated.
-        *
-        * Exceptions
-        *  CPUID paravirt-op uses pointers, not the native ISA
-        *  halt has no VMI equivalent; all VMI halts are "safe"
-        *  no MSR support yet - just trap and emulate.  VMI uses the
-        *    same ABI as the native ISA, but Linux wants exceptions
-        *    from bogus MSR read / write handled
-        *  rdpmc is not yet used in Linux
-        */
-
-       /* CPUID is special, so very special it gets wrapped like a present */
-       para_wrap(pv_cpu_ops.cpuid, vmi_cpuid, cpuid, CPUID);
-
-       para_fill(pv_cpu_ops.clts, CLTS);
-       para_fill(pv_cpu_ops.get_debugreg, GetDR);
-       para_fill(pv_cpu_ops.set_debugreg, SetDR);
-       para_fill(pv_cpu_ops.read_cr0, GetCR0);
-       para_fill(pv_mmu_ops.read_cr2, GetCR2);
-       para_fill(pv_mmu_ops.read_cr3, GetCR3);
-       para_fill(pv_cpu_ops.read_cr4, GetCR4);
-       para_fill(pv_cpu_ops.write_cr0, SetCR0);
-       para_fill(pv_mmu_ops.write_cr2, SetCR2);
-       para_fill(pv_mmu_ops.write_cr3, SetCR3);
-       para_fill(pv_cpu_ops.write_cr4, SetCR4);
-
-       para_fill(pv_irq_ops.save_fl.func, GetInterruptMask);
-       para_fill(pv_irq_ops.restore_fl.func, SetInterruptMask);
-       para_fill(pv_irq_ops.irq_disable.func, DisableInterrupts);
-       para_fill(pv_irq_ops.irq_enable.func, EnableInterrupts);
-
-       para_fill(pv_cpu_ops.wbinvd, WBINVD);
-       para_fill(pv_cpu_ops.read_tsc, RDTSC);
-
-       /* The following we emulate with trap and emulate for now */
-       /* paravirt_ops.read_msr = vmi_rdmsr */
-       /* paravirt_ops.write_msr = vmi_wrmsr */
-       /* paravirt_ops.rdpmc = vmi_rdpmc */
-
-       /* TR interface doesn't pass TR value, wrap */
-       para_wrap(pv_cpu_ops.load_tr_desc, vmi_set_tr, set_tr, SetTR);
-
-       /* LDT is special, too */
-       para_wrap(pv_cpu_ops.set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
-
-       para_fill(pv_cpu_ops.load_gdt, SetGDT);
-       para_fill(pv_cpu_ops.load_idt, SetIDT);
-       para_fill(pv_cpu_ops.store_gdt, GetGDT);
-       para_fill(pv_cpu_ops.store_idt, GetIDT);
-       para_fill(pv_cpu_ops.store_tr, GetTR);
-       pv_cpu_ops.load_tls = vmi_load_tls;
-       para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
-                 write_ldt_entry, WriteLDTEntry);
-       para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
-                 write_gdt_entry, WriteGDTEntry);
-       para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
-                 write_idt_entry, WriteIDTEntry);
-       para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
-       para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
-       para_fill(pv_cpu_ops.io_delay, IODelay);
-
-       para_wrap(pv_cpu_ops.start_context_switch, vmi_start_context_switch,
-                 set_lazy_mode, SetLazyMode);
-       para_wrap(pv_cpu_ops.end_context_switch, vmi_end_context_switch,
-                 set_lazy_mode, SetLazyMode);
-
-       para_wrap(pv_mmu_ops.lazy_mode.enter, vmi_enter_lazy_mmu,
-                 set_lazy_mode, SetLazyMode);
-       para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy_mmu,
-                 set_lazy_mode, SetLazyMode);
-
-       /* user and kernel flush are just handled with different flags to FlushTLB */
-       para_wrap(pv_mmu_ops.flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
-       para_wrap(pv_mmu_ops.flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
-       para_fill(pv_mmu_ops.flush_tlb_single, InvalPage);
-
-       /*
-        * Until a standard flag format can be agreed on, we need to
-        * implement these as wrappers in Linux.  Get the VMI ROM
-        * function pointers for the two backend calls.
-        */
-#ifdef CONFIG_X86_PAE
-       vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxELong);
-       vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxELong);
-#else
-       vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
-       vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
-#endif
-
-       if (vmi_ops.set_pte) {
-               pv_mmu_ops.set_pte = vmi_set_pte;
-               pv_mmu_ops.set_pte_at = vmi_set_pte_at;
-               pv_mmu_ops.set_pmd = vmi_set_pmd;
-#ifdef CONFIG_X86_PAE
-               pv_mmu_ops.set_pte_atomic = vmi_set_pte_atomic;
-               pv_mmu_ops.set_pud = vmi_set_pud;
-               pv_mmu_ops.pte_clear = vmi_pte_clear;
-               pv_mmu_ops.pmd_clear = vmi_pmd_clear;
-#endif
-       }
-
-       if (vmi_ops.update_pte) {
-               pv_mmu_ops.pte_update = vmi_update_pte;
-               pv_mmu_ops.pte_update_defer = vmi_update_pte_defer;
-       }
-
-       vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
-       if (vmi_ops.allocate_page) {
-               pv_mmu_ops.alloc_pte = vmi_allocate_pte;
-               pv_mmu_ops.alloc_pmd = vmi_allocate_pmd;
-               pv_mmu_ops.alloc_pmd_clone = vmi_allocate_pmd_clone;
-       }
-
-       vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
-       if (vmi_ops.release_page) {
-               pv_mmu_ops.release_pte = vmi_release_pte;
-               pv_mmu_ops.release_pmd = vmi_release_pmd;
-               pv_mmu_ops.pgd_free = vmi_pgd_free;
-       }
-
-       /* Set linear is needed in all cases */
-       vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
-
-       /*
-        * These MUST always be patched.  Don't support indirect jumps
-        * through these operations, as the VMI interface may use either
-        * a jump or a call to get to these operations, depending on
-        * the backend.  They are performance critical anyway, so requiring
-        * a patch is not a big problem.
-        */
-       pv_cpu_ops.irq_enable_sysexit = (void *)0xfeedbab0;
-       pv_cpu_ops.iret = (void *)0xbadbab0;
-
-#ifdef CONFIG_SMP
-       para_wrap(pv_apic_ops.startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
-       para_fill(apic->read, APICRead);
-       para_fill(apic->write, APICWrite);
-#endif
-
-       /*
-        * Check for VMI timer functionality by probing for a cycle frequency method
-        */
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
-       if (!disable_vmi_timer && rel->type != VMI_RELOCATION_NONE) {
-               vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
-               vmi_timer_ops.get_cycle_counter =
-                       vmi_get_function(VMI_CALL_GetCycleCounter);
-               vmi_timer_ops.get_wallclock =
-                       vmi_get_function(VMI_CALL_GetWallclockTime);
-               vmi_timer_ops.wallclock_updated =
-                       vmi_get_function(VMI_CALL_WallclockUpdated);
-               vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
-               vmi_timer_ops.cancel_alarm =
-                        vmi_get_function(VMI_CALL_CancelAlarm);
-               x86_init.timers.timer_init = vmi_time_init;
-#ifdef CONFIG_X86_LOCAL_APIC
-               x86_init.timers.setup_percpu_clockev = vmi_time_bsp_init;
-               x86_cpuinit.setup_percpu_clockev = vmi_time_ap_init;
-#endif
-               pv_time_ops.sched_clock = vmi_sched_clock;
-               x86_platform.calibrate_tsc = vmi_tsc_khz;
-               x86_platform.get_wallclock = vmi_get_wallclock;
-               x86_platform.set_wallclock = vmi_set_wallclock;
-
-               /* We have true wallclock functions; disable CMOS clock sync */
-               no_sync_cmos_clock = 1;
-       } else {
-               disable_noidle = 1;
-               disable_vmi_timer = 1;
-       }
-
-       para_fill(pv_irq_ops.safe_halt, Halt);
-
-       /*
-        * Alternative instruction rewriting doesn't happen soon enough
-        * to convert VMI_IRET to a call instead of a jump; so we have
-        * to do this before IRQs get reenabled.  Fortunately, it is
-        * idempotent.
-        */
-       apply_paravirt(__parainstructions, __parainstructions_end);
-
-       vmi_bringup();
-
-       return 1;
-}
-
-#undef para_fill
-
-void __init vmi_init(void)
-{
-       if (!vmi_rom)
-               probe_vmi_rom();
-       else
-               check_vmi_rom(vmi_rom);
-
-       /* In case probing for or validating the ROM failed, basil */
-       if (!vmi_rom)
-               return;
-
-       reserve_top_address(-vmi_rom->virtual_top);
-
-#ifdef CONFIG_X86_IO_APIC
-       /* This is virtual hardware; timer routing is wired correctly */
-       no_timer_check = 1;
-#endif
-}
-
-void __init vmi_activate(void)
-{
-       unsigned long flags;
-
-       if (!vmi_rom)
-               return;
-
-       local_irq_save(flags);
-       activate_vmi();
-       local_irq_restore(flags & X86_EFLAGS_IF);
-}
-
-static int __init parse_vmi(char *arg)
-{
-       if (!arg)
-               return -EINVAL;
-
-       if (!strcmp(arg, "disable_pge")) {
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
-               disable_pge = 1;
-       } else if (!strcmp(arg, "disable_pse")) {
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PSE);
-               disable_pse = 1;
-       } else if (!strcmp(arg, "disable_sep")) {
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
-               disable_sep = 1;
-       } else if (!strcmp(arg, "disable_tsc")) {
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC);
-               disable_tsc = 1;
-       } else if (!strcmp(arg, "disable_mtrr")) {
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_MTRR);
-               disable_mtrr = 1;
-       } else if (!strcmp(arg, "disable_timer")) {
-               disable_vmi_timer = 1;
-               disable_noidle = 1;
-       } else if (!strcmp(arg, "disable_noidle"))
-               disable_noidle = 1;
-       return 0;
-}
-
-early_param("vmi", parse_vmi);
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
deleted file mode 100644 (file)
index 5e1ff66..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * VMI paravirtual timer support routines.
- *
- * Copyright (C) 2007, VMware, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/cpumask.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/vmi.h>
-#include <asm/vmi_time.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/timer.h>
-#include <asm/i8253.h>
-#include <asm/irq_vectors.h>
-
-#define VMI_ONESHOT  (VMI_ALARM_IS_ONESHOT  | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-#define VMI_PERIODIC (VMI_ALARM_IS_PERIODIC | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-
-static DEFINE_PER_CPU(struct clock_event_device, local_events);
-
-static inline u32 vmi_counter(u32 flags)
-{
-       /* Given VMI_ONESHOT or VMI_PERIODIC, return the corresponding
-        * cycle counter. */
-       return flags & VMI_ALARM_COUNTER_MASK;
-}
-
-/* paravirt_ops.get_wallclock = vmi_get_wallclock */
-unsigned long vmi_get_wallclock(void)
-{
-       unsigned long long wallclock;
-       wallclock = vmi_timer_ops.get_wallclock(); // nsec
-       (void)do_div(wallclock, 1000000000);       // sec
-
-       return wallclock;
-}
-
-/* paravirt_ops.set_wallclock = vmi_set_wallclock */
-int vmi_set_wallclock(unsigned long now)
-{
-       return 0;
-}
-
-/* paravirt_ops.sched_clock = vmi_sched_clock */
-unsigned long long vmi_sched_clock(void)
-{
-       return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE));
-}
-
-/* x86_platform.calibrate_tsc = vmi_tsc_khz */
-unsigned long vmi_tsc_khz(void)
-{
-       unsigned long long khz;
-       khz = vmi_timer_ops.get_cycle_frequency();
-       (void)do_div(khz, 1000);
-       return khz;
-}
-
-static inline unsigned int vmi_get_timer_vector(void)
-{
-       return IRQ0_VECTOR;
-}
-
-/** vmi clockchip */
-#ifdef CONFIG_X86_LOCAL_APIC
-static unsigned int startup_timer_irq(unsigned int irq)
-{
-       unsigned long val = apic_read(APIC_LVTT);
-       apic_write(APIC_LVTT, vmi_get_timer_vector());
-
-       return (val & APIC_SEND_PENDING);
-}
-
-static void mask_timer_irq(unsigned int irq)
-{
-       unsigned long val = apic_read(APIC_LVTT);
-       apic_write(APIC_LVTT, val | APIC_LVT_MASKED);
-}
-
-static void unmask_timer_irq(unsigned int irq)
-{
-       unsigned long val = apic_read(APIC_LVTT);
-       apic_write(APIC_LVTT, val & ~APIC_LVT_MASKED);
-}
-
-static void ack_timer_irq(unsigned int irq)
-{
-       ack_APIC_irq();
-}
-
-static struct irq_chip vmi_chip __read_mostly = {
-       .name           = "VMI-LOCAL",
-       .startup        = startup_timer_irq,
-       .mask           = mask_timer_irq,
-       .unmask         = unmask_timer_irq,
-       .ack            = ack_timer_irq
-};
-#endif
-
-/** vmi clockevent */
-#define VMI_ALARM_WIRED_IRQ0    0x00000000
-#define VMI_ALARM_WIRED_LVTT    0x00010000
-static int vmi_wiring = VMI_ALARM_WIRED_IRQ0;
-
-static inline int vmi_get_alarm_wiring(void)
-{
-       return vmi_wiring;
-}
-
-static void vmi_timer_set_mode(enum clock_event_mode mode,
-                              struct clock_event_device *evt)
-{
-       cycle_t now, cycles_per_hz;
-       BUG_ON(!irqs_disabled());
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_ONESHOT:
-       case CLOCK_EVT_MODE_RESUME:
-               break;
-       case CLOCK_EVT_MODE_PERIODIC:
-               cycles_per_hz = vmi_timer_ops.get_cycle_frequency();
-               (void)do_div(cycles_per_hz, HZ);
-               now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_PERIODIC));
-               vmi_timer_ops.set_alarm(VMI_PERIODIC, now, cycles_per_hz);
-               break;
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               switch (evt->mode) {
-               case CLOCK_EVT_MODE_ONESHOT:
-                       vmi_timer_ops.cancel_alarm(VMI_ONESHOT);
-                       break;
-               case CLOCK_EVT_MODE_PERIODIC:
-                       vmi_timer_ops.cancel_alarm(VMI_PERIODIC);
-                       break;
-               default:
-                       break;
-               }
-               break;
-       default:
-               break;
-       }
-}
-
-static int vmi_timer_next_event(unsigned long delta,
-                               struct clock_event_device *evt)
-{
-       /* Unfortunately, set_next_event interface only passes relative
-        * expiry, but we want absolute expiry.  It'd be better if were
-        * were passed an absolute expiry, since a bunch of time may
-        * have been stolen between the time the delta is computed and
-        * when we set the alarm below. */
-       cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT));
-
-       BUG_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
-       vmi_timer_ops.set_alarm(VMI_ONESHOT, now + delta, 0);
-       return 0;
-}
-
-static struct clock_event_device vmi_clockevent = {
-       .name           = "vmi-timer",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 22,
-       .set_mode       = vmi_timer_set_mode,
-       .set_next_event = vmi_timer_next_event,
-       .rating         = 1000,
-       .irq            = 0,
-};
-
-static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = &__get_cpu_var(local_events);
-       evt->event_handler(evt);
-       return IRQ_HANDLED;
-}
-
-static struct irqaction vmi_clock_action  = {
-       .name           = "vmi-timer",
-       .handler        = vmi_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
-};
-
-static void __devinit vmi_time_init_clockevent(void)
-{
-       cycle_t cycles_per_msec;
-       struct clock_event_device *evt;
-
-       int cpu = smp_processor_id();
-       evt = &__get_cpu_var(local_events);
-
-       /* Use cycles_per_msec since div_sc params are 32-bits. */
-       cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
-       (void)do_div(cycles_per_msec, 1000);
-
-       memcpy(evt, &vmi_clockevent, sizeof(*evt));
-       /* Must pick .shift such that .mult fits in 32-bits.  Choosing
-        * .shift to be 22 allows 2^(32-22) cycles per nano-seconds
-        * before overflow. */
-       evt->mult = div_sc(cycles_per_msec, NSEC_PER_MSEC, evt->shift);
-       /* Upper bound is clockevent's use of ulong for cycle deltas. */
-       evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt);
-       evt->min_delta_ns = clockevent_delta2ns(1, evt);
-       evt->cpumask = cpumask_of(cpu);
-
-       printk(KERN_WARNING "vmi: registering clock event %s. mult=%u shift=%u\n",
-              evt->name, evt->mult, evt->shift);
-       clockevents_register_device(evt);
-}
-
-void __init vmi_time_init(void)
-{
-       unsigned int cpu;
-       /* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
-       outb_pit(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
-
-       vmi_time_init_clockevent();
-       setup_irq(0, &vmi_clock_action);
-       for_each_possible_cpu(cpu)
-               per_cpu(vector_irq, cpu)[vmi_get_timer_vector()] = 0;
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-void __devinit vmi_time_bsp_init(void)
-{
-       /*
-        * On APIC systems, we want local timers to fire on each cpu.  We do
-        * this by programming LVTT to deliver timer events to the IRQ handler
-        * for IRQ-0, since we can't re-use the APIC local timer handler
-        * without interfering with that code.
-        */
-       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
-       local_irq_disable();
-#ifdef CONFIG_SMP
-       /*
-        * XXX handle_percpu_irq only defined for SMP; we need to switch over
-        * to using it, since this is a local interrupt, which each CPU must
-        * handle individually without locking out or dropping simultaneous
-        * local timers on other CPUs.  We also don't want to trigger the
-        * quirk workaround code for interrupts which gets invoked from
-        * handle_percpu_irq via eoi, so we use our own IRQ chip.
-        */
-       set_irq_chip_and_handler_name(0, &vmi_chip, handle_percpu_irq, "lvtt");
-#else
-       set_irq_chip_and_handler_name(0, &vmi_chip, handle_edge_irq, "lvtt");
-#endif
-       vmi_wiring = VMI_ALARM_WIRED_LVTT;
-       apic_write(APIC_LVTT, vmi_get_timer_vector());
-       local_irq_enable();
-       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-}
-
-void __devinit vmi_time_ap_init(void)
-{
-       vmi_time_init_clockevent();
-       apic_write(APIC_LVTT, vmi_get_timer_vector());
-}
-#endif
-
-/** vmi clocksource */
-static struct clocksource clocksource_vmi;
-
-static cycle_t read_real_cycles(struct clocksource *cs)
-{
-       cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
-       return max(ret, clocksource_vmi.cycle_last);
-}
-
-static struct clocksource clocksource_vmi = {
-       .name                   = "vmi-timer",
-       .rating                 = 450,
-       .read                   = read_real_cycles,
-       .mask                   = CLOCKSOURCE_MASK(64),
-       .mult                   = 0, /* to be set */
-       .shift                  = 22,
-       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init init_vmi_clocksource(void)
-{
-       cycle_t cycles_per_msec;
-
-       if (!vmi_timer_ops.get_cycle_frequency)
-               return 0;
-       /* Use khz2mult rather than hz2mult since hz arg is only 32-bits. */
-       cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
-       (void)do_div(cycles_per_msec, 1000);
-
-       /* Note that clocksource.{mult, shift} converts in the opposite direction
-        * as clockevents.  */
-       clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
-                                                   clocksource_vmi.shift);
-
-       printk(KERN_WARNING "vmi: registering clock source khz=%lld\n", cycles_per_msec);
-       return clocksource_register(&clocksource_vmi);
-
-}
-module_init(init_vmi_clocksource);
index d0bb52296fa3a8f564cdb1964107e677494859ed..e03530aebfd0332635f901afa9f19f00317fa097 100644 (file)
@@ -242,6 +242,12 @@ SECTIONS
                __x86_cpu_dev_end = .;
        }
 
+       /*
+        * start address and size of operations which during runtime
+        * can be patched with virtualization friendly instructions or
+        * baremetal native ones. Think page table operations.
+        * Details in paravirt_types.h
+        */
        . = ALIGN(8);
        .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
                __parainstructions = .;
@@ -249,6 +255,11 @@ SECTIONS
                __parainstructions_end = .;
        }
 
+       /*
+        * struct alt_inst entries. From the header (alternative.h):
+        * "Alternative instructions for different CPU types or capabilities"
+        * Think locking instructions on spinlocks.
+        */
        . = ALIGN(8);
        .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
                __alt_instructions = .;
@@ -256,10 +267,27 @@ SECTIONS
                __alt_instructions_end = .;
        }
 
+       /*
+        * And here are the replacement instructions. The linker sticks
+        * them as binary blobs. The .altinstructions has enough data to
+        * get the address and the length of them to patch the kernel safely.
+        */
        .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
                *(.altinstr_replacement)
        }
 
+       /*
+        * struct iommu_table_entry entries are injected in this section.
+        * It is an array of IOMMUs which during run time gets sorted depending
+        * on its dependency order. After rootfs_initcall is complete
+        * this section can be safely removed.
+        */
+       .iommu_table : AT(ADDR(.iommu_table) - LOAD_OFFSET) {
+               __iommu_table = .;
+               *(.iommu_table)
+               __iommu_table_end = .;
+       }
+       . = ALIGN(8);
        /*
         * .exit.text is discard at runtime, not link time, to deal with
         *  references from .altinstructions and .eh_frame
@@ -273,7 +301,7 @@ SECTIONS
        }
 
 #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
-       PERCPU(PAGE_SIZE)
+       PERCPU(THREAD_SIZE)
 #endif
 
        . = ALIGN(PAGE_SIZE);
index b38bd8b92aa6c84ed9a00295eeaac73bade26458..66ca98aafdd6a73d7eea8834d1f1c930384b8268 100644 (file)
@@ -1870,17 +1870,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
                               struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
-       u64 old = c->dst.orig_val;
+       u64 old = c->dst.orig_val64;
 
        if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
            ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
-
                c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
                c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
                ctxt->eflags &= ~EFLG_ZF;
        } else {
-               c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
-                      (u32) c->regs[VCPU_REGS_RBX];
+               c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
+                       (u32) c->regs[VCPU_REGS_RBX];
 
                ctxt->eflags |= EFLG_ZF;
        }
@@ -2616,7 +2615,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
                                        c->src.valptr, c->src.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
-               c->src.orig_val = c->src.val;
+               c->src.orig_val64 = c->src.val64;
        }
 
        if (c->src2.type == OP_MEM) {
index 8d10c063d7f207451b087a11a8d7bf0c888f3695..4b7b73ce209894442eddd9df2b8f076408389b12 100644 (file)
@@ -64,6 +64,9 @@ static void pic_unlock(struct kvm_pic *s)
                if (!found)
                        found = s->kvm->bsp_vcpu;
 
+               if (!found)
+                       return;
+
                kvm_vcpu_kick(found);
        }
 }
index ffed06871c5cf389594244086ecb3685496b4258..63c314502993b33c1a53773d111eb69133668179 100644 (file)
@@ -43,7 +43,6 @@ struct kvm_kpic_state {
        u8 irr;         /* interrupt request register */
        u8 imr;         /* interrupt mask register */
        u8 isr;         /* interrupt service register */
-       u8 isr_ack;     /* interrupt ack detection */
        u8 priority_add;        /* highest irq priority */
        u8 irq_base;
        u8 read_reg_select;
@@ -56,6 +55,7 @@ struct kvm_kpic_state {
        u8 init4;               /* true if 4 byte init */
        u8 elcr;                /* PIIX edge/trigger selection */
        u8 elcr_mask;
+       u8 isr_ack;     /* interrupt ack detection */
        struct kvm_pic *pics_state;
 };
 
index 77d8c0f4817d5f10f88e725ad49b22642c1172c5..22b06f7660f4f44459ef62568659f745d2d8dc83 100644 (file)
@@ -1056,14 +1056,13 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
 
        vcpu->arch.apic = apic;
 
-       apic->regs_page = alloc_page(GFP_KERNEL);
+       apic->regs_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
        if (apic->regs_page == NULL) {
                printk(KERN_ERR "malloc apic regs error for vcpu %x\n",
                       vcpu->vcpu_id);
                goto nomem_free_apic;
        }
        apic->regs = page_address(apic->regs_page);
-       memset(apic->regs, 0, PAGE_SIZE);
        apic->vcpu = vcpu;
 
        hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
index bc5b9b8d4a33117259882835bfb884f4f8f37656..8a3f9f64f86f9e7fee5bc5112bf50a04fbe37b15 100644 (file)
@@ -766,7 +766,6 @@ static void init_vmcb(struct vcpu_svm *svm)
 
        control->iopm_base_pa = iopm_base;
        control->msrpm_base_pa = __pa(svm->msrpm);
-       control->tsc_offset = 0;
        control->int_ctl = V_INTR_MASKING_MASK;
 
        init_seg(&save->es);
@@ -902,6 +901,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
        svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
        svm->asid_generation = 0;
        init_vmcb(svm);
+       svm->vmcb->control.tsc_offset = 0-native_read_tsc();
 
        err = fx_init(&svm->vcpu);
        if (err)
@@ -3163,8 +3163,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        sync_lapic_to_cr8(vcpu);
 
        save_host_msrs(vcpu);
-       fs_selector = kvm_read_fs();
-       gs_selector = kvm_read_gs();
+       savesegment(fs, fs_selector);
+       savesegment(gs, gs_selector);
        ldt_selector = kvm_read_ldt();
        svm->vmcb->save.cr2 = vcpu->arch.cr2;
        /* required for live migration with NPT */
@@ -3251,10 +3251,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
        vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
-       kvm_load_fs(fs_selector);
-       kvm_load_gs(gs_selector);
-       kvm_load_ldt(ldt_selector);
        load_host_msrs(vcpu);
+       loadsegment(fs, fs_selector);
+#ifdef CONFIG_X86_64
+       load_gs_index(gs_selector);
+       wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+       loadsegment(gs, gs_selector);
+#endif
+       kvm_load_ldt(ldt_selector);
 
        reload_tss(vcpu);
 
index 49b25eee25acc075538a411fc24c23a326f02fd4..7bddfab120139435d1d10885520cc5293fefcc07 100644 (file)
@@ -803,7 +803,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
         */
        vmx->host_state.ldt_sel = kvm_read_ldt();
        vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
-       vmx->host_state.fs_sel = kvm_read_fs();
+       savesegment(fs, vmx->host_state.fs_sel);
        if (!(vmx->host_state.fs_sel & 7)) {
                vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
                vmx->host_state.fs_reload_needed = 0;
@@ -811,7 +811,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
                vmcs_write16(HOST_FS_SELECTOR, 0);
                vmx->host_state.fs_reload_needed = 1;
        }
-       vmx->host_state.gs_sel = kvm_read_gs();
+       savesegment(gs, vmx->host_state.gs_sel);
        if (!(vmx->host_state.gs_sel & 7))
                vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
        else {
@@ -841,27 +841,21 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
 
 static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 {
-       unsigned long flags;
-
        if (!vmx->host_state.loaded)
                return;
 
        ++vmx->vcpu.stat.host_state_reload;
        vmx->host_state.loaded = 0;
        if (vmx->host_state.fs_reload_needed)
-               kvm_load_fs(vmx->host_state.fs_sel);
+               loadsegment(fs, vmx->host_state.fs_sel);
        if (vmx->host_state.gs_ldt_reload_needed) {
                kvm_load_ldt(vmx->host_state.ldt_sel);
-               /*
-                * If we have to reload gs, we must take care to
-                * preserve our gs base.
-                */
-               local_irq_save(flags);
-               kvm_load_gs(vmx->host_state.gs_sel);
 #ifdef CONFIG_X86_64
-               wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+               load_gs_index(vmx->host_state.gs_sel);
+               wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+               loadsegment(gs, vmx->host_state.gs_sel);
 #endif
-               local_irq_restore(flags);
        }
        reload_tss();
 #ifdef CONFIG_X86_64
@@ -2589,8 +2583,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
        vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
        vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
-       vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs());    /* 22.2.4 */
-       vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs());    /* 22.2.4 */
+       vmcs_write16(HOST_FS_SELECTOR, 0);            /* 22.2.4 */
+       vmcs_write16(HOST_GS_SELECTOR, 0);            /* 22.2.4 */
        vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 #ifdef CONFIG_X86_64
        rdmsrl(MSR_FS_BASE, a);
index 3a09c625d5268ad4dc0f7a033d429c234babcb96..6c2ecf0a806d67040335f7c0c57c0b57fed3384d 100644 (file)
@@ -1991,13 +1991,14 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
                0 /* Reserved, DCA */ | F(XMM4_1) |
                F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
-               0 /* Reserved, AES */ | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX);
+               0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
+               F(F16C);
        /* cpuid 0x80000001.ecx */
        const u32 kvm_supported_word6_x86_features =
                F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
                F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
-               F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
-               0 /* SKINIT */ | 0 /* WDT */;
+               F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
+               0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
 
        /* all calls to cpuid_count() should be made on the same cpu */
        get_cpu();
index 9257510b4836837eb4cdff719000b716ff3bdd63..73b1e1a1f4891708a8714570e36ce62b15ba6fc7 100644 (file)
@@ -324,9 +324,8 @@ static void lguest_load_gdt(const struct desc_ptr *desc)
 }
 
 /*
- * For a single GDT entry which changes, we do the lazy thing: alter our GDT,
- * then tell the Host to reload the entire thing.  This operation is so rare
- * that this naive implementation is reasonable.
+ * For a single GDT entry which changes, we simply change our copy and
+ * then tell the host about it.
  */
 static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
                                   const void *desc, int type)
@@ -338,9 +337,13 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
 }
 
 /*
- * OK, I lied.  There are three "thread local storage" GDT entries which change
+ * There are three "thread local storage" GDT entries which change
  * on every context switch (these three entries are how glibc implements
- * __thread variables).  So we have a hypercall specifically for this case.
+ * __thread variables).  As an optimization, we have a hypercall
+ * specifically for this case.
+ *
+ * Wouldn't it be nicer to have a general LOAD_GDT_ENTRIES hypercall
+ * which took a range of entries?
  */
 static void lguest_load_tls(struct thread_struct *t, unsigned int cpu)
 {
@@ -788,22 +791,22 @@ static void lguest_flush_tlb_kernel(void)
  * simple as setting a bit.  We don't actually "ack" interrupts as such, we
  * just mask and unmask them.  I wonder if we should be cleverer?
  */
-static void disable_lguest_irq(unsigned int irq)
+static void disable_lguest_irq(struct irq_data *data)
 {
-       set_bit(irq, lguest_data.blocked_interrupts);
+       set_bit(data->irq, lguest_data.blocked_interrupts);
 }
 
-static void enable_lguest_irq(unsigned int irq)
+static void enable_lguest_irq(struct irq_data *data)
 {
-       clear_bit(irq, lguest_data.blocked_interrupts);
+       clear_bit(data->irq, lguest_data.blocked_interrupts);
 }
 
 /* This structure describes the lguest IRQ controller. */
 static struct irq_chip lguest_irq_controller = {
        .name           = "lguest",
-       .mask           = disable_lguest_irq,
-       .mask_ack       = disable_lguest_irq,
-       .unmask         = enable_lguest_irq,
+       .irq_mask       = disable_lguest_irq,
+       .irq_mask_ack   = disable_lguest_irq,
+       .irq_unmask     = enable_lguest_irq,
 };
 
 /*
@@ -835,12 +838,12 @@ static void __init lguest_init_IRQ(void)
  * rather than set them in lguest_init_IRQ we are called here every time an
  * lguest device needs an interrupt.
  *
- * FIXME: irq_to_desc_alloc_node() can fail due to lack of memory, we should
+ * FIXME: irq_alloc_desc_at() can fail due to lack of memory, we should
  * pass that up!
  */
 void lguest_setup_irq(unsigned int irq)
 {
-       irq_to_desc_alloc_node(irq, 0);
+       irq_alloc_desc_at(irq, 0);
        set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
                                      handle_level_irq, "level");
 }
index 5415a9d06f53b75c4a993b0bbe96508502691142..b908a59eccf52fe4ab22382ae793cb2a9f023e4f 100644 (file)
@@ -22,22 +22,187 @@ EXPORT_SYMBOL(memset);
 
 void *memmove(void *dest, const void *src, size_t n)
 {
-       int d0, d1, d2;
-
-       if (dest < src) {
-               memcpy(dest, src, n);
-       } else {
-               __asm__ __volatile__(
-                       "std\n\t"
-                       "rep\n\t"
-                       "movsb\n\t"
-                       "cld"
-                       : "=&c" (d0), "=&S" (d1), "=&D" (d2)
-                       :"0" (n),
-                        "1" (n-1+src),
-                        "2" (n-1+dest)
-                       :"memory");
-       }
-       return dest;
+       int d0,d1,d2,d3,d4,d5;
+       char *ret = dest;
+
+       __asm__ __volatile__(
+               /* Handle more 16bytes in loop */
+               "cmp $0x10, %0\n\t"
+               "jb     1f\n\t"
+
+               /* Decide forward/backward copy mode */
+               "cmp %2, %1\n\t"
+               "jb     2f\n\t"
+
+               /*
+                * movs instruction have many startup latency
+                * so we handle small size by general register.
+                */
+               "cmp  $680, %0\n\t"
+               "jb 3f\n\t"
+               /*
+                * movs instruction is only good for aligned case.
+                */
+               "mov %1, %3\n\t"
+               "xor %2, %3\n\t"
+               "and $0xff, %3\n\t"
+               "jz 4f\n\t"
+               "3:\n\t"
+               "sub $0x10, %0\n\t"
+
+               /*
+                * We gobble 16byts forward in each loop.
+                */
+               "3:\n\t"
+               "sub $0x10, %0\n\t"
+               "mov 0*4(%1), %3\n\t"
+               "mov 1*4(%1), %4\n\t"
+               "mov  %3, 0*4(%2)\n\t"
+               "mov  %4, 1*4(%2)\n\t"
+               "mov 2*4(%1), %3\n\t"
+               "mov 3*4(%1), %4\n\t"
+               "mov  %3, 2*4(%2)\n\t"
+               "mov  %4, 3*4(%2)\n\t"
+               "lea  0x10(%1), %1\n\t"
+               "lea  0x10(%2), %2\n\t"
+               "jae 3b\n\t"
+               "add $0x10, %0\n\t"
+               "jmp 1f\n\t"
+
+               /*
+                * Handle data forward by movs.
+                */
+               ".p2align 4\n\t"
+               "4:\n\t"
+               "mov -4(%1, %0), %3\n\t"
+               "lea -4(%2, %0), %4\n\t"
+               "shr $2, %0\n\t"
+               "rep movsl\n\t"
+               "mov %3, (%4)\n\t"
+               "jmp 11f\n\t"
+               /*
+                * Handle data backward by movs.
+                */
+               ".p2align 4\n\t"
+               "6:\n\t"
+               "mov (%1), %3\n\t"
+               "mov %2, %4\n\t"
+               "lea -4(%1, %0), %1\n\t"
+               "lea -4(%2, %0), %2\n\t"
+               "shr $2, %0\n\t"
+               "std\n\t"
+               "rep movsl\n\t"
+               "mov %3,(%4)\n\t"
+               "cld\n\t"
+               "jmp 11f\n\t"
+
+               /*
+                * Start to prepare for backward copy.
+                */
+               ".p2align 4\n\t"
+               "2:\n\t"
+               "cmp  $680, %0\n\t"
+               "jb 5f\n\t"
+               "mov %1, %3\n\t"
+               "xor %2, %3\n\t"
+               "and $0xff, %3\n\t"
+               "jz 6b\n\t"
+
+               /*
+                * Calculate copy position to tail.
+                */
+               "5:\n\t"
+               "add %0, %1\n\t"
+               "add %0, %2\n\t"
+               "sub $0x10, %0\n\t"
+
+               /*
+                * We gobble 16byts backward in each loop.
+                */
+               "7:\n\t"
+               "sub $0x10, %0\n\t"
+
+               "mov -1*4(%1), %3\n\t"
+               "mov -2*4(%1), %4\n\t"
+               "mov  %3, -1*4(%2)\n\t"
+               "mov  %4, -2*4(%2)\n\t"
+               "mov -3*4(%1), %3\n\t"
+               "mov -4*4(%1), %4\n\t"
+               "mov  %3, -3*4(%2)\n\t"
+               "mov  %4, -4*4(%2)\n\t"
+               "lea  -0x10(%1), %1\n\t"
+               "lea  -0x10(%2), %2\n\t"
+               "jae 7b\n\t"
+               /*
+                * Calculate copy position to head.
+                */
+               "add $0x10, %0\n\t"
+               "sub %0, %1\n\t"
+               "sub %0, %2\n\t"
+
+               /*
+                * Move data from 8 bytes to 15 bytes.
+                */
+               ".p2align 4\n\t"
+               "1:\n\t"
+               "cmp $8, %0\n\t"
+               "jb 8f\n\t"
+               "mov 0*4(%1), %3\n\t"
+               "mov 1*4(%1), %4\n\t"
+               "mov -2*4(%1, %0), %5\n\t"
+               "mov -1*4(%1, %0), %1\n\t"
+
+               "mov  %3, 0*4(%2)\n\t"
+               "mov  %4, 1*4(%2)\n\t"
+               "mov  %5, -2*4(%2, %0)\n\t"
+               "mov  %1, -1*4(%2, %0)\n\t"
+               "jmp 11f\n\t"
+
+               /*
+                * Move data from 4 bytes to 7 bytes.
+                */
+               ".p2align 4\n\t"
+               "8:\n\t"
+               "cmp $4, %0\n\t"
+               "jb 9f\n\t"
+               "mov 0*4(%1), %3\n\t"
+               "mov -1*4(%1, %0), %4\n\t"
+               "mov  %3, 0*4(%2)\n\t"
+               "mov  %4, -1*4(%2, %0)\n\t"
+               "jmp 11f\n\t"
+
+               /*
+                * Move data from 2 bytes to 3 bytes.
+                */
+               ".p2align 4\n\t"
+               "9:\n\t"
+               "cmp $2, %0\n\t"
+               "jb 10f\n\t"
+               "movw 0*2(%1), %%dx\n\t"
+               "movw -1*2(%1, %0), %%bx\n\t"
+               "movw %%dx, 0*2(%2)\n\t"
+               "movw %%bx, -1*2(%2, %0)\n\t"
+               "jmp 11f\n\t"
+
+               /*
+                * Move data for 1 byte.
+                */
+               ".p2align 4\n\t"
+               "10:\n\t"
+               "cmp $1, %0\n\t"
+               "jb 11f\n\t"
+               "movb (%1), %%cl\n\t"
+               "movb %%cl, (%2)\n\t"
+               ".p2align 4\n\t"
+               "11:"
+               : "=&c" (d0), "=&S" (d1), "=&D" (d2),
+                 "=r" (d3),"=r" (d4), "=r"(d5)
+               :"0" (n),
+                "1" (src),
+                "2" (dest)
+               :"memory");
+
+       return ret;
+
 }
 EXPORT_SYMBOL(memmove);
index bcbcd1e0f7d57fe4b3972adc24785dc6837386f6..75ef61e35e38aee1cf62b05a48f1add62b148f98 100644 (file)
 ENTRY(__memcpy)
 ENTRY(memcpy)
        CFI_STARTPROC
+       movq %rdi, %rax
 
        /*
-        * Put the number of full 64-byte blocks into %ecx.
-        * Tail portion is handled at the end:
+        * Use 32bit CMP here to avoid long NOP padding.
         */
-       movq %rdi, %rax
-       movl %edx, %ecx
-       shrl   $6, %ecx
-       jz .Lhandle_tail
+       cmp  $0x20, %edx
+       jb .Lhandle_tail
 
-       .p2align 4
-.Lloop_64:
        /*
-        * We decrement the loop index here - and the zero-flag is
-        * checked at the end of the loop (instructions inbetween do
-        * not change the zero flag):
+        * We check whether memory false dependece could occur,
+        * then jump to corresponding copy mode.
         */
-       decl %ecx
+       cmp  %dil, %sil
+       jl .Lcopy_backward
+       subl $0x20, %edx
+.Lcopy_forward_loop:
+       subq $0x20,     %rdx
 
        /*
-        * Move in blocks of 4x16 bytes:
+        * Move in blocks of 4x8 bytes:
         */
-       movq 0*8(%rsi),         %r11
-       movq 1*8(%rsi),         %r8
-       movq %r11,              0*8(%rdi)
-       movq %r8,               1*8(%rdi)
-
-       movq 2*8(%rsi),         %r9
-       movq 3*8(%rsi),         %r10
-       movq %r9,               2*8(%rdi)
-       movq %r10,              3*8(%rdi)
-
-       movq 4*8(%rsi),         %r11
-       movq 5*8(%rsi),         %r8
-       movq %r11,              4*8(%rdi)
-       movq %r8,               5*8(%rdi)
-
-       movq 6*8(%rsi),         %r9
-       movq 7*8(%rsi),         %r10
-       movq %r9,               6*8(%rdi)
-       movq %r10,              7*8(%rdi)
-
-       leaq 64(%rsi), %rsi
-       leaq 64(%rdi), %rdi
-
-       jnz  .Lloop_64
+       movq 0*8(%rsi), %r8
+       movq 1*8(%rsi), %r9
+       movq 2*8(%rsi), %r10
+       movq 3*8(%rsi), %r11
+       leaq 4*8(%rsi), %rsi
+
+       movq %r8,       0*8(%rdi)
+       movq %r9,       1*8(%rdi)
+       movq %r10,      2*8(%rdi)
+       movq %r11,      3*8(%rdi)
+       leaq 4*8(%rdi), %rdi
+       jae  .Lcopy_forward_loop
+       addq $0x20,     %rdx
+       jmp  .Lhandle_tail
+
+.Lcopy_backward:
+       /*
+        * Calculate copy position to tail.
+        */
+       addq %rdx,      %rsi
+       addq %rdx,      %rdi
+       subq $0x20,     %rdx
+       /*
+        * At most 3 ALU operations in one cycle,
+        * so append NOPS in the same 16bytes trunk.
+        */
+       .p2align 4
+.Lcopy_backward_loop:
+       subq $0x20,     %rdx
+       movq -1*8(%rsi),        %r8
+       movq -2*8(%rsi),        %r9
+       movq -3*8(%rsi),        %r10
+       movq -4*8(%rsi),        %r11
+       leaq -4*8(%rsi),        %rsi
+       movq %r8,               -1*8(%rdi)
+       movq %r9,               -2*8(%rdi)
+       movq %r10,              -3*8(%rdi)
+       movq %r11,              -4*8(%rdi)
+       leaq -4*8(%rdi),        %rdi
+       jae  .Lcopy_backward_loop
 
+       /*
+        * Calculate copy position to head.
+        */
+       addq $0x20,     %rdx
+       subq %rdx,      %rsi
+       subq %rdx,      %rdi
 .Lhandle_tail:
-       movl %edx, %ecx
-       andl  $63, %ecx
-       shrl   $3, %ecx
-       jz   .Lhandle_7
+       cmpq $16,       %rdx
+       jb   .Lless_16bytes
 
+       /*
+        * Move data from 16 bytes to 31 bytes.
+        */
+       movq 0*8(%rsi), %r8
+       movq 1*8(%rsi), %r9
+       movq -2*8(%rsi, %rdx),  %r10
+       movq -1*8(%rsi, %rdx),  %r11
+       movq %r8,       0*8(%rdi)
+       movq %r9,       1*8(%rdi)
+       movq %r10,      -2*8(%rdi, %rdx)
+       movq %r11,      -1*8(%rdi, %rdx)
+       retq
        .p2align 4
-.Lloop_8:
-       decl %ecx
-       movq (%rsi),            %r8
-       movq %r8,               (%rdi)
-       leaq 8(%rdi),           %rdi
-       leaq 8(%rsi),           %rsi
-       jnz  .Lloop_8
-
-.Lhandle_7:
-       movl %edx, %ecx
-       andl $7, %ecx
-       jz .Lend
+.Lless_16bytes:
+       cmpq $8,        %rdx
+       jb   .Lless_8bytes
+       /*
+        * Move data from 8 bytes to 15 bytes.
+        */
+       movq 0*8(%rsi), %r8
+       movq -1*8(%rsi, %rdx),  %r9
+       movq %r8,       0*8(%rdi)
+       movq %r9,       -1*8(%rdi, %rdx)
+       retq
+       .p2align 4
+.Lless_8bytes:
+       cmpq $4,        %rdx
+       jb   .Lless_3bytes
 
+       /*
+        * Move data from 4 bytes to 7 bytes.
+        */
+       movl (%rsi), %ecx
+       movl -4(%rsi, %rdx), %r8d
+       movl %ecx, (%rdi)
+       movl %r8d, -4(%rdi, %rdx)
+       retq
        .p2align 4
+.Lless_3bytes:
+       cmpl $0, %edx
+       je .Lend
+       /*
+        * Move data from 1 bytes to 3 bytes.
+        */
 .Lloop_1:
        movb (%rsi), %r8b
        movb %r8b, (%rdi)
        incq %rdi
        incq %rsi
-       decl %ecx
+       decl %edx
        jnz .Lloop_1
 
 .Lend:
-       ret
+       retq
        CFI_ENDPROC
 ENDPROC(memcpy)
 ENDPROC(__memcpy)
index 0a33909bf12213dbb0945d057e5c7c537296074e..6d0f0ec41b348ad2a912fdb184303c094ce1a996 100644 (file)
 #undef memmove
 void *memmove(void *dest, const void *src, size_t count)
 {
-       if (dest < src) {
-               return memcpy(dest, src, count);
-       } else {
-               char *p = dest + count;
-               const char *s = src + count;
-               while (count--)
-                       *--p = *--s;
-       }
-       return dest;
+       unsigned long d0,d1,d2,d3,d4,d5,d6,d7;
+       char *ret;
+
+       __asm__ __volatile__(
+               /* Handle more 32bytes in loop */
+               "mov %2, %3\n\t"
+               "cmp $0x20, %0\n\t"
+               "jb     1f\n\t"
+
+               /* Decide forward/backward copy mode */
+               "cmp %2, %1\n\t"
+               "jb     2f\n\t"
+
+               /*
+                * movsq instruction have many startup latency
+                * so we handle small size by general register.
+                */
+               "cmp  $680, %0\n\t"
+               "jb 3f\n\t"
+               /*
+                * movsq instruction is only good for aligned case.
+                */
+               "cmpb %%dil, %%sil\n\t"
+               "je 4f\n\t"
+               "3:\n\t"
+               "sub $0x20, %0\n\t"
+               /*
+                * We gobble 32byts forward in each loop.
+                */
+               "5:\n\t"
+               "sub $0x20, %0\n\t"
+               "movq 0*8(%1), %4\n\t"
+               "movq 1*8(%1), %5\n\t"
+               "movq 2*8(%1), %6\n\t"
+               "movq 3*8(%1), %7\n\t"
+               "leaq 4*8(%1), %1\n\t"
+
+               "movq %4, 0*8(%2)\n\t"
+               "movq %5, 1*8(%2)\n\t"
+               "movq %6, 2*8(%2)\n\t"
+               "movq %7, 3*8(%2)\n\t"
+               "leaq 4*8(%2), %2\n\t"
+               "jae 5b\n\t"
+               "addq $0x20, %0\n\t"
+               "jmp 1f\n\t"
+               /*
+                * Handle data forward by movsq.
+                */
+               ".p2align 4\n\t"
+               "4:\n\t"
+               "movq %0, %8\n\t"
+               "movq -8(%1, %0), %4\n\t"
+               "lea -8(%2, %0), %5\n\t"
+               "shrq $3, %8\n\t"
+               "rep movsq\n\t"
+               "movq %4, (%5)\n\t"
+               "jmp 13f\n\t"
+               /*
+                * Handle data backward by movsq.
+                */
+               ".p2align 4\n\t"
+               "7:\n\t"
+               "movq %0, %8\n\t"
+               "movq (%1), %4\n\t"
+               "movq %2, %5\n\t"
+               "leaq -8(%1, %0), %1\n\t"
+               "leaq -8(%2, %0), %2\n\t"
+               "shrq $3, %8\n\t"
+               "std\n\t"
+               "rep movsq\n\t"
+               "cld\n\t"
+               "movq %4, (%5)\n\t"
+               "jmp 13f\n\t"
+
+               /*
+                * Start to prepare for backward copy.
+                */
+               ".p2align 4\n\t"
+               "2:\n\t"
+               "cmp $680, %0\n\t"
+               "jb 6f \n\t"
+               "cmp %%dil, %%sil\n\t"
+               "je 7b \n\t"
+               "6:\n\t"
+               /*
+                * Calculate copy position to tail.
+                */
+               "addq %0, %1\n\t"
+               "addq %0, %2\n\t"
+               "subq $0x20, %0\n\t"
+               /*
+                * We gobble 32byts backward in each loop.
+                */
+               "8:\n\t"
+               "subq $0x20, %0\n\t"
+               "movq -1*8(%1), %4\n\t"
+               "movq -2*8(%1), %5\n\t"
+               "movq -3*8(%1), %6\n\t"
+               "movq -4*8(%1), %7\n\t"
+               "leaq -4*8(%1), %1\n\t"
+
+               "movq %4, -1*8(%2)\n\t"
+               "movq %5, -2*8(%2)\n\t"
+               "movq %6, -3*8(%2)\n\t"
+               "movq %7, -4*8(%2)\n\t"
+               "leaq -4*8(%2), %2\n\t"
+               "jae 8b\n\t"
+               /*
+                * Calculate copy position to head.
+                */
+               "addq $0x20, %0\n\t"
+               "subq %0, %1\n\t"
+               "subq %0, %2\n\t"
+               "1:\n\t"
+               "cmpq $16, %0\n\t"
+               "jb 9f\n\t"
+               /*
+                * Move data from 16 bytes to 31 bytes.
+                */
+               "movq 0*8(%1), %4\n\t"
+               "movq 1*8(%1), %5\n\t"
+               "movq -2*8(%1, %0), %6\n\t"
+               "movq -1*8(%1, %0), %7\n\t"
+               "movq %4, 0*8(%2)\n\t"
+               "movq %5, 1*8(%2)\n\t"
+               "movq %6, -2*8(%2, %0)\n\t"
+               "movq %7, -1*8(%2, %0)\n\t"
+               "jmp 13f\n\t"
+               ".p2align 4\n\t"
+               "9:\n\t"
+               "cmpq $8, %0\n\t"
+               "jb 10f\n\t"
+               /*
+                * Move data from 8 bytes to 15 bytes.
+                */
+               "movq 0*8(%1), %4\n\t"
+               "movq -1*8(%1, %0), %5\n\t"
+               "movq %4, 0*8(%2)\n\t"
+               "movq %5, -1*8(%2, %0)\n\t"
+               "jmp 13f\n\t"
+               "10:\n\t"
+               "cmpq $4, %0\n\t"
+               "jb 11f\n\t"
+               /*
+                * Move data from 4 bytes to 7 bytes.
+                */
+               "movl (%1), %4d\n\t"
+               "movl -4(%1, %0), %5d\n\t"
+               "movl %4d, (%2)\n\t"
+               "movl %5d, -4(%2, %0)\n\t"
+               "jmp 13f\n\t"
+               "11:\n\t"
+               "cmp $2, %0\n\t"
+               "jb 12f\n\t"
+               /*
+                * Move data from 2 bytes to 3 bytes.
+                */
+               "movw (%1), %4w\n\t"
+               "movw -2(%1, %0), %5w\n\t"
+               "movw %4w, (%2)\n\t"
+               "movw %5w, -2(%2, %0)\n\t"
+               "jmp 13f\n\t"
+               "12:\n\t"
+               "cmp $1, %0\n\t"
+               "jb 13f\n\t"
+               /*
+                * Move data for 1 byte.
+                */
+               "movb (%1), %4b\n\t"
+               "movb %4b, (%2)\n\t"
+               "13:\n\t"
+               : "=&d" (d0), "=&S" (d1), "=&D" (d2), "=&a" (ret) ,
+                 "=r"(d3), "=r"(d4), "=r"(d5), "=r"(d6), "=&c" (d7)
+               :"0" (count),
+                "1" (src),
+                "2" (dest)
+               :"memory");
+
+               return ret;
+
 }
 EXPORT_SYMBOL(memmove);
index a4c768397baae6054f5938fc4170fb0876ccdb80..55543397a8a795f295ef6e3731e6b9373c953958 100644 (file)
@@ -26,4 +26,6 @@ obj-$(CONFIG_NUMA)            += numa.o numa_$(BITS).o
 obj-$(CONFIG_K8_NUMA)          += k8topology_64.o
 obj-$(CONFIG_ACPI_NUMA)                += srat_$(BITS).o
 
+obj-$(CONFIG_HAVE_MEMBLOCK)            += memblock.o
+
 obj-$(CONFIG_MEMTEST)          += memtest.o
index 4c4508e8a2043015c1cce3eb49a46c0c435e9297..79b0b372d2d033ca35a4bb83295a332c17bbb6c4 100644 (file)
@@ -229,7 +229,16 @@ void vmalloc_sync_all(void)
 
                spin_lock_irqsave(&pgd_lock, flags);
                list_for_each_entry(page, &pgd_list, lru) {
-                       if (!vmalloc_sync_one(page_address(page), address))
+                       spinlock_t *pgt_lock;
+                       pmd_t *ret;
+
+                       pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+
+                       spin_lock(pgt_lock);
+                       ret = vmalloc_sync_one(page_address(page), address);
+                       spin_unlock(pgt_lock);
+
+                       if (!ret)
                                break;
                }
                spin_unlock_irqrestore(&pgd_lock, flags);
@@ -251,6 +260,8 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
        if (!(address >= VMALLOC_START && address < VMALLOC_END))
                return -1;
 
+       WARN_ON_ONCE(in_nmi());
+
        /*
         * Synchronize this task's top level page-table
         * with the 'reference' page table.
@@ -326,29 +337,7 @@ out:
 
 void vmalloc_sync_all(void)
 {
-       unsigned long address;
-
-       for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
-            address += PGDIR_SIZE) {
-
-               const pgd_t *pgd_ref = pgd_offset_k(address);
-               unsigned long flags;
-               struct page *page;
-
-               if (pgd_none(*pgd_ref))
-                       continue;
-
-               spin_lock_irqsave(&pgd_lock, flags);
-               list_for_each_entry(page, &pgd_list, lru) {
-                       pgd_t *pgd;
-                       pgd = (pgd_t *)page_address(page) + pgd_index(address);
-                       if (pgd_none(*pgd))
-                               set_pgd(pgd, *pgd_ref);
-                       else
-                               BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
-               }
-               spin_unlock_irqrestore(&pgd_lock, flags);
-       }
+       sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
 }
 
 /*
@@ -369,6 +358,8 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
        if (!(address >= VMALLOC_START && address < VMALLOC_END))
                return -1;
 
+       WARN_ON_ONCE(in_nmi());
+
        /*
         * Copy kernel mappings over when needed. This can also
         * happen within a race in page table update. In the later
@@ -894,8 +885,14 @@ spurious_fault(unsigned long error_code, unsigned long address)
        if (pmd_large(*pmd))
                return spurious_fault_check(error_code, (pte_t *) pmd);
 
+       /*
+        * Note: don't use pte_present() here, since it returns true
+        * if the _PAGE_PROTNONE bit is set.  However, this aliases the
+        * _PAGE_GLOBAL bit, which for kernel pages give false positives
+        * when CONFIG_DEBUG_PAGEALLOC is used.
+        */
        pte = pte_offset_kernel(pmd, address);
-       if (!pte_present(*pte))
+       if (!(pte_flags(*pte) & _PAGE_PRESENT))
                return 0;
 
        ret = spurious_fault_check(error_code, pte);
index b278535b14aa00ce5b46de5e5bdd01cc75dc0c8a..c0e28a13de7df55c1ee1b173b61fd2d18c50e49c 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/initrd.h>
 #include <linux/ioport.h>
 #include <linux/swap.h>
+#include <linux/memblock.h>
 
 #include <asm/cacheflush.h>
 #include <asm/e820.h>
@@ -33,6 +34,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
                                          int use_gbpages)
 {
        unsigned long puds, pmds, ptes, tables, start;
+       phys_addr_t base;
 
        puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
        tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
@@ -75,12 +77,12 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
 #else
        start = 0x8000;
 #endif
-       e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
+       base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
                                        tables, PAGE_SIZE);
-       if (e820_table_start == -1UL)
+       if (base == MEMBLOCK_ERROR)
                panic("Cannot find space for the kernel page tables");
 
-       e820_table_start >>= PAGE_SHIFT;
+       e820_table_start = base >> PAGE_SHIFT;
        e820_table_end = e820_table_start;
        e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
 
@@ -299,7 +301,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
        __flush_tlb_all();
 
        if (!after_bootmem && e820_table_end > e820_table_start)
-               reserve_early(e820_table_start << PAGE_SHIFT,
+               memblock_x86_reserve_range(e820_table_start << PAGE_SHIFT,
                                 e820_table_end << PAGE_SHIFT, "PGTABLE");
 
        if (!after_bootmem)
index bca79091b9d6158bcab97bdba2d8b767babeea46..5d0a6711c2826fb543c999c8153a6a214e80033d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/proc_fs.h>
 #include <linux/memory_hotplug.h>
 #include <linux/initrd.h>
@@ -67,7 +68,7 @@ static __init void *alloc_low_page(void)
                panic("alloc_low_page: ran out of memory");
 
        adr = __va(pfn * PAGE_SIZE);
-       memset(adr, 0, PAGE_SIZE);
+       clear_page(adr);
        return adr;
 }
 
@@ -422,49 +423,28 @@ static void __init add_one_highpage_init(struct page *page)
        totalhigh_pages++;
 }
 
-struct add_highpages_data {
-       unsigned long start_pfn;
-       unsigned long end_pfn;
-};
-
-static int __init add_highpages_work_fn(unsigned long start_pfn,
-                                        unsigned long end_pfn, void *datax)
+void __init add_highpages_with_active_regions(int nid,
+                        unsigned long start_pfn, unsigned long end_pfn)
 {
-       int node_pfn;
-       struct page *page;
-       unsigned long final_start_pfn, final_end_pfn;
-       struct add_highpages_data *data;
+       struct range *range;
+       int nr_range;
+       int i;
 
-       data = (struct add_highpages_data *)datax;
+       nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn);
 
-       final_start_pfn = max(start_pfn, data->start_pfn);
-       final_end_pfn = min(end_pfn, data->end_pfn);
-       if (final_start_pfn >= final_end_pfn)
-               return 0;
+       for (i = 0; i < nr_range; i++) {
+               struct page *page;
+               int node_pfn;
 
-       for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
-            node_pfn++) {
-               if (!pfn_valid(node_pfn))
-                       continue;
-               page = pfn_to_page(node_pfn);
-               add_one_highpage_init(page);
+               for (node_pfn = range[i].start; node_pfn < range[i].end;
+                    node_pfn++) {
+                       if (!pfn_valid(node_pfn))
+                               continue;
+                       page = pfn_to_page(node_pfn);
+                       add_one_highpage_init(page);
+               }
        }
-
-       return 0;
-
 }
-
-void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
-                                             unsigned long end_pfn)
-{
-       struct add_highpages_data data;
-
-       data.start_pfn = start_pfn;
-       data.end_pfn = end_pfn;
-
-       work_with_active_regions(nid, add_highpages_work_fn, &data);
-}
-
 #else
 static inline void permanent_kmaps_init(pgd_t *pgd_base)
 {
@@ -558,7 +538,7 @@ char swsusp_pg_dir[PAGE_SIZE]
 
 static inline void save_pg_dir(void)
 {
-       memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
+       copy_page(swsusp_pg_dir, swapper_pg_dir);
 }
 #else /* !CONFIG_ACPI_SLEEP */
 static inline void save_pg_dir(void)
@@ -712,14 +692,14 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
        highstart_pfn = highend_pfn = max_pfn;
        if (max_pfn > max_low_pfn)
                highstart_pfn = max_low_pfn;
-       e820_register_active_regions(0, 0, highend_pfn);
+       memblock_x86_register_active_regions(0, 0, highend_pfn);
        sparse_memory_present_with_active_regions(0);
        printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
                pages_to_mb(highend_pfn - highstart_pfn));
        num_physpages = highend_pfn;
        high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
 #else
-       e820_register_active_regions(0, 0, max_low_pfn);
+       memblock_x86_register_active_regions(0, 0, max_low_pfn);
        sparse_memory_present_with_active_regions(0);
        num_physpages = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
@@ -750,68 +730,12 @@ static void __init zone_sizes_init(void)
        free_area_init_nodes(max_zone_pfns);
 }
 
-#ifndef CONFIG_NO_BOOTMEM
-static unsigned long __init setup_node_bootmem(int nodeid,
-                                unsigned long start_pfn,
-                                unsigned long end_pfn,
-                                unsigned long bootmap)
-{
-       unsigned long bootmap_size;
-
-       /* don't touch min_low_pfn */
-       bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
-                                        bootmap >> PAGE_SHIFT,
-                                        start_pfn, end_pfn);
-       printk(KERN_INFO "  node %d low ram: %08lx - %08lx\n",
-               nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
-       printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
-                nodeid, bootmap, bootmap + bootmap_size);
-       free_bootmem_with_active_regions(nodeid, end_pfn);
-
-       return bootmap + bootmap_size;
-}
-#endif
-
 void __init setup_bootmem_allocator(void)
 {
-#ifndef CONFIG_NO_BOOTMEM
-       int nodeid;
-       unsigned long bootmap_size, bootmap;
-       /*
-        * Initialize the boot-time allocator (with low memory only):
-        */
-       bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT;
-       bootmap = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
-                                PAGE_SIZE);
-       if (bootmap == -1L)
-               panic("Cannot find bootmem map of size %ld\n", bootmap_size);
-       reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
-#endif
-
        printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
                 max_pfn_mapped<<PAGE_SHIFT);
        printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
 
-#ifndef CONFIG_NO_BOOTMEM
-       for_each_online_node(nodeid) {
-                unsigned long start_pfn, end_pfn;
-
-#ifdef CONFIG_NEED_MULTIPLE_NODES
-               start_pfn = node_start_pfn[nodeid];
-               end_pfn = node_end_pfn[nodeid];
-               if (start_pfn > max_low_pfn)
-                       continue;
-               if (end_pfn > max_low_pfn)
-                       end_pfn = max_low_pfn;
-#else
-               start_pfn = 0;
-               end_pfn = max_low_pfn;
-#endif
-               bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
-                                                bootmap);
-       }
-#endif
-
        after_bootmem = 1;
 }
 
@@ -1070,8 +994,3 @@ void mark_rodata_ro(void)
 }
 #endif
 
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
-                                  int flags)
-{
-       return reserve_bootmem(phys, len, flags);
-}
index 9a6674689a20f8e491f0a0f845079de9febaac5f..84346200e783bee9a9caf37e1d9a46d7936d97ba 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/initrd.h>
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include <linux/pfn.h>
@@ -52,8 +53,6 @@
 #include <asm/init.h>
 #include <linux/bootmem.h>
 
-static unsigned long dma_reserve __initdata;
-
 static int __init parse_direct_gbpages_off(char *arg)
 {
        direct_gbpages = 0;
@@ -97,6 +96,43 @@ static int __init nonx32_setup(char *str)
 }
 __setup("noexec32=", nonx32_setup);
 
+/*
+ * When memory was added/removed make sure all the processes MM have
+ * suitable PGD entries in the local PGD level page.
+ */
+void sync_global_pgds(unsigned long start, unsigned long end)
+{
+       unsigned long address;
+
+       for (address = start; address <= end; address += PGDIR_SIZE) {
+               const pgd_t *pgd_ref = pgd_offset_k(address);
+               unsigned long flags;
+               struct page *page;
+
+               if (pgd_none(*pgd_ref))
+                       continue;
+
+               spin_lock_irqsave(&pgd_lock, flags);
+               list_for_each_entry(page, &pgd_list, lru) {
+                       pgd_t *pgd;
+                       spinlock_t *pgt_lock;
+
+                       pgd = (pgd_t *)page_address(page) + pgd_index(address);
+                       pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+                       spin_lock(pgt_lock);
+
+                       if (pgd_none(*pgd))
+                               set_pgd(pgd, *pgd_ref);
+                       else
+                               BUG_ON(pgd_page_vaddr(*pgd)
+                                      != pgd_page_vaddr(*pgd_ref));
+
+                       spin_unlock(pgt_lock);
+               }
+               spin_unlock_irqrestore(&pgd_lock, flags);
+       }
+}
+
 /*
  * NOTE: This function is marked __ref because it calls __init function
  * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
@@ -293,7 +329,7 @@ static __ref void *alloc_low_page(unsigned long *phys)
                panic("alloc_low_page: ran out of memory");
 
        adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
-       memset(adr, 0, PAGE_SIZE);
+       clear_page(adr);
        *phys  = pfn * PAGE_SIZE;
        return adr;
 }
@@ -534,11 +570,13 @@ kernel_physical_mapping_init(unsigned long start,
                             unsigned long end,
                             unsigned long page_size_mask)
 {
-
+       bool pgd_changed = false;
        unsigned long next, last_map_addr = end;
+       unsigned long addr;
 
        start = (unsigned long)__va(start);
        end = (unsigned long)__va(end);
+       addr = start;
 
        for (; start < end; start = next) {
                pgd_t *pgd = pgd_offset_k(start);
@@ -563,7 +601,12 @@ kernel_physical_mapping_init(unsigned long start,
                spin_lock(&init_mm.page_table_lock);
                pgd_populate(&init_mm, pgd, __va(pud_phys));
                spin_unlock(&init_mm.page_table_lock);
+               pgd_changed = true;
        }
+
+       if (pgd_changed)
+               sync_global_pgds(addr, end);
+
        __flush_tlb_all();
 
        return last_map_addr;
@@ -573,23 +616,7 @@ kernel_physical_mapping_init(unsigned long start,
 void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
                                int acpi, int k8)
 {
-#ifndef CONFIG_NO_BOOTMEM
-       unsigned long bootmap_size, bootmap;
-
-       bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-       bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
-                                PAGE_SIZE);
-       if (bootmap == -1L)
-               panic("Cannot find bootmem map of size %ld\n", bootmap_size);
-       reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
-       /* don't touch min_low_pfn */
-       bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
-                                        0, end_pfn);
-       e820_register_active_regions(0, start_pfn, end_pfn);
-       free_bootmem_with_active_regions(0, end_pfn);
-#else
-       e820_register_active_regions(0, start_pfn, end_pfn);
-#endif
+       memblock_x86_register_active_regions(0, start_pfn, end_pfn);
 }
 #endif
 
@@ -799,52 +826,6 @@ void mark_rodata_ro(void)
 
 #endif
 
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
-                                  int flags)
-{
-#ifdef CONFIG_NUMA
-       int nid, next_nid;
-       int ret;
-#endif
-       unsigned long pfn = phys >> PAGE_SHIFT;
-
-       if (pfn >= max_pfn) {
-               /*
-                * This can happen with kdump kernels when accessing
-                * firmware tables:
-                */
-               if (pfn < max_pfn_mapped)
-                       return -EFAULT;
-
-               printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n",
-                               phys, len);
-               return -EFAULT;
-       }
-
-       /* Should check here against the e820 map to avoid double free */
-#ifdef CONFIG_NUMA
-       nid = phys_to_nid(phys);
-       next_nid = phys_to_nid(phys + len - 1);
-       if (nid == next_nid)
-               ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags);
-       else
-               ret = reserve_bootmem(phys, len, flags);
-
-       if (ret != 0)
-               return ret;
-
-#else
-       reserve_bootmem(phys, len, flags);
-#endif
-
-       if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
-               dma_reserve += len / PAGE_SIZE;
-               set_dma_reserve(dma_reserve);
-       }
-
-       return 0;
-}
-
 int kern_addr_valid(unsigned long addr)
 {
        unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
@@ -1003,6 +984,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
                }
 
        }
+       sync_global_pgds((unsigned long)start_page, end);
        return 0;
 }
 
index 84e236ce76ba9a8afd624cfc4c506ebaa654b926..72fc70cf6184c756b1157f272b0d5e2b7bcc0609 100644 (file)
@@ -74,7 +74,7 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
 /*
  * Map 'pfn' using fixed map 'type' and protections 'prot'
  */
-void *
+void __iomem *
 iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
 {
        /*
@@ -86,12 +86,12 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
        if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
                prot = PAGE_KERNEL_UC_MINUS;
 
-       return kmap_atomic_prot_pfn(pfn, type, prot);
+       return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, type, prot);
 }
 EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
 
 void
-iounmap_atomic(void *kvaddr, enum km_type type)
+iounmap_atomic(void __iomem *kvaddr, enum km_type type)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
index 3ba6e0608c55c3b81300db30e465093f58367f0a..0369843511dc34292b6b0e944fc53bcab7396f8d 100644 (file)
@@ -362,6 +362,11 @@ static inline pte_t * __init early_ioremap_pte(unsigned long addr)
        return &bm_pte[pte_index(addr)];
 }
 
+bool __init is_early_ioremap_ptep(pte_t *ptep)
+{
+       return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)];
+}
+
 static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
 
 void __init early_ioremap_init(void)
index 970ed579d4e4e86c6265828335b35e35024cfc38..804a3b6c6e14f6aba0cc36616d85ab882a121685 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/nodemask.h>
+#include <linux/memblock.h>
+
 #include <asm/io.h>
 #include <linux/pci_ids.h>
 #include <linux/acpi.h>
@@ -22,7 +24,7 @@
 #include <asm/numa.h>
 #include <asm/mpspec.h>
 #include <asm/apic.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 static struct bootnode __initdata nodes[8];
 static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
@@ -54,8 +56,8 @@ static __init int find_northbridge(void)
 static __init void early_get_boot_cpu_id(void)
 {
        /*
-        * need to get boot_cpu_id so can use that to create apicid_to_node
-        * in k8_scan_nodes()
+        * need to get the APIC ID of the BSP so can use that to
+        * create apicid_to_node in k8_scan_nodes()
         */
 #ifdef CONFIG_X86_MPPARSE
        /*
@@ -212,7 +214,7 @@ int __init k8_scan_nodes(void)
        bits = boot_cpu_data.x86_coreid_bits;
        cores = (1<<bits);
        apicid_base = 0;
-       /* need to get boot_cpu_id early for system with apicid lifting */
+       /* get the APIC ID of the BSP early for systems with apicid lifting */
        early_get_boot_cpu_id();
        if (boot_cpu_physical_apicid > 0) {
                pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
@@ -222,7 +224,7 @@ int __init k8_scan_nodes(void)
        for_each_node_mask(i, node_possible_map) {
                int j;
 
-               e820_register_active_regions(i,
+               memblock_x86_register_active_regions(i,
                                nodes[i].start >> PAGE_SHIFT,
                                nodes[i].end >> PAGE_SHIFT);
                for (j = apicid_base; j < cores + apicid_base; j++)
index b3b531a4f8e587e3560b2087e9c483b2cb1b0f93..d87dd6d042d64309fedac698dd1a5b28a8448594 100644 (file)
@@ -631,6 +631,8 @@ bool kmemcheck_fault(struct pt_regs *regs, unsigned long address,
        if (!pte)
                return false;
 
+       WARN_ON_ONCE(in_nmi());
+
        if (error_code & 2)
                kmemcheck_access(regs, address, KMEMCHECK_WRITE);
        else
index 63c19e27aa6f115badc42f0df6a33ffb1610e6c0..324aa3f072379a46c1f21668680d3b83b9cf10cc 100644 (file)
@@ -9,7 +9,7 @@ static bool opcode_is_prefix(uint8_t b)
                b == 0xf0 || b == 0xf2 || b == 0xf3
                /* Group 2 */
                || b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26
-               || b == 0x64 || b == 0x65 || b == 0x2e || b == 0x3e
+               || b == 0x64 || b == 0x65
                /* Group 3 */
                || b == 0x66
                /* Group 4 */
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c
new file mode 100644 (file)
index 0000000..aa11693
--- /dev/null
@@ -0,0 +1,348 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/range.h>
+
+/* Check for already reserved areas */
+static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
+{
+       struct memblock_region *r;
+       u64 addr = *addrp, last;
+       u64 size = *sizep;
+       bool changed = false;
+
+again:
+       last = addr + size;
+       for_each_memblock(reserved, r) {
+               if (last > r->base && addr < r->base) {
+                       size = r->base - addr;
+                       changed = true;
+                       goto again;
+               }
+               if (last > (r->base + r->size) && addr < (r->base + r->size)) {
+                       addr = round_up(r->base + r->size, align);
+                       size = last - addr;
+                       changed = true;
+                       goto again;
+               }
+               if (last <= (r->base + r->size) && addr >= r->base) {
+                       *sizep = 0;
+                       return false;
+               }
+       }
+       if (changed) {
+               *addrp = addr;
+               *sizep = size;
+       }
+       return changed;
+}
+
+/*
+ * Find next free range after start, and size is returned in *sizep
+ */
+u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
+{
+       struct memblock_region *r;
+
+       for_each_memblock(memory, r) {
+               u64 ei_start = r->base;
+               u64 ei_last = ei_start + r->size;
+               u64 addr;
+
+               addr = round_up(ei_start, align);
+               if (addr < start)
+                       addr = round_up(start, align);
+               if (addr >= ei_last)
+                       continue;
+               *sizep = ei_last - addr;
+               while (check_with_memblock_reserved_size(&addr, sizep, align))
+                       ;
+
+               if (*sizep)
+                       return addr;
+       }
+
+       return MEMBLOCK_ERROR;
+}
+
+static __init struct range *find_range_array(int count)
+{
+       u64 end, size, mem;
+       struct range *range;
+
+       size = sizeof(struct range) * count;
+       end = memblock.current_limit;
+
+       mem = memblock_find_in_range(0, end, size, sizeof(struct range));
+       if (mem == MEMBLOCK_ERROR)
+               panic("can not find more space for range array");
+
+       /*
+        * This range is tempoaray, so don't reserve it, it will not be
+        * overlapped because We will not alloccate new buffer before
+        * We discard this one
+        */
+       range = __va(mem);
+       memset(range, 0, size);
+
+       return range;
+}
+
+static void __init memblock_x86_subtract_reserved(struct range *range, int az)
+{
+       u64 final_start, final_end;
+       struct memblock_region *r;
+
+       /* Take out region array itself at first*/
+       memblock_free_reserved_regions();
+
+       memblock_dbg("Subtract (%ld early reservations)\n", memblock.reserved.cnt);
+
+       for_each_memblock(reserved, r) {
+               memblock_dbg("  [%010llx-%010llx]\n", (u64)r->base, (u64)r->base + r->size - 1);
+               final_start = PFN_DOWN(r->base);
+               final_end = PFN_UP(r->base + r->size);
+               if (final_start >= final_end)
+                       continue;
+               subtract_range(range, az, final_start, final_end);
+       }
+
+       /* Put region array back ? */
+       memblock_reserve_reserved_regions();
+}
+
+struct count_data {
+       int nr;
+};
+
+static int __init count_work_fn(unsigned long start_pfn,
+                               unsigned long end_pfn, void *datax)
+{
+       struct count_data *data = datax;
+
+       data->nr++;
+
+       return 0;
+}
+
+static int __init count_early_node_map(int nodeid)
+{
+       struct count_data data;
+
+       data.nr = 0;
+       work_with_active_regions(nodeid, count_work_fn, &data);
+
+       return data.nr;
+}
+
+int __init __get_free_all_memory_range(struct range **rangep, int nodeid,
+                        unsigned long start_pfn, unsigned long end_pfn)
+{
+       int count;
+       struct range *range;
+       int nr_range;
+
+       count = (memblock.reserved.cnt + count_early_node_map(nodeid)) * 2;
+
+       range = find_range_array(count);
+       nr_range = 0;
+
+       /*
+        * Use early_node_map[] and memblock.reserved.region to get range array
+        * at first
+        */
+       nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
+       subtract_range(range, count, 0, start_pfn);
+       subtract_range(range, count, end_pfn, -1ULL);
+
+       memblock_x86_subtract_reserved(range, count);
+       nr_range = clean_sort_range(range, count);
+
+       *rangep = range;
+       return nr_range;
+}
+
+int __init get_free_all_memory_range(struct range **rangep, int nodeid)
+{
+       unsigned long end_pfn = -1UL;
+
+#ifdef CONFIG_X86_32
+       end_pfn = max_low_pfn;
+#endif
+       return __get_free_all_memory_range(rangep, nodeid, 0, end_pfn);
+}
+
+static u64 __init __memblock_x86_memory_in_range(u64 addr, u64 limit, bool get_free)
+{
+       int i, count;
+       struct range *range;
+       int nr_range;
+       u64 final_start, final_end;
+       u64 free_size;
+       struct memblock_region *r;
+
+       count = (memblock.reserved.cnt + memblock.memory.cnt) * 2;
+
+       range = find_range_array(count);
+       nr_range = 0;
+
+       addr = PFN_UP(addr);
+       limit = PFN_DOWN(limit);
+
+       for_each_memblock(memory, r) {
+               final_start = PFN_UP(r->base);
+               final_end = PFN_DOWN(r->base + r->size);
+               if (final_start >= final_end)
+                       continue;
+               if (final_start >= limit || final_end <= addr)
+                       continue;
+
+               nr_range = add_range(range, count, nr_range, final_start, final_end);
+       }
+       subtract_range(range, count, 0, addr);
+       subtract_range(range, count, limit, -1ULL);
+
+       /* Subtract memblock.reserved.region in range ? */
+       if (!get_free)
+               goto sort_and_count_them;
+       for_each_memblock(reserved, r) {
+               final_start = PFN_DOWN(r->base);
+               final_end = PFN_UP(r->base + r->size);
+               if (final_start >= final_end)
+                       continue;
+               if (final_start >= limit || final_end <= addr)
+                       continue;
+
+               subtract_range(range, count, final_start, final_end);
+       }
+
+sort_and_count_them:
+       nr_range = clean_sort_range(range, count);
+
+       free_size = 0;
+       for (i = 0; i < nr_range; i++)
+               free_size += range[i].end - range[i].start;
+
+       return free_size << PAGE_SHIFT;
+}
+
+u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit)
+{
+       return __memblock_x86_memory_in_range(addr, limit, true);
+}
+
+u64 __init memblock_x86_memory_in_range(u64 addr, u64 limit)
+{
+       return __memblock_x86_memory_in_range(addr, limit, false);
+}
+
+void __init memblock_x86_reserve_range(u64 start, u64 end, char *name)
+{
+       if (start == end)
+               return;
+
+       if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end))
+               return;
+
+       memblock_dbg("    memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name);
+
+       memblock_reserve(start, end - start);
+}
+
+void __init memblock_x86_free_range(u64 start, u64 end)
+{
+       if (start == end)
+               return;
+
+       if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end))
+               return;
+
+       memblock_dbg("       memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1);
+
+       memblock_free(start, end - start);
+}
+
+/*
+ * Need to call this function after memblock_x86_register_active_regions,
+ * so early_node_map[] is filled already.
+ */
+u64 __init memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align)
+{
+       u64 addr;
+       addr = find_memory_core_early(nid, size, align, start, end);
+       if (addr != MEMBLOCK_ERROR)
+               return addr;
+
+       /* Fallback, should already have start end within node range */
+       return memblock_find_in_range(start, end, size, align);
+}
+
+/*
+ * Finds an active region in the address range from start_pfn to last_pfn and
+ * returns its range in ei_startpfn and ei_endpfn for the memblock entry.
+ */
+static int __init memblock_x86_find_active_region(const struct memblock_region *ei,
+                                 unsigned long start_pfn,
+                                 unsigned long last_pfn,
+                                 unsigned long *ei_startpfn,
+                                 unsigned long *ei_endpfn)
+{
+       u64 align = PAGE_SIZE;
+
+       *ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT;
+       *ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT;
+
+       /* Skip map entries smaller than a page */
+       if (*ei_startpfn >= *ei_endpfn)
+               return 0;
+
+       /* Skip if map is outside the node */
+       if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn)
+               return 0;
+
+       /* Check for overlaps */
+       if (*ei_startpfn < start_pfn)
+               *ei_startpfn = start_pfn;
+       if (*ei_endpfn > last_pfn)
+               *ei_endpfn = last_pfn;
+
+       return 1;
+}
+
+/* Walk the memblock.memory map and register active regions within a node */
+void __init memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+                                        unsigned long last_pfn)
+{
+       unsigned long ei_startpfn;
+       unsigned long ei_endpfn;
+       struct memblock_region *r;
+
+       for_each_memblock(memory, r)
+               if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+                                          &ei_startpfn, &ei_endpfn))
+                       add_active_range(nid, ei_startpfn, ei_endpfn);
+}
+
+/*
+ * Find the hole size (in bytes) in the memory range.
+ * @start: starting address of the memory range to scan
+ * @end: ending address of the memory range to scan
+ */
+u64 __init memblock_x86_hole_size(u64 start, u64 end)
+{
+       unsigned long start_pfn = start >> PAGE_SHIFT;
+       unsigned long last_pfn = end >> PAGE_SHIFT;
+       unsigned long ei_startpfn, ei_endpfn, ram = 0;
+       struct memblock_region *r;
+
+       for_each_memblock(memory, r)
+               if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+                                          &ei_startpfn, &ei_endpfn))
+                       ram += ei_endpfn - ei_startpfn;
+
+       return end - start - ((u64)ram << PAGE_SHIFT);
+}
index 18d244f702059b59f88b94f8da6a7312f43d58cc..92faf3a1c53e29fbf82767356fdca0508f9b693c 100644 (file)
@@ -6,8 +6,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/pfn.h>
-
-#include <asm/e820.h>
+#include <linux/memblock.h>
 
 static u64 patterns[] __initdata = {
        0,
@@ -35,7 +34,7 @@ static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
               (unsigned long long) pattern,
               (unsigned long long) start_bad,
               (unsigned long long) end_bad);
-       reserve_early(start_bad, end_bad, "BAD RAM");
+       memblock_x86_reserve_range(start_bad, end_bad, "BAD RAM");
 }
 
 static void __init memtest(u64 pattern, u64 start_phys, u64 size)
@@ -74,7 +73,7 @@ static void __init do_one_pass(u64 pattern, u64 start, u64 end)
        u64 size = 0;
 
        while (start < end) {
-               start = find_e820_area_size(start, &size, 1);
+               start = memblock_x86_find_in_range_size(start, &size, 1);
 
                /* done ? */
                if (start >= end)
index 809baaaf48b18d9f24f953b602001a562f2769c7..84a3e4c9f277d82175b1603dae6b0c9c40dc0aef 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/highmem.h>
 #include <linux/initrd.h>
@@ -120,7 +121,7 @@ int __init get_memcfg_numa_flat(void)
 
        node_start_pfn[0] = 0;
        node_end_pfn[0] = max_pfn;
-       e820_register_active_regions(0, 0, max_pfn);
+       memblock_x86_register_active_regions(0, 0, max_pfn);
        memory_present(0, 0, max_pfn);
        node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
 
@@ -161,14 +162,14 @@ static void __init allocate_pgdat(int nid)
                NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
        else {
                unsigned long pgdat_phys;
-               pgdat_phys = find_e820_area(min_low_pfn<<PAGE_SHIFT,
+               pgdat_phys = memblock_find_in_range(min_low_pfn<<PAGE_SHIFT,
                                 max_pfn_mapped<<PAGE_SHIFT,
                                 sizeof(pg_data_t),
                                 PAGE_SIZE);
                NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
                memset(buf, 0, sizeof(buf));
                sprintf(buf, "NODE_DATA %d",  nid);
-               reserve_early(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
+               memblock_x86_reserve_range(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
        }
        printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
                nid, (unsigned long)NODE_DATA(nid));
@@ -291,15 +292,15 @@ static __init unsigned long calculate_numa_remap_pages(void)
                                                 PTRS_PER_PTE);
                node_kva_target <<= PAGE_SHIFT;
                do {
-                       node_kva_final = find_e820_area(node_kva_target,
+                       node_kva_final = memblock_find_in_range(node_kva_target,
                                        ((u64)node_end_pfn[nid])<<PAGE_SHIFT,
                                                ((u64)size)<<PAGE_SHIFT,
                                                LARGE_PAGE_BYTES);
                        node_kva_target -= LARGE_PAGE_BYTES;
-               } while (node_kva_final == -1ULL &&
+               } while (node_kva_final == MEMBLOCK_ERROR &&
                         (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
 
-               if (node_kva_final == -1ULL)
+               if (node_kva_final == MEMBLOCK_ERROR)
                        panic("Can not get kva ram\n");
 
                node_remap_size[nid] = size;
@@ -318,15 +319,13 @@ static __init unsigned long calculate_numa_remap_pages(void)
                 *  but we could have some hole in high memory, and it will only
                 *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
                 *  to use it as free.
-                *  So reserve_early here, hope we don't run out of that array
+                *  So memblock_x86_reserve_range here, hope we don't run out of that array
                 */
-               reserve_early(node_kva_final,
+               memblock_x86_reserve_range(node_kva_final,
                              node_kva_final+(((u64)size)<<PAGE_SHIFT),
                              "KVA RAM");
 
                node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
-               remove_active_range(nid, node_remap_start_pfn[nid],
-                                        node_remap_start_pfn[nid] + size);
        }
        printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
                        reserve_pages);
@@ -367,14 +366,14 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
 
        kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
        do {
-               kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
+               kva_start_pfn = memblock_find_in_range(kva_target_pfn<<PAGE_SHIFT,
                                        max_low_pfn<<PAGE_SHIFT,
                                        kva_pages<<PAGE_SHIFT,
                                        PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
                kva_target_pfn -= PTRS_PER_PTE;
-       } while (kva_start_pfn == -1UL && kva_target_pfn > min_low_pfn);
+       } while (kva_start_pfn == MEMBLOCK_ERROR && kva_target_pfn > min_low_pfn);
 
-       if (kva_start_pfn == -1UL)
+       if (kva_start_pfn == MEMBLOCK_ERROR)
                panic("Can not get kva space\n");
 
        printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
@@ -382,7 +381,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
        printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
 
        /* avoid clash with initrd */
-       reserve_early(kva_start_pfn<<PAGE_SHIFT,
+       memblock_x86_reserve_range(kva_start_pfn<<PAGE_SHIFT,
                      (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
                     "KVA PG");
 #ifdef CONFIG_HIGHMEM
@@ -419,9 +418,6 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
        for_each_online_node(nid) {
                memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
                NODE_DATA(nid)->node_id = nid;
-#ifndef CONFIG_NO_BOOTMEM
-               NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
-#endif
        }
 
        setup_bootmem_allocator();
index a7bcc23ef96c989f5fef986cbd7816dfd551d20e..60f498511dd60b01a9eee62fdc0a69ba80d3082c 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -18,7 +19,7 @@
 #include <asm/dma.h>
 #include <asm/numa.h>
 #include <asm/acpi.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
@@ -86,16 +87,16 @@ static int __init allocate_cachealigned_memnodemap(void)
 
        addr = 0x8000;
        nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
-       nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT,
+       nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT,
                                      nodemap_size, L1_CACHE_BYTES);
-       if (nodemap_addr == -1UL) {
+       if (nodemap_addr == MEMBLOCK_ERROR) {
                printk(KERN_ERR
                       "NUMA: Unable to allocate Memory to Node hash map\n");
                nodemap_addr = nodemap_size = 0;
                return -1;
        }
        memnodemap = phys_to_virt(nodemap_addr);
-       reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
+       memblock_x86_reserve_range(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
 
        printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
               nodemap_addr, nodemap_addr + nodemap_size);
@@ -171,8 +172,8 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
        if (start < (MAX_DMA32_PFN<<PAGE_SHIFT) &&
            end > (MAX_DMA32_PFN<<PAGE_SHIFT))
                start = MAX_DMA32_PFN<<PAGE_SHIFT;
-       mem = find_e820_area(start, end, size, align);
-       if (mem != -1L)
+       mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+       if (mem != MEMBLOCK_ERROR)
                return __va(mem);
 
        /* extend the search scope */
@@ -181,8 +182,8 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
                start = MAX_DMA32_PFN<<PAGE_SHIFT;
        else
                start = MAX_DMA_PFN<<PAGE_SHIFT;
-       mem = find_e820_area(start, end, size, align);
-       if (mem != -1L)
+       mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+       if (mem != MEMBLOCK_ERROR)
                return __va(mem);
 
        printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
@@ -198,10 +199,6 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
        unsigned long start_pfn, last_pfn, nodedata_phys;
        const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
        int nid;
-#ifndef CONFIG_NO_BOOTMEM
-       unsigned long bootmap_start, bootmap_pages, bootmap_size;
-       void *bootmap;
-#endif
 
        if (!end)
                return;
@@ -226,7 +223,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
        if (node_data[nodeid] == NULL)
                return;
        nodedata_phys = __pa(node_data[nodeid]);
-       reserve_early(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
+       memblock_x86_reserve_range(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
        printk(KERN_INFO "  NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
                nodedata_phys + pgdat_size - 1);
        nid = phys_to_nid(nodedata_phys);
@@ -238,47 +235,6 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
        NODE_DATA(nodeid)->node_start_pfn = start_pfn;
        NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
 
-#ifndef CONFIG_NO_BOOTMEM
-       NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
-
-       /*
-        * Find a place for the bootmem map
-        * nodedata_phys could be on other nodes by alloc_bootmem,
-        * so need to sure bootmap_start not to be small, otherwise
-        * early_node_mem will get that with find_e820_area instead
-        * of alloc_bootmem, that could clash with reserved range
-        */
-       bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn);
-       bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
-       /*
-        * SMP_CACHE_BYTES could be enough, but init_bootmem_node like
-        * to use that to align to PAGE_SIZE
-        */
-       bootmap = early_node_mem(nodeid, bootmap_start, end,
-                                bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
-       if (bootmap == NULL)  {
-               free_early(nodedata_phys, nodedata_phys + pgdat_size);
-               node_data[nodeid] = NULL;
-               return;
-       }
-       bootmap_start = __pa(bootmap);
-       reserve_early(bootmap_start, bootmap_start+(bootmap_pages<<PAGE_SHIFT),
-                       "BOOTMAP");
-
-       bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
-                                        bootmap_start >> PAGE_SHIFT,
-                                        start_pfn, last_pfn);
-
-       printk(KERN_INFO "  bootmap [%016lx -  %016lx] pages %lx\n",
-                bootmap_start, bootmap_start + bootmap_size - 1,
-                bootmap_pages);
-       nid = phys_to_nid(bootmap_start);
-       if (nid != nodeid)
-               printk(KERN_INFO "    bootmap(%d) on node %d\n", nodeid, nid);
-
-       free_bootmem_with_active_regions(nodeid, end);
-#endif
-
        node_set_online(nodeid);
 }
 
@@ -416,7 +372,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
                nr_nodes = MAX_NUMNODES;
        }
 
-       size = (max_addr - addr - e820_hole_size(addr, max_addr)) / nr_nodes;
+       size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
        /*
         * Calculate the number of big nodes that can be allocated as a result
         * of consolidating the remainder.
@@ -452,7 +408,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
                         * non-reserved memory is less than the per-node size.
                         */
                        while (end - physnodes[i].start -
-                               e820_hole_size(physnodes[i].start, end) < size) {
+                               memblock_x86_hole_size(physnodes[i].start, end) < size) {
                                end += FAKE_NODE_MIN_SIZE;
                                if (end > physnodes[i].end) {
                                        end = physnodes[i].end;
@@ -466,7 +422,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
                         * this one must extend to the boundary.
                         */
                        if (end < dma32_end && dma32_end - end -
-                           e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+                           memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
                                end = dma32_end;
 
                        /*
@@ -475,7 +431,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
                         * physical node.
                         */
                        if (physnodes[i].end - end -
-                           e820_hole_size(end, physnodes[i].end) < size)
+                           memblock_x86_hole_size(end, physnodes[i].end) < size)
                                end = physnodes[i].end;
 
                        /*
@@ -503,7 +459,7 @@ static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
 {
        u64 end = start + size;
 
-       while (end - start - e820_hole_size(start, end) < size) {
+       while (end - start - memblock_x86_hole_size(start, end) < size) {
                end += FAKE_NODE_MIN_SIZE;
                if (end > max_addr) {
                        end = max_addr;
@@ -532,7 +488,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
         * creates a uniform distribution of node sizes across the entire
         * machine (but not necessarily over physical nodes).
         */
-       min_size = (max_addr - addr - e820_hole_size(addr, max_addr)) /
+       min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
                                                MAX_NUMNODES;
        min_size = max(min_size, FAKE_NODE_MIN_SIZE);
        if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
@@ -565,7 +521,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
                         * this one must extend to the boundary.
                         */
                        if (end < dma32_end && dma32_end - end -
-                           e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+                           memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
                                end = dma32_end;
 
                        /*
@@ -574,7 +530,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
                         * physical node.
                         */
                        if (physnodes[i].end - end -
-                           e820_hole_size(end, physnodes[i].end) < size)
+                           memblock_x86_hole_size(end, physnodes[i].end) < size)
                                end = physnodes[i].end;
 
                        /*
@@ -638,7 +594,7 @@ static int __init numa_emulation(unsigned long start_pfn,
         */
        remove_all_active_ranges();
        for_each_node_mask(i, node_possible_map) {
-               e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+               memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
                                                nodes[i].end >> PAGE_SHIFT);
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
        }
@@ -691,7 +647,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
        node_set(0, node_possible_map);
        for (i = 0; i < nr_cpu_ids; i++)
                numa_set_node(i, 0);
-       e820_register_active_regions(0, start_pfn, last_pfn);
+       memblock_x86_register_active_regions(0, start_pfn, last_pfn);
        setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
 }
 
@@ -703,9 +659,7 @@ unsigned long __init numa_free_all_bootmem(void)
        for_each_online_node(i)
                pages += free_all_bootmem_node(NODE_DATA(i));
 
-#ifdef CONFIG_NO_BOOTMEM
        pages += free_all_memory_core_early(MAX_NUMNODES);
-#endif
 
        return pages;
 }
index 5c4ee422590e5dc23aec0071e642bf246b627565..8be8c7d7bc89759a55059ea440af5b26e3d9e0c9 100644 (file)
@@ -87,7 +87,19 @@ static inline void pgd_list_del(pgd_t *pgd)
 #define UNSHARED_PTRS_PER_PGD                          \
        (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
 
-static void pgd_ctor(pgd_t *pgd)
+
+static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
+{
+       BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm));
+       virt_to_page(pgd)->index = (pgoff_t)mm;
+}
+
+struct mm_struct *pgd_page_get_mm(struct page *page)
+{
+       return (struct mm_struct *)page->index;
+}
+
+static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
 {
        /* If the pgd points to a shared pagetable level (either the
           ptes in non-PAE, or shared PMD in PAE), then just copy the
@@ -98,15 +110,13 @@ static void pgd_ctor(pgd_t *pgd)
                clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
                                swapper_pg_dir + KERNEL_PGD_BOUNDARY,
                                KERNEL_PGD_PTRS);
-               paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
-                                        __pa(swapper_pg_dir) >> PAGE_SHIFT,
-                                        KERNEL_PGD_BOUNDARY,
-                                        KERNEL_PGD_PTRS);
        }
 
        /* list required to sync kernel mapping updates */
-       if (!SHARED_KERNEL_PMD)
+       if (!SHARED_KERNEL_PMD) {
+               pgd_set_mm(pgd, mm);
                pgd_list_add(pgd);
+       }
 }
 
 static void pgd_dtor(pgd_t *pgd)
@@ -272,7 +282,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
         */
        spin_lock_irqsave(&pgd_lock, flags);
 
-       pgd_ctor(pgd);
+       pgd_ctor(mm, pgd);
        pgd_prepopulate_pmd(mm, pgd, pmds);
 
        spin_unlock_irqrestore(&pgd_lock, flags);
index 9324f13492d51bf005921e23bdef80bd67f2d2f1..a17dffd136c143898e91187cbd39d005b05779b6 100644 (file)
@@ -25,6 +25,7 @@
  */
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/acpi.h>
 #include <linux/nodemask.h>
@@ -264,7 +265,7 @@ int __init get_memcfg_from_srat(void)
                if (node_read_chunk(chunk->nid, chunk))
                        continue;
 
-               e820_register_active_regions(chunk->nid, chunk->start_pfn,
+               memblock_x86_register_active_regions(chunk->nid, chunk->start_pfn,
                                             min(chunk->end_pfn, max_pfn));
        }
        /* for out of order entries in SRAT */
index f9897f7a9ef1e25cfa81e9190a3449bec9e35f70..a35cb9d8b0606bc8f7123cd15f0017972a5e8dda 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/topology.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mm.h>
 #include <asm/proto.h>
 #include <asm/numa.h>
@@ -98,15 +99,15 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
        unsigned long phys;
 
        length = slit->header.length;
-       phys = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, length,
+       phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
                 PAGE_SIZE);
 
-       if (phys == -1L)
+       if (phys == MEMBLOCK_ERROR)
                panic(" Can not save slit!\n");
 
        acpi_slit = __va(phys);
        memcpy(acpi_slit, slit, length);
-       reserve_early(phys, phys + length, "ACPI SLIT");
+       memblock_x86_reserve_range(phys, phys + length, "ACPI SLIT");
 }
 
 /* Callback for Proximity Domain -> x2APIC mapping */
@@ -324,7 +325,7 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
                        pxmram = 0;
        }
 
-       e820ram = max_pfn - (e820_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
+       e820ram = max_pfn - (memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
        /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
        if ((long)(e820ram - pxmram) >= (1<<(20 - PAGE_SHIFT))) {
                printk(KERN_ERR
@@ -420,9 +421,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
                return -1;
        }
 
-       for_each_node_mask(i, nodes_parsed)
-               e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
-                                               nodes[i].end >> PAGE_SHIFT);
+       for (i = 0; i < num_node_memblks; i++)
+               memblock_x86_register_active_regions(memblk_nodeid[i],
+                               node_memblk_range[i].start >> PAGE_SHIFT,
+                               node_memblk_range[i].end >> PAGE_SHIFT);
+
        /* for out of order entries in SRAT */
        sort_node_map();
        if (!nodes_cover_memory(nodes)) {
index c03f14ab666742d6960ff3339ebcfe28a003308b..49358481c733235918cde7c576a3332fba50c364 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
@@ -52,6 +53,8 @@ union smp_flush_state {
    want false sharing in the per cpu data segment. */
 static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS];
 
+static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
+
 /*
  * We cannot call mmdrop() because we are in interrupt context,
  * instead update mm->cpu_vm_mask.
@@ -173,7 +176,7 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
        union smp_flush_state *f;
 
        /* Caller has disabled preemption */
-       sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+       sender = this_cpu_read(tlb_vector_offset);
        f = &flush_state[sender];
 
        /*
@@ -218,6 +221,47 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
        flush_tlb_others_ipi(cpumask, mm, va);
 }
 
+static void __cpuinit calculate_tlb_offset(void)
+{
+       int cpu, node, nr_node_vecs;
+       /*
+        * we are changing tlb_vector_offset for each CPU in runtime, but this
+        * will not cause inconsistency, as the write is atomic under X86. we
+        * might see more lock contentions in a short time, but after all CPU's
+        * tlb_vector_offset are changed, everything should go normal
+        *
+        * Note: if NUM_INVALIDATE_TLB_VECTORS % nr_online_nodes !=0, we might
+        * waste some vectors.
+        **/
+       if (nr_online_nodes > NUM_INVALIDATE_TLB_VECTORS)
+               nr_node_vecs = 1;
+       else
+               nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes;
+
+       for_each_online_node(node) {
+               int node_offset = (node % NUM_INVALIDATE_TLB_VECTORS) *
+                       nr_node_vecs;
+               int cpu_offset = 0;
+               for_each_cpu(cpu, cpumask_of_node(node)) {
+                       per_cpu(tlb_vector_offset, cpu) = node_offset +
+                               cpu_offset;
+                       cpu_offset++;
+                       cpu_offset = cpu_offset % nr_node_vecs;
+               }
+       }
+}
+
+static int tlb_cpuhp_notify(struct notifier_block *n,
+               unsigned long action, void *hcpu)
+{
+       switch (action & 0xf) {
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               calculate_tlb_offset();
+       }
+       return NOTIFY_OK;
+}
+
 static int __cpuinit init_smp_flush(void)
 {
        int i;
@@ -225,6 +269,8 @@ static int __cpuinit init_smp_flush(void)
        for (i = 0; i < ARRAY_SIZE(flush_state); i++)
                raw_spin_lock_init(&flush_state[i].tlbstate_lock);
 
+       calculate_tlb_offset();
+       hotcpu_notifier(tlb_cpuhp_notify, 0);
        return 0;
 }
 core_initcall(init_smp_flush);
index 3855096c59b81910fe827c76151e84bbac836770..2d49d4e19a3619c0be2c7d17a892b8aea582048f 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 #include <asm/stacktrace.h>
+#include <linux/compat.h>
 
 static void backtrace_warning_symbol(void *data, char *msg,
                                     unsigned long symbol)
@@ -48,14 +49,12 @@ static struct stacktrace_ops backtrace_ops = {
        .walk_stack     = print_context_stack,
 };
 
-struct frame_head {
-       struct frame_head *bp;
-       unsigned long ret;
-} __attribute__((packed));
-
-static struct frame_head *dump_user_backtrace(struct frame_head *head)
+#ifdef CONFIG_COMPAT
+static struct stack_frame_ia32 *
+dump_user_backtrace_32(struct stack_frame_ia32 *head)
 {
-       struct frame_head bufhead[2];
+       struct stack_frame_ia32 bufhead[2];
+       struct stack_frame_ia32 *fp;
 
        /* Also check accessibility of one struct frame_head beyond */
        if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
@@ -63,20 +62,66 @@ static struct frame_head *dump_user_backtrace(struct frame_head *head)
        if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
                return NULL;
 
-       oprofile_add_trace(bufhead[0].ret);
+       fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
+
+       oprofile_add_trace(bufhead[0].return_address);
+
+       /* frame pointers should strictly progress back up the stack
+       * (towards higher addresses) */
+       if (head >= fp)
+               return NULL;
+
+       return fp;
+}
+
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+       struct stack_frame_ia32 *head;
+
+       /* User process is 32-bit */
+       if (!current || !test_thread_flag(TIF_IA32))
+               return 0;
+
+       head = (struct stack_frame_ia32 *) regs->bp;
+       while (depth-- && head)
+               head = dump_user_backtrace_32(head);
+
+       return 1;
+}
+
+#else
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+       return 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
+{
+       struct stack_frame bufhead[2];
+
+       /* Also check accessibility of one struct stack_frame beyond */
+       if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
+               return NULL;
+       if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+               return NULL;
+
+       oprofile_add_trace(bufhead[0].return_address);
 
        /* frame pointers should strictly progress back up the stack
         * (towards higher addresses) */
-       if (head >= bufhead[0].bp)
+       if (head >= bufhead[0].next_frame)
                return NULL;
 
-       return bufhead[0].bp;
+       return bufhead[0].next_frame;
 }
 
 void
 x86_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
-       struct frame_head *head = (struct frame_head *)frame_pointer(regs);
+       struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);
 
        if (!user_mode_vm(regs)) {
                unsigned long stack = kernel_stack_pointer(regs);
@@ -86,6 +131,9 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
                return;
        }
 
+       if (x86_backtrace_32(regs, depth))
+               return;
+
        while (depth-- && head)
                head = dump_user_backtrace(head);
 }
index f6b48f6c595176a59c8e2fe5fa145bc11acca118..bd1489c3ce09b7416c400701f7fb407eae673615 100644 (file)
@@ -568,8 +568,13 @@ static int __init init_sysfs(void)
        int error;
 
        error = sysdev_class_register(&oprofile_sysclass);
-       if (!error)
-               error = sysdev_register(&device_oprofile);
+       if (error)
+               return error;
+
+       error = sysdev_register(&device_oprofile);
+       if (error)
+               sysdev_class_unregister(&oprofile_sysclass);
+
        return error;
 }
 
@@ -580,8 +585,10 @@ static void exit_sysfs(void)
 }
 
 #else
-#define init_sysfs() do { } while (0)
-#define exit_sysfs() do { } while (0)
+
+static inline int  init_sysfs(void) { return 0; }
+static inline void exit_sysfs(void) { }
+
 #endif /* CONFIG_PM */
 
 static int __init p4_init(char **cpu_type)
@@ -664,7 +671,10 @@ static int __init ppro_init(char **cpu_type)
        case 14:
                *cpu_type = "i386/core";
                break;
-       case 15: case 23:
+       case 0x0f:
+       case 0x16:
+       case 0x17:
+       case 0x1d:
                *cpu_type = "i386/core_2";
                break;
        case 0x1a:
@@ -685,9 +695,6 @@ static int __init ppro_init(char **cpu_type)
        return 1;
 }
 
-/* in order to get sysfs right */
-static int using_nmi;
-
 int __init op_nmi_init(struct oprofile_operations *ops)
 {
        __u8 vendor = boot_cpu_data.x86_vendor;
@@ -774,14 +781,15 @@ int __init op_nmi_init(struct oprofile_operations *ops)
 
        mux_init(ops);
 
-       init_sysfs();
-       using_nmi = 1;
+       ret = init_sysfs();
+       if (ret)
+               return ret;
+
        printk(KERN_INFO "oprofile: using NMI interrupt.\n");
        return 0;
 }
 
 void op_nmi_exit(void)
 {
-       if (using_nmi)
-               exit_sysfs();
+       exit_sysfs();
 }
index b67a6b5aa8d449ee06e0c22b586b6c51af4d2170..42fb46f8388304d5ab7a16281f58a530f3b7211c 100644 (file)
@@ -64,15 +64,22 @@ static u64 ibs_op_ctl;
  * IBS cpuid feature detection
  */
 
-#define IBS_CPUID_FEATURES      0x8000001b
+#define IBS_CPUID_FEATURES             0x8000001b
 
 /*
  * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
  * bit 0 is used to indicate the existence of IBS.
  */
-#define IBS_CAPS_AVAIL                 (1LL<<0)
-#define IBS_CAPS_RDWROPCNT             (1LL<<3)
-#define IBS_CAPS_OPCNT                 (1LL<<4)
+#define IBS_CAPS_AVAIL                 (1U<<0)
+#define IBS_CAPS_RDWROPCNT             (1U<<3)
+#define IBS_CAPS_OPCNT                 (1U<<4)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL                         0x1cc
+#define IBSCTL_LVT_OFFSET_VALID                (1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK         0x0F
 
 /*
  * IBS randomization macros
@@ -266,6 +273,74 @@ static void op_amd_stop_ibs(void)
                wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
+static inline int eilvt_is_available(int offset)
+{
+       /* check if we may assign a vector */
+       return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int ibs_eilvt_valid(void)
+{
+       u64 val;
+       int offset;
+
+       rdmsrl(MSR_AMD64_IBSCTL, val);
+       if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+               pr_err(FW_BUG "cpu %d, invalid IBS "
+                      "interrupt offset %d (MSR%08X=0x%016llx)",
+                      smp_processor_id(), offset,
+                      MSR_AMD64_IBSCTL, val);
+               return 0;
+       }
+
+       offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+       if (eilvt_is_available(offset))
+               return !0;
+
+       pr_err(FW_BUG "cpu %d, IBS interrupt offset %d "
+              "not available (MSR%08X=0x%016llx)",
+              smp_processor_id(), offset,
+              MSR_AMD64_IBSCTL, val);
+
+       return 0;
+}
+
+static inline int get_ibs_offset(void)
+{
+       u64 val;
+
+       rdmsrl(MSR_AMD64_IBSCTL, val);
+       if (!(val & IBSCTL_LVT_OFFSET_VALID))
+               return -EINVAL;
+
+       return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void)
+{
+       int offset;
+
+       offset = get_ibs_offset();
+       if (offset < 0)
+               goto failed;
+
+       if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+               return;
+failed:
+       pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
+               smp_processor_id());
+}
+
+static void clear_APIC_ibs(void)
+{
+       int offset;
+
+       offset = get_ibs_offset();
+       if (offset >= 0)
+               setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -376,13 +451,13 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
        }
 
        if (ibs_caps)
-               setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+               setup_APIC_ibs();
 }
 
 static void op_amd_cpu_shutdown(void)
 {
        if (ibs_caps)
-               setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+               clear_APIC_ibs();
 }
 
 static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -445,16 +520,11 @@ static void op_amd_stop(struct op_msrs const * const msrs)
        op_amd_stop_ibs();
 }
 
-static int __init_ibs_nmi(void)
+static int setup_ibs_ctl(int ibs_eilvt_off)
 {
-#define IBSCTL_LVTOFFSETVAL            (1 << 8)
-#define IBSCTL                         0x1cc
        struct pci_dev *cpu_cfg;
        int nodes;
        u32 value = 0;
-       u8 ibs_eilvt_off;
-
-       ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
 
        nodes = 0;
        cpu_cfg = NULL;
@@ -466,21 +536,60 @@ static int __init_ibs_nmi(void)
                        break;
                ++nodes;
                pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-                                      | IBSCTL_LVTOFFSETVAL);
+                                      | IBSCTL_LVT_OFFSET_VALID);
                pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-               if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+               if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
                        pci_dev_put(cpu_cfg);
                        printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-                               "IBSCTL = 0x%08x", value);
-                       return 1;
+                              "IBSCTL = 0x%08x\n", value);
+                       return -EINVAL;
                }
        } while (1);
 
        if (!nodes) {
-               printk(KERN_DEBUG "No CPU node configured for IBS");
-               return 1;
+               printk(KERN_DEBUG "No CPU node configured for IBS\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int force_ibs_eilvt_setup(void)
+{
+       int i;
+       int ret;
+
+       /* find the next free available EILVT entry */
+       for (i = 1; i < 4; i++) {
+               if (!eilvt_is_available(i))
+                       continue;
+               ret = setup_ibs_ctl(i);
+               if (ret)
+                       return ret;
+               return 0;
        }
 
+       printk(KERN_DEBUG "No EILVT entry available\n");
+
+       return -EBUSY;
+}
+
+static int __init_ibs_nmi(void)
+{
+       int ret;
+
+       if (ibs_eilvt_valid())
+               return 0;
+
+       ret = force_ibs_eilvt_setup();
+       if (ret)
+               return ret;
+
+       if (!ibs_eilvt_valid())
+               return -EFAULT;
+
+       pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
        return 0;
 }
 
index b34815408f582bd002854d83c8e5736b6de37b24..13700ec8e2e43587010594fe4e361ac88d29cb85 100644 (file)
@@ -304,7 +304,7 @@ static struct pci_raw_ops pci_olpc_conf = {
 
 int __init pci_olpc_init(void)
 {
-       printk(KERN_INFO "PCI: Using configuration type OLPC\n");
+       printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n");
        raw_pci_ops = &pci_olpc_conf;
        is_lx = is_geode_lx();
        return 0;
index e7e8c5f549563a6b65a4b139d8202ee878c80c74..87bb35e34ef175d0a8b3beedd5c4d76010c9169d 100644 (file)
@@ -113,6 +113,7 @@ static void __save_processor_state(struct saved_context *ctxt)
 void save_processor_state(void)
 {
        __save_processor_state(&saved_context);
+       save_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(save_processor_state);
@@ -229,6 +230,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
 void restore_processor_state(void)
 {
        __restore_processor_state(&saved_context);
+       restore_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(restore_processor_state);
index 1304bcec8ee57d1b15c8cb72aed55cea283d2d5b..7c0fedd98ea0ad215abc436b842e2bf8c27965ed 100644 (file)
@@ -106,6 +106,7 @@ static const struct file_operations u32_array_fops = {
        .open   = u32_array_open,
        .release= xen_array_release,
        .read   = u32_array_read,
+       .llseek = no_llseek,
 };
 
 struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
index 7d46c84414188bf401777e4d65a9652e5cc09fa5..63b83ceebd1a0984403af50aaefe29331d5f3132 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
@@ -1183,6 +1184,8 @@ asmlinkage void __init xen_start_kernel(void)
        local_irq_disable();
        early_boot_irqs_off();
 
+       memblock_init();
+
        xen_raw_console_write("mapping kernel into physical memory\n");
        pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
 
index 42086ac406af21da6d281687625684c0dddbe11c..f72d18c692217d67c45e57c16ea8585904097d1f 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -55,6 +56,7 @@
 #include <asm/e820.h>
 #include <asm/linkage.h>
 #include <asm/page.h>
+#include <asm/init.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -359,7 +361,8 @@ void make_lowmem_page_readonly(void *vaddr)
        unsigned int level;
 
        pte = lookup_address(address, &level);
-       BUG_ON(pte == NULL);
+       if (pte == NULL)
+               return;         /* vaddr missing */
 
        ptev = pte_wrprotect(*pte);
 
@@ -374,7 +377,8 @@ void make_lowmem_page_readwrite(void *vaddr)
        unsigned int level;
 
        pte = lookup_address(address, &level);
-       BUG_ON(pte == NULL);
+       if (pte == NULL)
+               return;         /* vaddr missing */
 
        ptev = pte_mkwrite(*pte);
 
@@ -1508,13 +1512,25 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #endif
 }
 
-#ifdef CONFIG_X86_32
 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
+       unsigned long pfn = pte_pfn(pte);
+
+#ifdef CONFIG_X86_32
        /* If there's an existing pte, then don't allow _PAGE_RW to be set */
        if (pte_val_ma(*ptep) & _PAGE_PRESENT)
                pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
                               pte_val_ma(pte));
+#endif
+
+       /*
+        * If the new pfn is within the range of the newly allocated
+        * kernel pagetable, and it isn't being mapped into an
+        * early_ioremap fixmap slot, make sure it is RO.
+        */
+       if (!is_early_ioremap_ptep(ptep) &&
+           pfn >= e820_table_start && pfn < e820_table_end)
+               pte = pte_wrprotect(pte);
 
        return pte;
 }
@@ -1527,7 +1543,6 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
 
        xen_set_pte(ptep, pte);
 }
-#endif
 
 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
 {
@@ -1814,7 +1829,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
        __xen_write_cr3(true, __pa(pgd));
        xen_mc_issue(PARAVIRT_LAZY_CPU);
 
-       reserve_early(__pa(xen_start_info->pt_base),
+       memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
@@ -1852,7 +1867,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
 
        pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
 
-       reserve_early(__pa(xen_start_info->pt_base),
+       memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
@@ -1969,14 +1984,9 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .alloc_pte = xen_alloc_pte_init,
        .release_pte = xen_release_pte_init,
        .alloc_pmd = xen_alloc_pmd_init,
-       .alloc_pmd_clone = paravirt_nop,
        .release_pmd = xen_release_pmd_init,
 
-#ifdef CONFIG_X86_64
-       .set_pte = xen_set_pte,
-#else
        .set_pte = xen_set_pte_init,
-#endif
        .set_pte_at = xen_set_pte_at,
        .set_pmd = xen_set_pmd_hyper,
 
index a013ec9d0c5410ebd8d1dbdaeec76fb182722d86..22471001b74c48dc26e499a549d4eb8549ed48e3 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <asm/xen/hypervisor.h>
 #include <xen/xen.h>
+#include <asm/iommu_table.h>
 
 int xen_swiotlb __read_mostly;
 
@@ -56,3 +57,7 @@ void __init pci_xen_swiotlb_init(void)
                dma_ops = &xen_swiotlb_dma_ops;
        }
 }
+IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
+                 0,
+                 pci_xen_swiotlb_init,
+                 0);
index 554c002a1e1afcd13a71c90a25eff86057e56832..0f456386cce5dc3a0c08ed45bfaf0a268be25819 100644 (file)
@@ -72,13 +72,17 @@ void __init xen_unplug_emulated_devices(void)
 {
        int r;
 
+       /* user explicitly requested no unplug */
+       if (xen_emul_unplug & XEN_UNPLUG_NEVER)
+               return;
        /* check the version of the xen platform PCI device */
        r = check_platform_magic();
        /* If the version matches enable the Xen platform PCI driver.
-        * Also enable the Xen platform PCI driver if the version is really old
-        * and the user told us to ignore it. */
+        * Also enable the Xen platform PCI driver if the host does
+        * not support the unplug protocol (XEN_PLATFORM_ERR_MAGIC)
+        * but the user told us that unplugging is unnecessary. */
        if (r && !(r == XEN_PLATFORM_ERR_MAGIC &&
-                       (xen_emul_unplug & XEN_UNPLUG_IGNORE)))
+                       (xen_emul_unplug & XEN_UNPLUG_UNNECESSARY)))
                return;
        /* Set the default value of xen_emul_unplug depending on whether or
         * not the Xen PV frontends and the Xen platform PCI driver have
@@ -99,7 +103,7 @@ void __init xen_unplug_emulated_devices(void)
                }
        }
        /* Now unplug the emulated devices */
-       if (!(xen_emul_unplug & XEN_UNPLUG_IGNORE))
+       if (!(xen_emul_unplug & XEN_UNPLUG_UNNECESSARY))
                outw(xen_emul_unplug, XEN_IOPORT_UNPLUG);
        xen_platform_pci_unplug = xen_emul_unplug;
 }
@@ -125,8 +129,10 @@ static int __init parse_xen_emul_unplug(char *arg)
                        xen_emul_unplug |= XEN_UNPLUG_AUX_IDE_DISKS;
                else if (!strncmp(p, "nics", l))
                        xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
-               else if (!strncmp(p, "ignore", l))
-                       xen_emul_unplug |= XEN_UNPLUG_IGNORE;
+               else if (!strncmp(p, "unnecessary", l))
+                       xen_emul_unplug |= XEN_UNPLUG_UNNECESSARY;
+               else if (!strncmp(p, "never", l))
+                       xen_emul_unplug |= XEN_UNPLUG_NEVER;
                else
                        printk(KERN_WARNING "unrecognised option '%s' "
                                 "in parameter 'xen_emul_unplug'\n", p);
index 328b003054267d074610fdce51c39b063fae48e6..9729c903404b1633a0eaed2b06bd0cfadabf9aa7 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
+#include <linux/memblock.h>
 
 #include <asm/elf.h>
 #include <asm/vdso.h>
@@ -129,7 +130,7 @@ char * __init xen_memory_setup(void)
         *  - xen_start_info
         * See comment above "struct start_info" in <xen/interface/xen.h>
         */
-       reserve_early(__pa(xen_start_info->mfn_list),
+       memblock_x86_reserve_range(__pa(xen_start_info->mfn_list),
                      __pa(xen_start_info->pt_base),
                        "XEN START INFO");
 
index e0500646585d4a5d7bc64338798ba955494ab387..23e061b9327bc45b9ba64024559c87202f7602b0 100644 (file)
@@ -224,7 +224,7 @@ static noinline int xen_spin_lock_slow(struct arch_spinlock *lock, bool irq_enab
                        goto out;
                }
 
-               flags = __raw_local_save_flags();
+               flags = arch_local_save_flags();
                if (irq_enable) {
                        ADD_STATS(taken_slow_irqenable, 1);
                        raw_local_irq_enable();
index 1a5353a753fcd10e1330c03d1af43a6fe9c5a5b7..b2bb5aa3b0540e42847a7664aa529cf5d2c0fb83 100644 (file)
@@ -489,8 +489,9 @@ static void xen_hvm_setup_cpu_clockevents(void)
 __init void xen_hvm_init_time_ops(void)
 {
        /* vector callback is needed otherwise we cannot receive interrupts
-        * on cpu > 0 */
-       if (!xen_have_vector_callback && num_present_cpus() > 1)
+        * on cpu > 0 and at this point we don't know how many cpus are
+        * available */
+       if (!xen_have_vector_callback)
                return;
        if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
                printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..dae9a8b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Xtensa IRQ flags handling functions
+ *
+ * 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.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IRQFLAGS_H
+#define _XTENSA_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("rsr %0,"__stringify(PS) : "=a" (flags));
+       return flags;
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       asm volatile("rsil %0, "__stringify(LOCKLEVEL)
+                    : "=a" (flags) :: "memory");
+       return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       arch_local_irq_save();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       unsigned long flags;
+       asm volatile("rsil %0, 0" : "=a" (flags) :: "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       asm volatile("wsr %0, "__stringify(PS)" ; rsync"
+                    :: "a" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & 0xf) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _XTENSA_IRQFLAGS_H */
index 62b1e8f3c13c38bb99e23bd457cc61e858628abe..1e7e09ab6cd7836802b7442b5436e3a25a775640 100644 (file)
 #define _XTENSA_SYSTEM_H
 
 #include <linux/stringify.h>
+#include <linux/irqflags.h>
 
 #include <asm/processor.h>
 
-/* interrupt control */
-
-#define local_save_flags(x)                                            \
-       __asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
-#define local_irq_restore(x)   do {                                    \
-       __asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync"       \
-                             :: "a" (x) : "memory"); } while(0);
-#define local_irq_save(x)      do {                                    \
-       __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)         \
-                             : "=a" (x) :: "memory");} while(0);
-
-static inline void local_irq_disable(void)
-{
-       unsigned long flags;
-       __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
-                             : "=a" (flags) :: "memory");
-}
-static inline void local_irq_enable(void)
-{
-       unsigned long flags;
-       __asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
-
-}
-
-static inline int irqs_disabled(void)
-{
-       unsigned long flags;
-       local_save_flags(flags);
-       return flags & 0xf;
-}
-
-
 #define smp_read_barrier_depends() do { } while(0)
 #define read_barrier_depends() do { } while(0)
 
index c64a5d387de51d9e0e4c2225a8ae348c05b331e8..87508886cbbdadb28d2843047cdbbb90e7656b77 100644 (file)
@@ -92,7 +92,7 @@ int show_interrupts(struct seq_file *p, void *v)
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
 
                for (action=action->next; action; action = action->next)
index 0f59b23096db628c23fe111f867e0fe55cda9e8c..b1febd0f6d2a5227f617d82c7d4687e190cfc456 100644 (file)
@@ -1454,7 +1454,7 @@ blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup)
 
        /* Currently we do not support hierarchy deeper than two level (0,1) */
        if (parent != cgroup->top_cgroup)
-               return ERR_PTR(-EINVAL);
+               return ERR_PTR(-EPERM);
 
        blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
        if (!blkcg)
index ddc68332d65568a0438b36007e4ff868ca55cf84..500eb859886e7ec989b2b1dc731eccc8d58dc85b 100644 (file)
@@ -1214,9 +1214,9 @@ static int __make_request(struct request_queue *q, struct bio *bio)
        int el_ret;
        unsigned int bytes = bio->bi_size;
        const unsigned short prio = bio_prio(bio);
-       const bool sync = (bio->bi_rw & REQ_SYNC);
-       const bool unplug = (bio->bi_rw & REQ_UNPLUG);
-       const unsigned int ff = bio->bi_rw & REQ_FAILFAST_MASK;
+       const bool sync = !!(bio->bi_rw & REQ_SYNC);
+       const bool unplug = !!(bio->bi_rw & REQ_UNPLUG);
+       const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK;
        int rw_flags;
 
        if ((bio->bi_rw & REQ_HARDBARRIER) &&
index ac0f7d46db631bea98f8887d72047d7e6b905c58..d4a586d8691ec5ed37311d1e3fc76aa0c310828f 100644 (file)
@@ -308,7 +308,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
                return PTR_ERR(bio);
 
        if (rq_data_dir(rq) == WRITE)
-               bio->bi_rw |= (1 << REQ_WRITE);
+               bio->bi_rw |= REQ_WRITE;
 
        if (do_copy)
                rq->cmd_flags |= REQ_COPY_USER;
index 38ff234012a4617e42a5950f362600219d04634b..0a2fd8a48a38ba7e7a6fa496438330f042047cd1 100644 (file)
@@ -369,6 +369,18 @@ static int attempt_merge(struct request_queue *q, struct request *req,
        if (!rq_mergeable(req) || !rq_mergeable(next))
                return 0;
 
+       /*
+        * Don't merge file system requests and discard requests
+        */
+       if ((req->cmd_flags & REQ_DISCARD) != (next->cmd_flags & REQ_DISCARD))
+               return 0;
+
+       /*
+        * Don't merge discard requests and secure discard requests
+        */
+       if ((req->cmd_flags & REQ_SECURE) != (next->cmd_flags & REQ_SECURE))
+               return 0;
+
        /*
         * not contiguous
         */
index b014f7739e987498605f806c8fc5a564952a611d..da8a8a40cd4c3596762590da48a6c823f62f9fb4 100644 (file)
@@ -522,6 +522,7 @@ int blk_register_queue(struct gendisk *disk)
                kobject_uevent(&q->kobj, KOBJ_REMOVE);
                kobject_del(&q->kobj);
                blk_trace_remove_sysfs(disk_to_dev(disk));
+               kobject_put(&dev->kobj);
                return ret;
        }
 
index 1340cce5721a755ee39e7c975a4813a3100537e6..f864012ec300d632d34c96ae5d0a2e991873cf8c 100644 (file)
@@ -130,14 +130,18 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
 
 static inline int blk_cpu_to_group(int cpu)
 {
+       int group = NR_CPUS;
 #ifdef CONFIG_SCHED_MC
        const struct cpumask *mask = cpu_coregroup_mask(cpu);
-       return cpumask_first(mask);
+       group = cpumask_first(mask);
 #elif defined(CONFIG_SCHED_SMT)
-       return cpumask_first(topology_thread_cpumask(cpu));
+       group = cpumask_first(topology_thread_cpumask(cpu));
 #else
        return cpu;
 #endif
+       if (likely(group < NR_CPUS))
+               return group;
+       return cpu;
 }
 
 /*
index 82d58829ba591eeef13a3ed4eca96b8a019c4d85..f20d6a789d484591e9fdb5642fa893c233c2b9b0 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/uio.h>
 #include <linux/idr.h>
 #include <linux/bsg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -426,7 +425,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
        /*
         * fill in all the output members
         */
-       hdr->device_status = status_byte(rq->errors);
+       hdr->device_status = rq->errors & 0xff;
        hdr->transport_status = host_byte(rq->errors);
        hdr->driver_status = driver_byte(rq->errors);
        hdr->info = 0;
@@ -843,9 +842,7 @@ static int bsg_open(struct inode *inode, struct file *file)
 {
        struct bsg_device *bd;
 
-       lock_kernel();
        bd = bsg_get_device(inode, file);
-       unlock_kernel();
 
        if (IS_ERR(bd))
                return PTR_ERR(bd);
@@ -968,6 +965,7 @@ static const struct file_operations bsg_fops = {
        .release        =       bsg_release,
        .unlocked_ioctl =       bsg_ioctl,
        .owner          =       THIS_MODULE,
+       .llseek         =       default_llseek,
 };
 
 void bsg_unregister_queue(struct request_queue *q)
index dfceb6386bd5e88478d56088c07b9c0babb995cc..4cd59b0d7c15b2b0df8c6e7323afe5cd51359969 100644 (file)
@@ -30,6 +30,7 @@ static const int cfq_slice_sync = HZ / 10;
 static int cfq_slice_async = HZ / 25;
 static const int cfq_slice_async_rq = 2;
 static int cfq_slice_idle = HZ / 125;
+static int cfq_group_idle = HZ / 125;
 static const int cfq_target_latency = HZ * 3/10; /* 300 ms */
 static const int cfq_hist_divisor = 4;
 
@@ -147,6 +148,8 @@ struct cfq_queue {
        struct cfq_queue *new_cfqq;
        struct cfq_group *cfqg;
        struct cfq_group *orig_cfqg;
+       /* Number of sectors dispatched from queue in single dispatch round */
+       unsigned long nr_sectors;
 };
 
 /*
@@ -208,6 +211,8 @@ struct cfq_group {
        struct hlist_node cfqd_node;
        atomic_t ref;
 #endif
+       /* number of requests that are on the dispatch list or inside driver */
+       int dispatched;
 };
 
 /*
@@ -280,6 +285,7 @@ struct cfq_data {
        unsigned int cfq_slice[2];
        unsigned int cfq_slice_async_rq;
        unsigned int cfq_slice_idle;
+       unsigned int cfq_group_idle;
        unsigned int cfq_latency;
        unsigned int cfq_group_isolation;
 
@@ -387,6 +393,21 @@ CFQ_CFQQ_FNS(wait_busy);
                        &cfqg->service_trees[i][j]: NULL) \
 
 
+static inline bool iops_mode(struct cfq_data *cfqd)
+{
+       /*
+        * If we are not idling on queues and it is a NCQ drive, parallel
+        * execution of requests is on and measuring time is not possible
+        * in most of the cases until and unless we drive shallower queue
+        * depths and that becomes a performance bottleneck. In such cases
+        * switch to start providing fairness in terms of number of IOs.
+        */
+       if (!cfqd->cfq_slice_idle && cfqd->hw_tag)
+               return true;
+       else
+               return false;
+}
+
 static inline enum wl_prio_t cfqq_prio(struct cfq_queue *cfqq)
 {
        if (cfq_class_idle(cfqq))
@@ -915,7 +936,6 @@ static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
                        slice_used = cfqq->allocated_slice;
        }
 
-       cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u", slice_used);
        return slice_used;
 }
 
@@ -923,19 +943,21 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
                                struct cfq_queue *cfqq)
 {
        struct cfq_rb_root *st = &cfqd->grp_service_tree;
-       unsigned int used_sl, charge_sl;
+       unsigned int used_sl, charge;
        int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg)
                        - cfqg->service_tree_idle.count;
 
        BUG_ON(nr_sync < 0);
-       used_sl = charge_sl = cfq_cfqq_slice_usage(cfqq);
+       used_sl = charge = cfq_cfqq_slice_usage(cfqq);
 
-       if (!cfq_cfqq_sync(cfqq) && !nr_sync)
-               charge_sl = cfqq->allocated_slice;
+       if (iops_mode(cfqd))
+               charge = cfqq->slice_dispatch;
+       else if (!cfq_cfqq_sync(cfqq) && !nr_sync)
+               charge = cfqq->allocated_slice;
 
        /* Can't update vdisktime while group is on service tree */
        cfq_rb_erase(&cfqg->rb_node, st);
-       cfqg->vdisktime += cfq_scale_slice(charge_sl, cfqg);
+       cfqg->vdisktime += cfq_scale_slice(charge, cfqg);
        __cfq_group_service_tree_add(st, cfqg);
 
        /* This group is being expired. Save the context */
@@ -949,6 +971,9 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
 
        cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
                                        st->min_vdisktime);
+       cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u"
+                       " sect=%u", used_sl, cfqq->slice_dispatch, charge,
+                       iops_mode(cfqd), cfqq->nr_sectors);
        cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
        cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
 }
@@ -1003,10 +1028,20 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
         */
        atomic_set(&cfqg->ref, 1);
 
-       /* Add group onto cgroup list */
-       sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
-       cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
+       /*
+        * Add group onto cgroup list. It might happen that bdi->dev is
+        * not initiliazed yet. Initialize this new group without major
+        * and minor info and this info will be filled in once a new thread
+        * comes for IO. See code above.
+        */
+       if (bdi->dev) {
+               sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+               cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
                                        MKDEV(major, minor));
+       } else
+               cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
+                                       0);
+
        cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev);
 
        /* Add group on cfqd list */
@@ -1596,6 +1631,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
                cfqq->allocated_slice = 0;
                cfqq->slice_end = 0;
                cfqq->slice_dispatch = 0;
+               cfqq->nr_sectors = 0;
 
                cfq_clear_cfqq_wait_request(cfqq);
                cfq_clear_cfqq_must_dispatch(cfqq);
@@ -1848,6 +1884,9 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
        BUG_ON(!service_tree);
        BUG_ON(!service_tree->count);
 
+       if (!cfqd->cfq_slice_idle)
+               return false;
+
        /* We never do for idle class queues. */
        if (prio == IDLE_WORKLOAD)
                return false;
@@ -1872,7 +1911,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
 {
        struct cfq_queue *cfqq = cfqd->active_queue;
        struct cfq_io_context *cic;
-       unsigned long sl;
+       unsigned long sl, group_idle = 0;
 
        /*
         * SSD device without seek penalty, disable idling. But only do so
@@ -1888,8 +1927,13 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        /*
         * idle is disabled, either manually or by past process history
         */
-       if (!cfqd->cfq_slice_idle || !cfq_should_idle(cfqd, cfqq))
-               return;
+       if (!cfq_should_idle(cfqd, cfqq)) {
+               /* no queue idling. Check for group idling */
+               if (cfqd->cfq_group_idle)
+                       group_idle = cfqd->cfq_group_idle;
+               else
+                       return;
+       }
 
        /*
         * still active requests from this queue, don't idle
@@ -1916,13 +1960,21 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
                return;
        }
 
+       /* There are other queues in the group, don't do group idle */
+       if (group_idle && cfqq->cfqg->nr_cfqq > 1)
+               return;
+
        cfq_mark_cfqq_wait_request(cfqq);
 
-       sl = cfqd->cfq_slice_idle;
+       if (group_idle)
+               sl = cfqd->cfq_group_idle;
+       else
+               sl = cfqd->cfq_slice_idle;
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
        cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
-       cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl);
+       cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu group_idle: %d", sl,
+                       group_idle ? 1 : 0);
 }
 
 /*
@@ -1938,9 +1990,11 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
        cfqq->next_rq = cfq_find_next_rq(cfqd, cfqq, rq);
        cfq_remove_request(rq);
        cfqq->dispatched++;
+       (RQ_CFQG(rq))->dispatched++;
        elv_dispatch_sort(q, rq);
 
        cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
+       cfqq->nr_sectors += blk_rq_sectors(rq);
        cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
                                        rq_data_dir(rq), rq_is_sync(rq));
 }
@@ -2206,7 +2260,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
                        cfqq = NULL;
                        goto keep_queue;
                } else
-                       goto expire;
+                       goto check_group_idle;
        }
 
        /*
@@ -2234,8 +2288,23 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
         * flight or is idling for a new request, allow either of these
         * conditions to happen (or time out) before selecting a new queue.
         */
-       if (timer_pending(&cfqd->idle_slice_timer) ||
-           (cfqq->dispatched && cfq_should_idle(cfqd, cfqq))) {
+       if (timer_pending(&cfqd->idle_slice_timer)) {
+               cfqq = NULL;
+               goto keep_queue;
+       }
+
+       if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
+               cfqq = NULL;
+               goto keep_queue;
+       }
+
+       /*
+        * If group idle is enabled and there are requests dispatched from
+        * this group, wait for requests to complete.
+        */
+check_group_idle:
+       if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1
+           && cfqq->cfqg->dispatched) {
                cfqq = NULL;
                goto keep_queue;
        }
@@ -3385,6 +3454,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
        WARN_ON(!cfqq->dispatched);
        cfqd->rq_in_driver--;
        cfqq->dispatched--;
+       (RQ_CFQG(rq))->dispatched--;
        cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg,
                        rq_start_time_ns(rq), rq_io_start_time_ns(rq),
                        rq_data_dir(rq), rq_is_sync(rq));
@@ -3414,7 +3484,10 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
                 * the queue.
                 */
                if (cfq_should_wait_busy(cfqd, cfqq)) {
-                       cfqq->slice_end = jiffies + cfqd->cfq_slice_idle;
+                       unsigned long extend_sl = cfqd->cfq_slice_idle;
+                       if (!cfqd->cfq_slice_idle)
+                               extend_sl = cfqd->cfq_group_idle;
+                       cfqq->slice_end = jiffies + extend_sl;
                        cfq_mark_cfqq_wait_busy(cfqq);
                        cfq_log_cfqq(cfqd, cfqq, "will busy wait");
                }
@@ -3850,6 +3923,7 @@ static void *cfq_init_queue(struct request_queue *q)
        cfqd->cfq_slice[1] = cfq_slice_sync;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
+       cfqd->cfq_group_idle = cfq_group_idle;
        cfqd->cfq_latency = 1;
        cfqd->cfq_group_isolation = 0;
        cfqd->hw_tag = -1;
@@ -3922,6 +3996,7 @@ SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
 SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0);
 SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0);
 SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
+SHOW_FUNCTION(cfq_group_idle_show, cfqd->cfq_group_idle, 1);
 SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
 SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
 SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
@@ -3954,6 +4029,7 @@ STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
 STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1,
                UINT_MAX, 0);
 STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
+STORE_FUNCTION(cfq_group_idle_store, &cfqd->cfq_group_idle, 0, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
@@ -3975,6 +4051,7 @@ static struct elv_fs_entry cfq_attrs[] = {
        CFQ_ATTR(slice_async),
        CFQ_ATTR(slice_async_rq),
        CFQ_ATTR(slice_idle),
+       CFQ_ATTR(group_idle),
        CFQ_ATTR(low_latency),
        CFQ_ATTR(group_isolation),
        __ATTR_NULL
@@ -4029,6 +4106,12 @@ static int __init cfq_init(void)
        if (!cfq_slice_idle)
                cfq_slice_idle = 1;
 
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+       if (!cfq_group_idle)
+               cfq_group_idle = 1;
+#else
+               cfq_group_idle = 0;
+#endif
        if (cfq_slab_setup())
                return -ENOMEM;
 
index ec585c9554d33c04b973537f9ac3216e332afa50..4e11559aa2b02d78c4d90c104e81e7a2e84aa05d 100644 (file)
@@ -938,6 +938,7 @@ int elv_register_queue(struct request_queue *q)
                        }
                }
                kobject_uevent(&e->kobj, KOBJ_ADD);
+               e->registered = 1;
        }
        return error;
 }
@@ -947,6 +948,7 @@ static void __elv_unregister_queue(struct elevator_queue *e)
 {
        kobject_uevent(&e->kobj, KOBJ_REMOVE);
        kobject_del(&e->kobj);
+       e->registered = 0;
 }
 
 void elv_unregister_queue(struct request_queue *q)
@@ -1009,18 +1011,19 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
 {
        struct elevator_queue *old_elevator, *e;
        void *data;
+       int err;
 
        /*
         * Allocate new elevator
         */
        e = elevator_alloc(q, new_e);
        if (!e)
-               return 0;
+               return -ENOMEM;
 
        data = elevator_init_queue(q, e);
        if (!data) {
                kobject_put(&e->kobj);
-               return 0;
+               return -ENOMEM;
        }
 
        /*
@@ -1041,10 +1044,13 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
 
        spin_unlock_irq(q->queue_lock);
 
-       __elv_unregister_queue(old_elevator);
+       if (old_elevator->registered) {
+               __elv_unregister_queue(old_elevator);
 
-       if (elv_register_queue(q))
-               goto fail_register;
+               err = elv_register_queue(q);
+               if (err)
+                       goto fail_register;
+       }
 
        /*
         * finally exit old elevator and turn off BYPASS.
@@ -1056,7 +1062,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
 
        blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
 
-       return 1;
+       return 0;
 
 fail_register:
        /*
@@ -1071,17 +1077,19 @@ fail_register:
        queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
        spin_unlock_irq(q->queue_lock);
 
-       return 0;
+       return err;
 }
 
-ssize_t elv_iosched_store(struct request_queue *q, const char *name,
-                         size_t count)
+/*
+ * Switch this queue to the given IO scheduler.
+ */
+int elevator_change(struct request_queue *q, const char *name)
 {
        char elevator_name[ELV_NAME_MAX];
        struct elevator_type *e;
 
        if (!q->elevator)
-               return count;
+               return -ENXIO;
 
        strlcpy(elevator_name, name, sizeof(elevator_name));
        e = elevator_get(strstrip(elevator_name));
@@ -1092,13 +1100,27 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name,
 
        if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
                elevator_put(e);
-               return count;
+               return 0;
        }
 
-       if (!elevator_switch(q, e))
-               printk(KERN_ERR "elevator: switch to %s failed\n",
-                                                       elevator_name);
-       return count;
+       return elevator_switch(q, e);
+}
+EXPORT_SYMBOL(elevator_change);
+
+ssize_t elv_iosched_store(struct request_queue *q, const char *name,
+                         size_t count)
+{
+       int ret;
+
+       if (!q->elevator)
+               return count;
+
+       ret = elevator_change(q, name);
+       if (!ret)
+               return count;
+
+       printk(KERN_ERR "elevator: switch to %s failed\n", name);
+       return ret;
 }
 
 ssize_t elv_iosched_show(struct request_queue *q, char *name)
index 1cd497d7a15aa2cdbd96be5139ca64be8135e528..e573077f1672e06bf159c9a242564c5436fc0a75 100644 (file)
@@ -101,13 +101,13 @@ config CRYPTO_MANAGER2
        select CRYPTO_BLKCIPHER2
        select CRYPTO_PCOMP2
 
-config CRYPTO_MANAGER_TESTS
-       bool "Run algolithms' self-tests"
+config CRYPTO_MANAGER_DISABLE_TESTS
+       bool "Disable run-time self tests"
        default y
        depends on CRYPTO_MANAGER2
        help
-         Run cryptomanager's tests for the new crypto algorithms being
-         registered.
+         Disable run-time self tests that normally take place at
+         algorithm registration.
 
 config CRYPTO_GF128MUL
        tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
index b8c59b889c6ea579e7a6bacd7241bbbc86cbe44c..f669822a7a443c81a04c8fb61d8d382a64546542 100644 (file)
@@ -47,8 +47,11 @@ static int hash_walk_next(struct crypto_hash_walk *walk)
        walk->data = crypto_kmap(walk->pg, 0);
        walk->data += offset;
 
-       if (offset & alignmask)
-               nbytes = alignmask + 1 - (offset & alignmask);
+       if (offset & alignmask) {
+               unsigned int unaligned = alignmask + 1 - (offset & alignmask);
+               if (nbytes > unaligned)
+                       nbytes = unaligned;
+       }
 
        walk->entrylen -= nbytes;
        return nbytes;
index 40bd391f34d90fc0b0619809beb0f09759b307f5..791d194958fa18ac0fb8006e5d565f789c1e4f92 100644 (file)
@@ -206,13 +206,16 @@ err:
        return NOTIFY_OK;
 }
 
-#ifdef CONFIG_CRYPTO_MANAGER_TESTS
 static int cryptomgr_test(void *data)
 {
        struct crypto_test_param *param = data;
        u32 type = param->type;
        int err = 0;
 
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+       goto skiptest;
+#endif
+
        if (type & CRYPTO_ALG_TESTED)
                goto skiptest;
 
@@ -267,7 +270,6 @@ err_put_module:
 err:
        return NOTIFY_OK;
 }
-#endif /* CONFIG_CRYPTO_MANAGER_TESTS */
 
 static int cryptomgr_notify(struct notifier_block *this, unsigned long msg,
                            void *data)
@@ -275,10 +277,8 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg,
        switch (msg) {
        case CRYPTO_MSG_ALG_REQUEST:
                return cryptomgr_schedule_probe(data);
-#ifdef CONFIG_CRYPTO_MANAGER_TESTS
        case CRYPTO_MSG_ALG_REGISTER:
                return cryptomgr_schedule_test(data);
-#endif
        }
 
        return NOTIFY_DONE;
index 249f903cc453b201270bb2db5c33be1856a5d324..873818d48e86939b9492a158a3cd86a9d16b97b9 100644 (file)
@@ -614,7 +614,7 @@ static const u32 S8[64] = {
 #define T3(x) pt[2 * (x) + 2]
 #define T4(x) pt[2 * (x) + 3]
 
-#define PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
+#define DES_PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
 
 /*
  * Encryption key expansion
@@ -639,22 +639,22 @@ unsigned long des_ekey(u32 *pe, const u8 *k)
        b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
        a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
 
-       pe[15 * 2 + 0] = PC2(a, b, c, d); d = rs[d];
-       pe[14 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[13 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[12 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[11 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[10 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 9 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 8 * 2 + 0] = PC2(d, a, b, c); c = rs[c];
-       pe[ 7 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 6 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 5 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 4 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 3 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 2 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 1 * 2 + 0] = PC2(c, d, a, b); b = rs[b];
-       pe[ 0 * 2 + 0] = PC2(b, c, d, a);
+       pe[15 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d];
+       pe[14 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[13 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[12 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[11 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[10 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 9 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 8 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c];
+       pe[ 7 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 6 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 5 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 4 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 3 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 2 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 1 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b];
+       pe[ 0 * 2 + 0] = DES_PC2(b, c, d, a);
 
        /* Check if first half is weak */
        w  = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
@@ -670,22 +670,22 @@ unsigned long des_ekey(u32 *pe, const u8 *k)
        /* Check if second half is weak */
        w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
 
-       pe[15 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
-       pe[14 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[13 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[12 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[11 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[10 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 9 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 8 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
-       pe[ 7 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 6 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 5 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 4 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 3 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 2 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[ 1 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
-       pe[ 0 * 2 + 1] = PC2(b, c, d, a);
+       pe[15 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+       pe[14 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[13 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[12 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[11 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[10 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 9 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 8 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+       pe[ 7 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 6 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 5 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 4 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 3 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 2 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[ 1 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+       pe[ 0 * 2 + 1] = DES_PC2(b, c, d, a);
 
        /* Fixup: 2413 5768 -> 1357 2468 */
        for (d = 0; d < 16; ++d) {
@@ -722,22 +722,22 @@ static void dkey(u32 *pe, const u8 *k)
        b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
        a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
 
-       pe[ 0 * 2] = PC2(a, b, c, d); d = rs[d];
-       pe[ 1 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 2 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 3 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 4 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 5 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 6 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 7 * 2] = PC2(d, a, b, c); c = rs[c];
-       pe[ 8 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 9 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[10 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[11 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[12 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[13 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[14 * 2] = PC2(c, d, a, b); b = rs[b];
-       pe[15 * 2] = PC2(b, c, d, a);
+       pe[ 0 * 2] = DES_PC2(a, b, c, d); d = rs[d];
+       pe[ 1 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 2 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 3 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 4 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 5 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 6 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 7 * 2] = DES_PC2(d, a, b, c); c = rs[c];
+       pe[ 8 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 9 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[10 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[11 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[12 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[13 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[14 * 2] = DES_PC2(c, d, a, b); b = rs[b];
+       pe[15 * 2] = DES_PC2(b, c, d, a);
 
        /* Skip to next table set */
        pt += 512;
@@ -747,22 +747,22 @@ static void dkey(u32 *pe, const u8 *k)
        b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1];
        a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1];
 
-       pe[ 0 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
-       pe[ 1 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 2 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 3 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 4 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 5 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-       pe[ 6 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-       pe[ 7 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
-       pe[ 8 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[ 9 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[10 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[11 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[12 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-       pe[13 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-       pe[14 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
-       pe[15 * 2 + 1] = PC2(b, c, d, a);
+       pe[ 0 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+       pe[ 1 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 2 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 3 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 4 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 5 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+       pe[ 6 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+       pe[ 7 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+       pe[ 8 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[ 9 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[10 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[11 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[12 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+       pe[13 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+       pe[14 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+       pe[15 * 2 + 1] = DES_PC2(b, c, d, a);
 
        /* Fixup: 2413 5768 -> 1357 2468 */
        for (d = 0; d < 16; ++d) {
index abd980c729ebce5a57e833a0937bf233dc8937cc..fa8c8f78c8d4c1838d121e6131b05162858b2802 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "internal.h"
 
-#ifndef CONFIG_CRYPTO_MANAGER_TESTS
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
 
 /* a perfect nop */
 int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
@@ -2542,6 +2542,6 @@ non_fips_alg:
        return -EINVAL;
 }
 
-#endif /* CONFIG_CRYPTO_MANAGER_TESTS */
+#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
 
 EXPORT_SYMBOL_GPL(alg_test);
index ae473445ad6daf11254ee269c3194c9ed03e0cb1..a2aea53a75ed9fdf99058f9676429c84104c2f27 100644 (file)
@@ -50,7 +50,7 @@ obj-$(CONFIG_SPI)             += spi/
 obj-y                          += net/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_FUSION)           += message/
-obj-$(CONFIG_FIREWIRE)         += firewire/
+obj-y                          += firewire/
 obj-y                          += ieee1394/
 obj-$(CONFIG_UIO)              += uio/
 obj-y                          += cdrom/
index b811f2173f6f167c84700040fe2720bafb43156f..88681aca88c581891399e18b056d9a6df94a9e01 100644 (file)
@@ -105,7 +105,7 @@ config ACPI_EC_DEBUGFS
 
          Be aware that using this interface can confuse your Embedded
          Controller in a way that a normal reboot is not enough. You then
-         have to power of your system, and remove the laptop battery for
+         have to power off your system, and remove the laptop battery for
          some seconds.
          An Embedded Controller typically is available on laptops and reads
          sensor values like battery state and temperature.
index b76848c80be34729c56bd20d04f75f9f534cbb36..6afceb3d4034edef3a868722e41af82873057e74 100644 (file)
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <asm/mwait.h>
 
 #define ACPI_PROCESSOR_AGGREGATOR_CLASS        "acpi_pad"
 #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
 #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
 static DEFINE_MUTEX(isolated_cpus_lock);
 
-#define MWAIT_SUBSTATE_MASK    (0xf)
-#define MWAIT_CSTATE_MASK      (0xf)
-#define MWAIT_SUBSTATE_SIZE    (4)
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK     (0x2)
 static unsigned long power_saving_mwait_eax;
 
 static unsigned char tsc_detected_unstable;
@@ -382,31 +377,32 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device)
        device_remove_file(&device->dev, &dev_attr_rrtime);
 }
 
-/* Query firmware how many CPUs should be idle */
-static int acpi_pad_pur(acpi_handle handle, int *num_cpus)
+/*
+ * Query firmware how many CPUs should be idle
+ * return -1 on failure
+ */
+static int acpi_pad_pur(acpi_handle handle)
 {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        union acpi_object *package;
-       int rev, num, ret = -EINVAL;
+       int num = -1;
 
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
-               return -EINVAL;
+               return num;
 
        if (!buffer.length || !buffer.pointer)
-               return -EINVAL;
+               return num;
 
        package = buffer.pointer;
-       if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2)
-               goto out;
-       rev = package->package.elements[0].integer.value;
-       num = package->package.elements[1].integer.value;
-       if (rev != 1 || num < 0)
-               goto out;
-       *num_cpus = num;
-       ret = 0;
-out:
+
+       if (package->type == ACPI_TYPE_PACKAGE &&
+               package->package.count == 2 &&
+               package->package.elements[0].integer.value == 1) /* rev 1 */
+
+               num = package->package.elements[1].integer.value;
+
        kfree(buffer.pointer);
-       return ret;
+       return num;
 }
 
 /* Notify firmware how many CPUs are idle */
@@ -433,7 +429,8 @@ static void acpi_pad_handle_notify(acpi_handle handle)
        uint32_t idle_cpus;
 
        mutex_lock(&isolated_cpus_lock);
-       if (acpi_pad_pur(handle, &num_cpus)) {
+       num_cpus = acpi_pad_pur(handle);
+       if (num_cpus < 0) {
                mutex_unlock(&isolated_cpus_lock);
                return;
        }
index df85b53a674fc33105fa1434b3800db7ab26a423..7dad9160f20998112cc302d0a239c9fa27fcd429 100644 (file)
@@ -854,6 +854,7 @@ struct acpi_bit_register_info {
        ACPI_BITMASK_POWER_BUTTON_STATUS   | \
        ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
        ACPI_BITMASK_RT_CLOCK_STATUS       | \
+       ACPI_BITMASK_PCIEXP_WAKE_DISABLE   | \
        ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
index 74c24d517f81768a6a00418db71c9f93be335b2e..4093522eed45692012b5da617c57187ef20c4458 100644 (file)
@@ -109,7 +109,7 @@ void acpi_ex_enter_interpreter(void)
  *
  * DESCRIPTION: Reacquire the interpreter execution region from within the
  *              interpreter code. Failure to enter the interpreter region is a
- *              fatal system error. Used in  conjuction with
+ *              fatal system error. Used in  conjunction with
  *              relinquish_interpreter
  *
  ******************************************************************************/
index 22cfcfbd9fff77cd4cd5bb77be80c244461b2df5..491191e6cf692bffe1811a22674a0eb0720c3771 100644 (file)
@@ -149,7 +149,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
 
                        /*
                         * 16-, 32-, and 64-bit cases must use the move macros that perform
-                        * endian conversion and/or accomodate hardware that cannot perform
+                        * endian conversion and/or accommodate hardware that cannot perform
                         * misaligned memory transfers
                         */
                case ACPI_RSC_MOVE16:
index 907e350f1c7df58370cb0e68a399b91d903ec466..fca34ccfd294a782e3f05312d99d5b5fdef5bfb4 100644 (file)
@@ -34,6 +34,6 @@ config ACPI_APEI_ERST_DEBUG
        depends on ACPI_APEI
        help
          ERST is a way provided by APEI to save and retrieve hardware
-         error infomation to and from a persistent store. Enable this
+         error information to and from a persistent store. Enable this
          if you want to debugging and testing the ERST kernel support
          and firmware implementation.
index 73fd0c7487c1ae0b1311f4d7e1c048ddc809153a..4a904a4bf05f83a1b952ec2365811f8c5db931e1 100644 (file)
@@ -445,11 +445,15 @@ EXPORT_SYMBOL_GPL(apei_resources_sub);
 int apei_resources_request(struct apei_resources *resources,
                           const char *desc)
 {
-       struct apei_res *res, *res_bak;
+       struct apei_res *res, *res_bak = NULL;
        struct resource *r;
+       int rc;
 
-       apei_resources_sub(resources, &apei_resources_all);
+       rc = apei_resources_sub(resources, &apei_resources_all);
+       if (rc)
+               return rc;
 
+       rc = -EINVAL;
        list_for_each_entry(res, &resources->iomem, list) {
                r = request_mem_region(res->start, res->end - res->start,
                                       desc);
@@ -475,7 +479,11 @@ int apei_resources_request(struct apei_resources *resources,
                }
        }
 
-       apei_resources_merge(&apei_resources_all, resources);
+       rc = apei_resources_merge(&apei_resources_all, resources);
+       if (rc) {
+               pr_err(APEI_PFX "Fail to merge resources!\n");
+               goto err_unmap_ioport;
+       }
 
        return 0;
 err_unmap_ioport:
@@ -491,12 +499,13 @@ err_unmap_iomem:
                        break;
                release_mem_region(res->start, res->end - res->start);
        }
-       return -EINVAL;
+       return rc;
 }
 EXPORT_SYMBOL_GPL(apei_resources_request);
 
 void apei_resources_release(struct apei_resources *resources)
 {
+       int rc;
        struct apei_res *res;
 
        list_for_each_entry(res, &resources->iomem, list)
@@ -504,7 +513,9 @@ void apei_resources_release(struct apei_resources *resources)
        list_for_each_entry(res, &resources->ioport, list)
                release_region(res->start, res->end - res->start);
 
-       apei_resources_sub(&apei_resources_all, resources);
+       rc = apei_resources_sub(&apei_resources_all, resources);
+       if (rc)
+               pr_err(APEI_PFX "Fail to sub resources!\n");
 }
 EXPORT_SYMBOL_GPL(apei_resources_release);
 
index 465c885938ee89a45db10f1f39d1ceb8cba41cf9..cf29df69380b8dd32585a074c53efc7af7a65471 100644 (file)
@@ -426,7 +426,9 @@ DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
 
 static int einj_check_table(struct acpi_table_einj *einj_tab)
 {
-       if (einj_tab->header_length != sizeof(struct acpi_table_einj))
+       if ((einj_tab->header_length !=
+            (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header)))
+           && (einj_tab->header_length != sizeof(struct acpi_table_einj)))
                return -EINVAL;
        if (einj_tab->header.length < sizeof(struct acpi_table_einj))
                return -EINVAL;
index 5281ddda2777c99c40f0830c1d4e5022cc5b37aa..de73caf3cebc8955e1502de7eac4eee0218c3fe6 100644 (file)
@@ -2,7 +2,7 @@
  * APEI Error Record Serialization Table debug support
  *
  * ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store. This file provide the
+ * information to and from a persistent store. This file provide the
  * debugging/testing support for ERST kernel support and firmware
  * implementation.
  *
@@ -111,11 +111,13 @@ retry:
                goto out;
        }
        if (len > erst_dbg_buf_len) {
-               kfree(erst_dbg_buf);
+               void *p;
                rc = -ENOMEM;
-               erst_dbg_buf = kmalloc(len, GFP_KERNEL);
-               if (!erst_dbg_buf)
+               p = kmalloc(len, GFP_KERNEL);
+               if (!p)
                        goto out;
+               kfree(erst_dbg_buf);
+               erst_dbg_buf = p;
                erst_dbg_buf_len = len;
                goto retry;
        }
@@ -150,11 +152,13 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf,
        if (mutex_lock_interruptible(&erst_dbg_mutex))
                return -EINTR;
        if (usize > erst_dbg_buf_len) {
-               kfree(erst_dbg_buf);
+               void *p;
                rc = -ENOMEM;
-               erst_dbg_buf = kmalloc(usize, GFP_KERNEL);
-               if (!erst_dbg_buf)
+               p = kmalloc(usize, GFP_KERNEL);
+               if (!p)
                        goto out;
+               kfree(erst_dbg_buf);
+               erst_dbg_buf = p;
                erst_dbg_buf_len = usize;
        }
        rc = copy_from_user(erst_dbg_buf, ubuf, usize);
@@ -180,6 +184,7 @@ static const struct file_operations erst_dbg_ops = {
        .read           = erst_dbg_read,
        .write          = erst_dbg_write,
        .unlocked_ioctl = erst_dbg_ioctl,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice erst_dbg_dev = {
index 18645f4e83cdd2f22d526276b320dac631be8940..1211c03149e8c7c258fee89dd1109e1e6b901c26 100644 (file)
@@ -2,7 +2,7 @@
  * APEI Error Record Serialization Table support
  *
  * ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store.
+ * information to and from a persistent store.
  *
  * For more information about ERST, please refer to ACPI Specification
  * version 4.0, section 17.4.
@@ -266,13 +266,30 @@ static int erst_exec_move_data(struct apei_exec_context *ctx,
 {
        int rc;
        u64 offset;
+       void *src, *dst;
+
+       /* ioremap does not work in interrupt context */
+       if (in_interrupt()) {
+               pr_warning(ERST_PFX
+                          "MOVE_DATA can not be used in interrupt context");
+               return -EBUSY;
+       }
 
        rc = __apei_exec_read_register(entry, &offset);
        if (rc)
                return rc;
-       memmove((void *)ctx->dst_base + offset,
-               (void *)ctx->src_base + offset,
-               ctx->var2);
+
+       src = ioremap(ctx->src_base + offset, ctx->var2);
+       if (!src)
+               return -ENOMEM;
+       dst = ioremap(ctx->dst_base + offset, ctx->var2);
+       if (!dst)
+               return -ENOMEM;
+
+       memmove(dst, src, ctx->var2);
+
+       iounmap(src);
+       iounmap(dst);
 
        return 0;
 }
@@ -750,7 +767,9 @@ __setup("erst_disable", setup_erst_disable);
 
 static int erst_check_table(struct acpi_table_erst *erst_tab)
 {
-       if (erst_tab->header_length != sizeof(struct acpi_table_erst))
+       if ((erst_tab->header_length !=
+            (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
+           && (erst_tab->header_length != sizeof(struct acpi_table_einj)))
                return -EINVAL;
        if (erst_tab->header.length < sizeof(struct acpi_table_erst))
                return -EINVAL;
index 385a6059714a72dd32256685a2606586b92d771e..0d505e59214df73dfb40b67b7d5fc45a2d48e127 100644 (file)
@@ -302,7 +302,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev)
        struct ghes *ghes = NULL;
        int rc = -EINVAL;
 
-       generic = ghes_dev->dev.platform_data;
+       generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
        if (!generic->enabled)
                return -ENODEV;
 
index 343168d1826626c202171c3a53c5b5e4c2090a65..1a3508a7fe03f157c2e0144727bbeb5c244d2a46 100644 (file)
@@ -137,20 +137,23 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
 
 static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
-       struct acpi_hest_generic *generic;
        struct platform_device *ghes_dev;
        struct ghes_arr *ghes_arr = data;
        int rc;
 
        if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
                return 0;
-       generic = (struct acpi_hest_generic *)hest_hdr;
-       if (!generic->enabled)
+
+       if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
                return 0;
        ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
        if (!ghes_dev)
                return -ENOMEM;
-       ghes_dev->dev.platform_data = generic;
+
+       rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *));
+       if (rc)
+               goto err;
+
        rc = platform_device_add(ghes_dev);
        if (rc)
                goto err;
index 8f8bd736d4ff11919656e79d2ef9442b037fafff..542e5390389120de7ecd7da4cb7bd059baa18b01 100644 (file)
@@ -142,7 +142,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr,
        list_add_tail_rcu(&map->list, &acpi_iomaps);
        spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
 
-       return vaddr + (paddr - pg_off);
+       return map->vaddr + (paddr - map->paddr);
 err_unmap:
        iounmap(vaddr);
        return NULL;
index dc58402b0a177a4e03e8dc54e7a094804edc1d36..98417201e9ce3881257354e7c2a360ee019a4e39 100644 (file)
@@ -273,7 +273,6 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
-       POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_POWER_NOW,
        POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_FULL,
index 2bb28b9d91c4c2643106ed0d63069ae85799d136..af308d03f49235a6da0b30791e6857c824e8e32f 100644 (file)
@@ -183,6 +183,8 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
 {
        printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
        acpi_osi_setup("!Windows 2006");
+       acpi_osi_setup("!Windows 2006 SP1");
+       acpi_osi_setup("!Windows 2006 SP2");
        return 0;
 }
 static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
@@ -202,6 +204,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                },
        },
        {
+       /*
+        * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
+        * driver (e.g. nouveau) when user press brightness hotkey.
+        * Currently, nouveau driver didn't do the job and it causes there
+        * have a infinite while loop in DSDT when user press hotkey.
+        * We add MSI GX723's dmi information to this table for workaround
+        * this issue.
+        * Will remove MSI GX723 from the table after nouveau grows support.
+        */
+       .callback = dmi_disable_osi_vista,
+       .ident = "MSI GX723",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
+               },
+       },
+       {
        .callback = dmi_disable_osi_vista,
        .ident = "Sony VGN-NS10J_S",
        .matches = {
@@ -226,6 +245,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                },
        },
        {
+       .callback = dmi_disable_osi_vista,
+       .ident = "Toshiba Satellite L355",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+               },
+       },
+       {
        .callback = dmi_disable_osi_win7,
        .ident = "ASUS K50IJ",
        .matches = {
@@ -233,6 +260,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
                },
        },
+       {
+       .callback = dmi_disable_osi_vista,
+       .ident = "Toshiba P305D",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index 5c221ab535d5b0a459516a16034f80a94a7d1bb4..310e3b9749cbbacdabb3c03d288a6b42874aa41b 100644 (file)
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(acpi_root_dir);
 static int set_power_nocheck(const struct dmi_system_id *id)
 {
        printk(KERN_NOTICE PREFIX "%s detected - "
-               "disable power check in power transistion\n", id->ident);
+               "disable power check in power transition\n", id->ident);
        acpi_power_nocheck = 1;
        return 0;
 }
@@ -80,23 +80,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id)
 
 static struct dmi_system_id dsdt_dmi_table[] __initdata = {
        /*
-        * Insyde BIOS on some TOSHIBA machines corrupt the DSDT.
+        * Invoke DSDT corruption work-around on all Toshiba Satellite.
         * https://bugzilla.kernel.org/show_bug.cgi?id=14679
         */
        {
         .callback = set_copy_dsdt,
-        .ident = "TOSHIBA Satellite A505",
+        .ident = "TOSHIBA Satellite",
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"),
-               },
-       },
-       {
-        .callback = set_copy_dsdt,
-        .ident = "TOSHIBA Satellite L505D",
-        .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
                },
        },
        {}
@@ -1027,7 +1019,7 @@ static int __init acpi_init(void)
 
        /*
         * If the laptop falls into the DMI check table, the power state check
-        * will be disabled in the course of device power transistion.
+        * will be disabled in the course of device power transition.
         */
        dmi_check_system(power_nocheck_dmi_table);
 
index 7de27d49c4b9fca8fe773e2444ba8e240417585d..6355b575ee5ac22498b32953e0955cb2811e81ba 100644 (file)
@@ -69,6 +69,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
 
 static const struct file_operations cm_fops = {
        .write = cm_write,
+       .llseek = default_llseek,
 };
 
 int __init acpi_debugfs_init(void)
index 0e869b3f81ca90ced23d929ad54a9cabd9048d08..411620ef84c2e83811adc73c8cd255f58a99549b 100644 (file)
@@ -101,6 +101,7 @@ static struct file_operations acpi_ec_io_ops = {
        .open  = acpi_ec_open_io,
        .read  = acpi_ec_read_io,
        .write = acpi_ec_write_io,
+       .llseek = default_llseek,
 };
 
 int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
index d439314a75d8b183f4eecda98a3a6ef4dbcfa7ee..85d908993809d39147ecdc4c9c4bc2203bf28d0e 100644 (file)
@@ -110,6 +110,7 @@ static const struct file_operations acpi_system_event_ops = {
        .read = acpi_system_read_event,
        .release = acpi_system_close_event,
        .poll = acpi_system_poll_event,
+       .llseek = default_llseek,
 };
 #endif /* CONFIG_ACPI_PROC_EVENT */
 
index 8a3b840c0bb268d0580cd5550c41986bf3c09662..d94d2953c9740f34675eeb576e00e74ee621bfd2 100644 (file)
@@ -369,7 +369,9 @@ static void __exit acpi_fan_exit(void)
 
        acpi_bus_unregister_driver(&acpi_fan_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
        remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
 
        return;
 }
index 1f67057af2a571991481bb761d157320b9d3f329..3ba8d1f44a73ed3b234e810f5316f6531e4d6718 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
-#include <linux/pci-aspm.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
@@ -226,22 +225,31 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle,
        return status;
 }
 
-static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
+static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
+                                       u32 support,
+                                       u32 *control)
 {
        acpi_status status;
-       u32 support_set, result, capbuf[3];
+       u32 result, capbuf[3];
+
+       support &= OSC_PCI_SUPPORT_MASKS;
+       support |= root->osc_support_set;
 
-       /* do _OSC query for all possible controls */
-       support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS);
        capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-       capbuf[OSC_SUPPORT_TYPE] = support_set;
-       capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+       capbuf[OSC_SUPPORT_TYPE] = support;
+       if (control) {
+               *control &= OSC_PCI_CONTROL_MASKS;
+               capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
+       } else {
+               /* Run _OSC query for all possible controls. */
+               capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+       }
 
        status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
        if (ACPI_SUCCESS(status)) {
-               root->osc_support_set = support_set;
-               root->osc_control_qry = result;
-               root->osc_queried = 1;
+               root->osc_support_set = support;
+               if (control)
+                       *control = result;
        }
        return status;
 }
@@ -255,7 +263,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
        if (ACPI_FAILURE(status))
                return status;
        mutex_lock(&osc_lock);
-       status = acpi_pci_query_osc(root, flags);
+       status = acpi_pci_query_osc(root, flags, NULL);
        mutex_unlock(&osc_lock);
        return status;
 }
@@ -365,55 +373,70 @@ out:
 EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 
 /**
- * acpi_pci_osc_control_set - commit requested control to Firmware
- * @handle: acpi_handle for the target ACPI object
- * @flags: driver's requested control bits
+ * acpi_pci_osc_control_set - Request control of PCI root _OSC features.
+ * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
+ * @mask: Mask of _OSC bits to request control of, place to store control mask.
+ * @req: Mask of _OSC bits the control of is essential to the caller.
+ *
+ * Run _OSC query for @mask and if that is successful, compare the returned
+ * mask of control bits with @req.  If all of the @req bits are set in the
+ * returned mask, run _OSC request for it.
  *
- * Attempt to take control from Firmware on requested control bits.
+ * The variable at the @mask address may be modified regardless of whether or
+ * not the function returns success.  On success it will contain the mask of
+ * _OSC bits the BIOS has granted control of, but its contents are meaningless
+ * on failure.
  **/
-acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags)
+acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
 {
+       struct acpi_pci_root *root;
        acpi_status status;
-       u32 control_req, result, capbuf[3];
+       u32 ctrl, capbuf[3];
        acpi_handle tmp;
-       struct acpi_pci_root *root;
 
-       status = acpi_get_handle(handle, "_OSC", &tmp);
-       if (ACPI_FAILURE(status))
-               return status;
+       if (!mask)
+               return AE_BAD_PARAMETER;
 
-       control_req = (flags & OSC_PCI_CONTROL_MASKS);
-       if (!control_req)
+       ctrl = *mask & OSC_PCI_CONTROL_MASKS;
+       if ((ctrl & req) != req)
                return AE_TYPE;
 
        root = acpi_pci_find_root(handle);
        if (!root)
                return AE_NOT_EXIST;
 
+       status = acpi_get_handle(handle, "_OSC", &tmp);
+       if (ACPI_FAILURE(status))
+               return status;
+
        mutex_lock(&osc_lock);
+
+       *mask = ctrl | root->osc_control_set;
        /* No need to evaluate _OSC if the control was already granted. */
-       if ((root->osc_control_set & control_req) == control_req)
+       if ((root->osc_control_set & ctrl) == ctrl)
                goto out;
 
-       /* Need to query controls first before requesting them */
-       if (!root->osc_queried) {
-               status = acpi_pci_query_osc(root, root->osc_support_set);
+       /* Need to check the available controls bits before requesting them. */
+       while (*mask) {
+               status = acpi_pci_query_osc(root, root->osc_support_set, mask);
                if (ACPI_FAILURE(status))
                        goto out;
+               if (ctrl == *mask)
+                       break;
+               ctrl = *mask;
        }
-       if ((root->osc_control_qry & control_req) != control_req) {
-               printk(KERN_DEBUG
-                      "Firmware did not grant requested _OSC control\n");
+
+       if ((ctrl & req) != req) {
                status = AE_SUPPORT;
                goto out;
        }
 
        capbuf[OSC_QUERY_TYPE] = 0;
        capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
-       capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req;
-       status = acpi_pci_run_osc(handle, capbuf, &result);
+       capbuf[OSC_CONTROL_TYPE] = ctrl;
+       status = acpi_pci_run_osc(handle, capbuf, mask);
        if (ACPI_SUCCESS(status))
-               root->osc_control_set = result;
+               root->osc_control_set = *mask;
 out:
        mutex_unlock(&osc_lock);
        return status;
@@ -544,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
        if (flags != base_flags)
                acpi_pci_osc_support(root, flags);
 
-       status = acpi_pci_osc_control_set(root->device->handle,
-                                         OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
-               pcie_no_aspm();
-       }
-
        pci_acpi_add_bus_pm_notifier(device, root->bus);
        if (device->wakeup.flags.run_wake)
                device_set_run_wake(root->bus->bridge, true);
index e9699aaed1092874b0f275d2ca86a8142850db1c..bec561c14bebee3a77817bdce8fa09b939f85ac0 100644 (file)
@@ -28,12 +28,6 @@ static int set_no_mwait(const struct dmi_system_id *id)
 }
 
 static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
-       {
-       set_no_mwait, "IFL91 board", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-       DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
-       DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
        {
        set_no_mwait, "Extensa 5220", {
        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -352,4 +346,5 @@ void __init acpi_early_processor_set_pdc(void)
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
                            early_init_pdc, NULL, NULL, NULL);
+       acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
 }
index 15602189238942cc9db03b9d9f25c18823128ea0..347eb21b235302d44d0c5e2d768ce3a8870142f2 100644 (file)
@@ -850,7 +850,7 @@ static int __init acpi_processor_init(void)
                printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
                        acpi_idle_driver.name);
        } else {
-               printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s",
+               printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
                        cpuidle_get_driver()->name);
        }
 
index ba1bd263d903094692c3683c9557e8b919d1d985..3a73a93596e88a29c1e66fabec91dd2d0db96f6c 100644 (file)
@@ -447,8 +447,8 @@ int acpi_processor_notify_smm(struct module *calling_module)
        if (!try_module_get(calling_module))
                return -EINVAL;
 
-       /* is_done is set to negative if an error occured,
-        * and to postitive if _no_ error occured, but SMM
+       /* is_done is set to negative if an error occurred,
+        * and to postitive if _no_ error occurred, but SMM
         * was already notified. This avoids double notification
         * which might lead to unexpected results...
         */
index cf82989ae7568c3c54ded69d16829a2851119d80..4754ff6e70e6daa25b13df6f115745eb7bfb7e55 100644 (file)
@@ -363,6 +363,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
        return 0;
 }
 
+static int __init init_nvs_nosave(const struct dmi_system_id *d)
+{
+       acpi_nvs_nosave();
+       return 0;
+}
+
 static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
        {
        .callback = init_old_suspend_ordering,
@@ -397,6 +403,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-SR11M",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Everex StepNote Series",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index 68e2e4582fa2f18968058c8125704a23f151cb62..f8588f81048ac989d6af1d727693a234f54bc27b 100644 (file)
@@ -100,7 +100,7 @@ static const struct acpi_dlevel acpi_debug_levels[] = {
        ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
 };
 
-static int param_get_debug_layer(char *buffer, struct kernel_param *kp)
+static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
 {
        int result = 0;
        int i;
@@ -128,7 +128,7 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp)
        return result;
 }
 
-static int param_get_debug_level(char *buffer, struct kernel_param *kp)
+static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
 {
        int result = 0;
        int i;
@@ -149,10 +149,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp)
        return result;
 }
 
-module_param_call(debug_layer, param_set_uint, param_get_debug_layer,
-                 &acpi_dbg_layer, 0644);
-module_param_call(debug_level, param_set_uint, param_get_debug_level,
-                 &acpi_dbg_level, 0644);
+static struct kernel_param_ops param_ops_debug_layer = {
+       .set = param_set_uint,
+       .get = param_get_debug_layer,
+};
+
+static struct kernel_param_ops param_ops_debug_level = {
+       .set = param_set_uint,
+       .get = param_get_debug_level,
+};
+
+module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644);
+module_param_cb(debug_level, &param_ops_debug_level, &acpi_dbg_level, 0644);
 
 static char trace_method_name[6];
 module_param_string(trace_method_name, trace_method_name, 6, 0644);
index c5fef01b3c9591701fb03ae86290a6b5b643c32a..b836761265988590cea46dbcffc39d30ea3c5578 100644 (file)
@@ -59,8 +59,8 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
                                  "support\n"));
                *cap |= ACPI_VIDEO_BACKLIGHT;
                if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
-                       printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness "
-                                       "control misses _BQC function\n");
+                       printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
+                               "cannot determine initial brightness\n");
                /* We have backlight support, no need to scan further */
                return AE_CTRL_TERMINATE;
        }
index d31590e7011bf895092535d15af5df6cc2e62df5..2737b97522052e7a653eb9c7622132a07a6bcded 100644 (file)
@@ -298,7 +298,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
 
                amba_put_disable_pclk(dev);
 
-               if (cid == 0xb105f00d)
+               if (cid == AMBA_CID)
                        dev->periphid = pid;
 
                if (!dev->periphid)
index 65e3e2708371962a3878061a8b71666230e80c2c..11ec911016c6ab3e81cefe7e202c4cc4c95762f0 100644 (file)
@@ -828,6 +828,7 @@ config PATA_SAMSUNG_CF
 config PATA_WINBOND_VLB
        tristate "Winbond W83759A VLB PATA support (Experimental)"
        depends on ISA && EXPERIMENTAL
+       select PATA_LEGACY
        help
          Support for the Winbond W83759A controller on Vesa Local Bus
          systems.
index 158eaa961b1e6f0d247f78691b8f4b309a9d6622..c501af5b12b959209bde413d9b8bbe35f7be5068 100644 (file)
@@ -89,7 +89,6 @@ obj-$(CONFIG_PATA_QDI)                += pata_qdi.o
 obj-$(CONFIG_PATA_RB532)       += pata_rb532_cf.o
 obj-$(CONFIG_PATA_RZ1000)      += pata_rz1000.o
 obj-$(CONFIG_PATA_SAMSUNG_CF)  += pata_samsung_cf.o
-obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
 
 obj-$(CONFIG_PATA_PXA)         += pata_pxa.o
 
@@ -100,7 +99,7 @@ obj-$(CONFIG_ATA_GENERIC)    += ata_generic.o
 # Should be last libata driver
 obj-$(CONFIG_PATA_LEGACY)      += pata_legacy.o
 
-libata-objs    := libata-core.o libata-scsi.o libata-eh.o
+libata-y       := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
 libata-$(CONFIG_ATA_SFF)       += libata-sff.o
 libata-$(CONFIG_SATA_PMP)      += libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)      += libata-acpi.o
index fe75d8befc3a27aaa5d6c8048cbaa498416c7322..328826381a2dc38def47aba259e78da11b24b5b0 100644 (file)
@@ -60,6 +60,7 @@ enum board_ids {
        board_ahci,
        board_ahci_ign_iferr,
        board_ahci_nosntf,
+       board_ahci_yes_fbs,
 
        /* board IDs for specific chipsets in alphabetical order */
        board_ahci_mcp65,
@@ -89,6 +90,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
 
+static struct scsi_host_template ahci_sht = {
+       AHCI_SHT("ahci"),
+};
+
 static struct ata_port_operations ahci_vt8251_ops = {
        .inherits               = &ahci_ops,
        .hardreset              = ahci_vt8251_hardreset,
@@ -132,6 +137,14 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_yes_fbs] =
+       {
+               AHCI_HFLAGS     (AHCI_HFLAG_YES_FBS),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
        /* by chipsets */
        [board_ahci_mcp65] =
        {
@@ -244,6 +257,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
        { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
        { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
+       { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
+       { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
+       { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -362,6 +378,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* Marvell */
        { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },        /* 6145 */
        { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },        /* 6121 */
+       { PCI_DEVICE(0x1b4b, 0x9123),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
 
        /* Promise */
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
@@ -1190,9 +1208,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                ata_port_pbar_desc(ap, AHCI_PCI_BAR,
                                   0x100 + ap->port_no * 0x80, "port");
 
-               /* set initial link pm policy */
-               ap->pm_policy = NOT_AVAILABLE;
-
                /* set enclosure management message type */
                if (ap->flags & ATA_FLAG_EM)
                        ap->em_message_type = hpriv->em_msg_type;
index 7113c5724471c7df3a37bae273bef3c73fb45d1b..329cbbb91284ad4dd3b7e4f486ea82f2737ae1b3 100644 (file)
@@ -72,6 +72,7 @@ enum {
        AHCI_CMD_RESET          = (1 << 8),
        AHCI_CMD_CLR_BUSY       = (1 << 10),
 
+       RX_FIS_PIO_SETUP        = 0x20, /* offset of PIO Setup FIS data */
        RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
        RX_FIS_SDB              = 0x58, /* offset of SDB FIS data */
        RX_FIS_UNK              = 0x60, /* offset of Unknown FIS data */
@@ -201,7 +202,6 @@ enum {
        AHCI_HFLAG_MV_PATA              = (1 << 4), /* PATA port */
        AHCI_HFLAG_NO_MSI               = (1 << 5), /* no PCI MSI */
        AHCI_HFLAG_NO_PMP               = (1 << 6), /* no PMP */
-       AHCI_HFLAG_NO_HOTPLUG           = (1 << 7), /* ignore PxSERR.DIAG.N */
        AHCI_HFLAG_SECT255              = (1 << 8), /* max 255 sectors */
        AHCI_HFLAG_YES_NCQ              = (1 << 9), /* force NCQ cap on */
        AHCI_HFLAG_NO_SUSPEND           = (1 << 10), /* don't suspend */
@@ -209,13 +209,14 @@ enum {
                                                        link offline */
        AHCI_HFLAG_NO_SNTF              = (1 << 12), /* no sntf */
        AHCI_HFLAG_NO_FPDMA_AA          = (1 << 13), /* no FPDMA AA */
+       AHCI_HFLAG_YES_FBS              = (1 << 14), /* force FBS cap on */
 
        /* ap->flags bits */
 
        AHCI_FLAG_COMMON                = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                          ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                          ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
-                                         ATA_FLAG_IPM,
+                                         ATA_FLAG_LPM,
 
        ICH_MAP                         = 0x90, /* ICH MAP register */
 
@@ -297,7 +298,17 @@ struct ahci_host_priv {
 
 extern int ahci_ignore_sss;
 
-extern struct scsi_host_template ahci_sht;
+extern struct device_attribute *ahci_shost_attrs[];
+extern struct device_attribute *ahci_sdev_attrs[];
+
+#define AHCI_SHT(drv_name)                                             \
+       ATA_NCQ_SHT(drv_name),                                          \
+       .can_queue              = AHCI_MAX_CMDS - 1,                    \
+       .sg_tablesize           = AHCI_MAX_SG,                          \
+       .dma_boundary           = AHCI_DMA_BOUNDARY,                    \
+       .shost_attrs            = ahci_shost_attrs,                     \
+       .sdev_attrs             = ahci_sdev_attrs
+
 extern struct ata_port_operations ahci_ops;
 
 void ahci_save_initial_config(struct device *dev,
index 4e97f33cca4406212b9769c6c13fc11afc02bc4a..6fef1fa75c549ea3a442f617693882313c826844 100644 (file)
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
+static struct scsi_host_template ahci_platform_sht = {
+       AHCI_SHT("ahci_platform"),
+};
+
 static int __init ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -125,9 +129,6 @@ static int __init ahci_probe(struct platform_device *pdev)
                ata_port_desc(ap, "mmio %pR", mem);
                ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
 
-               /* set initial link pm policy */
-               ap->pm_policy = NOT_AVAILABLE;
-
                /* set enclosure management message type */
                if (ap->flags & ATA_FLAG_EM)
                        ap->em_message_type = hpriv->em_msg_type;
@@ -145,7 +146,7 @@ static int __init ahci_probe(struct platform_device *pdev)
        ahci_print_info(host, "platform");
 
        rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-                              &ahci_sht);
+                              &ahci_platform_sht);
        if (rc)
                goto err0;
 
index cc5f7726bde704bb4931bfce4d58666e41555db5..6981f7680a006493c66ba66c5e90fff9b05985b3 100644 (file)
@@ -35,6 +35,7 @@
 enum {
        ATA_GEN_CLASS_MATCH             = (1 << 0),
        ATA_GEN_FORCE_DMA               = (1 << 1),
+       ATA_GEN_INTEL_IDER              = (1 << 2),
 };
 
 /**
@@ -108,6 +109,49 @@ static struct ata_port_operations generic_port_ops = {
 
 static int all_generic_ide;            /* Set to claim all devices */
 
+/**
+ *     is_intel_ider           -       identify intel IDE-R devices
+ *     @dev: PCI device
+ *
+ *     Distinguish Intel IDE-R controller devices from other Intel IDE
+ *     devices. IDE-R devices have no timing registers and are in
+ *     most respects virtual. They should be driven by the ata_generic
+ *     driver.
+ *
+ *     IDE-R devices have PCI offset 0xF8.L as zero, later Intel ATA has
+ *     it non zero. All Intel ATA has 0x40 writable (timing), but it is
+ *     not writable on IDE-R devices (this is guaranteed).
+ */
+
+static int is_intel_ider(struct pci_dev *dev)
+{
+       /* For Intel IDE the value at 0xF8 is only zero on IDE-R
+          interfaces */
+       u32 r;
+       u16 t;
+
+       /* Check the manufacturing ID, it will be zero for IDE-R */
+       pci_read_config_dword(dev, 0xF8, &r);
+       /* Not IDE-R: punt so that ata_(old)piix gets it */
+       if (r != 0)
+               return 0;
+       /* 0xF8 will also be zero on some early Intel IDE devices
+          but they will have a sane timing register */
+       pci_read_config_word(dev, 0x40, &t);
+       if (t != 0)
+               return 0;
+       /* Finally check if the timing register is writable so that
+          we eliminate any early devices hot-docked in a docking
+          station */
+       pci_write_config_word(dev, 0x40, 1);
+       pci_read_config_word(dev, 0x40, &t);
+       if (t) {
+               pci_write_config_word(dev, 0x40, 0);
+               return 0;
+       }
+       return 1;
+}
+
 /**
  *     ata_generic_init                -       attach generic IDE
  *     @dev: PCI device found
@@ -134,6 +178,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
        if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
                return -ENODEV;
 
+       if (id->driver_data & ATA_GEN_INTEL_IDER)
+               if (!is_intel_ider(dev))
+                       return -ENODEV;
+
        /* Devices that need care */
        if (dev->vendor == PCI_VENDOR_ID_UMC &&
            dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
@@ -186,7 +234,11 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3),  },
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5),  },
-#endif 
+#endif
+       /* Intel, IDE class device */
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 
+         .driver_data = ATA_GEN_INTEL_IDER },
        /* Must come last. If you add entries adjust this table appropriately */
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
          .driver_data = ATA_GEN_CLASS_MATCH },
index 3971bc0a4838235ea26f4bff0b97ec7dd3335b69..6cb14ca8ee853f44683062c9b5b1274afa50e336 100644 (file)
@@ -158,7 +158,6 @@ struct piix_map_db {
 struct piix_host_priv {
        const int *map;
        u32 saved_iocfg;
-       spinlock_t sidpr_lock;  /* FIXME: remove once locking in EH is fixed */
        void __iomem *sidpr;
 };
 
@@ -175,6 +174,8 @@ static int piix_sidpr_scr_read(struct ata_link *link,
                               unsigned int reg, u32 *val);
 static int piix_sidpr_scr_write(struct ata_link *link,
                                unsigned int reg, u32 val);
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                             unsigned hints);
 static bool piix_irq_check(struct ata_port *ap);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
@@ -209,6 +210,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
        /* Intel ICH3 (E7500/1) UDMA 100 */
        { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+       /* Intel ICH4-L */
+       { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
        /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */
        { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
        { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
@@ -302,6 +305,10 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (CPT) */
        { 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (PBG) */
+       { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (PBG) */
+       { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        { }     /* terminate list */
 };
 
@@ -344,11 +351,22 @@ static struct ata_port_operations ich_pata_ops = {
        .set_dmamode            = ich_set_dmamode,
 };
 
+static struct device_attribute *piix_sidpr_shost_attrs[] = {
+       &dev_attr_link_power_management_policy,
+       NULL
+};
+
+static struct scsi_host_template piix_sidpr_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+       .shost_attrs            = piix_sidpr_shost_attrs,
+};
+
 static struct ata_port_operations piix_sidpr_sata_ops = {
        .inherits               = &piix_sata_ops,
        .hardreset              = sata_std_hardreset,
        .scr_read               = piix_sidpr_scr_read,
        .scr_write              = piix_sidpr_scr_write,
+       .set_lpm                = piix_sidpr_set_lpm,
 };
 
 static const struct piix_map_db ich5_map_db = {
@@ -952,15 +970,12 @@ static int piix_sidpr_scr_read(struct ata_link *link,
                               unsigned int reg, u32 *val)
 {
        struct piix_host_priv *hpriv = link->ap->host->private_data;
-       unsigned long flags;
 
        if (reg >= ARRAY_SIZE(piix_sidx_map))
                return -EINVAL;
 
-       spin_lock_irqsave(&hpriv->sidpr_lock, flags);
        piix_sidpr_sel(link, reg);
        *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
-       spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
        return 0;
 }
 
@@ -968,18 +983,21 @@ static int piix_sidpr_scr_write(struct ata_link *link,
                                unsigned int reg, u32 val)
 {
        struct piix_host_priv *hpriv = link->ap->host->private_data;
-       unsigned long flags;
 
        if (reg >= ARRAY_SIZE(piix_sidx_map))
                return -EINVAL;
 
-       spin_lock_irqsave(&hpriv->sidpr_lock, flags);
        piix_sidpr_sel(link, reg);
        iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
-       spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
        return 0;
 }
 
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                             unsigned hints)
+{
+       return sata_link_scr_lpm(link, policy, false);
+}
+
 static bool piix_irq_check(struct ata_port *ap)
 {
        if (unlikely(!ap->ioaddr.bmdma_addr))
@@ -1539,6 +1557,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
        struct device *dev = &pdev->dev;
        struct ata_port_info port_info[2];
        const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
+       struct scsi_host_template *sht = &piix_sht;
        unsigned long port_flags;
        struct ata_host *host;
        struct piix_host_priv *hpriv;
@@ -1573,7 +1592,6 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
-       spin_lock_init(&hpriv->sidpr_lock);
 
        /* Save IOCFG, this will be used for cable detection, quirk
         * detection and restoration on detach.  This is necessary
@@ -1608,6 +1626,8 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
                rc = piix_init_sidpr(host);
                if (rc)
                        return rc;
+               if (host->ports[0]->ops == &piix_sidpr_sata_ops)
+                       sht = &piix_sidpr_sht;
        }
 
        /* apply IOCFG bit18 quirk */
@@ -1634,7 +1654,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
        host->flags |= ATA_HOST_PARALLEL_SCAN;
 
        pci_set_master(pdev);
-       return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht);
+       return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
 }
 
 static void piix_remove_one(struct pci_dev *pdev)
index 81e772a94d59857187fda27dbfe7702469fb590f..ebc08d65b3dd04c9af94da0d7146d3a165ce9803 100644 (file)
@@ -56,9 +56,8 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)
 module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
 MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
 
-static int ahci_enable_alpm(struct ata_port *ap,
-               enum link_pm policy);
-static void ahci_disable_alpm(struct ata_port *ap);
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                       unsigned hints);
 static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
 static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
                              size_t size);
@@ -121,7 +120,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
                   ahci_read_em_buffer, ahci_store_em_buffer);
 
-static struct device_attribute *ahci_shost_attrs[] = {
+struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_link_power_management_policy,
        &dev_attr_em_message_type,
        &dev_attr_em_message,
@@ -132,22 +131,14 @@ static struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_em_buffer,
        NULL
 };
+EXPORT_SYMBOL_GPL(ahci_shost_attrs);
 
-static struct device_attribute *ahci_sdev_attrs[] = {
+struct device_attribute *ahci_sdev_attrs[] = {
        &dev_attr_sw_activity,
        &dev_attr_unload_heads,
        NULL
 };
-
-struct scsi_host_template ahci_sht = {
-       ATA_NCQ_SHT("ahci"),
-       .can_queue              = AHCI_MAX_CMDS - 1,
-       .sg_tablesize           = AHCI_MAX_SG,
-       .dma_boundary           = AHCI_DMA_BOUNDARY,
-       .shost_attrs            = ahci_shost_attrs,
-       .sdev_attrs             = ahci_sdev_attrs,
-};
-EXPORT_SYMBOL_GPL(ahci_sht);
+EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
 
 struct ata_port_operations ahci_ops = {
        .inherits               = &sata_pmp_port_ops,
@@ -172,8 +163,7 @@ struct ata_port_operations ahci_ops = {
        .pmp_attach             = ahci_pmp_attach,
        .pmp_detach             = ahci_pmp_detach,
 
-       .enable_pm              = ahci_enable_alpm,
-       .disable_pm             = ahci_disable_alpm,
+       .set_lpm                = ahci_set_lpm,
        .em_show                = ahci_led_show,
        .em_store               = ahci_led_store,
        .sw_activity_show       = ahci_activity_show,
@@ -430,6 +420,12 @@ void ahci_save_initial_config(struct device *dev,
                cap &= ~HOST_CAP_SNTF;
        }
 
+       if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
+               dev_printk(KERN_INFO, dev,
+                          "controller can do FBS, turning on CAP_FBS\n");
+               cap |= HOST_CAP_FBS;
+       }
+
        if (force_port_map && port_map != force_port_map) {
                dev_printk(KERN_INFO, dev, "forcing port_map 0x%x -> 0x%x\n",
                           port_map, force_port_map);
@@ -571,7 +567,7 @@ int ahci_stop_engine(struct ata_port *ap)
        writel(tmp, port_mmio + PORT_CMD);
 
        /* wait for engine to stop. This could be as long as 500 msec */
-       tmp = ata_wait_register(port_mmio + PORT_CMD,
+       tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
                                PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
        if (tmp & PORT_CMD_LIST_ON)
                return -EIO;
@@ -618,7 +614,7 @@ static int ahci_stop_fis_rx(struct ata_port *ap)
        writel(tmp, port_mmio + PORT_CMD);
 
        /* wait for completion, spec says 500ms, give it 1000 */
-       tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
+       tmp = ata_wait_register(ap, port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
                                PORT_CMD_FIS_ON, 10, 1000);
        if (tmp & PORT_CMD_FIS_ON)
                return -EBUSY;
@@ -644,127 +640,56 @@ static void ahci_power_up(struct ata_port *ap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
-static void ahci_disable_alpm(struct ata_port *ap)
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                       unsigned int hints)
 {
+       struct ata_port *ap = link->ap;
        struct ahci_host_priv *hpriv = ap->host->private_data;
-       void __iomem *port_mmio = ahci_port_base(ap);
-       u32 cmd;
        struct ahci_port_priv *pp = ap->private_data;
-
-       /* IPM bits should be disabled by libata-core */
-       /* get the existing command bits */
-       cmd = readl(port_mmio + PORT_CMD);
-
-       /* disable ALPM and ASP */
-       cmd &= ~PORT_CMD_ASP;
-       cmd &= ~PORT_CMD_ALPE;
-
-       /* force the interface back to active */
-       cmd |= PORT_CMD_ICC_ACTIVE;
-
-       /* write out new cmd value */
-       writel(cmd, port_mmio + PORT_CMD);
-       cmd = readl(port_mmio + PORT_CMD);
-
-       /* wait 10ms to be sure we've come out of any low power state */
-       msleep(10);
-
-       /* clear out any PhyRdy stuff from interrupt status */
-       writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
-
-       /* go ahead and clean out PhyRdy Change from Serror too */
-       ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
-
-       /*
-        * Clear flag to indicate that we should ignore all PhyRdy
-        * state changes
-        */
-       hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
-
-       /*
-        * Enable interrupts on Phy Ready.
-        */
-       pp->intr_mask |= PORT_IRQ_PHYRDY;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-
-       /*
-        * don't change the link pm policy - we can be called
-        * just to turn of link pm temporarily
-        */
-}
-
-static int ahci_enable_alpm(struct ata_port *ap,
-       enum link_pm policy)
-{
-       struct ahci_host_priv *hpriv = ap->host->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
-       u32 cmd;
-       struct ahci_port_priv *pp = ap->private_data;
-       u32 asp;
-
-       /* Make sure the host is capable of link power management */
-       if (!(hpriv->cap & HOST_CAP_ALPM))
-               return -EINVAL;
 
-       switch (policy) {
-       case MAX_PERFORMANCE:
-       case NOT_AVAILABLE:
+       if (policy != ATA_LPM_MAX_POWER) {
                /*
-                * if we came here with NOT_AVAILABLE,
-                * it just means this is the first time we
-                * have tried to enable - default to max performance,
-                * and let the user go to lower power modes on request.
+                * Disable interrupts on Phy Ready. This keeps us from
+                * getting woken up due to spurious phy ready
+                * interrupts.
                 */
-               ahci_disable_alpm(ap);
-               return 0;
-       case MIN_POWER:
-               /* configure HBA to enter SLUMBER */
-               asp = PORT_CMD_ASP;
-               break;
-       case MEDIUM_POWER:
-               /* configure HBA to enter PARTIAL */
-               asp = 0;
-               break;
-       default:
-               return -EINVAL;
+               pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+               sata_link_scr_lpm(link, policy, false);
        }
 
-       /*
-        * Disable interrupts on Phy Ready. This keeps us from
-        * getting woken up due to spurious phy ready interrupts
-        * TBD - Hot plug should be done via polling now, is
-        * that even supported?
-        */
-       pp->intr_mask &= ~PORT_IRQ_PHYRDY;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+       if (hpriv->cap & HOST_CAP_ALPM) {
+               u32 cmd = readl(port_mmio + PORT_CMD);
 
-       /*
-        * Set a flag to indicate that we should ignore all PhyRdy
-        * state changes since these can happen now whenever we
-        * change link state
-        */
-       hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
+               if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
+                       cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
+                       cmd |= PORT_CMD_ICC_ACTIVE;
 
-       /* get the existing command bits */
-       cmd = readl(port_mmio + PORT_CMD);
+                       writel(cmd, port_mmio + PORT_CMD);
+                       readl(port_mmio + PORT_CMD);
 
-       /*
-        * Set ASP based on Policy
-        */
-       cmd |= asp;
+                       /* wait 10ms to be sure we've come out of LPM state */
+                       ata_msleep(ap, 10);
+               } else {
+                       cmd |= PORT_CMD_ALPE;
+                       if (policy == ATA_LPM_MIN_POWER)
+                               cmd |= PORT_CMD_ASP;
 
-       /*
-        * Setting this bit will instruct the HBA to aggressively
-        * enter a lower power link state when it's appropriate and
-        * based on the value set above for ASP
-        */
-       cmd |= PORT_CMD_ALPE;
+                       /* write out new cmd value */
+                       writel(cmd, port_mmio + PORT_CMD);
+               }
+       }
 
-       /* write out new cmd value */
-       writel(cmd, port_mmio + PORT_CMD);
-       cmd = readl(port_mmio + PORT_CMD);
+       if (policy == ATA_LPM_MAX_POWER) {
+               sata_link_scr_lpm(link, policy, false);
+
+               /* turn PHYRDY IRQ back on */
+               pp->intr_mask |= PORT_IRQ_PHYRDY;
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+       }
 
-       /* IPM bits should be set by libata-core */
        return 0;
 }
 
@@ -815,7 +740,7 @@ static void ahci_start_port(struct ata_port *ap)
                                                               emp->led_state,
                                                               4);
                                if (rc == -EBUSY)
-                                       msleep(1);
+                                       ata_msleep(ap, 1);
                                else
                                        break;
                        }
@@ -874,7 +799,7 @@ int ahci_reset_controller(struct ata_host *host)
                 * reset must complete within 1 second, or
                 * the hardware should be considered fried.
                 */
-               tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
+               tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
                                        HOST_RESET, 10, 1000);
 
                if (tmp & HOST_RESET) {
@@ -1254,7 +1179,7 @@ int ahci_kick_engine(struct ata_port *ap)
        writel(tmp, port_mmio + PORT_CMD);
 
        rc = 0;
-       tmp = ata_wait_register(port_mmio + PORT_CMD,
+       tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
                                PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
        if (tmp & PORT_CMD_CLO)
                rc = -EIO;
@@ -1284,8 +1209,8 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
        writel(1, port_mmio + PORT_CMD_ISSUE);
 
        if (timeout_msec) {
-               tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
-                                       1, timeout_msec);
+               tmp = ata_wait_register(ap, port_mmio + PORT_CMD_ISSUE,
+                                       0x1, 0x1, 1, timeout_msec);
                if (tmp & 0x1) {
                        ahci_kick_engine(ap);
                        return -EBUSY;
@@ -1320,7 +1245,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        /* issue the first D2H Register FIS */
        msecs = 0;
        now = jiffies;
-       if (time_after(now, deadline))
+       if (time_after(deadline, now))
                msecs = jiffies_to_msecs(deadline - now);
 
        tf.ctl |= ATA_SRST;
@@ -1332,7 +1257,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        }
 
        /* spec says at least 5us, but be generous and sleep for 1ms */
-       msleep(1);
+       ata_msleep(ap, 1);
 
        /* issue the second D2H Register FIS */
        tf.ctl &= ~ATA_SRST;
@@ -1662,15 +1587,10 @@ static void ahci_port_intr(struct ata_port *ap)
        if (unlikely(resetting))
                status &= ~PORT_IRQ_BAD_PMP;
 
-       /* If we are getting PhyRdy, this is
-        * just a power state change, we should
-        * clear out this, plus the PhyRdy/Comm
-        * Wake bits from Serror
-        */
-       if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
-               (status & PORT_IRQ_PHYRDY)) {
+       /* if LPM is enabled, PHYRDY doesn't mean anything */
+       if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
                status &= ~PORT_IRQ_PHYRDY;
-               ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
+               ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
        }
 
        if (unlikely(status & PORT_IRQ_ERROR)) {
@@ -1832,12 +1752,24 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
 {
        struct ahci_port_priv *pp = qc->ap->private_data;
-       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+       u8 *rx_fis = pp->rx_fis;
 
        if (pp->fbs_enabled)
-               d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+               rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+
+       /*
+        * After a successful execution of an ATA PIO data-in command,
+        * the device doesn't send D2H Reg FIS to update the TF and
+        * the host should take TF and E_Status from the preceding PIO
+        * Setup FIS.
+        */
+       if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
+           !(qc->flags & ATA_QCFLAG_FAILED)) {
+               ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
+               qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15];
+       } else
+               ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
 
-       ata_tf_from_fis(d2h_fis, &qc->result_tf);
        return true;
 }
 
@@ -2036,9 +1968,15 @@ static int ahci_port_start(struct ata_port *ap)
                u32 cmd = readl(port_mmio + PORT_CMD);
                if (cmd & PORT_CMD_FBSCP)
                        pp->fbs_supported = true;
-               else
+               else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
+                       dev_printk(KERN_INFO, dev,
+                                  "port %d can do FBS, forcing FBSCP\n",
+                                  ap->port_no);
+                       pp->fbs_supported = true;
+               } else
                        dev_printk(KERN_WARNING, dev,
-                                  "The port is not capable of FBS\n");
+                                  "port %d is not capable of FBS\n",
+                                  ap->port_no);
        }
 
        if (pp->fbs_supported) {
index 7ef7c4f216fa58567e161c82118155411d070074..7f77c67d267ca454f63b5501ab1bb82d5fe9f16d 100644 (file)
@@ -68,7 +68,7 @@
 #include <linux/ratelimit.h>
 
 #include "libata.h"
-
+#include "libata-transport.h"
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
@@ -91,8 +91,6 @@ const struct ata_port_operations sata_port_ops = {
 static unsigned int ata_dev_init_params(struct ata_device *dev,
                                        u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
-static unsigned int ata_dev_set_feature(struct ata_device *dev,
-                                       u8 enable, u8 feature);
 static void ata_dev_xfermask(struct ata_device *dev);
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
@@ -1017,7 +1015,7 @@ const char *ata_mode_string(unsigned long xfer_mask)
        return "<n/a>";
 }
 
-static const char *sata_spd_string(unsigned int spd)
+const char *sata_spd_string(unsigned int spd)
 {
        static const char * const spd_str[] = {
                "1.5 Gbps",
@@ -1030,182 +1028,6 @@ static const char *sata_spd_string(unsigned int spd)
        return spd_str[spd - 1];
 }
 
-static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
-{
-       struct ata_link *link = dev->link;
-       struct ata_port *ap = link->ap;
-       u32 scontrol;
-       unsigned int err_mask;
-       int rc;
-
-       /*
-        * disallow DIPM for drivers which haven't set
-        * ATA_FLAG_IPM.  This is because when DIPM is enabled,
-        * phy ready will be set in the interrupt status on
-        * state changes, which will cause some drivers to
-        * think there are errors - additionally drivers will
-        * need to disable hot plug.
-        */
-       if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) {
-               ap->pm_policy = NOT_AVAILABLE;
-               return -EINVAL;
-       }
-
-       /*
-        * For DIPM, we will only enable it for the
-        * min_power setting.
-        *
-        * Why?  Because Disks are too stupid to know that
-        * If the host rejects a request to go to SLUMBER
-        * they should retry at PARTIAL, and instead it
-        * just would give up.  So, for medium_power to
-        * work at all, we need to only allow HIPM.
-        */
-       rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
-       if (rc)
-               return rc;
-
-       switch (policy) {
-       case MIN_POWER:
-               /* no restrictions on IPM transitions */
-               scontrol &= ~(0x3 << 8);
-               rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-               if (rc)
-                       return rc;
-
-               /* enable DIPM */
-               if (dev->flags & ATA_DFLAG_DIPM)
-                       err_mask = ata_dev_set_feature(dev,
-                                       SETFEATURES_SATA_ENABLE, SATA_DIPM);
-               break;
-       case MEDIUM_POWER:
-               /* allow IPM to PARTIAL */
-               scontrol &= ~(0x1 << 8);
-               scontrol |= (0x2 << 8);
-               rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-               if (rc)
-                       return rc;
-
-               /*
-                * we don't have to disable DIPM since IPM flags
-                * disallow transitions to SLUMBER, which effectively
-                * disable DIPM if it does not support PARTIAL
-                */
-               break;
-       case NOT_AVAILABLE:
-       case MAX_PERFORMANCE:
-               /* disable all IPM transitions */
-               scontrol |= (0x3 << 8);
-               rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-               if (rc)
-                       return rc;
-
-               /*
-                * we don't have to disable DIPM since IPM flags
-                * disallow all transitions which effectively
-                * disable DIPM anyway.
-                */
-               break;
-       }
-
-       /* FIXME: handle SET FEATURES failure */
-       (void) err_mask;
-
-       return 0;
-}
-
-/**
- *     ata_dev_enable_pm - enable SATA interface power management
- *     @dev:  device to enable power management
- *     @policy: the link power management policy
- *
- *     Enable SATA Interface power management.  This will enable
- *     Device Interface Power Management (DIPM) for min_power
- *     policy, and then call driver specific callbacks for
- *     enabling Host Initiated Power management.
- *
- *     Locking: Caller.
- *     Returns: -EINVAL if IPM is not supported, 0 otherwise.
- */
-void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
-{
-       int rc = 0;
-       struct ata_port *ap = dev->link->ap;
-
-       /* set HIPM first, then DIPM */
-       if (ap->ops->enable_pm)
-               rc = ap->ops->enable_pm(ap, policy);
-       if (rc)
-               goto enable_pm_out;
-       rc = ata_dev_set_dipm(dev, policy);
-
-enable_pm_out:
-       if (rc)
-               ap->pm_policy = MAX_PERFORMANCE;
-       else
-               ap->pm_policy = policy;
-       return /* rc */;        /* hopefully we can use 'rc' eventually */
-}
-
-#ifdef CONFIG_PM
-/**
- *     ata_dev_disable_pm - disable SATA interface power management
- *     @dev: device to disable power management
- *
- *     Disable SATA Interface power management.  This will disable
- *     Device Interface Power Management (DIPM) without changing
- *     policy,  call driver specific callbacks for disabling Host
- *     Initiated Power management.
- *
- *     Locking: Caller.
- *     Returns: void
- */
-static void ata_dev_disable_pm(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->link->ap;
-
-       ata_dev_set_dipm(dev, MAX_PERFORMANCE);
-       if (ap->ops->disable_pm)
-               ap->ops->disable_pm(ap);
-}
-#endif /* CONFIG_PM */
-
-void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
-{
-       ap->pm_policy = policy;
-       ap->link.eh_info.action |= ATA_EH_LPM;
-       ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
-       ata_port_schedule_eh(ap);
-}
-
-#ifdef CONFIG_PM
-static void ata_lpm_enable(struct ata_host *host)
-{
-       struct ata_link *link;
-       struct ata_port *ap;
-       struct ata_device *dev;
-       int i;
-
-       for (i = 0; i < host->n_ports; i++) {
-               ap = host->ports[i];
-               ata_for_each_link(link, ap, EDGE) {
-                       ata_for_each_dev(dev, link, ALL)
-                               ata_dev_disable_pm(dev);
-               }
-       }
-}
-
-static void ata_lpm_disable(struct ata_host *host)
-{
-       int i;
-
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap = host->ports[i];
-               ata_lpm_schedule(ap, ap->pm_policy);
-       }
-}
-#endif /* CONFIG_PM */
-
 /**
  *     ata_dev_classify - determine device type based on ATA-spec signature
  *     @tf: ATA taskfile register set for device to be identified
@@ -1806,8 +1628,14 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
                }
        }
 
+       if (ap->ops->error_handler)
+               ata_eh_release(ap);
+
        rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout));
 
+       if (ap->ops->error_handler)
+               ata_eh_acquire(ap);
+
        ata_sff_flush_pio_task(ap);
 
        if (!rc) {
@@ -2564,13 +2392,6 @@ int ata_dev_configure(struct ata_device *dev)
        if (dev->flags & ATA_DFLAG_LBA48)
                dev->max_sectors = ATA_MAX_SECTORS_LBA48;
 
-       if (!(dev->horkage & ATA_HORKAGE_IPM)) {
-               if (ata_id_has_hipm(dev->id))
-                       dev->flags |= ATA_DFLAG_HIPM;
-               if (ata_id_has_dipm(dev->id))
-                       dev->flags |= ATA_DFLAG_DIPM;
-       }
-
        /* Limit PATA drive on SATA cable bridge transfers to udma5,
           200 sectors */
        if (ata_dev_knobble(dev)) {
@@ -2591,13 +2412,6 @@ int ata_dev_configure(struct ata_device *dev)
                dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
                                         dev->max_sectors);
 
-       if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
-               dev->horkage |= ATA_HORKAGE_IPM;
-
-               /* reset link pm_policy for this port to no pm */
-               ap->pm_policy = MAX_PERFORMANCE;
-       }
-
        if (ap->ops->dev_config)
                ap->ops->dev_config(dev);
 
@@ -3596,7 +3410,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
                        warned = 1;
                }
 
-               msleep(50);
+               ata_msleep(link->ap, 50);
        }
 }
 
@@ -3617,7 +3431,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
 int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
                                int (*check_ready)(struct ata_link *link))
 {
-       msleep(ATA_WAIT_AFTER_RESET);
+       ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
 
        return ata_wait_ready(link, deadline, check_ready);
 }
@@ -3628,7 +3442,7 @@ int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
  *     @params: timing parameters { interval, duratinon, timeout } in msec
  *     @deadline: deadline jiffies for the operation
  *
-     Make sure SStatus of @link reaches stable state, determined by
+ *     Make sure SStatus of @link reaches stable state, determined by
  *     holding the same value where DET is not 1 for @duration polled
  *     every @interval, before @timeout.  Timeout constraints the
  *     beginning of the stable state.  Because DET gets stuck at 1 on
@@ -3665,7 +3479,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
        last_jiffies = jiffies;
 
        while (1) {
-               msleep(interval);
+               ata_msleep(link->ap, interval);
                if ((rc = sata_scr_read(link, SCR_STATUS, &cur)))
                        return rc;
                cur &= 0xf;
@@ -3730,7 +3544,7 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
                 * immediately after resuming.  Delay 200ms before
                 * debouncing.
                 */
-               msleep(200);
+               ata_msleep(link->ap, 200);
 
                /* is SControl restored correctly? */
                if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
@@ -3759,6 +3573,72 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
        return rc != -EINVAL ? rc : 0;
 }
 
+/**
+ *     sata_link_scr_lpm - manipulate SControl IPM and SPM fields
+ *     @link: ATA link to manipulate SControl for
+ *     @policy: LPM policy to configure
+ *     @spm_wakeup: initiate LPM transition to active state
+ *
+ *     Manipulate the IPM field of the SControl register of @link
+ *     according to @policy.  If @policy is ATA_LPM_MAX_POWER and
+ *     @spm_wakeup is %true, the SPM field is manipulated to wake up
+ *     the link.  This function also clears PHYRDY_CHG before
+ *     returning.
+ *
+ *     LOCKING:
+ *     EH context.
+ *
+ *     RETURNS:
+ *     0 on succes, -errno otherwise.
+ */
+int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                     bool spm_wakeup)
+{
+       struct ata_eh_context *ehc = &link->eh_context;
+       bool woken_up = false;
+       u32 scontrol;
+       int rc;
+
+       rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
+       if (rc)
+               return rc;
+
+       switch (policy) {
+       case ATA_LPM_MAX_POWER:
+               /* disable all LPM transitions */
+               scontrol |= (0x3 << 8);
+               /* initiate transition to active state */
+               if (spm_wakeup) {
+                       scontrol |= (0x4 << 12);
+                       woken_up = true;
+               }
+               break;
+       case ATA_LPM_MED_POWER:
+               /* allow LPM to PARTIAL */
+               scontrol &= ~(0x1 << 8);
+               scontrol |= (0x2 << 8);
+               break;
+       case ATA_LPM_MIN_POWER:
+               /* no restrictions on LPM transitions */
+               scontrol &= ~(0x3 << 8);
+               break;
+       default:
+               WARN_ON(1);
+       }
+
+       rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+       if (rc)
+               return rc;
+
+       /* give the link time to transit out of LPM state */
+       if (woken_up)
+               msleep(10);
+
+       /* clear PHYRDY_CHG from SError */
+       ehc->i.serror &= ~SERR_PHYRDY_CHG;
+       return sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+}
+
 /**
  *     ata_std_prereset - prepare for reset
  *     @link: ATA link to be reset
@@ -3868,7 +3748,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
        /* Couldn't find anything in SATA I/II specs, but AHCI-1.1
         * 10.4.2 says at least 1 ms.
         */
-       msleep(1);
+       ata_msleep(link->ap, 1);
 
        /* bring link back */
        rc = sata_link_resume(link, timing, deadline);
@@ -4551,6 +4431,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
 }
+
 /**
  *     ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES
  *     @dev: Device to which command will be sent
@@ -4566,8 +4447,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
  *     RETURNS:
  *     0 on success, AC_ERR_* mask otherwise.
  */
-static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,
-                                       u8 feature)
+unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
 {
        struct ata_taskfile tf;
        unsigned int err_mask;
@@ -4943,8 +4823,13 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
  *     ata_qc_complete - Complete an active ATA command
  *     @qc: Command to complete
  *
- *     Indicate to the mid and upper layers that an ATA
- *     command has completed, with either an ok or not-ok status.
+ *     Indicate to the mid and upper layers that an ATA command has
+ *     completed, with either an ok or not-ok status.
+ *
+ *     Refrain from calling this function multiple times when
+ *     successfully completing multiple NCQ commands.
+ *     ata_qc_complete_multiple() should be used instead, which will
+ *     properly update IRQ expect state.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
@@ -5037,6 +4922,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
  *     requests normally.  ap->qc_active and @qc_active is compared
  *     and commands are completed accordingly.
  *
+ *     Always use this function when completing multiple NCQ commands
+ *     from IRQ handlers instead of calling ata_qc_complete()
+ *     multiple times to keep IRQ expect status properly in sync.
+ *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  *
@@ -5111,15 +5000,18 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
        qc->flags |= ATA_QCFLAG_ACTIVE;
        ap->qc_active |= 1 << qc->tag;
 
-       /* We guarantee to LLDs that they will have at least one
+       /*
+        * We guarantee to LLDs that they will have at least one
         * non-zero sg if the command is a data command.
         */
-       BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes));
+       if (WARN_ON_ONCE(ata_is_data(prot) &&
+                        (!qc->sg || !qc->n_elem || !qc->nbytes)))
+               goto sys_err;
 
        if (ata_is_dma(prot) || (ata_is_pio(prot) &&
                                 (ap->flags & ATA_FLAG_PIO_DMA)))
                if (ata_sg_setup(qc))
-                       goto sg_err;
+                       goto sys_err;
 
        /* if device is sleeping, schedule reset and abort the link */
        if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
@@ -5136,7 +5028,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
                goto err;
        return;
 
-sg_err:
+sys_err:
        qc->err_mask |= AC_ERR_SYSTEM;
 err:
        ata_qc_complete(qc);
@@ -5415,15 +5307,21 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
  */
 int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
 {
+       unsigned int ehi_flags = ATA_EHI_QUIET;
        int rc;
 
        /*
-        * disable link pm on all ports before requesting
-        * any pm activity
+        * On some hardware, device fails to respond after spun down
+        * for suspend.  As the device won't be used before being
+        * resumed, we don't need to touch the device.  Ask EH to skip
+        * the usual stuff and proceed directly to suspend.
+        *
+        * http://thread.gmane.org/gmane.linux.ide/46764
         */
-       ata_lpm_enable(host);
+       if (mesg.event == PM_EVENT_SUSPEND)
+               ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
 
-       rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
+       rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
        if (rc == 0)
                host->dev->power.power_state = mesg;
        return rc;
@@ -5445,9 +5343,6 @@ void ata_host_resume(struct ata_host *host)
        ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
                            ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
        host->dev->power.power_state = PMSG_ON;
-
-       /* reenable link pm */
-       ata_lpm_disable(host);
 }
 #endif
 
@@ -5502,7 +5397,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
        int i;
 
        /* clear everything except for devices */
-       memset(link, 0, offsetof(struct ata_link, device[0]));
+       memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
+              ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);
 
        link->ap = ap;
        link->pmp = pmp;
@@ -5576,7 +5472,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
        ap = kzalloc(sizeof(*ap), GFP_KERNEL);
        if (!ap)
                return NULL;
-
+       
        ap->pflags |= ATA_PFLAG_INITIALIZING;
        ap->lock = &host->lock;
        ap->print_id = -1;
@@ -5680,6 +5576,7 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
        dev_set_drvdata(dev, host);
 
        spin_lock_init(&host->lock);
+       mutex_init(&host->eh_mutex);
        host->dev = dev;
        host->n_ports = max_ports;
 
@@ -5977,6 +5874,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
                   unsigned long flags, struct ata_port_operations *ops)
 {
        spin_lock_init(&host->lock);
+       mutex_init(&host->eh_mutex);
        host->dev = dev;
        host->flags = flags;
        host->ops = ops;
@@ -6007,7 +5905,7 @@ static void async_port_probe(void *data, async_cookie_t cookie)
                spin_lock_irqsave(ap->lock, flags);
 
                ehi->probe_mask |= ATA_ALL_DEVICES;
-               ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
+               ehi->action |= ATA_EH_RESET;
                ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
                ap->pflags &= ~ATA_PFLAG_INITIALIZING;
@@ -6078,9 +5976,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        for (i = 0; i < host->n_ports; i++)
                host->ports[i]->print_id = ata_print_id++;
 
+       
+       /* Create associated sysfs transport objects  */
+       for (i = 0; i < host->n_ports; i++) {
+               rc = ata_tport_add(host->dev,host->ports[i]);
+               if (rc) {
+                       goto err_tadd;
+               }
+       }
+
        rc = ata_scsi_add_hosts(host, sht);
        if (rc)
-               return rc;
+               goto err_tadd;
 
        /* associate with ACPI nodes */
        ata_acpi_associate(host);
@@ -6121,6 +6028,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        }
 
        return 0;
+
+ err_tadd:
+       while (--i >= 0) {
+               ata_tport_delete(host->ports[i]);
+       }
+       return rc;
+
 }
 
 /**
@@ -6211,6 +6125,13 @@ static void ata_port_detach(struct ata_port *ap)
        cancel_rearming_delayed_work(&ap->hotplug_task);
 
  skip_eh:
+       if (ap->pmp_link) {
+               int i;
+               for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
+                       ata_tlink_delete(&ap->pmp_link[i]);
+       }
+       ata_tport_delete(ap);
+
        /* remove the associated SCSI host */
        scsi_remove_host(ap->scsi_host);
 }
@@ -6527,7 +6448,7 @@ static void __init ata_parse_force_param(void)
 
 static int __init ata_init(void)
 {
-       int rc = -ENOMEM;
+       int rc;
 
        ata_parse_force_param();
 
@@ -6537,12 +6458,25 @@ static int __init ata_init(void)
                return rc;
        }
 
+       libata_transport_init();
+       ata_scsi_transport_template = ata_attach_transport();
+       if (!ata_scsi_transport_template) {
+               ata_sff_exit();
+               rc = -ENOMEM;
+               goto err_out;
+       }               
+
        printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
        return 0;
+
+err_out:
+       return rc;
 }
 
 static void __exit ata_exit(void)
 {
+       ata_release_transport(ata_scsi_transport_template);
+       libata_transport_exit();
        ata_sff_exit();
        kfree(ata_force_tbl);
 }
@@ -6557,8 +6491,36 @@ int ata_ratelimit(void)
        return __ratelimit(&ratelimit);
 }
 
+/**
+ *     ata_msleep - ATA EH owner aware msleep
+ *     @ap: ATA port to attribute the sleep to
+ *     @msecs: duration to sleep in milliseconds
+ *
+ *     Sleeps @msecs.  If the current task is owner of @ap's EH, the
+ *     ownership is released before going to sleep and reacquired
+ *     after the sleep is complete.  IOW, other ports sharing the
+ *     @ap->host will be allowed to own the EH while this task is
+ *     sleeping.
+ *
+ *     LOCKING:
+ *     Might sleep.
+ */
+void ata_msleep(struct ata_port *ap, unsigned int msecs)
+{
+       bool owns_eh = ap && ap->host->eh_owner == current;
+
+       if (owns_eh)
+               ata_eh_release(ap);
+
+       msleep(msecs);
+
+       if (owns_eh)
+               ata_eh_acquire(ap);
+}
+
 /**
  *     ata_wait_register - wait until register value changes
+ *     @ap: ATA port to wait register for, can be NULL
  *     @reg: IO-mapped register
  *     @mask: Mask to apply to read register value
  *     @val: Wait condition
@@ -6580,7 +6542,7 @@ int ata_ratelimit(void)
  *     RETURNS:
  *     The final register value.
  */
-u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
                      unsigned long interval, unsigned long timeout)
 {
        unsigned long deadline;
@@ -6595,7 +6557,7 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
        deadline = ata_deadline(jiffies, timeout);
 
        while ((tmp & mask) == val && time_before(jiffies, deadline)) {
-               msleep(interval);
+               ata_msleep(ap, interval);
                tmp = ioread32(reg);
        }
 
@@ -6671,6 +6633,7 @@ EXPORT_SYMBOL_GPL(sata_set_spd);
 EXPORT_SYMBOL_GPL(ata_wait_after_reset);
 EXPORT_SYMBOL_GPL(sata_link_debounce);
 EXPORT_SYMBOL_GPL(sata_link_resume);
+EXPORT_SYMBOL_GPL(sata_link_scr_lpm);
 EXPORT_SYMBOL_GPL(ata_std_prereset);
 EXPORT_SYMBOL_GPL(sata_link_hardreset);
 EXPORT_SYMBOL_GPL(sata_std_hardreset);
@@ -6678,6 +6641,7 @@ EXPORT_SYMBOL_GPL(ata_std_postreset);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_pair);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_msleep);
 EXPORT_SYMBOL_GPL(ata_wait_register);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
index c9ae299b83428d039c13cce845e7acc497bcff13..5e590504f3aa15c6c3c73450327a0494c264d20f 100644 (file)
@@ -57,6 +57,7 @@ enum {
        /* error flags */
        ATA_EFLAG_IS_IO                 = (1 << 0),
        ATA_EFLAG_DUBIOUS_XFER          = (1 << 1),
+       ATA_EFLAG_OLD_ER                = (1 << 31),
 
        /* error categories */
        ATA_ECAT_NONE                   = 0,
@@ -396,14 +397,9 @@ static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
        return NULL;
 }
 
-static void ata_ering_clear(struct ata_ering *ering)
-{
-       memset(ering, 0, sizeof(*ering));
-}
-
-static int ata_ering_map(struct ata_ering *ering,
-                        int (*map_fn)(struct ata_ering_entry *, void *),
-                        void *arg)
+int ata_ering_map(struct ata_ering *ering,
+                 int (*map_fn)(struct ata_ering_entry *, void *),
+                 void *arg)
 {
        int idx, rc = 0;
        struct ata_ering_entry *ent;
@@ -422,6 +418,17 @@ static int ata_ering_map(struct ata_ering *ering,
        return rc;
 }
 
+int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+       ent->eflags |= ATA_EFLAG_OLD_ER;
+       return 0;
+}
+
+static void ata_ering_clear(struct ata_ering *ering)
+{
+       ata_ering_map(ering, ata_ering_clear_cb, NULL);
+}
+
 static unsigned int ata_eh_dev_action(struct ata_device *dev)
 {
        struct ata_eh_context *ehc = &dev->link->eh_context;
@@ -455,6 +462,41 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev,
        }
 }
 
+/**
+ *     ata_eh_acquire - acquire EH ownership
+ *     @ap: ATA port to acquire EH ownership for
+ *
+ *     Acquire EH ownership for @ap.  This is the basic exclusion
+ *     mechanism for ports sharing a host.  Only one port hanging off
+ *     the same host can claim the ownership of EH.
+ *
+ *     LOCKING:
+ *     EH context.
+ */
+void ata_eh_acquire(struct ata_port *ap)
+{
+       mutex_lock(&ap->host->eh_mutex);
+       WARN_ON_ONCE(ap->host->eh_owner);
+       ap->host->eh_owner = current;
+}
+
+/**
+ *     ata_eh_release - release EH ownership
+ *     @ap: ATA port to release EH ownership for
+ *
+ *     Release EH ownership for @ap if the caller.  The caller must
+ *     have acquired EH ownership using ata_eh_acquire() previously.
+ *
+ *     LOCKING:
+ *     EH context.
+ */
+void ata_eh_release(struct ata_port *ap)
+{
+       WARN_ON_ONCE(ap->host->eh_owner != current);
+       ap->host->eh_owner = NULL;
+       mutex_unlock(&ap->host->eh_mutex);
+}
+
 /**
  *     ata_scsi_timed_out - SCSI layer time out callback
  *     @cmd: timed out SCSI command
@@ -572,19 +614,19 @@ void ata_scsi_error(struct Scsi_Host *host)
                int nr_timedout = 0;
 
                spin_lock_irqsave(ap->lock, flags);
-               
+
                /* This must occur under the ap->lock as we don't want
                   a polled recovery to race the real interrupt handler
-                  
+
                   The lost_interrupt handler checks for any completed but
                   non-notified command and completes much like an IRQ handler.
-                  
+
                   We then fall into the error recovery code which will treat
                   this as if normal completion won the race */
 
                if (ap->ops->lost_interrupt)
                        ap->ops->lost_interrupt(ap);
-                       
+
                list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
                        struct ata_queued_cmd *qc;
 
@@ -628,15 +670,17 @@ void ata_scsi_error(struct Scsi_Host *host)
                ap->eh_tries = ATA_EH_MAX_TRIES;
        } else
                spin_unlock_wait(ap->lock);
-               
+
        /* If we timed raced normal completion and there is nothing to
           recover nr_timedout == 0 why exactly are we doing error recovery ? */
 
- repeat:
        /* invoke error handler */
        if (ap->ops->error_handler) {
                struct ata_link *link;
 
+               /* acquire EH ownership */
+               ata_eh_acquire(ap);
+ repeat:
                /* kill fast drain timer */
                del_timer_sync(&ap->fastdrain_timer);
 
@@ -711,6 +755,7 @@ void ata_scsi_error(struct Scsi_Host *host)
                host->host_eh_scheduled = 0;
 
                spin_unlock_irqrestore(ap->lock, flags);
+               ata_eh_release(ap);
        } else {
                WARN_ON(ata_qc_from_tag(ap, ap->link.active_tag) == NULL);
                ap->ops->eng_timeout(ap);
@@ -772,7 +817,7 @@ void ata_port_wait_eh(struct ata_port *ap)
 
        /* make sure SCSI EH is complete */
        if (scsi_host_in_recovery(ap->scsi_host)) {
-               msleep(10);
+               ata_msleep(ap, 10);
                goto retry;
        }
 }
@@ -1573,9 +1618,9 @@ static void ata_eh_analyze_serror(struct ata_link *link)
         * host links.  For disabled PMP links, only N bit is
         * considered as X bit is left at 1 for link plugging.
         */
-       hotplug_mask = 0;
-
-       if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
+       if (link->lpm_policy != ATA_LPM_MAX_POWER)
+               hotplug_mask = 0;       /* hotplug doesn't work w/ LPM */
+       else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
                hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
        else
                hotplug_mask = SERR_PHYRDY_CHG;
@@ -1755,7 +1800,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
        struct speed_down_verdict_arg *arg = void_arg;
        int cat;
 
-       if (ent->timestamp < arg->since)
+       if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
                return -1;
 
        cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
@@ -2777,8 +2822,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
        ata_eh_done(link, NULL, ATA_EH_RESET);
        if (slave)
                ata_eh_done(slave, NULL, ATA_EH_RESET);
-       ehc->last_reset = jiffies;      /* update to completion time */
+       ehc->last_reset = jiffies;              /* update to completion time */
        ehc->i.action |= ATA_EH_REVALIDATE;
+       link->lpm_policy = ATA_LPM_UNKNOWN;     /* reset LPM state */
 
        rc = 0;
  out:
@@ -2810,8 +2856,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
                        "reset failed (errno=%d), retrying in %u secs\n",
                        rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
 
+               ata_eh_release(ap);
                while (delta)
                        delta = schedule_timeout_uninterruptible(delta);
+               ata_eh_acquire(ap);
        }
 
        if (try == max_tries - 1) {
@@ -3204,6 +3252,124 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
        return rc;
 }
 
+/**
+ *     ata_eh_set_lpm - configure SATA interface power management
+ *     @link: link to configure power management
+ *     @policy: the link power management policy
+ *     @r_failed_dev: out parameter for failed device
+ *
+ *     Enable SATA Interface power management.  This will enable
+ *     Device Interface Power Management (DIPM) for min_power
+ *     policy, and then call driver specific callbacks for
+ *     enabling Host Initiated Power management.
+ *
+ *     LOCKING:
+ *     EH context.
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                         struct ata_device **r_failed_dev)
+{
+       struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
+       struct ata_eh_context *ehc = &link->eh_context;
+       struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
+       unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
+       unsigned int err_mask;
+       int rc;
+
+       /* if the link or host doesn't do LPM, noop */
+       if ((link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
+               return 0;
+
+       /*
+        * DIPM is enabled only for MIN_POWER as some devices
+        * misbehave when the host NACKs transition to SLUMBER.  Order
+        * device and link configurations such that the host always
+        * allows DIPM requests.
+        */
+       ata_for_each_dev(dev, link, ENABLED) {
+               bool hipm = ata_id_has_hipm(dev->id);
+               bool dipm = ata_id_has_dipm(dev->id);
+
+               /* find the first enabled and LPM enabled devices */
+               if (!link_dev)
+                       link_dev = dev;
+
+               if (!lpm_dev && (hipm || dipm))
+                       lpm_dev = dev;
+
+               hints &= ~ATA_LPM_EMPTY;
+               if (!hipm)
+                       hints &= ~ATA_LPM_HIPM;
+
+               /* disable DIPM before changing link config */
+               if (policy != ATA_LPM_MIN_POWER && dipm) {
+                       err_mask = ata_dev_set_feature(dev,
+                                       SETFEATURES_SATA_DISABLE, SATA_DIPM);
+                       if (err_mask && err_mask != AC_ERR_DEV) {
+                               ata_dev_printk(dev, KERN_WARNING,
+                                       "failed to disable DIPM, Emask 0x%x\n",
+                                       err_mask);
+                               rc = -EIO;
+                               goto fail;
+                       }
+               }
+       }
+
+       if (ap) {
+               rc = ap->ops->set_lpm(link, policy, hints);
+               if (!rc && ap->slave_link)
+                       rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
+       } else
+               rc = sata_pmp_set_lpm(link, policy, hints);
+
+       /*
+        * Attribute link config failure to the first (LPM) enabled
+        * device on the link.
+        */
+       if (rc) {
+               if (rc == -EOPNOTSUPP) {
+                       link->flags |= ATA_LFLAG_NO_LPM;
+                       return 0;
+               }
+               dev = lpm_dev ? lpm_dev : link_dev;
+               goto fail;
+       }
+
+       /* host config updated, enable DIPM if transitioning to MIN_POWER */
+       ata_for_each_dev(dev, link, ENABLED) {
+               if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+                       err_mask = ata_dev_set_feature(dev,
+                                       SETFEATURES_SATA_ENABLE, SATA_DIPM);
+                       if (err_mask && err_mask != AC_ERR_DEV) {
+                               ata_dev_printk(dev, KERN_WARNING,
+                                       "failed to enable DIPM, Emask 0x%x\n",
+                                       err_mask);
+                               rc = -EIO;
+                               goto fail;
+                       }
+               }
+       }
+
+       link->lpm_policy = policy;
+       if (ap && ap->slave_link)
+               ap->slave_link->lpm_policy = policy;
+       return 0;
+
+fail:
+       /* if no device or only one more chance is left, disable LPM */
+       if (!dev || ehc->tries[dev->devno] <= 2) {
+               ata_link_printk(link, KERN_WARNING,
+                               "disabling LPM on the link\n");
+               link->flags |= ATA_LFLAG_NO_LPM;
+       }
+       if (r_failed_dev)
+               *r_failed_dev = dev;
+       return rc;
+}
+
 static int ata_link_nr_enabled(struct ata_link *link)
 {
        struct ata_device *dev;
@@ -3235,6 +3401,10 @@ static int ata_eh_skip_recovery(struct ata_link *link)
        if (link->flags & ATA_LFLAG_DISABLED)
                return 1;
 
+       /* skip if explicitly requested */
+       if (ehc->i.flags & ATA_EHI_NO_RECOVERY)
+               return 1;
+
        /* thaw frozen port and recover failed devices */
        if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
                return 0;
@@ -3284,6 +3454,16 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
        ehc->saved_xfer_mode[dev->devno] = 0;
        ehc->saved_ncq_enabled &= ~(1 << dev->devno);
 
+       /* the link maybe in a deep sleep, wake it up */
+       if (link->lpm_policy > ATA_LPM_MAX_POWER) {
+               if (ata_is_host_link(link))
+                       link->ap->ops->set_lpm(link, ATA_LPM_MAX_POWER,
+                                              ATA_LPM_EMPTY);
+               else
+                       sata_pmp_set_lpm(link, ATA_LPM_MAX_POWER,
+                                        ATA_LPM_EMPTY);
+       }
+
        /* Record and count probe trials on the ering.  The specific
         * error mask used is irrelevant.  Because a successful device
         * detection clears the ering, this count accumulates only if
@@ -3385,8 +3565,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 {
        struct ata_link *link;
        struct ata_device *dev;
-       int nr_failed_devs;
-       int rc;
+       int rc, nr_fails;
        unsigned long flags, deadline;
 
        DPRINTK("ENTER\n");
@@ -3427,7 +3606,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 
  retry:
        rc = 0;
-       nr_failed_devs = 0;
 
        /* if UNLOADING, finish immediately */
        if (ap->pflags & ATA_PFLAG_UNLOADING)
@@ -3497,8 +3675,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                if (time_before_eq(deadline, now))
                        break;
 
+               ata_eh_release(ap);
                deadline = wait_for_completion_timeout(&ap->park_req_pending,
                                                       deadline - now);
+               ata_eh_acquire(ap);
        } while (deadline);
        ata_for_each_link(link, ap, EDGE) {
                ata_for_each_dev(dev, link, ALL) {
@@ -3512,13 +3692,17 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        }
 
        /* the rest */
-       ata_for_each_link(link, ap, EDGE) {
+       nr_fails = 0;
+       ata_for_each_link(link, ap, PMP_FIRST) {
                struct ata_eh_context *ehc = &link->eh_context;
 
+               if (sata_pmp_attached(ap) && ata_is_host_link(link))
+                       goto config_lpm;
+
                /* revalidate existing devices and attach new ones */
                rc = ata_eh_revalidate_and_attach(link, &dev);
                if (rc)
-                       goto dev_fail;
+                       goto rest_fail;
 
                /* if PMP got attached, return, pmp EH will take care of it */
                if (link->device->class == ATA_DEV_PMP) {
@@ -3530,7 +3714,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                if (ehc->i.flags & ATA_EHI_SETMODE) {
                        rc = ata_set_mode(link, &dev);
                        if (rc)
-                               goto dev_fail;
+                               goto rest_fail;
                        ehc->i.flags &= ~ATA_EHI_SETMODE;
                }
 
@@ -3543,7 +3727,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                                        continue;
                                rc = atapi_eh_clear_ua(dev);
                                if (rc)
-                                       goto dev_fail;
+                                       goto rest_fail;
                        }
                }
 
@@ -3553,21 +3737,25 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                                continue;
                        rc = ata_eh_maybe_retry_flush(dev);
                        if (rc)
-                               goto dev_fail;
+                               goto rest_fail;
                }
 
+       config_lpm:
                /* configure link power saving */
-               if (ehc->i.action & ATA_EH_LPM)
-                       ata_for_each_dev(dev, link, ALL)
-                               ata_dev_enable_pm(dev, ap->pm_policy);
+               if (link->lpm_policy != ap->target_lpm_policy) {
+                       rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev);
+                       if (rc)
+                               goto rest_fail;
+               }
 
                /* this link is okay now */
                ehc->i.flags = 0;
                continue;
 
-dev_fail:
-               nr_failed_devs++;
-               ata_eh_handle_dev_fail(dev, rc);
+       rest_fail:
+               nr_fails++;
+               if (dev)
+                       ata_eh_handle_dev_fail(dev, rc);
 
                if (ap->pflags & ATA_PFLAG_FROZEN) {
                        /* PMP reset requires working host port.
@@ -3579,7 +3767,7 @@ dev_fail:
                }
        }
 
-       if (nr_failed_devs)
+       if (nr_fails)
                goto retry;
 
  out:
index 224faabd7b7efd1adf769ded4f0d4989604a012c..3120596d4afc9aaba293f100f7a075ace6438f9e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/libata.h>
 #include <linux/slab.h>
 #include "libata.h"
+#include "libata-transport.h"
 
 const struct ata_port_operations sata_pmp_port_ops = {
        .inherits               = &sata_port_ops,
@@ -184,6 +185,27 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
        return 0;
 }
 
+/**
+ *     sata_pmp_set_lpm - configure LPM for a PMP link
+ *     @link: PMP link to configure LPM for
+ *     @policy: target LPM policy
+ *     @hints: LPM hints
+ *
+ *     Configure LPM for @link.  This function will contain any PMP
+ *     specific workarounds if necessary.
+ *
+ *     LOCKING:
+ *     EH context.
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                    unsigned hints)
+{
+       return sata_link_scr_lpm(link, policy, true);
+}
+
 /**
  *     sata_pmp_read_gscr - read GSCR block of SATA PMP
  *     @dev: PMP device
@@ -312,10 +334,10 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
        return rc;
 }
 
-static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
 {
        struct ata_link *pmp_link = ap->pmp_link;
-       int i;
+       int i, err;
 
        if (!pmp_link) {
                pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
@@ -327,6 +349,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
                        ata_link_init(ap, &pmp_link[i], i);
 
                ap->pmp_link = pmp_link;
+
+               for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
+                       err = ata_tlink_add(&pmp_link[i]);
+                       if (err) {
+                               goto err_tlink;
+                       }
+               }
        }
 
        for (i = 0; i < nr_ports; i++) {
@@ -339,6 +368,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
        }
 
        return 0;
+  err_tlink:
+       while (--i >= 0)
+               ata_tlink_delete(&pmp_link[i]);
+       kfree(pmp_link);
+       ap->pmp_link = NULL;
+       return err;
 }
 
 static void sata_pmp_quirks(struct ata_port *ap)
@@ -351,6 +386,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
        if (vendor == 0x1095 && devid == 0x3726) {
                /* sil3726 quirks */
                ata_for_each_link(link, ap, EDGE) {
+                       /* link reports offline after LPM */
+                       link->flags |= ATA_LFLAG_NO_LPM;
+
                        /* Class code report is unreliable and SRST
                         * times out under certain configurations.
                         */
@@ -366,6 +404,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
        } else if (vendor == 0x1095 && devid == 0x4723) {
                /* sil4723 quirks */
                ata_for_each_link(link, ap, EDGE) {
+                       /* link reports offline after LPM */
+                       link->flags |= ATA_LFLAG_NO_LPM;
+
                        /* class code report is unreliable */
                        if (link->pmp < 2)
                                link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -378,6 +419,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
        } else if (vendor == 0x1095 && devid == 0x4726) {
                /* sil4726 quirks */
                ata_for_each_link(link, ap, EDGE) {
+                       /* link reports offline after LPM */
+                       link->flags |= ATA_LFLAG_NO_LPM;
+
                        /* Class code report is unreliable and SRST
                         * times out under certain configurations.
                         * Config device can be at port 0 or 5 and
@@ -938,15 +982,25 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
        if (rc)
                goto link_fail;
 
-       /* Connection status might have changed while resetting other
-        * links, check SATA_PMP_GSCR_ERROR before returning.
-        */
-
        /* clear SNotification */
        rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
        if (rc == 0)
                sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
 
+       /*
+        * If LPM is active on any fan-out port, hotplug wouldn't
+        * work.  Return w/ PHY event notification disabled.
+        */
+       ata_for_each_link(link, ap, EDGE)
+               if (link->lpm_policy > ATA_LPM_MAX_POWER)
+                       return 0;
+
+       /*
+        * Connection status might have changed while resetting other
+        * links, enable notification and check SATA_PMP_GSCR_ERROR
+        * before returning.
+        */
+
        /* enable notification */
        if (pmp_dev->flags & ATA_DFLAG_AN) {
                gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
index a89172c100f5645c3317dbe6b87c4cd797a4649c..d050e073e57035a99b969c50205a4227ed6a8812 100644 (file)
@@ -51,8 +51,8 @@
 #include <asm/unaligned.h>
 
 #include "libata.h"
+#include "libata-transport.h"
 
-#define SECTOR_SIZE            512
 #define ATA_SCSI_RBUF_SIZE     4096
 
 static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
@@ -64,9 +64,6 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
                                        const struct scsi_device *scsidev);
 static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
                                            const struct scsi_device *scsidev);
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-                             unsigned int id, unsigned int lun);
-
 
 #define RW_RECOVERY_MPAGE 0x1
 #define RW_RECOVERY_MPAGE_LEN 12
@@ -106,83 +103,55 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
        0, 30   /* extended self test time, see 05-359r1 */
 };
 
-/*
- * libata transport template.  libata doesn't do real transport stuff.
- * It just needs the eh_timed_out hook.
- */
-static struct scsi_transport_template ata_scsi_transport_template = {
-       .eh_strategy_handler    = ata_scsi_error,
-       .eh_timed_out           = ata_scsi_timed_out,
-       .user_scan              = ata_scsi_user_scan,
-};
-
-
-static const struct {
-       enum link_pm    value;
-       const char      *name;
-} link_pm_policy[] = {
-       { NOT_AVAILABLE, "max_performance" },
-       { MIN_POWER, "min_power" },
-       { MAX_PERFORMANCE, "max_performance" },
-       { MEDIUM_POWER, "medium_power" },
+static const char *ata_lpm_policy_names[] = {
+       [ATA_LPM_UNKNOWN]       = "max_performance",
+       [ATA_LPM_MAX_POWER]     = "max_performance",
+       [ATA_LPM_MED_POWER]     = "medium_power",
+       [ATA_LPM_MIN_POWER]     = "min_power",
 };
 
-static const char *ata_scsi_lpm_get(enum link_pm policy)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++)
-               if (link_pm_policy[i].value == policy)
-                       return link_pm_policy[i].name;
-
-       return NULL;
-}
-
-static ssize_t ata_scsi_lpm_put(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
+static ssize_t ata_scsi_lpm_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
 {
        struct Scsi_Host *shost = class_to_shost(dev);
        struct ata_port *ap = ata_shost_to_port(shost);
-       enum link_pm policy = 0;
-       int i;
+       enum ata_lpm_policy policy;
+       unsigned long flags;
 
-       /*
-        * we are skipping array location 0 on purpose - this
-        * is because a value of NOT_AVAILABLE is displayed
-        * to the user as max_performance, but when the user
-        * writes "max_performance", they actually want the
-        * value to match MAX_PERFORMANCE.
-        */
-       for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
-               const int len = strlen(link_pm_policy[i].name);
-               if (strncmp(link_pm_policy[i].name, buf, len) == 0) {
-                       policy = link_pm_policy[i].value;
+       /* UNKNOWN is internal state, iterate from MAX_POWER */
+       for (policy = ATA_LPM_MAX_POWER;
+            policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) {
+               const char *name = ata_lpm_policy_names[policy];
+
+               if (strncmp(name, buf, strlen(name)) == 0)
                        break;
-               }
        }
-       if (!policy)
+       if (policy == ARRAY_SIZE(ata_lpm_policy_names))
                return -EINVAL;
 
-       ata_lpm_schedule(ap, policy);
+       spin_lock_irqsave(ap->lock, flags);
+       ap->target_lpm_policy = policy;
+       ata_port_schedule_eh(ap);
+       spin_unlock_irqrestore(ap->lock, flags);
+
        return count;
 }
 
-static ssize_t
-ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t ata_scsi_lpm_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
 {
        struct Scsi_Host *shost = class_to_shost(dev);
        struct ata_port *ap = ata_shost_to_port(shost);
-       const char *policy =
-               ata_scsi_lpm_get(ap->pm_policy);
 
-       if (!policy)
+       if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names))
                return -EINVAL;
 
-       return snprintf(buf, 23, "%s\n", policy);
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       ata_lpm_policy_names[ap->target_lpm_policy]);
 }
 DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
-               ata_scsi_lpm_show, ata_scsi_lpm_put);
+           ata_scsi_lpm_show, ata_scsi_lpm_store);
 EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
 
 static ssize_t ata_scsi_park_show(struct device *device,
@@ -516,7 +485,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
        memset(scsi_cmd, 0, sizeof(scsi_cmd));
 
        if (args[3]) {
-               argsize = SECTOR_SIZE * args[3];
+               argsize = ATA_SECT_SIZE * args[3];
                argbuf = kmalloc(argsize, GFP_KERNEL);
                if (argbuf == NULL) {
                        rc = -ENOMEM;
@@ -1150,8 +1119,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
                blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
        } else {
                /* ATA devices must be sector aligned */
+               sdev->sector_size = ata_id_logical_sector_size(dev->id);
                blk_queue_update_dma_alignment(sdev->request_queue,
-                                              ATA_SECT_SIZE - 1);
+                                              sdev->sector_size - 1);
                sdev->manage_start_stop = 1;
        }
 
@@ -1166,6 +1136,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
                scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
        }
 
+       dev->sdev = sdev;
        return 0;
 }
 
@@ -1696,7 +1667,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                goto nothing_to_do;
 
        qc->flags |= ATA_QCFLAG_IO;
-       qc->nbytes = n_block * ATA_SECT_SIZE;
+       qc->nbytes = n_block * scmd->device->sector_size;
 
        rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
                             qc->tag);
@@ -2001,6 +1972,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
                0x89,   /* page 0x89, ata info page */
                0xb0,   /* page 0xb0, block limits page */
                0xb1,   /* page 0xb1, block device characteristics page */
+               0xb2,   /* page 0xb2, thin provisioning page */
        };
 
        rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
@@ -2123,7 +2095,7 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
 
 static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
 {
-       u32 min_io_sectors;
+       u16 min_io_sectors;
 
        rbuf[1] = 0xb0;
        rbuf[3] = 0x3c;         /* required VPD size with unmap support */
@@ -2135,10 +2107,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
         * logical than physical sector size we need to figure out what the
         * latter is.
         */
-       if (ata_id_has_large_logical_sectors(args->id))
-               min_io_sectors = ata_id_logical_per_physical_sectors(args->id);
-       else
-               min_io_sectors = 1;
+       min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id);
        put_unaligned_be16(min_io_sectors, &rbuf[6]);
 
        /*
@@ -2172,6 +2141,16 @@ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
        return 0;
 }
 
+static unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf)
+{
+       /* SCSI Thin Provisioning VPD page: SBC-3 rev 22 or later */
+       rbuf[1] = 0xb2;
+       rbuf[3] = 0x4;
+       rbuf[5] = 1 << 6;       /* TPWS */
+
+       return 0;
+}
+
 /**
  *     ata_scsiop_noop - Command handler that simply returns success.
  *     @args: device IDENTIFY data / SCSI command of interest.
@@ -2397,21 +2376,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
 {
        struct ata_device *dev = args->dev;
        u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
-       u8 log_per_phys = 0;
-       u16 lowest_aligned = 0;
-       u16 word_106 = dev->id[106];
-       u16 word_209 = dev->id[209];
-
-       if ((word_106 & 0xc000) == 0x4000) {
-               /* Number and offset of logical sectors per physical sector */
-               if (word_106 & (1 << 13))
-                       log_per_phys = word_106 & 0xf;
-               if ((word_209 & 0xc000) == 0x4000) {
-                       u16 first = dev->id[209] & 0x3fff;
-                       if (first > 0)
-                               lowest_aligned = (1 << log_per_phys) - first;
-               }
-       }
+       u32 sector_size; /* physical sector size in bytes */
+       u8 log2_per_phys;
+       u16 lowest_aligned;
+
+       sector_size = ata_id_logical_sector_size(dev->id);
+       log2_per_phys = ata_id_log2_per_physical_sector(dev->id);
+       lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys);
 
        VPRINTK("ENTER\n");
 
@@ -2426,8 +2397,10 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
                rbuf[3] = last_lba;
 
                /* sector size */
-               rbuf[6] = ATA_SECT_SIZE >> 8;
-               rbuf[7] = ATA_SECT_SIZE & 0xff;
+               rbuf[4] = sector_size >> (8 * 3);
+               rbuf[5] = sector_size >> (8 * 2);
+               rbuf[6] = sector_size >> (8 * 1);
+               rbuf[7] = sector_size;
        } else {
                /* sector count, 64-bit */
                rbuf[0] = last_lba >> (8 * 7);
@@ -2440,11 +2413,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
                rbuf[7] = last_lba;
 
                /* sector size */
-               rbuf[10] = ATA_SECT_SIZE >> 8;
-               rbuf[11] = ATA_SECT_SIZE & 0xff;
+               rbuf[ 8] = sector_size >> (8 * 3);
+               rbuf[ 9] = sector_size >> (8 * 2);
+               rbuf[10] = sector_size >> (8 * 1);
+               rbuf[11] = sector_size;
 
                rbuf[12] = 0;
-               rbuf[13] = log_per_phys;
+               rbuf[13] = log2_per_phys;
                rbuf[14] = (lowest_aligned >> 8) & 0x3f;
                rbuf[15] = lowest_aligned;
 
@@ -2888,9 +2863,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
        tf->device = dev->devno ?
                tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
 
-       /* READ/WRITE LONG use a non-standard sect_size */
-       qc->sect_size = ATA_SECT_SIZE;
        switch (tf->command) {
+       /* READ/WRITE LONG use a non-standard sect_size */
        case ATA_CMD_READ_LONG:
        case ATA_CMD_READ_LONG_ONCE:
        case ATA_CMD_WRITE_LONG:
@@ -2898,6 +2872,45 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
                if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
                        goto invalid_fld;
                qc->sect_size = scsi_bufflen(scmd);
+               break;
+
+       /* commands using reported Logical Block size (e.g. 512 or 4K) */
+       case ATA_CMD_CFA_WRITE_NE:
+       case ATA_CMD_CFA_TRANS_SECT:
+       case ATA_CMD_CFA_WRITE_MULT_NE:
+       /* XXX: case ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE: */
+       case ATA_CMD_READ:
+       case ATA_CMD_READ_EXT:
+       case ATA_CMD_READ_QUEUED:
+       /* XXX: case ATA_CMD_READ_QUEUED_EXT: */
+       case ATA_CMD_FPDMA_READ:
+       case ATA_CMD_READ_MULTI:
+       case ATA_CMD_READ_MULTI_EXT:
+       case ATA_CMD_PIO_READ:
+       case ATA_CMD_PIO_READ_EXT:
+       case ATA_CMD_READ_STREAM_DMA_EXT:
+       case ATA_CMD_READ_STREAM_EXT:
+       case ATA_CMD_VERIFY:
+       case ATA_CMD_VERIFY_EXT:
+       case ATA_CMD_WRITE:
+       case ATA_CMD_WRITE_EXT:
+       case ATA_CMD_WRITE_FUA_EXT:
+       case ATA_CMD_WRITE_QUEUED:
+       case ATA_CMD_WRITE_QUEUED_FUA_EXT:
+       case ATA_CMD_FPDMA_WRITE:
+       case ATA_CMD_WRITE_MULTI:
+       case ATA_CMD_WRITE_MULTI_EXT:
+       case ATA_CMD_WRITE_MULTI_FUA_EXT:
+       case ATA_CMD_PIO_WRITE:
+       case ATA_CMD_PIO_WRITE_EXT:
+       case ATA_CMD_WRITE_STREAM_DMA_EXT:
+       case ATA_CMD_WRITE_STREAM_EXT:
+               qc->sect_size = scmd->device->sector_size;
+               break;
+
+       /* Everything else uses 512 byte "sectors" */
+       default:
+               qc->sect_size = ATA_SECT_SIZE;
        }
 
        /*
@@ -3250,6 +3263,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
                case 0xb1:
                        ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
                        break;
+               case 0xb2:
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
+                       break;
                default:
                        ata_scsi_invalid_field(cmd, done);
                        break;
@@ -3334,7 +3350,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                *(struct ata_port **)&shost->hostdata[0] = ap;
                ap->scsi_host = shost;
 
-               shost->transportt = &ata_scsi_transport_template;
+               shost->transportt = ata_scsi_transport_template;
                shost->unique_id = ap->print_id;
                shost->max_id = 16;
                shost->max_lun = 1;
@@ -3393,6 +3409,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
                        if (!IS_ERR(sdev)) {
                                dev->sdev = sdev;
                                scsi_device_put(sdev);
+                       } else {
+                               dev->sdev = NULL;
                        }
                }
        }
@@ -3616,8 +3634,8 @@ void ata_scsi_hotplug(struct work_struct *work)
  *     RETURNS:
  *     Zero.
  */
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-                             unsigned int id, unsigned int lun)
+int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+                      unsigned int id, unsigned int lun)
 {
        struct ata_port *ap = ata_shost_to_port(shost);
        unsigned long flags;
index 674c1436491f5e5e6df3a2334ee7f995775f7634..14d18bf812556d99c463c70c70d4897e7b33055d 100644 (file)
@@ -222,7 +222,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
        timeout = ata_deadline(timer_start, tmout_pat);
        while (status != 0xff && (status & ATA_BUSY) &&
               time_before(jiffies, timeout)) {
-               msleep(50);
+               ata_msleep(ap, 50);
                status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
        }
 
@@ -234,7 +234,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
        timeout = ata_deadline(timer_start, tmout);
        while (status != 0xff && (status & ATA_BUSY) &&
               time_before(jiffies, timeout)) {
-               msleep(50);
+               ata_msleep(ap, 50);
                status = ap->ops->sff_check_status(ap);
        }
 
@@ -360,7 +360,7 @@ static void ata_dev_select(struct ata_port *ap, unsigned int device,
 
        if (wait) {
                if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
-                       msleep(150);
+                       ata_msleep(ap, 150);
                ata_wait_idle(ap);
        }
 }
@@ -418,6 +418,7 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
                if (ioaddr->ctl_addr)
                        iowrite8(tf->ctl, ioaddr->ctl_addr);
                ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
        }
 
        if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
@@ -453,6 +454,8 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
                iowrite8(tf->device, ioaddr->device_addr);
                VPRINTK("device 0x%X\n", tf->device);
        }
+
+       ata_wait_idle(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_tf_load);
 
@@ -1042,7 +1045,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
                     u8 status, int in_wq)
 {
-       struct ata_eh_info *ehi = &ap->link.eh_info;
+       struct ata_link *link = qc->dev->link;
+       struct ata_eh_info *ehi = &link->eh_info;
        unsigned long flags = 0;
        int poll_next;
 
@@ -1298,8 +1302,14 @@ fsm_start:
 }
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 
-void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay)
+void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)
 {
+       struct ata_port *ap = link->ap;
+
+       WARN_ON((ap->sff_pio_task_link != NULL) &&
+               (ap->sff_pio_task_link != link));
+       ap->sff_pio_task_link = link;
+
        /* may fail if ata_sff_flush_pio_task() in progress */
        queue_delayed_work(ata_sff_wq, &ap->sff_pio_task,
                           msecs_to_jiffies(delay));
@@ -1321,14 +1331,18 @@ static void ata_sff_pio_task(struct work_struct *work)
 {
        struct ata_port *ap =
                container_of(work, struct ata_port, sff_pio_task.work);
+       struct ata_link *link = ap->sff_pio_task_link;
        struct ata_queued_cmd *qc;
        u8 status;
        int poll_next;
 
+       BUG_ON(ap->sff_pio_task_link == NULL); 
        /* qc can be NULL if timeout occurred */
-       qc = ata_qc_from_tag(ap, ap->link.active_tag);
-       if (!qc)
+       qc = ata_qc_from_tag(ap, link->active_tag);
+       if (!qc) {
+               ap->sff_pio_task_link = NULL;
                return;
+       }
 
 fsm_start:
        WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE);
@@ -1342,14 +1356,19 @@ fsm_start:
         */
        status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
        if (status & ATA_BUSY) {
-               msleep(2);
+               ata_msleep(ap, 2);
                status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
                if (status & ATA_BUSY) {
-                       ata_sff_queue_pio_task(ap, ATA_SHORT_PAUSE);
+                       ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
                        return;
                }
        }
 
+       /*
+        * hsm_move() may trigger another command to be processed.
+        * clean the link beforehand.
+        */
+       ap->sff_pio_task_link = NULL;
        /* move the HSM */
        poll_next = ata_sff_hsm_move(ap, qc, status, 1);
 
@@ -1376,6 +1395,7 @@ fsm_start:
 unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
+       struct ata_link *link = qc->dev->link;
 
        /* Use polling pio if the LLD doesn't handle
         * interrupt driven pio and atapi CDB interrupt.
@@ -1396,7 +1416,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                ap->hsm_task_state = HSM_ST_LAST;
 
                if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_sff_queue_pio_task(ap, 0);
+                       ata_sff_queue_pio_task(link, 0);
 
                break;
 
@@ -1409,7 +1429,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                if (qc->tf.flags & ATA_TFLAG_WRITE) {
                        /* PIO data out protocol */
                        ap->hsm_task_state = HSM_ST_FIRST;
-                       ata_sff_queue_pio_task(ap, 0);
+                       ata_sff_queue_pio_task(link, 0);
 
                        /* always send first data block using the
                         * ata_sff_pio_task() codepath.
@@ -1419,7 +1439,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                        ap->hsm_task_state = HSM_ST;
 
                        if (qc->tf.flags & ATA_TFLAG_POLLING)
-                               ata_sff_queue_pio_task(ap, 0);
+                               ata_sff_queue_pio_task(link, 0);
 
                        /* if polling, ata_sff_pio_task() handles the
                         * rest.  otherwise, interrupt handler takes
@@ -1441,7 +1461,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                /* send cdb by polling if no cdb interrupt */
                if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
                    (qc->tf.flags & ATA_TFLAG_POLLING))
-                       ata_sff_queue_pio_task(ap, 0);
+                       ata_sff_queue_pio_task(link, 0);
                break;
 
        default:
@@ -1917,7 +1937,7 @@ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
        unsigned int dev1 = devmask & (1 << 1);
        int rc, ret = 0;
 
-       msleep(ATA_WAIT_AFTER_RESET);
+       ata_msleep(ap, ATA_WAIT_AFTER_RESET);
 
        /* always check readiness of the master device */
        rc = ata_sff_wait_ready(link, deadline);
@@ -1946,7 +1966,7 @@ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
                        lbal = ioread8(ioaddr->lbal_addr);
                        if ((nsect == 1) && (lbal == 1))
                                break;
-                       msleep(50);     /* give drive a breather */
+                       ata_msleep(ap, 50);     /* give drive a breather */
                }
 
                rc = ata_sff_wait_ready(link, deadline);
@@ -2734,10 +2754,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_dumb_qc_prep);
 unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-
-       /* see ata_dma_blacklisted() */
-       BUG_ON((ap->flags & ATA_FLAG_PIO_POLLING) &&
-              qc->tf.protocol == ATAPI_PROT_DMA);
+       struct ata_link *link = qc->dev->link;
 
        /* defer PIO handling to sff_qc_issue */
        if (!ata_is_dma(qc->tf.protocol))
@@ -2766,7 +2783,7 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
 
                /* send cdb by polling if no cdb interrupt */
                if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       ata_sff_queue_pio_task(ap, 0);
+                       ata_sff_queue_pio_task(link, 0);
                break;
 
        default:
@@ -3325,7 +3342,7 @@ int __init ata_sff_init(void)
        return 0;
 }
 
-void __exit ata_sff_exit(void)
+void ata_sff_exit(void)
 {
        destroy_workqueue(ata_sff_wq);
 }
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
new file mode 100644 (file)
index 0000000..ce9dc62
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ *  Copyright 2008 ioogle, Inc.  All rights reserved.
+ *     Released under GPL v2.
+ *
+ * Libata transport class.
+ *
+ * The ATA transport class contains common code to deal with ATA HBAs,
+ * an approximated representation of ATA topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and management
+ * interfaces to user-space.
+ *
+ * There are 3 objects defined in in this class:
+ * - ata_port
+ * - ata_link
+ * - ata_device
+ * Each port has a link object. Each link can have up to two devices for PATA
+ * and generally one for SATA.
+ * If there is SATA port multiplier [PMP], 15 additional ata_link object are
+ * created.
+ *
+ * These objects are created when the ata host is initialized and when a PMP is
+ * found. They are removed only when the HBA is removed, cleaned before the
+ * error handler runs.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <scsi/scsi_transport.h>
+#include <linux/libata.h>
+#include <linux/hdreg.h>
+#include <linux/uaccess.h>
+
+#include "libata.h"
+#include "libata-transport.h"
+
+#define ATA_PORT_ATTRS         2
+#define ATA_LINK_ATTRS         3
+#define ATA_DEV_ATTRS          9
+
+struct scsi_transport_template;
+struct scsi_transport_template *ata_scsi_transport_template;
+
+struct ata_internal {
+       struct scsi_transport_template t;
+
+       struct device_attribute private_port_attrs[ATA_PORT_ATTRS];
+       struct device_attribute private_link_attrs[ATA_LINK_ATTRS];
+       struct device_attribute private_dev_attrs[ATA_DEV_ATTRS];
+
+       struct transport_container link_attr_cont;
+       struct transport_container dev_attr_cont;
+
+       /*
+        * The array of null terminated pointers to attributes
+        * needed by scsi_sysfs.c
+        */
+       struct device_attribute *link_attrs[ATA_LINK_ATTRS + 1];
+       struct device_attribute *port_attrs[ATA_PORT_ATTRS + 1];
+       struct device_attribute *dev_attrs[ATA_DEV_ATTRS + 1];
+};
+#define to_ata_internal(tmpl)  container_of(tmpl, struct ata_internal, t)
+
+
+#define tdev_to_device(d)                                      \
+       container_of((d), struct ata_device, tdev)
+#define transport_class_to_dev(dev)                            \
+       tdev_to_device((dev)->parent)
+
+#define tdev_to_link(d)                                                \
+       container_of((d), struct ata_link, tdev)
+#define transport_class_to_link(dev)                           \
+       tdev_to_link((dev)->parent)
+
+#define tdev_to_port(d)                                                \
+       container_of((d), struct ata_port, tdev)
+#define transport_class_to_port(dev)                           \
+       tdev_to_port((dev)->parent)
+
+
+/* Device objects are always created whit link objects */
+static int ata_tdev_add(struct ata_device *dev);
+static void ata_tdev_delete(struct ata_device *dev);
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define ATA_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+       struct device_attribute device_attr_##_prefix##_##_name = \
+       __ATTR(_name,_mode,_show,_store)
+
+#define ata_bitfield_name_match(title, table)                  \
+static ssize_t                                                 \
+get_ata_##title##_names(u32 table_key, char *buf)              \
+{                                                              \
+       char *prefix = "";                                      \
+       ssize_t len = 0;                                        \
+       int i;                                                  \
+                                                               \
+       for (i = 0; i < ARRAY_SIZE(table); i++) {               \
+               if (table[i].value & table_key) {               \
+                       len += sprintf(buf + len, "%s%s",       \
+                               prefix, table[i].name);         \
+                       prefix = ", ";                          \
+               }                                               \
+       }                                                       \
+       len += sprintf(buf + len, "\n");                        \
+       return len;                                             \
+}
+
+#define ata_bitfield_name_search(title, table)                 \
+static ssize_t                                                 \
+get_ata_##title##_names(u32 table_key, char *buf)              \
+{                                                              \
+       ssize_t len = 0;                                        \
+       int i;                                                  \
+                                                               \
+       for (i = 0; i < ARRAY_SIZE(table); i++) {               \
+               if (table[i].value == table_key) {              \
+                       len += sprintf(buf + len, "%s",         \
+                               table[i].name);                 \
+                       break;                                  \
+               }                                               \
+       }                                                       \
+       len += sprintf(buf + len, "\n");                        \
+       return len;                                             \
+}
+
+static struct {
+       u32             value;
+       char            *name;
+} ata_class_names[] = {
+       { ATA_DEV_UNKNOWN,              "unknown" },
+       { ATA_DEV_ATA,                  "ata" },
+       { ATA_DEV_ATA_UNSUP,            "ata" },
+       { ATA_DEV_ATAPI,                "atapi" },
+       { ATA_DEV_ATAPI_UNSUP,          "atapi" },
+       { ATA_DEV_PMP,                  "pmp" },
+       { ATA_DEV_PMP_UNSUP,            "pmp" },
+       { ATA_DEV_SEMB,                 "semb" },
+       { ATA_DEV_SEMB_UNSUP,           "semb" },
+       { ATA_DEV_NONE,                 "none" }
+};
+ata_bitfield_name_search(class, ata_class_names)
+
+
+static struct {
+       u32             value;
+       char            *name;
+} ata_err_names[] = {
+       { AC_ERR_DEV,                   "DeviceError" },
+       { AC_ERR_HSM,                   "HostStateMachineError" },
+       { AC_ERR_TIMEOUT,               "Timeout" },
+       { AC_ERR_MEDIA,                 "MediaError" },
+       { AC_ERR_ATA_BUS,               "BusError" },
+       { AC_ERR_HOST_BUS,              "HostBusError" },
+       { AC_ERR_SYSTEM,                "SystemError" },
+       { AC_ERR_INVALID,               "InvalidArg" },
+       { AC_ERR_OTHER,                 "Unknown" },
+       { AC_ERR_NODEV_HINT,            "NoDeviceHint" },
+       { AC_ERR_NCQ,                   "NCQError" }
+};
+ata_bitfield_name_match(err, ata_err_names)
+
+static struct {
+       u32             value;
+       char            *name;
+} ata_xfer_names[] = {
+       { XFER_UDMA_7,                  "XFER_UDMA_7" },
+       { XFER_UDMA_6,                  "XFER_UDMA_6" },
+       { XFER_UDMA_5,                  "XFER_UDMA_5" },
+       { XFER_UDMA_4,                  "XFER_UDMA_4" },
+       { XFER_UDMA_3,                  "XFER_UDMA_3" },
+       { XFER_UDMA_2,                  "XFER_UDMA_2" },
+       { XFER_UDMA_1,                  "XFER_UDMA_1" },
+       { XFER_UDMA_0,                  "XFER_UDMA_0" },
+       { XFER_MW_DMA_4,                "XFER_MW_DMA_4" },
+       { XFER_MW_DMA_3,                "XFER_MW_DMA_3" },
+       { XFER_MW_DMA_2,                "XFER_MW_DMA_2" },
+       { XFER_MW_DMA_1,                "XFER_MW_DMA_1" },
+       { XFER_MW_DMA_0,                "XFER_MW_DMA_0" },
+       { XFER_SW_DMA_2,                "XFER_SW_DMA_2" },
+       { XFER_SW_DMA_1,                "XFER_SW_DMA_1" },
+       { XFER_SW_DMA_0,                "XFER_SW_DMA_0" },
+       { XFER_PIO_6,                   "XFER_PIO_6" },
+       { XFER_PIO_5,                   "XFER_PIO_5" },
+       { XFER_PIO_4,                   "XFER_PIO_4" },
+       { XFER_PIO_3,                   "XFER_PIO_3" },
+       { XFER_PIO_2,                   "XFER_PIO_2" },
+       { XFER_PIO_1,                   "XFER_PIO_1" },
+       { XFER_PIO_0,                   "XFER_PIO_0" },
+       { XFER_PIO_SLOW,                "XFER_PIO_SLOW" }
+};
+ata_bitfield_name_match(xfer,ata_xfer_names)
+
+/*
+ * ATA Port attributes
+ */
+#define ata_port_show_simple(field, name, format_string, cast)         \
+static ssize_t                                                         \
+show_ata_port_##name(struct device *dev,                               \
+                    struct device_attribute *attr, char *buf)          \
+{                                                                      \
+       struct ata_port *ap = transport_class_to_port(dev);             \
+                                                                       \
+       return snprintf(buf, 20, format_string, cast ap->field);        \
+}
+
+#define ata_port_simple_attr(field, name, format_string, type)         \
+       ata_port_show_simple(field, name, format_string, (type))        \
+static DEVICE_ATTR(name, S_IRUGO, show_ata_port_##name, NULL)
+
+ata_port_simple_attr(nr_pmp_links, nr_pmp_links, "%d\n", int);
+ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long);
+
+static DECLARE_TRANSPORT_CLASS(ata_port_class,
+                              "ata_port", NULL, NULL, NULL);
+
+static void ata_tport_release(struct device *dev)
+{
+       put_device(dev->parent);
+}
+
+/**
+ * ata_is_port --  check if a struct device represents a ATA port
+ * @dev:       device to check
+ *
+ * Returns:
+ *     %1 if the device represents a ATA Port, %0 else
+ */
+int ata_is_port(const struct device *dev)
+{
+       return dev->release == ata_tport_release;
+}
+
+static int ata_tport_match(struct attribute_container *cont,
+                          struct device *dev)
+{
+       if (!ata_is_port(dev))
+               return 0;
+       return &ata_scsi_transport_template->host_attrs.ac == cont;
+}
+
+/**
+ * ata_tport_delete  --  remove ATA PORT
+ * @port:      ATA PORT to remove
+ *
+ * Removes the specified ATA PORT.  Remove the associated link as well.
+ */
+void ata_tport_delete(struct ata_port *ap)
+{
+       struct device *dev = &ap->tdev;
+
+       ata_tlink_delete(&ap->link);
+
+       transport_remove_device(dev);
+       device_del(dev);
+       transport_destroy_device(dev);
+       put_device(dev);
+}
+
+/** ata_tport_add - initialize a transport ATA port structure
+ *
+ * @parent:    parent device
+ * @ap:                existing ata_port structure
+ *
+ * Initialize a ATA port structure for sysfs.  It will be added to the device
+ * tree below the device specified by @parent which could be a PCI device.
+ *
+ * Returns %0 on success
+ */
+int ata_tport_add(struct device *parent,
+                 struct ata_port *ap)
+{
+       int error;
+       struct device *dev = &ap->tdev;
+
+       device_initialize(dev);
+
+       dev->parent = get_device(parent);
+       dev->release = ata_tport_release;
+       dev_set_name(dev, "ata%d", ap->print_id);
+       transport_setup_device(dev);
+       error = device_add(dev);
+       if (error) {
+               goto tport_err;
+       }
+
+       transport_add_device(dev);
+       transport_configure_device(dev);
+
+       error = ata_tlink_add(&ap->link);
+       if (error) {
+               goto tport_link_err;
+       }
+       return 0;
+
+ tport_link_err:
+       transport_remove_device(dev);
+       device_del(dev);
+
+ tport_err:
+       transport_destroy_device(dev);
+       put_device(dev);
+       return error;
+}
+
+
+/*
+ * ATA link attributes
+ */
+
+
+#define ata_link_show_linkspeed(field)                                 \
+static ssize_t                                                         \
+show_ata_link_##field(struct device *dev,                              \
+                     struct device_attribute *attr, char *buf)         \
+{                                                                      \
+       struct ata_link *link = transport_class_to_link(dev);           \
+                                                                       \
+       return sprintf(buf,"%s\n", sata_spd_string(fls(link->field)));  \
+}
+
+#define ata_link_linkspeed_attr(field)                                 \
+       ata_link_show_linkspeed(field)                                  \
+static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
+
+ata_link_linkspeed_attr(hw_sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd);
+
+
+static DECLARE_TRANSPORT_CLASS(ata_link_class,
+               "ata_link", NULL, NULL, NULL);
+
+static void ata_tlink_release(struct device *dev)
+{
+       put_device(dev->parent);
+}
+
+/**
+ * ata_is_link --  check if a struct device represents a ATA link
+ * @dev:       device to check
+ *
+ * Returns:
+ *     %1 if the device represents a ATA link, %0 else
+ */
+int ata_is_link(const struct device *dev)
+{
+       return dev->release == ata_tlink_release;
+}
+
+static int ata_tlink_match(struct attribute_container *cont,
+                          struct device *dev)
+{
+       struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+       if (!ata_is_link(dev))
+               return 0;
+       return &i->link_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tlink_delete  --  remove ATA LINK
+ * @port:      ATA LINK to remove
+ *
+ * Removes the specified ATA LINK.  remove associated ATA device(s) as well.
+ */
+void ata_tlink_delete(struct ata_link *link)
+{
+       struct device *dev = &link->tdev;
+       struct ata_device *ata_dev;
+
+       ata_for_each_dev(ata_dev, link, ALL) {
+               ata_tdev_delete(ata_dev);
+       }
+
+       transport_remove_device(dev);
+       device_del(dev);
+       transport_destroy_device(dev);
+       put_device(dev);
+}
+
+/**
+ * ata_tlink_add  --  initialize a transport ATA link structure
+ * @link:      allocated ata_link structure.
+ *
+ * Initialize an ATA LINK structure for sysfs.  It will be added in the
+ * device tree below the ATA PORT it belongs to.
+ *
+ * Returns %0 on success
+ */
+int ata_tlink_add(struct ata_link *link)
+{
+       struct device *dev = &link->tdev;
+       struct ata_port *ap = link->ap;
+       struct ata_device *ata_dev;
+       int error;
+
+       device_initialize(dev);
+       dev->parent = get_device(&ap->tdev);
+       dev->release = ata_tlink_release;
+       if (ata_is_host_link(link))
+               dev_set_name(dev, "link%d", ap->print_id);
+        else
+               dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp);
+
+       transport_setup_device(dev);
+
+       error = device_add(dev);
+       if (error) {
+               goto tlink_err;
+       }
+
+       transport_add_device(dev);
+       transport_configure_device(dev);
+
+       ata_for_each_dev(ata_dev, link, ALL) {
+               error = ata_tdev_add(ata_dev);
+               if (error) {
+                       goto tlink_dev_err;
+               }
+       }
+       return 0;
+  tlink_dev_err:
+       while (--ata_dev >= link->device) {
+               ata_tdev_delete(ata_dev);
+       }
+       transport_remove_device(dev);
+       device_del(dev);
+  tlink_err:
+       transport_destroy_device(dev);
+       put_device(dev);
+       return error;
+}
+
+/*
+ * ATA device attributes
+ */
+
+#define ata_dev_show_class(title, field)                               \
+static ssize_t                                                         \
+show_ata_dev_##field(struct device *dev,                               \
+                    struct device_attribute *attr, char *buf)          \
+{                                                                      \
+       struct ata_device *ata_dev = transport_class_to_dev(dev);       \
+                                                                       \
+       return get_ata_##title##_names(ata_dev->field, buf);            \
+}
+
+#define ata_dev_attr(title, field)                                     \
+       ata_dev_show_class(title, field)                                \
+static DEVICE_ATTR(field, S_IRUGO, show_ata_dev_##field, NULL)
+
+ata_dev_attr(class, class);
+ata_dev_attr(xfer, pio_mode);
+ata_dev_attr(xfer, dma_mode);
+ata_dev_attr(xfer, xfer_mode);
+
+
+#define ata_dev_show_simple(field, format_string, cast)                \
+static ssize_t                                                         \
+show_ata_dev_##field(struct device *dev,                               \
+                    struct device_attribute *attr, char *buf)          \
+{                                                                      \
+       struct ata_device *ata_dev = transport_class_to_dev(dev);       \
+                                                                       \
+       return snprintf(buf, 20, format_string, cast ata_dev->field);   \
+}
+
+#define ata_dev_simple_attr(field, format_string, type)        \
+       ata_dev_show_simple(field, format_string, (type))       \
+static DEVICE_ATTR(field, S_IRUGO,                     \
+                  show_ata_dev_##field, NULL)
+
+ata_dev_simple_attr(spdn_cnt, "%d\n", int);
+
+struct ata_show_ering_arg {
+       char* buf;
+       int written;
+};
+
+static int ata_show_ering(struct ata_ering_entry *ent, void *void_arg)
+{
+       struct ata_show_ering_arg* arg = void_arg;
+       struct timespec time;
+
+       jiffies_to_timespec(ent->timestamp,&time);
+       arg->written += sprintf(arg->buf + arg->written,
+                              "[%5lu.%06lu]",
+                              time.tv_sec, time.tv_nsec);
+       arg->written += get_ata_err_names(ent->err_mask,
+                                         arg->buf + arg->written);
+       return 0;
+}
+
+static ssize_t
+show_ata_dev_ering(struct device *dev,
+                  struct device_attribute *attr, char *buf)
+{
+       struct ata_device *ata_dev = transport_class_to_dev(dev);
+       struct ata_show_ering_arg arg = { buf, 0 };
+
+       ata_ering_map(&ata_dev->ering, ata_show_ering, &arg);
+       return arg.written;
+}
+
+
+static DEVICE_ATTR(ering, S_IRUGO, show_ata_dev_ering, NULL);
+
+static ssize_t
+show_ata_dev_id(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct ata_device *ata_dev = transport_class_to_dev(dev);
+       int written = 0, i = 0;
+
+       if (ata_dev->class == ATA_DEV_PMP)
+               return 0;
+       for(i=0;i<ATA_ID_WORDS;i++)  {
+               written += snprintf(buf+written, 20, "%04x%c",
+                                   ata_dev->id[i],
+                                   ((i+1) & 7) ? ' ' : '\n');
+       }
+       return written;
+}
+
+static DEVICE_ATTR(id, S_IRUGO, show_ata_dev_id, NULL);
+
+static ssize_t
+show_ata_dev_gscr(struct device *dev,
+                 struct device_attribute *attr, char *buf)
+{
+       struct ata_device *ata_dev = transport_class_to_dev(dev);
+       int written = 0, i = 0;
+
+       if (ata_dev->class != ATA_DEV_PMP)
+               return 0;
+       for(i=0;i<SATA_PMP_GSCR_DWORDS;i++)  {
+               written += snprintf(buf+written, 20, "%08x%c",
+                                   ata_dev->gscr[i],
+                                   ((i+1) & 3) ? ' ' : '\n');
+       }
+       if (SATA_PMP_GSCR_DWORDS & 3)
+               buf[written-1] = '\n';
+       return written;
+}
+
+static DEVICE_ATTR(gscr, S_IRUGO, show_ata_dev_gscr, NULL);
+
+static DECLARE_TRANSPORT_CLASS(ata_dev_class,
+                              "ata_device", NULL, NULL, NULL);
+
+static void ata_tdev_release(struct device *dev)
+{
+       put_device(dev->parent);
+}
+
+/**
+ * ata_is_ata_dev  --  check if a struct device represents a ATA device
+ * @dev:       device to check
+ *
+ * Returns:
+ *     %1 if the device represents a ATA device, %0 else
+ */
+int ata_is_ata_dev(const struct device *dev)
+{
+       return dev->release == ata_tdev_release;
+}
+
+static int ata_tdev_match(struct attribute_container *cont,
+                         struct device *dev)
+{
+       struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+       if (!ata_is_ata_dev(dev))
+               return 0;
+       return &i->dev_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tdev_free  --  free a ATA LINK
+ * @dev:       ATA PHY to free
+ *
+ * Frees the specified ATA PHY.
+ *
+ * Note:
+ *   This function must only be called on a PHY that has not
+ *   successfully been added using ata_tdev_add().
+ */
+static void ata_tdev_free(struct ata_device *dev)
+{
+       transport_destroy_device(&dev->tdev);
+       put_device(&dev->tdev);
+}
+
+/**
+ * ata_tdev_delete  --  remove ATA device
+ * @port:      ATA PORT to remove
+ *
+ * Removes the specified ATA device.
+ */
+static void ata_tdev_delete(struct ata_device *ata_dev)
+{
+       struct device *dev = &ata_dev->tdev;
+
+       transport_remove_device(dev);
+       device_del(dev);
+       ata_tdev_free(ata_dev);
+}
+
+
+/**
+ * ata_tdev_add  --  initialize a transport ATA device structure.
+ * @ata_dev:   ata_dev structure.
+ *
+ * Initialize an ATA device structure for sysfs.  It will be added in the
+ * device tree below the ATA LINK device it belongs to.
+ *
+ * Returns %0 on success
+ */
+static int ata_tdev_add(struct ata_device *ata_dev)
+{
+       struct device *dev = &ata_dev->tdev;
+       struct ata_link *link = ata_dev->link;
+       struct ata_port *ap = link->ap;
+       int error;
+
+       device_initialize(dev);
+       dev->parent = get_device(&link->tdev);
+       dev->release = ata_tdev_release;
+       if (ata_is_host_link(link))
+               dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
+        else
+               dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp);
+
+       transport_setup_device(dev);
+       error = device_add(dev);
+       if (error) {
+               ata_tdev_free(ata_dev);
+               return error;
+       }
+
+       transport_add_device(dev);
+       transport_configure_device(dev);
+       return 0;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_TEMPLATE(attrb, field, perm, test)                       \
+       i->private_##attrb[count] = dev_attr_##field;                   \
+       i->private_##attrb[count].attr.mode = perm;                     \
+       i->attrb[count] = &i->private_##attrb[count];                   \
+       if (test)                                                       \
+               count++
+
+#define SETUP_LINK_ATTRIBUTE(field)                                    \
+       SETUP_TEMPLATE(link_attrs, field, S_IRUGO, 1)
+
+#define SETUP_PORT_ATTRIBUTE(field)                                    \
+       SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
+
+#define SETUP_DEV_ATTRIBUTE(field)                                     \
+       SETUP_TEMPLATE(dev_attrs, field, S_IRUGO, 1)
+
+/**
+ * ata_attach_transport  --  instantiate ATA transport template
+ */
+struct scsi_transport_template *ata_attach_transport(void)
+{
+       struct ata_internal *i;
+       int count;
+
+       i = kzalloc(sizeof(struct ata_internal), GFP_KERNEL);
+       if (!i)
+               return NULL;
+
+       i->t.eh_strategy_handler        = ata_scsi_error;
+       i->t.eh_timed_out               = ata_scsi_timed_out;
+       i->t.user_scan                  = ata_scsi_user_scan;
+
+       i->t.host_attrs.ac.attrs = &i->port_attrs[0];
+       i->t.host_attrs.ac.class = &ata_port_class.class;
+       i->t.host_attrs.ac.match = ata_tport_match;
+       transport_container_register(&i->t.host_attrs);
+
+       i->link_attr_cont.ac.class = &ata_link_class.class;
+       i->link_attr_cont.ac.attrs = &i->link_attrs[0];
+       i->link_attr_cont.ac.match = ata_tlink_match;
+       transport_container_register(&i->link_attr_cont);
+
+       i->dev_attr_cont.ac.class = &ata_dev_class.class;
+       i->dev_attr_cont.ac.attrs = &i->dev_attrs[0];
+       i->dev_attr_cont.ac.match = ata_tdev_match;
+       transport_container_register(&i->dev_attr_cont);
+
+       count = 0;
+       SETUP_PORT_ATTRIBUTE(nr_pmp_links);
+       SETUP_PORT_ATTRIBUTE(idle_irq);
+       BUG_ON(count > ATA_PORT_ATTRS);
+       i->port_attrs[count] = NULL;
+
+       count = 0;
+       SETUP_LINK_ATTRIBUTE(hw_sata_spd_limit);
+       SETUP_LINK_ATTRIBUTE(sata_spd_limit);
+       SETUP_LINK_ATTRIBUTE(sata_spd);
+       BUG_ON(count > ATA_LINK_ATTRS);
+       i->link_attrs[count] = NULL;
+
+       count = 0;
+       SETUP_DEV_ATTRIBUTE(class);
+       SETUP_DEV_ATTRIBUTE(pio_mode);
+       SETUP_DEV_ATTRIBUTE(dma_mode);
+       SETUP_DEV_ATTRIBUTE(xfer_mode);
+       SETUP_DEV_ATTRIBUTE(spdn_cnt);
+       SETUP_DEV_ATTRIBUTE(ering);
+       SETUP_DEV_ATTRIBUTE(id);
+       SETUP_DEV_ATTRIBUTE(gscr);
+       BUG_ON(count > ATA_DEV_ATTRS);
+       i->dev_attrs[count] = NULL;
+
+       return &i->t;
+}
+
+/**
+ * ata_release_transport  --  release ATA transport template instance
+ * @t:         transport template instance
+ */
+void ata_release_transport(struct scsi_transport_template *t)
+{
+       struct ata_internal *i = to_ata_internal(t);
+
+       transport_container_unregister(&i->t.host_attrs);
+       transport_container_unregister(&i->link_attr_cont);
+       transport_container_unregister(&i->dev_attr_cont);
+
+       kfree(i);
+}
+
+__init int libata_transport_init(void)
+{
+       int error;
+
+       error = transport_class_register(&ata_link_class);
+       if (error)
+               goto out_unregister_transport;
+       error = transport_class_register(&ata_port_class);
+       if (error)
+               goto out_unregister_link;
+       error = transport_class_register(&ata_dev_class);
+       if (error)
+               goto out_unregister_port;
+       return 0;
+
+ out_unregister_port:
+       transport_class_unregister(&ata_port_class);
+ out_unregister_link:
+       transport_class_unregister(&ata_link_class);
+ out_unregister_transport:
+       return error;
+
+}
+
+void __exit libata_transport_exit(void)
+{
+       transport_class_unregister(&ata_link_class);
+       transport_class_unregister(&ata_port_class);
+       transport_class_unregister(&ata_dev_class);
+}
diff --git a/drivers/ata/libata-transport.h b/drivers/ata/libata-transport.h
new file mode 100644 (file)
index 0000000..2820cf8
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _LIBATA_TRANSPORT_H
+#define _LIBATA_TRANSPORT_H
+
+
+extern struct scsi_transport_template *ata_scsi_transport_template;
+
+int ata_tlink_add(struct ata_link *link);
+void ata_tlink_delete(struct ata_link *link);
+
+int ata_tport_add(struct device *parent, struct ata_port *ap);
+void ata_tport_delete(struct ata_port *ap);
+
+struct scsi_transport_template *ata_attach_transport(void);
+void ata_release_transport(struct scsi_transport_template *t);
+
+__init int libata_transport_init(void);
+void __exit libata_transport_exit(void);
+#endif
index 9ce1ecc63e394227348aae2a513a6cd204748748..a9be110dbf5175de1f66942c5d21da98ab86b053 100644 (file)
@@ -86,6 +86,8 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 extern int ata_dev_configure(struct ata_device *dev);
 extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
 extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+extern unsigned int ata_dev_set_feature(struct ata_device *dev,
+                                       u8 enable, u8 feature);
 extern void ata_sg_clean(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern void ata_qc_issue(struct ata_queued_cmd *qc);
@@ -100,8 +102,7 @@ extern int sata_link_init_spd(struct ata_link *link);
 extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern struct ata_port *ata_port_alloc(struct ata_host *host);
-extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
-extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
+extern const char *sata_spd_string(unsigned int spd);
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
@@ -137,10 +138,15 @@ extern void ata_scsi_hotplug(struct work_struct *work);
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
 extern void ata_scsi_dev_rescan(struct work_struct *work);
 extern int ata_bus_probe(struct ata_port *ap);
+extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+                             unsigned int id, unsigned int lun);
+
 
 /* libata-eh.c */
 extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
 extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
+extern void ata_eh_acquire(struct ata_port *ap);
+extern void ata_eh_release(struct ata_port *ap);
 extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 extern void ata_scsi_error(struct Scsi_Host *host);
 extern void ata_port_wait_eh(struct ata_port *ap);
@@ -164,11 +170,16 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                          ata_postreset_fn_t postreset,
                          struct ata_link **r_failed_disk);
 extern void ata_eh_finish(struct ata_port *ap);
+extern int ata_ering_map(struct ata_ering *ering,
+                        int (*map_fn)(struct ata_ering_entry *, void *),
+                        void *arg);
 
 /* libata-pmp.c */
 #ifdef CONFIG_SATA_PMP
 extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
 extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
+extern int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                           unsigned hints);
 extern int sata_pmp_attach(struct ata_device *dev);
 #else /* CONFIG_SATA_PMP */
 static inline int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val)
@@ -181,6 +192,12 @@ static inline int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
        return -EINVAL;
 }
 
+static inline int sata_pmp_set_lpm(struct ata_link *link,
+                                  enum ata_lpm_policy policy, unsigned hints)
+{
+       return -EINVAL;
+}
+
 static inline int sata_pmp_attach(struct ata_device *dev)
 {
        return -EINVAL;
index ba43f0f8c880a21aa1b8b1d3b9ae3d8c3487d415..2215632e4b317684a818b0ee5cbb7037fe064079 100644 (file)
@@ -74,7 +74,8 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
        /* Odd numbered device ids are the units with enable bits (the -R cards) */
-       if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+       if ((pdev->device & 1) &&
+           !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
                return -ENOENT;
 
        return ata_sff_prereset(link, deadline);
index 9cae65de750e10777260d2e3e9d9bbab2026b768..ec2c777fcdb008efec7399e29054ef967cc3bed4 100644 (file)
@@ -826,7 +826,7 @@ static void bfin_dev_select(struct ata_port *ap, unsigned int device)
  *     @ctl: value to write
  */
 
-static u8 bfin_set_devctl(struct ata_port *ap, u8 ctl)
+static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
 {
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
        write_atapi_register(base, ATA_REG_CTRL, ctl);
@@ -1046,7 +1046,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
                        dev1 = 0;
                        break;
                }
-               msleep(50);     /* give drive a breather */
+               ata_msleep(ap, 50);     /* give drive a breather */
        }
        if (dev1)
                ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
@@ -1087,7 +1087,7 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
         *
         * Old drivers/ide uses the 2mS rule and then waits for ready
         */
-       msleep(150);
+       ata_msleep(ap, 150);
 
        /* Before we perform post reset processing we want to see if
         * the bus shows 0xFF because the odd clown forgets the D7
index e5f289f59ca3203cc1d2ef7938925e60ef727159..549d28dbf90dd89db7b26e8f0e4f335616a64541 100644 (file)
@@ -161,6 +161,17 @@ static int cmd640_port_start(struct ata_port *ap)
        return 0;
 }
 
+static bool cmd640_sff_irq_check(struct ata_port *ap)
+{
+       struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
+       int irq_reg             = ap->port_no ? ARTIM23 : CFR;
+       u8  irq_stat, irq_mask  = ap->port_no ? 0x10 : 0x04;
+
+       pci_read_config_byte(pdev, irq_reg, &irq_stat);
+
+       return irq_stat & irq_mask;
+}
+
 static struct scsi_host_template cmd640_sht = {
        ATA_PIO_SHT(DRV_NAME),
 };
@@ -169,6 +180,7 @@ static struct ata_port_operations cmd640_port_ops = {
        .inherits       = &ata_sff_port_ops,
        /* In theory xfer_noirq is not needed once we kill the prefetcher */
        .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_irq_check  = cmd640_sff_irq_check,
        .qc_issue       = cmd640_qc_issue,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = cmd640_set_piomode,
index 9f5da1c7454be3e06f37586a77dc1377e7cd4a9d..905ff76d3cbbc0d18e828cd45922b53fd935f275 100644 (file)
@@ -121,14 +121,8 @@ static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 m
 
                if (pair) {
                        struct ata_timing tp;
-
                        ata_timing_compute(pair, pair->pio_mode, &tp, T, 0);
                        ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
-                       if (pair->dma_mode) {
-                               ata_timing_compute(pair, pair->dma_mode,
-                                               &tp, T, 0);
-                               ata_timing_merge(&tp, &t, &t, ATA_TIMING_SETUP);
-                       }
                }
        }
 
index 9df1ff7e1eaac84751766ec04c48b8f40da963c7..eaf194138f219f187e819fd56f4cce86b0cc90f7 100644 (file)
@@ -44,6 +44,9 @@
  *  Specific support is included for the ht6560a/ht6560b/opti82c611a/
  *  opti82c465mv/promise 20230c/20630/qdi65x0/winbond83759A
  *
+ *  Support for the Winbond 83759A when operating in advanced mode.
+ *  Multichip mode is not currently supported.
+ *
  *  Use the autospeed and pio_mask options with:
  *     Appian ADI/2 aka CLPD7220 or AIC25VL01.
  *  Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with
@@ -135,12 +138,18 @@ static int ht6560b;               /* HT 6560A on primary 1, second 2, both 3 */
 static int opti82c611a;                /* Opti82c611A on primary 1, sec 2, both 3 */
 static int opti82c46x;         /* Opti 82c465MV present(pri/sec autodetect) */
 static int qdi;                        /* Set to probe QDI controllers */
-static int winbond;            /* Set to probe Winbond controllers,
-                                       give I/O port if non standard */
 static int autospeed;          /* Chip present which snoops speed changes */
 static int pio_mask = ATA_PIO4;        /* PIO range for autospeed devices */
 static int iordy_mask = 0xFFFFFFFF;    /* Use iordy if available */
 
+#ifdef PATA_WINBOND_VLB_MODULE
+static int winbond = 1;                /* Set to probe Winbond controllers,
+                                       give I/O port if non standard */
+#else
+static int winbond;            /* Set to probe Winbond controllers,
+                                       give I/O port if non standard */
+#endif
+
 /**
  *     legacy_probe_add        -       Add interface to probe list
  *     @port: Controller port
@@ -1297,6 +1306,7 @@ MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for legacy ATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("pata_winbond");
 
 module_param(probe_all, int, 0);
 module_param(autospeed, int, 0);
@@ -1305,6 +1315,7 @@ module_param(ht6560b, int, 0);
 module_param(opti82c611a, int, 0);
 module_param(opti82c46x, int, 0);
 module_param(qdi, int, 0);
+module_param(winbond, int, 0);
 module_param(pio_mask, int, 0);
 module_param(iordy_mask, int, 0);
 
index e944aa0c5517caaed7fc3cb8f10639245e8a3e3f..806292160b3f3c89ae698b9d279ea5d35c943680 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ata.h>
 #include <linux/libata.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -168,63 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
 };
 
 
-struct pcmcia_config_check {
-       unsigned long ctl_base;
-       int skip_vcc;
-       int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-                                  cistpl_cftable_entry_t *cfg,
-                                  cistpl_cftable_entry_t *dflt,
-                                  unsigned int vcc,
-                                  void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-       struct pcmcia_config_check *stk = priv_data;
-
-       /* Check for matching Vcc, unless we're desperate */
-       if (!stk->skip_vcc) {
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               }
+       int *is_kme = priv_data;
+
+       if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+               pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+               pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
        }
+       pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               pdev->resource[0]->start = io->win[0].base;
-               if (!(io->flags & CISTPL_IO_16BIT)) {
-                       pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-                       pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-               }
-               if (io->nwin == 2) {
-                       pdev->resource[0]->end = 8;
-                       pdev->resource[1]->start = io->win[1].base;
-                       pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-                       if (pcmcia_request_io(pdev) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->resource[1]->start;
-               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-                       pdev->resource[0]->end = io->win[0].len;
-                       pdev->resource[1]->end = 0;
-                       if (pcmcia_request_io(pdev) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->resource[0]->start + 0x0e;
-               } else
+       if (pdev->resource[1]->end) {
+               pdev->resource[0]->end = 8;
+               pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+       } else {
+               if (pdev->resource[0]->end < 16)
                        return -ENODEV;
-               /* If we've got this far, we're done */
-               return 0;
        }
-       return -ENODEV;
+
+       return pcmcia_request_io(pdev);
 }
 
 /**
@@ -239,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 {
        struct ata_host *host;
        struct ata_port *ap;
-       struct pcmcia_config_check *stk = NULL;
        int is_kme = 0, ret = -ENOMEM, p;
        unsigned long io_base, ctl_base;
        void __iomem *io_addr, *ctl_addr;
@@ -247,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        struct ata_port_operations *ops = &pcmcia_port_ops;
 
        /* Set up attributes in order to probe card and get resources */
-       pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-       pdev->conf.Attributes = CONF_ENABLE_IRQ;
-       pdev->conf.IntType = INT_MEMORY_AND_IO;
+       pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+               CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
        /* See if we have a manufacturer identifier. Use it to set is_kme for
           vendor quirks */
@@ -258,25 +217,21 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
                  ((pdev->card_id == PRODID_KME_KXLC005_A) ||
                   (pdev->card_id == PRODID_KME_KXLC005_B)));
 
-       /* Allocate resoure probing structures */
-
-       stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-       if (!stk)
-               goto out1;
-       stk->is_kme = is_kme;
-       stk->skip_vcc = io_base = ctl_base = 0;
-
-       if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
-               stk->skip_vcc = 1;
-               if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+       if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
+               pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
+               if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
                        goto failed; /* No suitable config found */
        }
        io_base = pdev->resource[0]->start;
-       ctl_base = stk->ctl_base;
+       if (pdev->resource[1]->end)
+               ctl_base = pdev->resource[1]->start;
+       else
+               ctl_base = pdev->resource[0]->start + 0x0e;
+
        if (!pdev->irq)
                goto failed;
 
-       ret = pcmcia_request_configuration(pdev, &pdev->conf);
+       ret = pcmcia_enable_device(pdev);
        if (ret)
                goto failed;
 
@@ -329,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
                goto failed;
 
        pdev->priv = host;
-       kfree(stk);
        return 0;
 
 failed:
-       kfree(stk);
        pcmcia_disable_device(pdev);
-out1:
        return ret;
 }
 
@@ -430,9 +382,7 @@ MODULE_DEVICE_TABLE(pcmcia, pcmcia_devices);
 
 static struct pcmcia_driver pcmcia_driver = {
        .owner          = THIS_MODULE,
-       .drv = {
-               .name           = DRV_NAME,
-       },
+       .name           = DRV_NAME,
        .id_table       = pcmcia_devices,
        .probe          = pcmcia_init_one,
        .remove         = pcmcia_remove_one,
index c39f213e1bbcba37605d39928125182edbb903c5..c2ed5868dda6086ded4335539eb7fddfd37135a9 100644 (file)
@@ -44,6 +44,27 @@ static void pdc202xx_exec_command(struct ata_port *ap,
        ndelay(400);
 }
 
+static bool pdc202xx_irq_check(struct ata_port *ap)
+{
+       struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
+       unsigned long master    = pci_resource_start(pdev, 4);
+       u8 sc1d                 = inb(master + 0x1d);
+
+       if (ap->port_no) {
+               /*
+                * bit 7: error, bit 6: interrupting,
+                * bit 5: FIFO full, bit 4: FIFO empty
+                */
+               return sc1d & 0x40;
+       } else  {
+               /*
+                * bit 3: error, bit 2: interrupting,
+                * bit 1: FIFO full, bit 0: FIFO empty
+                */
+               return sc1d & 0x04;
+       }
+}
+
 /**
  *     pdc202xx_configure_piomode      -       set chip PIO timing
  *     @ap: ATA interface
@@ -282,6 +303,7 @@ static struct ata_port_operations pdc2024x_port_ops = {
        .set_dmamode            = pdc202xx_set_dmamode,
 
        .sff_exec_command       = pdc202xx_exec_command,
+       .sff_irq_check          = pdc202xx_irq_check,
 };
 
 static struct ata_port_operations pdc2026x_port_ops = {
@@ -297,6 +319,7 @@ static struct ata_port_operations pdc2026x_port_ops = {
        .port_start             = pdc2026x_port_start,
 
        .sff_exec_command       = pdc202xx_exec_command,
+       .sff_irq_check          = pdc202xx_irq_check,
 };
 
 static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 6f9cfb24b751fbefb816bed7bb5b32399135c149..8a51d673e5b29e5073978ba9cdc11baa314fc88f 100644 (file)
@@ -322,7 +322,7 @@ static int pata_s3c_wait_after_reset(struct ata_link *link,
 {
        int rc;
 
-       msleep(ATA_WAIT_AFTER_RESET);
+       ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
 
        /* always check readiness of the master device */
        rc = ata_sff_wait_ready(link, deadline);
index fe36966f7e347dedd4781cef96fcec5ff79e62f3..093715c3273a9fd0fa00cec911f83972710615fa 100644 (file)
@@ -530,7 +530,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
         *
         * Old drivers/ide uses the 2mS rule and then waits for ready.
         */
-       msleep(150);
+       ata_msleep(ap, 150);
 
        /* always check readiness of the master device */
        rc = ata_sff_wait_ready(link, deadline);
@@ -559,7 +559,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
                        lbal = in_be32(ioaddr->lbal_addr);
                        if ((nsect == 1) && (lbal == 1))
                                break;
-                       msleep(50);     /* give drive a breather */
+                       ata_msleep(ap, 50);     /* give drive a breather */
                }
 
                rc = ata_sff_wait_ready(link, deadline);
index d3190d7ec304034458c6979f08f40059ac80643e..00eefbd84b33ebc927224f6dc343fd0f71707a42 100644 (file)
@@ -202,14 +202,25 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-void sil680_sff_exec_command(struct ata_port *ap,
-                                       const struct ata_taskfile *tf)
+static void sil680_sff_exec_command(struct ata_port *ap,
+                                   const struct ata_taskfile *tf)
 {
        DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
        iowrite8(tf->command, ap->ioaddr.command_addr);
        ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+static bool sil680_sff_irq_check(struct ata_port *ap)
+{
+       struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
+       unsigned long addr      = sil680_selreg(ap, 1);
+       u8 val;
+
+       pci_read_config_byte(pdev, addr, &val);
+
+       return val & 0x08;
+}
+
 static struct scsi_host_template sil680_sht = {
        ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -218,6 +229,7 @@ static struct scsi_host_template sil680_sht = {
 static struct ata_port_operations sil680_port_ops = {
        .inherits               = &ata_bmdma32_port_ops,
        .sff_exec_command       = sil680_sff_exec_command,
+       .sff_irq_check          = sil680_sff_irq_check,
        .cable_detect           = sil680_cable_detect,
        .set_piomode            = sil680_set_piomode,
        .set_dmamode            = sil680_set_dmamode,
index 98548f640c8eae74bc408b67273f529dd9b8a310..7f5d020ed56c445b712198d4d4bb133ec77e2761 100644 (file)
@@ -227,6 +227,16 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
        return 0;
 }
 
+static bool sl82c105_sff_irq_check(struct ata_port *ap)
+{
+       struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
+       u32 val, mask           = ap->port_no ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+
+       pci_read_config_dword(pdev, 0x40, &val);
+
+       return val & mask;
+}
+
 static struct scsi_host_template sl82c105_sht = {
        ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -239,6 +249,7 @@ static struct ata_port_operations sl82c105_port_ops = {
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = sl82c105_set_piomode,
        .prereset       = sl82c105_pre_reset,
+       .sff_irq_check  = sl82c105_sff_irq_check,
 };
 
 /**
index 5e659885de162e7ef3cf38e3e1f8a67098108712..ac8d7d97e4085d4122b33fbd58bde6951f3ef2e7 100644 (file)
@@ -417,6 +417,8 @@ static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
                        tf->lbam,
                        tf->lbah);
        }
+
+       ata_wait_idle(ap);
 }
 
 static int via_port_start(struct ata_port *ap)
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
deleted file mode 100644 (file)
index 6d8619b..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- *    pata_winbond.c - Winbond VLB ATA controllers
- *     (C) 2006 Red Hat
- *
- *    Support for the Winbond 83759A when operating in advanced mode.
- *    Multichip mode is not currently supported.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/platform_device.h>
-
-#define DRV_NAME "pata_winbond"
-#define DRV_VERSION "0.0.3"
-
-#define NR_HOST 4      /* Two winbond controllers, two channels each */
-
-struct winbond_data {
-       unsigned long config;
-       struct platform_device *platform_dev;
-};
-
-static struct ata_host *winbond_host[NR_HOST];
-static struct winbond_data winbond_data[NR_HOST];
-static int nr_winbond_host;
-
-#ifdef MODULE
-static int probe_winbond = 1;
-#else
-static int probe_winbond;
-#endif
-
-static DEFINE_SPINLOCK(winbond_lock);
-
-static void winbond_writecfg(unsigned long port, u8 reg, u8 val)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&winbond_lock, flags);
-       outb(reg, port + 0x01);
-       outb(val, port + 0x02);
-       spin_unlock_irqrestore(&winbond_lock, flags);
-}
-
-static u8 winbond_readcfg(unsigned long port, u8 reg)
-{
-       u8 val;
-
-       unsigned long flags;
-       spin_lock_irqsave(&winbond_lock, flags);
-       outb(reg, port + 0x01);
-       val = inb(port + 0x02);
-       spin_unlock_irqrestore(&winbond_lock, flags);
-
-       return val;
-}
-
-static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-       struct ata_timing t;
-       struct winbond_data *winbond = ap->host->private_data;
-       int active, recovery;
-       u8 reg;
-       int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
-
-       reg = winbond_readcfg(winbond->config, 0x81);
-
-       /* Get the timing data in cycles */
-       if (reg & 0x40)         /* Fast VLB bus, assume 50MHz */
-               ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
-       else
-               ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-       active = (clamp_val(t.active, 3, 17) - 1) & 0x0F;
-       recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F;
-       timing = (active << 4) | recovery;
-       winbond_writecfg(winbond->config, timing, reg);
-
-       /* Load the setup timing */
-
-       reg = 0x35;
-       if (adev->class != ATA_DEV_ATA)
-               reg |= 0x08;    /* FIFO off */
-       if (!ata_pio_need_iordy(adev))
-               reg |= 0x02;    /* IORDY off */
-       reg |= (clamp_val(t.setup, 0, 3) << 6);
-       winbond_writecfg(winbond->config, timing + 1, reg);
-}
-
-
-static unsigned int winbond_data_xfer(struct ata_device *dev,
-                       unsigned char *buf, unsigned int buflen, int rw)
-{
-       struct ata_port *ap = dev->link->ap;
-       int slop = buflen & 3;
-
-       if (ata_id_has_dword_io(dev->id)) {
-               if (rw == READ)
-                       ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-               else
-                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-
-               if (unlikely(slop)) {
-                       __le32 pad;
-                       if (rw == READ) {
-                               pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
-                               memcpy(buf + buflen - slop, &pad, slop);
-                       } else {
-                               memcpy(&pad, buf + buflen - slop, slop);
-                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-                       }
-                       buflen += 4 - slop;
-               }
-       } else
-               buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
-
-       return buflen;
-}
-
-static struct scsi_host_template winbond_sht = {
-       ATA_PIO_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations winbond_port_ops = {
-       .inherits       = &ata_sff_port_ops,
-       .sff_data_xfer  = winbond_data_xfer,
-       .cable_detect   = ata_cable_40wire,
-       .set_piomode    = winbond_set_piomode,
-};
-
-/**
- *     winbond_init_one                -       attach a winbond interface
- *     @type: Type to display
- *     @io: I/O port start
- *     @irq: interrupt line
- *     @fast: True if on a > 33Mhz VLB
- *
- *     Register a VLB bus IDE interface. Such interfaces are PIO and we
- *     assume do not support IRQ sharing.
- */
-
-static __init int winbond_init_one(unsigned long port)
-{
-       struct platform_device *pdev;
-       u8 reg;
-       int i, rc;
-
-       reg = winbond_readcfg(port, 0x81);
-       reg |= 0x80;    /* jumpered mode off */
-       winbond_writecfg(port, 0x81, reg);
-       reg = winbond_readcfg(port, 0x83);
-       reg |= 0xF0;    /* local control */
-       winbond_writecfg(port, 0x83, reg);
-       reg = winbond_readcfg(port, 0x85);
-       reg |= 0xF0;    /* programmable timing */
-       winbond_writecfg(port, 0x85, reg);
-
-       reg = winbond_readcfg(port, 0x81);
-
-       if (!(reg & 0x03))              /* Disabled */
-               return -ENODEV;
-
-       for (i = 0; i < 2 ; i ++) {
-               unsigned long cmd_port = 0x1F0 - (0x80 * i);
-               unsigned long ctl_port = cmd_port + 0x206;
-               struct ata_host *host;
-               struct ata_port *ap;
-               void __iomem *cmd_addr, *ctl_addr;
-
-               if (!(reg & (1 << i)))
-                       continue;
-
-               pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0);
-               if (IS_ERR(pdev))
-                       return PTR_ERR(pdev);
-
-               rc = -ENOMEM;
-               host = ata_host_alloc(&pdev->dev, 1);
-               if (!host)
-                       goto err_unregister;
-               ap = host->ports[0];
-
-               rc = -ENOMEM;
-               cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8);
-               ctl_addr = devm_ioport_map(&pdev->dev, ctl_port, 1);
-               if (!cmd_addr || !ctl_addr)
-                       goto err_unregister;
-
-               ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port);
-
-               ap->ops = &winbond_port_ops;
-               ap->pio_mask = ATA_PIO4;
-               ap->flags |= ATA_FLAG_SLAVE_POSS;
-               ap->ioaddr.cmd_addr = cmd_addr;
-               ap->ioaddr.altstatus_addr = ctl_addr;
-               ap->ioaddr.ctl_addr = ctl_addr;
-               ata_sff_std_ports(&ap->ioaddr);
-
-               /* hook in a private data structure per channel */
-               host->private_data = &winbond_data[nr_winbond_host];
-               winbond_data[nr_winbond_host].config = port;
-               winbond_data[nr_winbond_host].platform_dev = pdev;
-
-               /* activate */
-               rc = ata_host_activate(host, 14 + i, ata_sff_interrupt, 0,
-                                      &winbond_sht);
-               if (rc)
-                       goto err_unregister;
-
-               winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev);
-       }
-
-       return 0;
-
- err_unregister:
-       platform_device_unregister(pdev);
-       return rc;
-}
-
-/**
- *     winbond_init            -       attach winbond interfaces
- *
- *     Attach winbond IDE interfaces by scanning the ports it may occupy.
- */
-
-static __init int winbond_init(void)
-{
-       static const unsigned long config[2] = { 0x130, 0x1B0 };
-
-       int ct = 0;
-       int i;
-
-       if (probe_winbond == 0)
-               return -ENODEV;
-
-       /*
-        *      Check both base addresses
-        */
-
-       for (i = 0; i < 2; i++) {
-               if (probe_winbond & (1<<i)) {
-                       int ret = 0;
-                       unsigned long port = config[i];
-
-                       if (request_region(port, 2, "pata_winbond")) {
-                               ret = winbond_init_one(port);
-                               if (ret <= 0)
-                                       release_region(port, 2);
-                               else ct+= ret;
-                       }
-               }
-       }
-       if (ct != 0)
-               return 0;
-       return -ENODEV;
-}
-
-static __exit void winbond_exit(void)
-{
-       int i;
-
-       for (i = 0; i < nr_winbond_host; i++) {
-               ata_host_detach(winbond_host[i]);
-               release_region(winbond_data[i].config, 2);
-               platform_device_unregister(winbond_data[i].platform_dev);
-       }
-}
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for Winbond VL ATA");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_init(winbond_init);
-module_exit(winbond_exit);
-
-module_param(probe_winbond, int, 0);
-
index 2673a3d1480654ceec39f2ab144b15cde72ba72e..6cf57c5c2b5f3d50d966e63bf1e1ad0d32dea13d 100644 (file)
@@ -1459,7 +1459,7 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
 {
        struct scatterlist *sg = qc->sg;
        struct ata_port *ap = qc->ap;
-       u32 dma_chan;
+       int dma_chan;
        struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
        int err;
index 7325f77480dcb77296d148f8566bd64148a4cf3e..b0214d00d50bb469de76b40fb8a4f81f70cbb161 100644 (file)
@@ -678,7 +678,7 @@ static void sata_fsl_port_stop(struct ata_port *ap)
        iowrite32(temp, hcr_base + HCONTROL);
 
        /* Poll for controller to go offline - should happen immediately */
-       ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
+       ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
 
        ap->private_data = NULL;
        dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ,
@@ -729,7 +729,8 @@ try_offline_again:
        iowrite32(temp, hcr_base + HCONTROL);
 
        /* Poll for controller to go offline */
-       temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 500);
+       temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE,
+                                1, 500);
 
        if (temp & ONLINE) {
                ata_port_printk(ap, KERN_ERR,
@@ -752,7 +753,7 @@ try_offline_again:
        /*
         * PHY reset should remain asserted for atleast 1ms
         */
-       msleep(1);
+       ata_msleep(ap, 1);
 
        /*
         * Now, bring the host controller online again, this can take time
@@ -766,7 +767,7 @@ try_offline_again:
        temp |= HCONTROL_PMP_ATTACHED;
        iowrite32(temp, hcr_base + HCONTROL);
 
-       temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
+       temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);
 
        if (!(temp & ONLINE)) {
                ata_port_printk(ap, KERN_ERR,
@@ -784,7 +785,7 @@ try_offline_again:
         * presence
         */
 
-       temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0, 1, 500);
+       temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);
        if ((!(temp & 0x10)) || ata_link_offline(link)) {
                ata_port_printk(ap, KERN_WARNING,
                                "No Device OR PHYRDY change,Hstatus = 0x%x\n",
@@ -797,7 +798,7 @@ try_offline_again:
         * Wait for the first D2H from device,i.e,signature update notification
         */
        start_jiffies = jiffies;
-       temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0x10,
+       temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0x10,
                        500, jiffies_to_msecs(deadline - start_jiffies));
 
        if ((temp & 0xFF) != 0x18) {
@@ -880,7 +881,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
                iowrite32(pmp, CQPMP + hcr_base);
        iowrite32(1, CQ + hcr_base);
 
-       temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000);
+       temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);
        if (temp & 0x1) {
                ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
 
@@ -896,7 +897,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
                goto err;
        }
 
-       msleep(1);
+       ata_msleep(ap, 1);
 
        /*
         * SATA device enters reset state after receving a Control register
@@ -915,7 +916,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
        if (pmp != SATA_PMP_CTRL_PORT)
                iowrite32(pmp, CQPMP + hcr_base);
        iowrite32(1, CQ + hcr_base);
-       msleep(150);            /* ?? */
+       ata_msleep(ap, 150);            /* ?? */
 
        /*
         * The above command would have signalled an interrupt on command
@@ -1137,17 +1138,13 @@ static void sata_fsl_host_intr(struct ata_port *ap)
                        ioread32(hcr_base + CE));
 
                for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
-                       if (done_mask & (1 << i)) {
-                               qc = ata_qc_from_tag(ap, i);
-                               if (qc) {
-                                       ata_qc_complete(qc);
-                               }
+                       if (done_mask & (1 << i))
                                DPRINTK
                                    ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
                                     i, ioread32(hcr_base + CC),
                                     ioread32(hcr_base + CA));
-                       }
                }
+               ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
                return;
 
        } else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
index a36149ebf4a2c835717ab820915a4f76af0201ee..83a44471b1897b7d93acb7220ce0ac71a492c28b 100644 (file)
@@ -614,7 +614,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
 
        writew(IDMA_CTL_RST_ATA, idma_ctl);
        readw(idma_ctl);        /* flush */
-       msleep(1);
+       ata_msleep(ap, 1);
        writew(0, idma_ctl);
 
        rc = sata_link_resume(link, timing, deadline);
index 9463c71dd38ece66e4ad777208381573754e3f64..bf74a36d3cc3b4904363e97d4656c9e48fbe1a6f 100644 (file)
@@ -1898,19 +1898,25 @@ static void mv_bmdma_start(struct ata_queued_cmd *qc)
  *     LOCKING:
  *     Inherited from caller.
  */
-static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+static void mv_bmdma_stop_ap(struct ata_port *ap)
 {
-       struct ata_port *ap = qc->ap;
        void __iomem *port_mmio = mv_ap_base(ap);
        u32 cmd;
 
        /* clear start/stop bit */
        cmd = readl(port_mmio + BMDMA_CMD);
-       cmd &= ~ATA_DMA_START;
-       writelfl(cmd, port_mmio + BMDMA_CMD);
+       if (cmd & ATA_DMA_START) {
+               cmd &= ~ATA_DMA_START;
+               writelfl(cmd, port_mmio + BMDMA_CMD);
+
+               /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+               ata_sff_dma_pause(ap);
+       }
+}
 
-       /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-       ata_sff_dma_pause(ap);
+static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+{
+       mv_bmdma_stop_ap(qc->ap);
 }
 
 /**
@@ -1934,8 +1940,21 @@ static u8 mv_bmdma_status(struct ata_port *ap)
        reg = readl(port_mmio + BMDMA_STATUS);
        if (reg & ATA_DMA_ACTIVE)
                status = ATA_DMA_ACTIVE;
-       else
+       else if (reg & ATA_DMA_ERR)
                status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR;
+       else {
+               /*
+                * Just because DMA_ACTIVE is 0 (DMA completed),
+                * this does _not_ mean the device is "done".
+                * So we should not yet be signalling ATA_DMA_INTR
+                * in some cases.  Eg. DSM/TRIM, and perhaps others.
+                */
+               mv_bmdma_stop_ap(ap);
+               if (ioread8(ap->ioaddr.altstatus_addr) & ATA_BUSY)
+                       status = 0;
+               else
+                       status = ATA_DMA_INTR;
+       }
        return status;
 }
 
@@ -1995,6 +2014,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
 
        switch (tf->protocol) {
        case ATA_PROT_DMA:
+               if (tf->command == ATA_CMD_DSM)
+                       return;
+               /* fall-thru */
        case ATA_PROT_NCQ:
                break;  /* continue below */
        case ATA_PROT_PIO:
@@ -2094,6 +2116,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
        if ((tf->protocol != ATA_PROT_DMA) &&
            (tf->protocol != ATA_PROT_NCQ))
                return;
+       if (tf->command == ATA_CMD_DSM)
+               return;  /* use bmdma for this */
 
        /* Fill in Gen IIE command request block */
        if (!(tf->flags & ATA_TFLAG_WRITE))
@@ -2260,7 +2284,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
        }
 
        if (qc->tf.flags & ATA_TFLAG_POLLING)
-               ata_sff_queue_pio_task(ap, 0);
+               ata_sff_queue_pio_task(link, 0);
        return 0;
 }
 
@@ -2289,6 +2313,12 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
+               if (qc->tf.command == ATA_CMD_DSM) {
+                       if (!ap->ops->bmdma_setup)  /* no bmdma on GEN_I */
+                               return AC_ERR_OTHER;
+                       break;  /* use bmdma for this */
+               }
+               /* fall thru */
        case ATA_PROT_NCQ:
                mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
                pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
@@ -2713,18 +2743,11 @@ static void mv_err_intr(struct ata_port *ap)
        }
 }
 
-static void mv_process_crpb_response(struct ata_port *ap,
+static bool mv_process_crpb_response(struct ata_port *ap,
                struct mv_crpb *response, unsigned int tag, int ncq_enabled)
 {
        u8 ata_status;
        u16 edma_status = le16_to_cpu(response->flags);
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
-
-       if (unlikely(!qc)) {
-               ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
-                               __func__, tag);
-               return;
-       }
 
        /*
         * edma_status from a response queue entry:
@@ -2738,13 +2761,14 @@ static void mv_process_crpb_response(struct ata_port *ap,
                         * Error will be seen/handled by
                         * mv_err_intr().  So do nothing at all here.
                         */
-                       return;
+                       return false;
                }
        }
        ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
        if (!ac_err_mask(ata_status))
-               ata_qc_complete(qc);
+               return true;
        /* else: leave it for mv_err_intr() */
+       return false;
 }
 
 static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
@@ -2753,6 +2777,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
        struct mv_host_priv *hpriv = ap->host->private_data;
        u32 in_index;
        bool work_done = false;
+       u32 done_mask = 0;
        int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
 
        /* Get the hardware queue position index */
@@ -2773,15 +2798,19 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
                        /* Gen II/IIE: get command tag from CRPB entry */
                        tag = le16_to_cpu(response->id) & 0x1f;
                }
-               mv_process_crpb_response(ap, response, tag, ncq_enabled);
+               if (mv_process_crpb_response(ap, response, tag, ncq_enabled))
+                       done_mask |= 1 << tag;
                work_done = true;
        }
 
-       /* Update the software queue position index in hardware */
-       if (work_done)
+       if (work_done) {
+               ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+
+               /* Update the software queue position index in hardware */
                writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
                         (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
                         port_mmio + EDMA_RSP_Q_OUT_PTR);
+       }
 }
 
 static void mv_port_intr(struct ata_port *ap, u32 port_cause)
index cb89ef8d99d94468ed2cfba330f19b65d413d524..7254e255fd7868b6bfdb82d4d1e17dec560bebb0 100644 (file)
@@ -873,29 +873,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                        ata_port_freeze(ap);
                else
                        ata_port_abort(ap);
-               return 1;
+               return -1;
        }
 
-       if (likely(flags & NV_CPB_RESP_DONE)) {
-               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
-               VPRINTK("CPB flags done, flags=0x%x\n", flags);
-               if (likely(qc)) {
-                       DPRINTK("Completing qc from tag %d\n", cpb_num);
-                       ata_qc_complete(qc);
-               } else {
-                       struct ata_eh_info *ehi = &ap->link.eh_info;
-                       /* Notifier bits set without a command may indicate the drive
-                          is misbehaving. Raise host state machine violation on this
-                          condition. */
-                       ata_port_printk(ap, KERN_ERR,
-                                       "notifier for tag %d with no cmd?\n",
-                                       cpb_num);
-                       ehi->err_mask |= AC_ERR_HSM;
-                       ehi->action |= ATA_EH_RESET;
-                       ata_port_freeze(ap);
-                       return 1;
-               }
-       }
+       if (likely(flags & NV_CPB_RESP_DONE))
+               return 1;
        return 0;
 }
 
@@ -1018,6 +1000,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                              NV_ADMA_STAT_CPBERR |
                              NV_ADMA_STAT_CMD_COMPLETE)) {
                        u32 check_commands = notifier_clears[i];
+                       u32 done_mask = 0;
                        int pos, rc;
 
                        if (status & NV_ADMA_STAT_CPBERR) {
@@ -1034,10 +1017,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                                pos--;
                                rc = nv_adma_check_cpb(ap, pos,
                                                notifier_error & (1 << pos));
-                               if (unlikely(rc))
+                               if (rc > 0)
+                                       done_mask |= 1 << pos;
+                               else if (unlikely(rc < 0))
                                        check_commands = 0;
                                check_commands &= ~(1 << pos);
                        }
+                       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
                }
        }
 
@@ -2132,7 +2118,6 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        struct ata_eh_info *ehi = &ap->link.eh_info;
        u32 sactive;
        u32 done_mask;
-       int i;
        u8 host_stat;
        u8 lack_dhfis = 0;
 
@@ -2152,27 +2137,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        sactive = readl(pp->sactive_block);
        done_mask = pp->qc_active ^ sactive;
 
-       if (unlikely(done_mask & sactive)) {
-               ata_ehi_clear_desc(ehi);
-               ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
-                                 "(%08x->%08x)", pp->qc_active, sactive);
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_RESET;
-               return -EINVAL;
-       }
-       for (i = 0; i < ATA_MAX_QUEUE; i++) {
-               if (!(done_mask & (1 << i)))
-                       continue;
-
-               qc = ata_qc_from_tag(ap, i);
-               if (qc) {
-                       ata_qc_complete(qc);
-                       pp->qc_active &= ~(1 << i);
-                       pp->dhfis_bits &= ~(1 << i);
-                       pp->dmafis_bits &= ~(1 << i);
-                       pp->sdbfis_bits |= (1 << i);
-               }
-       }
+       pp->qc_active &= ~done_mask;
+       pp->dhfis_bits &= ~done_mask;
+       pp->dmafis_bits &= ~done_mask;
+       pp->sdbfis_bits |= done_mask;
+       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
 
        if (!ap->qc_active) {
                DPRINTK("over\n");
index be7726d7686dd1b11368948ff2cd8645a5368dbd..af41c6fd1254876028866b53a323fe2edb1aac8b 100644 (file)
@@ -589,9 +589,9 @@ static int sil24_init_port(struct ata_port *ap)
                sil24_clear_pmp(ap);
 
        writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-       ata_wait_register(port + PORT_CTRL_STAT,
+       ata_wait_register(ap, port + PORT_CTRL_STAT,
                          PORT_CS_INIT, PORT_CS_INIT, 10, 100);
-       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+       tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
                                PORT_CS_RDY, 0, 10, 100);
 
        if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
@@ -631,7 +631,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
        writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
 
        irq_mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
-       irq_stat = ata_wait_register(port + PORT_IRQ_STAT, irq_mask, 0x0,
+       irq_stat = ata_wait_register(ap, port + PORT_IRQ_STAT, irq_mask, 0x0,
                                     10, timeout_msec);
 
        writel(irq_mask, port + PORT_IRQ_STAT); /* clear IRQs */
@@ -719,9 +719,9 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
                                "state, performing PORT_RST\n");
 
                writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
-               msleep(10);
+               ata_msleep(ap, 10);
                writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-               ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
+               ata_wait_register(ap, port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
                                  10, 5000);
 
                /* restore port configuration */
@@ -740,7 +740,7 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
                tout_msec = 5000;
 
        writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
-       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+       tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
                                PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10,
                                tout_msec);
 
@@ -1253,7 +1253,7 @@ static void sil24_init_controller(struct ata_host *host)
                tmp = readl(port + PORT_CTRL_STAT);
                if (tmp & PORT_CS_PORT_RST) {
                        writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-                       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                       tmp = ata_wait_register(NULL, port + PORT_CTRL_STAT,
                                                PORT_CS_PORT_RST,
                                                PORT_CS_PORT_RST, 10, 100);
                        if (tmp & PORT_CS_PORT_RST)
index 4730c42a5ee58c54a295dc6a72e493f7b91cd411..c21589986c695f38756d1ced8a13422acfa3cac9 100644 (file)
@@ -349,7 +349,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
 
        /* wait for phy to become ready, if necessary */
        do {
-               msleep(200);
+               ata_msleep(link->ap, 200);
                svia_scr_read(link, SCR_STATUS, &sstatus);
                if ((sstatus & 0xf) != 1)
                        break;
index ee9ddeb53417c7da782d252f7d9e4f8113ee44b4..8cb0347dec2848e4d6c33f5276b9ba986a9f3fac 100644 (file)
@@ -3156,7 +3156,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
 {  
        struct atm_dev *dev;  
        IADEV *iadev;  
-        unsigned long flags;
        int ret;
 
        iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
@@ -3188,19 +3187,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
        ia_dev[iadev_count] = iadev;
        _ia_dev[iadev_count] = dev;
        iadev_count++;
-       spin_lock_init(&iadev->misc_lock);
-       /* First fixes first. I don't want to think about this now. */
-       spin_lock_irqsave(&iadev->misc_lock, flags); 
        if (ia_init(dev) || ia_start(dev)) {  
                IF_INIT(printk("IA register failed!\n");)
                iadev_count--;
                ia_dev[iadev_count] = NULL;
                _ia_dev[iadev_count] = NULL;
-               spin_unlock_irqrestore(&iadev->misc_lock, flags); 
                ret = -EINVAL;
                goto err_out_deregister_dev;
        }
-       spin_unlock_irqrestore(&iadev->misc_lock, flags); 
        IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
 
        iadev->next_board = ia_boards;  
index b2cd20f549cb4d474edb0a2a9a2f419d40d5072b..077735e0e04bfdd1d12f048ac8006f8a598832f8 100644 (file)
@@ -1022,7 +1022,7 @@ typedef struct iadev_t {
        struct dle_q rx_dle_q;  
        struct free_desc_q *rx_free_desc_qhead;  
        struct sk_buff_head rx_dma_q;  
-        spinlock_t rx_lock, misc_lock;
+       spinlock_t rx_lock;
        struct atm_vcc **rx_open;       /* list of all open VCs */  
         u16 num_rx_desc, rx_buf_sz, rxing;
         u32 rx_pkt_ram, rx_tmp_cnt;
index f916ddf63938a03444c2ad6e4d8a6b63c46212aa..f46138ab38b6c310fffc589681f727840a05c646 100644 (file)
@@ -444,6 +444,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
        struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
        struct solos_card *card = atmdev->dev_data;
        struct sk_buff *skb;
+       unsigned int len;
 
        spin_lock(&card->cli_queue_lock);
        skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
@@ -451,11 +452,12 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
        if(skb == NULL)
                return sprintf(buf, "No data.\n");
 
-       memcpy(buf, skb->data, skb->len);
-       dev_dbg(&card->dev->dev, "len: %d\n", skb->len);
+       len = skb->len;
+       memcpy(buf, skb->data, len);
+       dev_dbg(&card->dev->dev, "len: %d\n", len);
 
        kfree_skb(skb);
-       return skb->len;
+       return len;
 }
 
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size)
index c8a44f5e0584bec3d72e4bbada17ebb80efdd20b..40af43ebd92d355e5b96092d0f4b4ac0a3fd05ea 100644 (file)
@@ -568,7 +568,7 @@ static int _request_firmware(const struct firmware **firmware_p,
 out:
        if (retval) {
                release_firmware(firmware);
-               firmware_p = NULL;
+               *firmware_p = NULL;
        }
 
        return retval;
index cbccf9a3cee49a67b0952e633065f54ff7357747..abe46edfe5b41b9c2c5b39640c94c2208ffe283b 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP)  += main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)       += runtime.o
 obj-$(CONFIG_PM_OPS)   += generic_ops.o
 obj-$(CONFIG_PM_TRACE_RTC)     += trace.o
+obj-$(CONFIG_PM_OPP)   += opp.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
index 4b29d4981253a22d8386b50dd74ca1a046ca6682..81f2c84697f450544f3dfef66b1726cdfac83728 100644 (file)
@@ -46,7 +46,7 @@ int pm_generic_runtime_suspend(struct device *dev)
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int ret;
 
-       ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
+       ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
 
        return ret;
 }
@@ -65,7 +65,7 @@ int pm_generic_runtime_resume(struct device *dev)
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int ret;
 
-       ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
+       ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
 
        return ret;
 }
index 5419a49ff135121ce608004f40a211a9587b5cf5..31b526661ec4d78346c3b6edd04b733705285797 100644 (file)
@@ -51,6 +51,8 @@ static pm_message_t pm_transition;
  */
 static bool transition_started;
 
+static int async_error;
+
 /**
  * device_pm_init - Initialize the PM-related part of a device object.
  * @dev: Device object being initialized.
@@ -59,7 +61,9 @@ void device_pm_init(struct device *dev)
 {
        dev->power.status = DPM_ON;
        init_completion(&dev->power.completion);
-       dev->power.wakeup_count = 0;
+       complete_all(&dev->power.completion);
+       dev->power.wakeup = NULL;
+       spin_lock_init(&dev->power.lock);
        pm_runtime_init(dev);
 }
 
@@ -119,6 +123,7 @@ void device_pm_remove(struct device *dev)
        mutex_lock(&dpm_list_mtx);
        list_del_init(&dev->power.entry);
        mutex_unlock(&dpm_list_mtx);
+       device_wakeup_disable(dev);
        pm_runtime_remove(dev);
 }
 
@@ -406,7 +411,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
 static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
 {
        ktime_t calltime;
-       s64 usecs64;
+       u64 usecs64;
        int usecs;
 
        calltime = ktime_get();
@@ -599,6 +604,7 @@ static void dpm_resume(pm_message_t state)
        INIT_LIST_HEAD(&list);
        mutex_lock(&dpm_list_mtx);
        pm_transition = state;
+       async_error = 0;
 
        list_for_each_entry(dev, &dpm_list, power.entry) {
                if (dev->power.status < DPM_OFF)
@@ -828,8 +834,6 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
        return error;
 }
 
-static int async_error;
-
 /**
  * device_suspend - Execute "suspend" callbacks for given device.
  * @dev: Device to handle.
@@ -884,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        device_unlock(dev);
        complete_all(&dev->power.completion);
 
+       if (error)
+               async_error = error;
+
        return error;
 }
 
@@ -893,10 +900,8 @@ static void async_suspend(void *data, async_cookie_t cookie)
        int error;
 
        error = __device_suspend(dev, pm_transition, true);
-       if (error) {
+       if (error)
                pm_dev_err(dev, pm_transition, " async", error);
-               async_error = error;
-       }
 
        put_device(dev);
 }
@@ -1084,8 +1089,9 @@ EXPORT_SYMBOL_GPL(__suspend_report_result);
  * @dev: Device to wait for.
  * @subordinate: Device that needs to wait for @dev.
  */
-void device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
+int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
 {
        dpm_wait(dev, subordinate->power.async_suspend);
+       return async_error;
 }
 EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644 (file)
index 0000000..2bb9b4c
--- /dev/null
@@ -0,0 +1,628 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *     Nishanth Menon
+ *     Romit Dasgupta
+ *     Kevin Hilman
+ *
+ * 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/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ *     |- device 1 (represents voltage domain 1)
+ *     |       |- opp 1 (availability, freq, voltage)
+ *     |       |- opp 2 ..
+ *     ...     ...
+ *     |       `- opp n ..
+ *     |- device 2 (represents the next voltage domain)
+ *     ...
+ *     `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node:      opp list node. The nodes are maintained throughout the lifetime
+ *             of boot. It is expected only an optimal set of OPPs are
+ *             added to the library by the SoC framework.
+ *             RCU usage: opp list is traversed with RCU locks. node
+ *             modification is possible realtime, hence the modifications
+ *             are protected by the dev_opp_list_lock for integrity.
+ *             IMPORTANT: the opp nodes should be maintained in increasing
+ *             order.
+ * @available: true/false - marks if this OPP as available or not
+ * @rate:      Frequency in hertz
+ * @u_volt:    Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp:   points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+       struct list_head node;
+
+       bool available;
+       unsigned long rate;
+       unsigned long u_volt;
+
+       struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node:      list node - contains the devices with OPPs that
+ *             have been registered. Nodes once added are not modified in this
+ *             list.
+ *             RCU usage: nodes are not modified in the list of device_opp,
+ *             however addition is possible and is secured by dev_opp_list_lock
+ * @dev:       device pointer
+ * @opp_list:  list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+       struct list_head node;
+
+       struct device *dev;
+       struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev:       device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+       struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+       if (unlikely(IS_ERR_OR_NULL(dev))) {
+               pr_err("%s: Invalid parameters\n", __func__);
+               return ERR_PTR(-EINVAL);
+       }
+
+       list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+               if (tmp_dev_opp->dev == dev) {
+                       dev_opp = tmp_dev_opp;
+                       break;
+               }
+       }
+
+       return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp:       opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+       struct opp *tmp_opp;
+       unsigned long v = 0;
+
+       tmp_opp = rcu_dereference(opp);
+       if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+               pr_err("%s: Invalid parameters\n", __func__);
+       else
+               v = tmp_opp->u_volt;
+
+       return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp:       opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+       struct opp *tmp_opp;
+       unsigned long f = 0;
+
+       tmp_opp = rcu_dereference(opp);
+       if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+               pr_err("%s: Invalid parameters\n", __func__);
+       else
+               f = tmp_opp->rate;
+
+       return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev:       device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+       struct device_opp *dev_opp;
+       struct opp *temp_opp;
+       int count = 0;
+
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               int r = PTR_ERR(dev_opp);
+               dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+               return r;
+       }
+
+       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+               if (temp_opp->available)
+                       count++;
+       }
+
+       return count;
+}
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @dev:               device for which we do this operation
+ * @freq:              frequency to search for
+ * @is_available:      true/false - match for available opp
+ *
+ * Searches for exact match in the opp list and returns pointer to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+                               bool available)
+{
+       struct device_opp *dev_opp;
+       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               int r = PTR_ERR(dev_opp);
+               dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+               return ERR_PTR(r);
+       }
+
+       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+               if (temp_opp->available == available &&
+                               temp_opp->rate == freq) {
+                       opp = temp_opp;
+                       break;
+               }
+       }
+
+       return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev:       device for which we do this operation
+ * @freq:      Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+       struct device_opp *dev_opp;
+       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+       if (!dev || !freq) {
+               dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+               return ERR_PTR(-EINVAL);
+       }
+
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp))
+               return opp;
+
+       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+               if (temp_opp->available && temp_opp->rate >= *freq) {
+                       opp = temp_opp;
+                       *freq = opp->rate;
+                       break;
+               }
+       }
+
+       return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev:       device for which we do this operation
+ * @freq:      Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+       struct device_opp *dev_opp;
+       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+       if (!dev || !freq) {
+               dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+               return ERR_PTR(-EINVAL);
+       }
+
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp))
+               return opp;
+
+       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+               if (temp_opp->available) {
+                       /* go to the next node, before choosing prev */
+                       if (temp_opp->rate > *freq)
+                               break;
+                       else
+                               opp = temp_opp;
+               }
+       }
+       if (!IS_ERR(opp))
+               *freq = opp->rate;
+
+       return opp;
+}
+
+/**
+ * opp_add()  - Add an OPP table from a table definitions
+ * @dev:       device for which we do this operation
+ * @freq:      Frequency in Hz for this OPP
+ * @u_volt:    Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+       struct device_opp *dev_opp = NULL;
+       struct opp *opp, *new_opp;
+       struct list_head *head;
+
+       /* allocate new OPP node */
+       new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+       if (!new_opp) {
+               dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
+               return -ENOMEM;
+       }
+
+       /* Hold our list modification lock here */
+       mutex_lock(&dev_opp_list_lock);
+
+       /* Check for existing list for 'dev' */
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               /*
+                * Allocate a new device OPP table. In the infrequent case
+                * where a new device is needed to be added, we pay this
+                * penalty.
+                */
+               dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+               if (!dev_opp) {
+                       mutex_unlock(&dev_opp_list_lock);
+                       kfree(new_opp);
+                       dev_warn(dev,
+                               "%s: Unable to create device OPP structure\n",
+                               __func__);
+                       return -ENOMEM;
+               }
+
+               dev_opp->dev = dev;
+               INIT_LIST_HEAD(&dev_opp->opp_list);
+
+               /* Secure the device list modification */
+               list_add_rcu(&dev_opp->node, &dev_opp_list);
+       }
+
+       /* populate the opp table */
+       new_opp->dev_opp = dev_opp;
+       new_opp->rate = freq;
+       new_opp->u_volt = u_volt;
+       new_opp->available = true;
+
+       /* Insert new OPP in order of increasing frequency */
+       head = &dev_opp->opp_list;
+       list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+               if (new_opp->rate < opp->rate)
+                       break;
+               else
+                       head = &opp->node;
+       }
+
+       list_add_rcu(&new_opp->node, head);
+       mutex_unlock(&dev_opp_list_lock);
+
+       return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev:               device for which we do this operation
+ * @freq:              OPP frequency to modify availability
+ * @availability_req:  availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+               bool availability_req)
+{
+       struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+       struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+       int r = 0;
+
+       /* keep the node allocated */
+       new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+       if (!new_opp) {
+               dev_warn(dev, "%s: Unable to create OPP\n", __func__);
+               return -ENOMEM;
+       }
+
+       mutex_lock(&dev_opp_list_lock);
+
+       /* Find the device_opp */
+       list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+               if (dev == tmp_dev_opp->dev) {
+                       dev_opp = tmp_dev_opp;
+                       break;
+               }
+       }
+       if (IS_ERR(dev_opp)) {
+               r = PTR_ERR(dev_opp);
+               dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+               goto unlock;
+       }
+
+       /* Do we have the frequency? */
+       list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+               if (tmp_opp->rate == freq) {
+                       opp = tmp_opp;
+                       break;
+               }
+       }
+       if (IS_ERR(opp)) {
+               r = PTR_ERR(opp);
+               goto unlock;
+       }
+
+       /* Is update really needed? */
+       if (opp->available == availability_req)
+               goto unlock;
+       /* copy the old data over */
+       *new_opp = *opp;
+
+       /* plug in new node */
+       new_opp->available = availability_req;
+
+       list_replace_rcu(&opp->node, &new_opp->node);
+       mutex_unlock(&dev_opp_list_lock);
+       synchronize_rcu();
+
+       /* clean up old opp */
+       new_opp = opp;
+       goto out;
+
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
+out:
+       kfree(new_opp);
+       return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev:       device for which we do this operation
+ * @freq:      OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+       return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev:       device for which we do this operation
+ * @freq:      OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+       return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev:       device for which we do this operation
+ * @table:     Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is  important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table)
+{
+       struct device_opp *dev_opp;
+       struct opp *opp;
+       struct cpufreq_frequency_table *freq_table;
+       int i = 0;
+
+       /* Pretend as if I am an updater */
+       mutex_lock(&dev_opp_list_lock);
+
+       dev_opp = find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               int r = PTR_ERR(dev_opp);
+               mutex_unlock(&dev_opp_list_lock);
+               dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+               return r;
+       }
+
+       freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+                            (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+       if (!freq_table) {
+               mutex_unlock(&dev_opp_list_lock);
+               dev_warn(dev, "%s: Unable to allocate frequency table\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       list_for_each_entry(opp, &dev_opp->opp_list, node) {
+               if (opp->available) {
+                       freq_table[i].index = i;
+                       freq_table[i].frequency = opp->rate / 1000;
+                       i++;
+               }
+       }
+       mutex_unlock(&dev_opp_list_lock);
+
+       freq_table[i].index = i;
+       freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+       *table = &freq_table[0];
+
+       return 0;
+}
+#endif         /* CONFIG_CPU_FREQ */
index c0bd03c83b9cad1dbbb9341aa70f13e85b520760..698dde74258792544098eb8866e77ee72303c865 100644 (file)
@@ -34,6 +34,7 @@ extern void device_pm_move_last(struct device *);
 
 static inline void device_pm_init(struct device *dev)
 {
+       spin_lock_init(&dev->power.lock);
        pm_runtime_init(dev);
 }
 
@@ -59,6 +60,7 @@ static inline void device_pm_move_last(struct device *dev) {}
 
 extern int dpm_sysfs_add(struct device *);
 extern void dpm_sysfs_remove(struct device *);
+extern void rpm_sysfs_remove(struct device *);
 
 #else /* CONFIG_PM */
 
index b78c401ffa7380f67f29dbddf1fecf1396746e85..1dd8676d7f55705a84ad26ff77544b0518c02723 100644 (file)
@@ -2,17 +2,55 @@
  * drivers/base/power/runtime.c - Helper functions for device run-time PM
  *
  * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
  *
  * This file is released under the GPLv2.
  */
 
 #include <linux/sched.h>
 #include <linux/pm_runtime.h>
-#include <linux/jiffies.h>
+#include "power.h"
 
-static int __pm_runtime_resume(struct device *dev, bool from_wq);
-static int __pm_request_idle(struct device *dev);
-static int __pm_request_resume(struct device *dev);
+static int rpm_resume(struct device *dev, int rpmflags);
+static int rpm_suspend(struct device *dev, int rpmflags);
+
+/**
+ * update_pm_runtime_accounting - Update the time accounting of power states
+ * @dev: Device to update the accounting for
+ *
+ * In order to be able to have time accounting of the various power states
+ * (as used by programs such as PowerTOP to show the effectiveness of runtime
+ * PM), we need to track the time spent in each state.
+ * update_pm_runtime_accounting must be called each time before the
+ * runtime_status field is updated, to account the time in the old state
+ * correctly.
+ */
+void update_pm_runtime_accounting(struct device *dev)
+{
+       unsigned long now = jiffies;
+       int delta;
+
+       delta = now - dev->power.accounting_timestamp;
+
+       if (delta < 0)
+               delta = 0;
+
+       dev->power.accounting_timestamp = now;
+
+       if (dev->power.disable_depth > 0)
+               return;
+
+       if (dev->power.runtime_status == RPM_SUSPENDED)
+               dev->power.suspended_jiffies += delta;
+       else
+               dev->power.active_jiffies += delta;
+}
+
+static void __update_runtime_status(struct device *dev, enum rpm_status status)
+{
+       update_pm_runtime_accounting(dev);
+       dev->power.runtime_status = status;
+}
 
 /**
  * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
@@ -40,62 +78,154 @@ static void pm_runtime_cancel_pending(struct device *dev)
        dev->power.request = RPM_REQ_NONE;
 }
 
-/**
- * __pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
+/*
+ * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time.
+ * @dev: Device to handle.
  *
- * This function must be called under dev->power.lock with interrupts disabled.
+ * Compute the autosuspend-delay expiration time based on the device's
+ * power.last_busy time.  If the delay has already expired or is disabled
+ * (negative) or the power.use_autosuspend flag isn't set, return 0.
+ * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ *
+ * This function may be called either with or without dev->power.lock held.
+ * Either way it can be racy, since power.last_busy may be updated at any time.
  */
-static int __pm_runtime_idle(struct device *dev)
-       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
+{
+       int autosuspend_delay;
+       long elapsed;
+       unsigned long last_busy;
+       unsigned long expires = 0;
+
+       if (!dev->power.use_autosuspend)
+               goto out;
+
+       autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay);
+       if (autosuspend_delay < 0)
+               goto out;
+
+       last_busy = ACCESS_ONCE(dev->power.last_busy);
+       elapsed = jiffies - last_busy;
+       if (elapsed < 0)
+               goto out;       /* jiffies has wrapped around. */
+
+       /*
+        * If the autosuspend_delay is >= 1 second, align the timer by rounding
+        * up to the nearest second.
+        */
+       expires = last_busy + msecs_to_jiffies(autosuspend_delay);
+       if (autosuspend_delay >= 1000)
+               expires = round_jiffies(expires);
+       expires += !expires;
+       if (elapsed >= expires - last_busy)
+               expires = 0;    /* Already expired. */
+
+ out:
+       return expires;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
+
+/**
+ * rpm_check_suspend_allowed - Test whether a device may be suspended.
+ * @dev: Device to test.
+ */
+static int rpm_check_suspend_allowed(struct device *dev)
 {
        int retval = 0;
 
        if (dev->power.runtime_error)
                retval = -EINVAL;
-       else if (dev->power.idle_notification)
-               retval = -EINPROGRESS;
        else if (atomic_read(&dev->power.usage_count) > 0
-           || dev->power.disable_depth > 0
-           || dev->power.runtime_status != RPM_ACTIVE)
+           || dev->power.disable_depth > 0)
                retval = -EAGAIN;
        else if (!pm_children_suspended(dev))
                retval = -EBUSY;
+
+       /* Pending resume requests take precedence over suspends. */
+       else if ((dev->power.deferred_resume
+                       && dev->power.status == RPM_SUSPENDING)
+           || (dev->power.request_pending
+                       && dev->power.request == RPM_REQ_RESUME))
+               retval = -EAGAIN;
+       else if (dev->power.runtime_status == RPM_SUSPENDED)
+               retval = 1;
+
+       return retval;
+}
+
+/**
+ * rpm_idle - Notify device bus type if the device can be suspended.
+ * @dev: Device to notify the bus type about.
+ * @rpmflags: Flag bits.
+ *
+ * Check if the device's run-time PM status allows it to be suspended.  If
+ * another idle notification has been started earlier, return immediately.  If
+ * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
+ * run the ->runtime_idle() callback directly.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int rpm_idle(struct device *dev, int rpmflags)
+{
+       int (*callback)(struct device *);
+       int retval;
+
+       retval = rpm_check_suspend_allowed(dev);
+       if (retval < 0)
+               ;       /* Conditions are wrong. */
+
+       /* Idle notifications are allowed only in the RPM_ACTIVE state. */
+       else if (dev->power.runtime_status != RPM_ACTIVE)
+               retval = -EAGAIN;
+
+       /*
+        * Any pending request other than an idle notification takes
+        * precedence over us, except that the timer may be running.
+        */
+       else if (dev->power.request_pending &&
+           dev->power.request > RPM_REQ_IDLE)
+               retval = -EAGAIN;
+
+       /* Act as though RPM_NOWAIT is always set. */
+       else if (dev->power.idle_notification)
+               retval = -EINPROGRESS;
        if (retval)
                goto out;
 
-       if (dev->power.request_pending) {
-               /*
-                * If an idle notification request is pending, cancel it.  Any
-                * other pending request takes precedence over us.
-                */
-               if (dev->power.request == RPM_REQ_IDLE) {
-                       dev->power.request = RPM_REQ_NONE;
-               } else if (dev->power.request != RPM_REQ_NONE) {
-                       retval = -EAGAIN;
-                       goto out;
+       /* Pending requests need to be canceled. */
+       dev->power.request = RPM_REQ_NONE;
+
+       if (dev->power.no_callbacks) {
+               /* Assume ->runtime_idle() callback would have suspended. */
+               retval = rpm_suspend(dev, rpmflags);
+               goto out;
+       }
+
+       /* Carry out an asynchronous or a synchronous idle notification. */
+       if (rpmflags & RPM_ASYNC) {
+               dev->power.request = RPM_REQ_IDLE;
+               if (!dev->power.request_pending) {
+                       dev->power.request_pending = true;
+                       queue_work(pm_wq, &dev->power.work);
                }
+               goto out;
        }
 
        dev->power.idle_notification = true;
 
-       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
-               spin_unlock_irq(&dev->power.lock);
-
-               dev->bus->pm->runtime_idle(dev);
-
-               spin_lock_irq(&dev->power.lock);
-       } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
-               spin_unlock_irq(&dev->power.lock);
-
-               dev->type->pm->runtime_idle(dev);
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle)
+               callback = dev->bus->pm->runtime_idle;
+       else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle)
+               callback = dev->type->pm->runtime_idle;
+       else if (dev->class && dev->class->pm)
+               callback = dev->class->pm->runtime_idle;
+       else
+               callback = NULL;
 
-               spin_lock_irq(&dev->power.lock);
-       } else if (dev->class && dev->class->pm
-           && dev->class->pm->runtime_idle) {
+       if (callback) {
                spin_unlock_irq(&dev->power.lock);
 
-               dev->class->pm->runtime_idle(dev);
+               callback(dev);
 
                spin_lock_irq(&dev->power.lock);
        }
@@ -108,113 +238,99 @@ static int __pm_runtime_idle(struct device *dev)
 }
 
 /**
- * pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
+ * rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
  */
-int pm_runtime_idle(struct device *dev)
+static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
        int retval;
 
-       spin_lock_irq(&dev->power.lock);
-       retval = __pm_runtime_idle(dev);
-       spin_unlock_irq(&dev->power.lock);
+       if (!cb)
+               return -ENOSYS;
 
-       return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_idle);
-
-
-/**
- * update_pm_runtime_accounting - Update the time accounting of power states
- * @dev: Device to update the accounting for
- *
- * In order to be able to have time accounting of the various power states
- * (as used by programs such as PowerTOP to show the effectiveness of runtime
- * PM), we need to track the time spent in each state.
- * update_pm_runtime_accounting must be called each time before the
- * runtime_status field is updated, to account the time in the old state
- * correctly.
- */
-void update_pm_runtime_accounting(struct device *dev)
-{
-       unsigned long now = jiffies;
-       int delta;
-
-       delta = now - dev->power.accounting_timestamp;
-
-       if (delta < 0)
-               delta = 0;
+       spin_unlock_irq(&dev->power.lock);
 
-       dev->power.accounting_timestamp = now;
+       retval = cb(dev);
 
-       if (dev->power.disable_depth > 0)
-               return;
-
-       if (dev->power.runtime_status == RPM_SUSPENDED)
-               dev->power.suspended_jiffies += delta;
-       else
-               dev->power.active_jiffies += delta;
-}
+       spin_lock_irq(&dev->power.lock);
+       dev->power.runtime_error = retval;
 
-static void __update_runtime_status(struct device *dev, enum rpm_status status)
-{
-       update_pm_runtime_accounting(dev);
-       dev->power.runtime_status = status;
+       return retval;
 }
 
 /**
- * __pm_runtime_suspend - Carry out run-time suspend of given device.
+ * rpm_suspend - Carry out run-time suspend of given device.
  * @dev: Device to suspend.
- * @from_wq: If set, the function has been called via pm_wq.
+ * @rpmflags: Flag bits.
  *
- * Check if the device can be suspended and run the ->runtime_suspend() callback
- * provided by its bus type.  If another suspend has been started earlier, wait
- * for it to finish.  If an idle notification or suspend request is pending or
- * scheduled, cancel it.
+ * Check if the device's run-time PM status allows it to be suspended.  If
+ * another suspend has been started earlier, either return immediately or wait
+ * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
+ * pending idle notification.  If the RPM_ASYNC flag is set then queue a
+ * suspend request; otherwise run the ->runtime_suspend() callback directly.
+ * If a deferred resume was requested while the callback was running then carry
+ * it out; otherwise send an idle notification for the device (if the suspend
+ * failed) or for its parent (if the suspend succeeded).
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
-int __pm_runtime_suspend(struct device *dev, bool from_wq)
+static int rpm_suspend(struct device *dev, int rpmflags)
        __releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
+       int (*callback)(struct device *);
        struct device *parent = NULL;
-       bool notify = false;
-       int retval = 0;
+       int retval;
 
-       dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
-               from_wq ? " from workqueue" : "");
+       dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
 
  repeat:
-       if (dev->power.runtime_error) {
-               retval = -EINVAL;
-               goto out;
-       }
+       retval = rpm_check_suspend_allowed(dev);
 
-       /* Pending resume requests take precedence over us. */
-       if (dev->power.request_pending
-           && dev->power.request == RPM_REQ_RESUME) {
+       if (retval < 0)
+               ;       /* Conditions are wrong. */
+
+       /* Synchronous suspends are not allowed in the RPM_RESUMING state. */
+       else if (dev->power.runtime_status == RPM_RESUMING &&
+           !(rpmflags & RPM_ASYNC))
                retval = -EAGAIN;
+       if (retval)
                goto out;
+
+       /* If the autosuspend_delay time hasn't expired yet, reschedule. */
+       if ((rpmflags & RPM_AUTO)
+           && dev->power.runtime_status != RPM_SUSPENDING) {
+               unsigned long expires = pm_runtime_autosuspend_expiration(dev);
+
+               if (expires != 0) {
+                       /* Pending requests need to be canceled. */
+                       dev->power.request = RPM_REQ_NONE;
+
+                       /*
+                        * Optimization: If the timer is already running and is
+                        * set to expire at or before the autosuspend delay,
+                        * avoid the overhead of resetting it.  Just let it
+                        * expire; pm_suspend_timer_fn() will take care of the
+                        * rest.
+                        */
+                       if (!(dev->power.timer_expires && time_before_eq(
+                           dev->power.timer_expires, expires))) {
+                               dev->power.timer_expires = expires;
+                               mod_timer(&dev->power.suspend_timer, expires);
+                       }
+                       dev->power.timer_autosuspends = 1;
+                       goto out;
+               }
        }
 
        /* Other scheduled or pending requests need to be canceled. */
        pm_runtime_cancel_pending(dev);
 
-       if (dev->power.runtime_status == RPM_SUSPENDED)
-               retval = 1;
-       else if (dev->power.runtime_status == RPM_RESUMING
-           || dev->power.disable_depth > 0
-           || atomic_read(&dev->power.usage_count) > 0)
-               retval = -EAGAIN;
-       else if (!pm_children_suspended(dev))
-               retval = -EBUSY;
-       if (retval)
-               goto out;
-
        if (dev->power.runtime_status == RPM_SUSPENDING) {
                DEFINE_WAIT(wait);
 
-               if (from_wq) {
+               if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
                        retval = -EINPROGRESS;
                        goto out;
                }
@@ -236,46 +352,42 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
                goto repeat;
        }
 
-       __update_runtime_status(dev, RPM_SUSPENDING);
        dev->power.deferred_resume = false;
+       if (dev->power.no_callbacks)
+               goto no_callback;       /* Assume success. */
+
+       /* Carry out an asynchronous or a synchronous suspend. */
+       if (rpmflags & RPM_ASYNC) {
+               dev->power.request = (rpmflags & RPM_AUTO) ?
+                   RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND;
+               if (!dev->power.request_pending) {
+                       dev->power.request_pending = true;
+                       queue_work(pm_wq, &dev->power.work);
+               }
+               goto out;
+       }
 
-       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->bus->pm->runtime_suspend(dev);
-
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else if (dev->type && dev->type->pm
-           && dev->type->pm->runtime_suspend) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->type->pm->runtime_suspend(dev);
-
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else if (dev->class && dev->class->pm
-           && dev->class->pm->runtime_suspend) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->class->pm->runtime_suspend(dev);
+       __update_runtime_status(dev, RPM_SUSPENDING);
 
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else {
-               retval = -ENOSYS;
-       }
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
+               callback = dev->bus->pm->runtime_suspend;
+       else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend)
+               callback = dev->type->pm->runtime_suspend;
+       else if (dev->class && dev->class->pm)
+               callback = dev->class->pm->runtime_suspend;
+       else
+               callback = NULL;
 
+       retval = rpm_callback(callback, dev);
        if (retval) {
                __update_runtime_status(dev, RPM_ACTIVE);
-               if (retval == -EAGAIN || retval == -EBUSY) {
-                       if (dev->power.timer_expires == 0)
-                               notify = true;
+               dev->power.deferred_resume = 0;
+               if (retval == -EAGAIN || retval == -EBUSY)
                        dev->power.runtime_error = 0;
-               } else {
+               else
                        pm_runtime_cancel_pending(dev);
-               }
        } else {
+ no_callback:
                __update_runtime_status(dev, RPM_SUSPENDED);
                pm_runtime_deactivate_timer(dev);
 
@@ -287,14 +399,11 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
        wake_up_all(&dev->power.wait_queue);
 
        if (dev->power.deferred_resume) {
-               __pm_runtime_resume(dev, false);
+               rpm_resume(dev, 0);
                retval = -EAGAIN;
                goto out;
        }
 
-       if (notify)
-               __pm_runtime_idle(dev);
-
        if (parent && !parent->power.ignore_children) {
                spin_unlock_irq(&dev->power.lock);
 
@@ -304,72 +413,69 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
        }
 
  out:
-       dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);
-
-       return retval;
-}
-
-/**
- * pm_runtime_suspend - Carry out run-time suspend of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_suspend(struct device *dev)
-{
-       int retval;
-
-       spin_lock_irq(&dev->power.lock);
-       retval = __pm_runtime_suspend(dev, false);
-       spin_unlock_irq(&dev->power.lock);
+       dev_dbg(dev, "%s returns %d\n", __func__, retval);
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(pm_runtime_suspend);
 
 /**
- * __pm_runtime_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out run-time resume of given device.
  * @dev: Device to resume.
- * @from_wq: If set, the function has been called via pm_wq.
+ * @rpmflags: Flag bits.
  *
- * Check if the device can be woken up and run the ->runtime_resume() callback
- * provided by its bus type.  If another resume has been started earlier, wait
- * for it to finish.  If there's a suspend running in parallel with this
- * function, wait for it to finish and resume the device.  Cancel any scheduled
- * or pending requests.
+ * Check if the device's run-time PM status allows it to be resumed.  Cancel
+ * any scheduled or pending requests.  If another resume has been started
+ * earlier, either return imediately or wait for it to finish, depending on the
+ * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
+ * parallel with this function, either tell the other process to resume after
+ * suspending (deferred_resume) or wait for it to finish.  If the RPM_ASYNC
+ * flag is set then queue a resume request; otherwise run the
+ * ->runtime_resume() callback directly.  Queue an idle notification for the
+ * device if the resume succeeded.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
-int __pm_runtime_resume(struct device *dev, bool from_wq)
+static int rpm_resume(struct device *dev, int rpmflags)
        __releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
+       int (*callback)(struct device *);
        struct device *parent = NULL;
        int retval = 0;
 
-       dev_dbg(dev, "__pm_runtime_resume()%s!\n",
-               from_wq ? " from workqueue" : "");
+       dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
 
  repeat:
-       if (dev->power.runtime_error) {
+       if (dev->power.runtime_error)
                retval = -EINVAL;
+       else if (dev->power.disable_depth > 0)
+               retval = -EAGAIN;
+       if (retval)
                goto out;
-       }
 
-       pm_runtime_cancel_pending(dev);
+       /*
+        * Other scheduled or pending requests need to be canceled.  Small
+        * optimization: If an autosuspend timer is running, leave it running
+        * rather than cancelling it now only to restart it again in the near
+        * future.
+        */
+       dev->power.request = RPM_REQ_NONE;
+       if (!dev->power.timer_autosuspends)
+               pm_runtime_deactivate_timer(dev);
 
-       if (dev->power.runtime_status == RPM_ACTIVE)
+       if (dev->power.runtime_status == RPM_ACTIVE) {
                retval = 1;
-       else if (dev->power.disable_depth > 0)
-               retval = -EAGAIN;
-       if (retval)
                goto out;
+       }
 
        if (dev->power.runtime_status == RPM_RESUMING
            || dev->power.runtime_status == RPM_SUSPENDING) {
                DEFINE_WAIT(wait);
 
-               if (from_wq) {
+               if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
                        if (dev->power.runtime_status == RPM_SUSPENDING)
                                dev->power.deferred_resume = true;
-                       retval = -EINPROGRESS;
+                       else
+                               retval = -EINPROGRESS;
                        goto out;
                }
 
@@ -391,6 +497,34 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
                goto repeat;
        }
 
+       /*
+        * See if we can skip waking up the parent.  This is safe only if
+        * power.no_callbacks is set, because otherwise we don't know whether
+        * the resume will actually succeed.
+        */
+       if (dev->power.no_callbacks && !parent && dev->parent) {
+               spin_lock(&dev->parent->power.lock);
+               if (dev->parent->power.disable_depth > 0
+                   || dev->parent->power.ignore_children
+                   || dev->parent->power.runtime_status == RPM_ACTIVE) {
+                       atomic_inc(&dev->parent->power.child_count);
+                       spin_unlock(&dev->parent->power.lock);
+                       goto no_callback;       /* Assume success. */
+               }
+               spin_unlock(&dev->parent->power.lock);
+       }
+
+       /* Carry out an asynchronous or a synchronous resume. */
+       if (rpmflags & RPM_ASYNC) {
+               dev->power.request = RPM_REQ_RESUME;
+               if (!dev->power.request_pending) {
+                       dev->power.request_pending = true;
+                       queue_work(pm_wq, &dev->power.work);
+               }
+               retval = 0;
+               goto out;
+       }
+
        if (!parent && dev->parent) {
                /*
                 * Increment the parent's resume counter and resume it if
@@ -408,7 +542,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
                 */
                if (!parent->power.disable_depth
                    && !parent->power.ignore_children) {
-                       __pm_runtime_resume(parent, false);
+                       rpm_resume(parent, 0);
                        if (parent->power.runtime_status != RPM_ACTIVE)
                                retval = -EBUSY;
                }
@@ -420,39 +554,26 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
                goto repeat;
        }
 
-       __update_runtime_status(dev, RPM_RESUMING);
-
-       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->bus->pm->runtime_resume(dev);
-
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else if (dev->type && dev->type->pm
-           && dev->type->pm->runtime_resume) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->type->pm->runtime_resume(dev);
+       if (dev->power.no_callbacks)
+               goto no_callback;       /* Assume success. */
 
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else if (dev->class && dev->class->pm
-           && dev->class->pm->runtime_resume) {
-               spin_unlock_irq(&dev->power.lock);
-
-               retval = dev->class->pm->runtime_resume(dev);
+       __update_runtime_status(dev, RPM_RESUMING);
 
-               spin_lock_irq(&dev->power.lock);
-               dev->power.runtime_error = retval;
-       } else {
-               retval = -ENOSYS;
-       }
+       if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
+               callback = dev->bus->pm->runtime_resume;
+       else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume)
+               callback = dev->type->pm->runtime_resume;
+       else if (dev->class && dev->class->pm)
+               callback = dev->class->pm->runtime_resume;
+       else
+               callback = NULL;
 
+       retval = rpm_callback(callback, dev);
        if (retval) {
                __update_runtime_status(dev, RPM_SUSPENDED);
                pm_runtime_cancel_pending(dev);
        } else {
+ no_callback:
                __update_runtime_status(dev, RPM_ACTIVE);
                if (parent)
                        atomic_inc(&parent->power.child_count);
@@ -460,7 +581,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
        wake_up_all(&dev->power.wait_queue);
 
        if (!retval)
-               __pm_request_idle(dev);
+               rpm_idle(dev, RPM_ASYNC);
 
  out:
        if (parent) {
@@ -471,27 +592,11 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
                spin_lock_irq(&dev->power.lock);
        }
 
-       dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval);
+       dev_dbg(dev, "%s returns %d\n", __func__, retval);
 
        return retval;
 }
 
-/**
- * pm_runtime_resume - Carry out run-time resume of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_resume(struct device *dev)
-{
-       int retval;
-
-       spin_lock_irq(&dev->power.lock);
-       retval = __pm_runtime_resume(dev, false);
-       spin_unlock_irq(&dev->power.lock);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_resume);
-
 /**
  * pm_runtime_work - Universal run-time PM work function.
  * @work: Work structure used for scheduling the execution of this function.
@@ -517,13 +622,16 @@ static void pm_runtime_work(struct work_struct *work)
        case RPM_REQ_NONE:
                break;
        case RPM_REQ_IDLE:
-               __pm_runtime_idle(dev);
+               rpm_idle(dev, RPM_NOWAIT);
                break;
        case RPM_REQ_SUSPEND:
-               __pm_runtime_suspend(dev, true);
+               rpm_suspend(dev, RPM_NOWAIT);
+               break;
+       case RPM_REQ_AUTOSUSPEND:
+               rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
                break;
        case RPM_REQ_RESUME:
-               __pm_runtime_resume(dev, true);
+               rpm_resume(dev, RPM_NOWAIT);
                break;
        }
 
@@ -531,118 +639,11 @@ static void pm_runtime_work(struct work_struct *work)
        spin_unlock_irq(&dev->power.lock);
 }
 
-/**
- * __pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- *
- * Check if the device's run-time PM status is correct for suspending the device
- * and queue up a request to run __pm_runtime_idle() for it.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_idle(struct device *dev)
-{
-       int retval = 0;
-
-       if (dev->power.runtime_error)
-               retval = -EINVAL;
-       else if (atomic_read(&dev->power.usage_count) > 0
-           || dev->power.disable_depth > 0
-           || dev->power.runtime_status == RPM_SUSPENDED
-           || dev->power.runtime_status == RPM_SUSPENDING)
-               retval = -EAGAIN;
-       else if (!pm_children_suspended(dev))
-               retval = -EBUSY;
-       if (retval)
-               return retval;
-
-       if (dev->power.request_pending) {
-               /* Any requests other then RPM_REQ_IDLE take precedence. */
-               if (dev->power.request == RPM_REQ_NONE)
-                       dev->power.request = RPM_REQ_IDLE;
-               else if (dev->power.request != RPM_REQ_IDLE)
-                       retval = -EAGAIN;
-               return retval;
-       }
-
-       dev->power.request = RPM_REQ_IDLE;
-       dev->power.request_pending = true;
-       queue_work(pm_wq, &dev->power.work);
-
-       return retval;
-}
-
-/**
- * pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- */
-int pm_request_idle(struct device *dev)
-{
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&dev->power.lock, flags);
-       retval = __pm_request_idle(dev);
-       spin_unlock_irqrestore(&dev->power.lock, flags);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(pm_request_idle);
-
-/**
- * __pm_request_suspend - Submit a suspend request for given device.
- * @dev: Device to suspend.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_suspend(struct device *dev)
-{
-       int retval = 0;
-
-       if (dev->power.runtime_error)
-               return -EINVAL;
-
-       if (dev->power.runtime_status == RPM_SUSPENDED)
-               retval = 1;
-       else if (atomic_read(&dev->power.usage_count) > 0
-           || dev->power.disable_depth > 0)
-               retval = -EAGAIN;
-       else if (dev->power.runtime_status == RPM_SUSPENDING)
-               retval = -EINPROGRESS;
-       else if (!pm_children_suspended(dev))
-               retval = -EBUSY;
-       if (retval < 0)
-               return retval;
-
-       pm_runtime_deactivate_timer(dev);
-
-       if (dev->power.request_pending) {
-               /*
-                * Pending resume requests take precedence over us, but we can
-                * overtake any other pending request.
-                */
-               if (dev->power.request == RPM_REQ_RESUME)
-                       retval = -EAGAIN;
-               else if (dev->power.request != RPM_REQ_SUSPEND)
-                       dev->power.request = retval ?
-                                               RPM_REQ_NONE : RPM_REQ_SUSPEND;
-               return retval;
-       } else if (retval) {
-               return retval;
-       }
-
-       dev->power.request = RPM_REQ_SUSPEND;
-       dev->power.request_pending = true;
-       queue_work(pm_wq, &dev->power.work);
-
-       return 0;
-}
-
 /**
  * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
  * @data: Device pointer passed by pm_schedule_suspend().
  *
- * Check if the time is right and execute __pm_request_suspend() in that case.
+ * Check if the time is right and queue a suspend request.
  */
 static void pm_suspend_timer_fn(unsigned long data)
 {
@@ -656,7 +657,8 @@ static void pm_suspend_timer_fn(unsigned long data)
        /* If 'expire' is after 'jiffies' we've been called too early. */
        if (expires > 0 && !time_after(expires, jiffies)) {
                dev->power.timer_expires = 0;
-               __pm_request_suspend(dev);
+               rpm_suspend(dev, dev->power.timer_autosuspends ?
+                   (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
        }
 
        spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -670,47 +672,25 @@ static void pm_suspend_timer_fn(unsigned long data)
 int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        unsigned long flags;
-       int retval = 0;
+       int retval;
 
        spin_lock_irqsave(&dev->power.lock, flags);
 
-       if (dev->power.runtime_error) {
-               retval = -EINVAL;
-               goto out;
-       }
-
        if (!delay) {
-               retval = __pm_request_suspend(dev);
+               retval = rpm_suspend(dev, RPM_ASYNC);
                goto out;
        }
 
-       pm_runtime_deactivate_timer(dev);
-
-       if (dev->power.request_pending) {
-               /*
-                * Pending resume requests take precedence over us, but any
-                * other pending requests have to be canceled.
-                */
-               if (dev->power.request == RPM_REQ_RESUME) {
-                       retval = -EAGAIN;
-                       goto out;
-               }
-               dev->power.request = RPM_REQ_NONE;
-       }
-
-       if (dev->power.runtime_status == RPM_SUSPENDED)
-               retval = 1;
-       else if (atomic_read(&dev->power.usage_count) > 0
-           || dev->power.disable_depth > 0)
-               retval = -EAGAIN;
-       else if (!pm_children_suspended(dev))
-               retval = -EBUSY;
+       retval = rpm_check_suspend_allowed(dev);
        if (retval)
                goto out;
 
+       /* Other scheduled or pending requests need to be canceled. */
+       pm_runtime_cancel_pending(dev);
+
        dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
-       if (!dev->power.timer_expires)
-               dev->power.timer_expires = 1;
+       dev->power.timer_expires += !dev->power.timer_expires;
+       dev->power.timer_autosuspends = 0;
        mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
 
  out:
@@ -721,103 +701,88 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
 EXPORT_SYMBOL_GPL(pm_schedule_suspend);
 
 /**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
+ * __pm_runtime_idle - Entry point for run-time idle operations.
+ * @dev: Device to send idle notification for.
+ * @rpmflags: Flag bits.
  *
- * This function must be called under dev->power.lock with interrupts disabled.
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero.  Then carry out an idle
+ * notification, either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-static int __pm_request_resume(struct device *dev)
+int __pm_runtime_idle(struct device *dev, int rpmflags)
 {
-       int retval = 0;
-
-       if (dev->power.runtime_error)
-               return -EINVAL;
-
-       if (dev->power.runtime_status == RPM_ACTIVE)
-               retval = 1;
-       else if (dev->power.runtime_status == RPM_RESUMING)
-               retval = -EINPROGRESS;
-       else if (dev->power.disable_depth > 0)
-               retval = -EAGAIN;
-       if (retval < 0)
-               return retval;
-
-       pm_runtime_deactivate_timer(dev);
+       unsigned long flags;
+       int retval;
 
-       if (dev->power.runtime_status == RPM_SUSPENDING) {
-               dev->power.deferred_resume = true;
-               return retval;
+       if (rpmflags & RPM_GET_PUT) {
+               if (!atomic_dec_and_test(&dev->power.usage_count))
+                       return 0;
        }
-       if (dev->power.request_pending) {
-               /* If non-resume request is pending, we can overtake it. */
-               dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
-               return retval;
-       }
-       if (retval)
-               return retval;
 
-       dev->power.request = RPM_REQ_RESUME;
-       dev->power.request_pending = true;
-       queue_work(pm_wq, &dev->power.work);
+       spin_lock_irqsave(&dev->power.lock, flags);
+       retval = rpm_idle(dev, rpmflags);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
 
        return retval;
 }
+EXPORT_SYMBOL_GPL(__pm_runtime_idle);
 
 /**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
+ * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * @dev: Device to suspend.
+ * @rpmflags: Flag bits.
+ *
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero.  Then carry out a suspend,
+ * either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-int pm_request_resume(struct device *dev)
+int __pm_runtime_suspend(struct device *dev, int rpmflags)
 {
        unsigned long flags;
        int retval;
 
+       if (rpmflags & RPM_GET_PUT) {
+               if (!atomic_dec_and_test(&dev->power.usage_count))
+                       return 0;
+       }
+
        spin_lock_irqsave(&dev->power.lock, flags);
-       retval = __pm_request_resume(dev);
+       retval = rpm_suspend(dev, rpmflags);
        spin_unlock_irqrestore(&dev->power.lock, flags);
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(pm_request_resume);
+EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
 
 /**
- * __pm_runtime_get - Reference count a device and wake it up, if necessary.
- * @dev: Device to handle.
- * @sync: If set and the device is suspended, resume it synchronously.
+ * __pm_runtime_resume - Entry point for run-time resume operations.
+ * @dev: Device to resume.
+ * @rpmflags: Flag bits.
+ *
+ * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
+ * carry out a resume, either synchronous or asynchronous.
  *
- * Increment the usage count of the device and resume it or submit a resume
- * request for it, depending on the value of @sync.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-int __pm_runtime_get(struct device *dev, bool sync)
+int __pm_runtime_resume(struct device *dev, int rpmflags)
 {
+       unsigned long flags;
        int retval;
 
-       atomic_inc(&dev->power.usage_count);
-       retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+       if (rpmflags & RPM_GET_PUT)
+               atomic_inc(&dev->power.usage_count);
 
-       return retval;
-}
-EXPORT_SYMBOL_GPL(__pm_runtime_get);
-
-/**
- * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
- * @dev: Device to handle.
- * @sync: If the device's bus type is to be notified, do that synchronously.
- *
- * Decrement the usage count of the device and if it reaches zero, carry out a
- * synchronous idle notification or submit an idle notification request for it,
- * depending on the value of @sync.
- */
-int __pm_runtime_put(struct device *dev, bool sync)
-{
-       int retval = 0;
-
-       if (atomic_dec_and_test(&dev->power.usage_count))
-               retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);
+       spin_lock_irqsave(&dev->power.lock, flags);
+       retval = rpm_resume(dev, rpmflags);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(__pm_runtime_put);
+EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
 /**
  * __pm_runtime_set_status - Set run-time PM status of a device.
@@ -968,7 +933,7 @@ int pm_runtime_barrier(struct device *dev)
 
        if (dev->power.request_pending
            && dev->power.request == RPM_REQ_RESUME) {
-               __pm_runtime_resume(dev, false);
+               rpm_resume(dev, 0);
                retval = 1;
        }
 
@@ -1017,7 +982,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
                 */
                pm_runtime_get_noresume(dev);
 
-               __pm_runtime_resume(dev, false);
+               rpm_resume(dev, 0);
 
                pm_runtime_put_noidle(dev);
        }
@@ -1065,7 +1030,7 @@ void pm_runtime_forbid(struct device *dev)
 
        dev->power.runtime_auto = false;
        atomic_inc(&dev->power.usage_count);
-       __pm_runtime_resume(dev, false);
+       rpm_resume(dev, 0);
 
  out:
        spin_unlock_irq(&dev->power.lock);
@@ -1086,21 +1051,118 @@ void pm_runtime_allow(struct device *dev)
 
        dev->power.runtime_auto = true;
        if (atomic_dec_and_test(&dev->power.usage_count))
-               __pm_runtime_idle(dev);
+               rpm_idle(dev, RPM_AUTO);
 
  out:
        spin_unlock_irq(&dev->power.lock);
 }
 EXPORT_SYMBOL_GPL(pm_runtime_allow);
 
+/**
+ * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * @dev: Device to handle.
+ *
+ * Set the power.no_callbacks flag, which tells the PM core that this
+ * device is power-managed through its parent and has no run-time PM
+ * callbacks of its own.  The run-time sysfs attributes will be removed.
+ *
+ */
+void pm_runtime_no_callbacks(struct device *dev)
+{
+       spin_lock_irq(&dev->power.lock);
+       dev->power.no_callbacks = 1;
+       spin_unlock_irq(&dev->power.lock);
+       if (device_is_registered(dev))
+               rpm_sysfs_remove(dev);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
+
+/**
+ * update_autosuspend - Handle a change to a device's autosuspend settings.
+ * @dev: Device to handle.
+ * @old_delay: The former autosuspend_delay value.
+ * @old_use: The former use_autosuspend value.
+ *
+ * Prevent runtime suspend if the new delay is negative and use_autosuspend is
+ * set; otherwise allow it.  Send an idle notification if suspends are allowed.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static void update_autosuspend(struct device *dev, int old_delay, int old_use)
+{
+       int delay = dev->power.autosuspend_delay;
+
+       /* Should runtime suspend be prevented now? */
+       if (dev->power.use_autosuspend && delay < 0) {
+
+               /* If it used to be allowed then prevent it. */
+               if (!old_use || old_delay >= 0) {
+                       atomic_inc(&dev->power.usage_count);
+                       rpm_resume(dev, 0);
+               }
+       }
+
+       /* Runtime suspend should be allowed now. */
+       else {
+
+               /* If it used to be prevented then allow it. */
+               if (old_use && old_delay < 0)
+                       atomic_dec(&dev->power.usage_count);
+
+               /* Maybe we can autosuspend now. */
+               rpm_idle(dev, RPM_AUTO);
+       }
+}
+
+/**
+ * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value.
+ * @dev: Device to handle.
+ * @delay: Value of the new delay in milliseconds.
+ *
+ * Set the device's power.autosuspend_delay value.  If it changes to negative
+ * and the power.use_autosuspend flag is set, prevent run-time suspends.  If it
+ * changes the other way, allow run-time suspends.
+ */
+void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
+{
+       int old_delay, old_use;
+
+       spin_lock_irq(&dev->power.lock);
+       old_delay = dev->power.autosuspend_delay;
+       old_use = dev->power.use_autosuspend;
+       dev->power.autosuspend_delay = delay;
+       update_autosuspend(dev, old_delay, old_use);
+       spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
+
+/**
+ * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag.
+ * @dev: Device to handle.
+ * @use: New value for use_autosuspend.
+ *
+ * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * suspends as needed.
+ */
+void __pm_runtime_use_autosuspend(struct device *dev, bool use)
+{
+       int old_delay, old_use;
+
+       spin_lock_irq(&dev->power.lock);
+       old_delay = dev->power.autosuspend_delay;
+       old_use = dev->power.use_autosuspend;
+       dev->power.use_autosuspend = use;
+       update_autosuspend(dev, old_delay, old_use);
+       spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
+
 /**
  * pm_runtime_init - Initialize run-time PM fields in given device object.
  * @dev: Device object to initialize.
  */
 void pm_runtime_init(struct device *dev)
 {
-       spin_lock_init(&dev->power.lock);
-
        dev->power.runtime_status = RPM_SUSPENDED;
        dev->power.idle_notification = false;
 
index e56b4388fe61004a1f85e0209cbc59bd60f4d1fb..0b1e46bf3e56950e45366ab46a664992ac2c1f0f 100644 (file)
  *     attribute is set to "enabled" by bus type code or device drivers and in
  *     that cases it should be safe to leave the default value.
  *
+ *     autosuspend_delay_ms - Report/change a device's autosuspend_delay value
+ *
+ *     Some drivers don't want to carry out a runtime suspend as soon as a
+ *     device becomes idle; they want it always to remain idle for some period
+ *     of time before suspending it.  This period is the autosuspend_delay
+ *     value (expressed in milliseconds) and it can be controlled by the user.
+ *     If the value is negative then the device will never be runtime
+ *     suspended.
+ *
+ *     NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay
+ *     value are used only if the driver calls pm_runtime_use_autosuspend().
+ *
  *     wakeup_count - Report the number of wakeup events related to the device
  */
 
 static const char enabled[] = "enabled";
 static const char disabled[] = "disabled";
 
+const char power_group_name[] = "power";
+EXPORT_SYMBOL_GPL(power_group_name);
+
 #ifdef CONFIG_PM_RUNTIME
 static const char ctrl_auto[] = "auto";
 static const char ctrl_on[] = "on";
@@ -170,6 +185,33 @@ static ssize_t rtpm_status_show(struct device *dev,
 }
 
 static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
+
+static ssize_t autosuspend_delay_ms_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       if (!dev->power.use_autosuspend)
+               return -EIO;
+       return sprintf(buf, "%d\n", dev->power.autosuspend_delay);
+}
+
+static ssize_t autosuspend_delay_ms_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t n)
+{
+       long delay;
+
+       if (!dev->power.use_autosuspend)
+               return -EIO;
+
+       if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+               return -EINVAL;
+
+       pm_runtime_set_autosuspend_delay(dev, delay);
+       return n;
+}
+
+static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
+               autosuspend_delay_ms_store);
+
 #endif
 
 static ssize_t
@@ -210,11 +252,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
 static ssize_t wakeup_count_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%lu\n", dev->power.wakeup_count);
+       unsigned long count = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               count = dev->power.wakeup->event_count;
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
 }
 
 static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL);
-#endif
+
+static ssize_t wakeup_active_count_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       unsigned long count = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               count = dev->power.wakeup->active_count;
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
+
+static ssize_t wakeup_hit_count_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       unsigned long count = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               count = dev->power.wakeup->hit_count;
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
+
+static ssize_t wakeup_active_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       unsigned int active = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               active = dev->power.wakeup->active;
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL);
+
+static ssize_t wakeup_total_time_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       s64 msec = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               msec = ktime_to_ms(dev->power.wakeup->total_time);
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL);
+
+static ssize_t wakeup_max_time_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       s64 msec = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               msec = ktime_to_ms(dev->power.wakeup->max_time);
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL);
+
+static ssize_t wakeup_last_time_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       s64 msec = 0;
+       bool enabled = false;
+
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               msec = ktime_to_ms(dev->power.wakeup->last_time);
+               enabled = true;
+       }
+       spin_unlock_irq(&dev->power.lock);
+       return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_ADVANCED_DEBUG
 #ifdef CONFIG_PM_RUNTIME
@@ -279,19 +432,20 @@ static DEVICE_ATTR(async, 0644, async_show, async_store);
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
 static struct attribute * power_attrs[] = {
-#ifdef CONFIG_PM_RUNTIME
-       &dev_attr_control.attr,
-       &dev_attr_runtime_status.attr,
-       &dev_attr_runtime_suspended_time.attr,
-       &dev_attr_runtime_active_time.attr,
-#endif
        &dev_attr_wakeup.attr,
 #ifdef CONFIG_PM_SLEEP
        &dev_attr_wakeup_count.attr,
+       &dev_attr_wakeup_active_count.attr,
+       &dev_attr_wakeup_hit_count.attr,
+       &dev_attr_wakeup_active.attr,
+       &dev_attr_wakeup_total_time_ms.attr,
+       &dev_attr_wakeup_max_time_ms.attr,
+       &dev_attr_wakeup_last_time_ms.attr,
 #endif
 #ifdef CONFIG_PM_ADVANCED_DEBUG
        &dev_attr_async.attr,
 #ifdef CONFIG_PM_RUNTIME
+       &dev_attr_runtime_status.attr,
        &dev_attr_runtime_usage.attr,
        &dev_attr_runtime_active_kids.attr,
        &dev_attr_runtime_enabled.attr,
@@ -300,10 +454,53 @@ static struct attribute * power_attrs[] = {
        NULL,
 };
 static struct attribute_group pm_attr_group = {
-       .name   = "power",
+       .name   = power_group_name,
        .attrs  = power_attrs,
 };
 
+#ifdef CONFIG_PM_RUNTIME
+
+static struct attribute *runtime_attrs[] = {
+#ifndef CONFIG_PM_ADVANCED_DEBUG
+       &dev_attr_runtime_status.attr,
+#endif
+       &dev_attr_control.attr,
+       &dev_attr_runtime_suspended_time.attr,
+       &dev_attr_runtime_active_time.attr,
+       &dev_attr_autosuspend_delay_ms.attr,
+       NULL,
+};
+static struct attribute_group pm_runtime_attr_group = {
+       .name   = power_group_name,
+       .attrs  = runtime_attrs,
+};
+
+int dpm_sysfs_add(struct device *dev)
+{
+       int rc;
+
+       rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
+       if (rc == 0 && !dev->power.no_callbacks) {
+               rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
+               if (rc)
+                       sysfs_remove_group(&dev->kobj, &pm_attr_group);
+       }
+       return rc;
+}
+
+void rpm_sysfs_remove(struct device *dev)
+{
+       sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
+}
+
+void dpm_sysfs_remove(struct device *dev)
+{
+       rpm_sysfs_remove(dev);
+       sysfs_remove_group(&dev->kobj, &pm_attr_group);
+}
+
+#else /* CONFIG_PM_RUNTIME */
+
 int dpm_sysfs_add(struct device * dev)
 {
        return sysfs_create_group(&dev->kobj, &pm_attr_group);
@@ -313,3 +510,5 @@ void dpm_sysfs_remove(struct device * dev)
 {
        sysfs_remove_group(&dev->kobj, &pm_attr_group);
 }
+
+#endif
index 0a1a2c4dbc6e75e5647117b97ae1f055c2fdb080..9f4258df4cfdbace7c80d889154738f17c7d8461 100644 (file)
@@ -188,8 +188,10 @@ static int show_file_hash(unsigned int value)
 static int show_dev_hash(unsigned int value)
 {
        int match = 0;
-       struct list_head *entry = dpm_list.prev;
+       struct list_head *entry;
 
+       device_pm_lock();
+       entry = dpm_list.prev;
        while (entry != &dpm_list) {
                struct device * dev = to_device(entry);
                unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH);
@@ -199,11 +201,43 @@ static int show_dev_hash(unsigned int value)
                }
                entry = entry->prev;
        }
+       device_pm_unlock();
        return match;
 }
 
 static unsigned int hash_value_early_read;
 
+int show_trace_dev_match(char *buf, size_t size)
+{
+       unsigned int value = hash_value_early_read / (USERHASH * FILEHASH);
+       int ret = 0;
+       struct list_head *entry;
+
+       /*
+        * It's possible that multiple devices will match the hash and we can't
+        * tell which is the culprit, so it's best to output them all.
+        */
+       device_pm_lock();
+       entry = dpm_list.prev;
+       while (size && entry != &dpm_list) {
+               struct device *dev = to_device(entry);
+               unsigned int hash = hash_string(DEVSEED, dev_name(dev),
+                                               DEVHASH);
+               if (hash == value) {
+                       int len = snprintf(buf, size, "%s\n",
+                                           dev_driver_string(dev));
+                       if (len > size)
+                               len = size;
+                       buf += len;
+                       ret += len;
+                       size -= len;
+               }
+               entry = entry->prev;
+       }
+       device_pm_unlock();
+       return ret;
+}
+
 static int early_resume_init(void)
 {
        hash_value_early_read = read_magic_time();
index eb594facfc3f8a027e982fb9b67984643c400219..71c5528e1c357a81112c6f79b1e91f013a58e3aa 100644 (file)
 #include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/suspend.h>
-#include <linux/pm.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include "power.h"
+
+#define TIMEOUT                100
 
 /*
  * If set, the suspend/hibernate code will abort transitions to a sleep state
 bool events_check_enabled;
 
 /* The counter of registered wakeup events. */
-static unsigned long event_count;
+static atomic_t event_count = ATOMIC_INIT(0);
 /* A preserved old value of event_count. */
-static unsigned long saved_event_count;
+static unsigned int saved_count;
 /* The counter of wakeup events being processed. */
-static unsigned long events_in_progress;
+static atomic_t events_in_progress = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(events_lock);
 
 static void pm_wakeup_timer_fn(unsigned long data);
 
-static DEFINE_TIMER(events_timer, pm_wakeup_timer_fn, 0, 0);
-static unsigned long events_timer_expires;
+static LIST_HEAD(wakeup_sources);
+
+/**
+ * wakeup_source_create - Create a struct wakeup_source object.
+ * @name: Name of the new wakeup source.
+ */
+struct wakeup_source *wakeup_source_create(const char *name)
+{
+       struct wakeup_source *ws;
+
+       ws = kzalloc(sizeof(*ws), GFP_KERNEL);
+       if (!ws)
+               return NULL;
+
+       spin_lock_init(&ws->lock);
+       if (name)
+               ws->name = kstrdup(name, GFP_KERNEL);
+
+       return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_create);
+
+/**
+ * wakeup_source_destroy - Destroy a struct wakeup_source object.
+ * @ws: Wakeup source to destroy.
+ */
+void wakeup_source_destroy(struct wakeup_source *ws)
+{
+       if (!ws)
+               return;
+
+       spin_lock_irq(&ws->lock);
+       while (ws->active) {
+               spin_unlock_irq(&ws->lock);
+
+               schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
+
+               spin_lock_irq(&ws->lock);
+       }
+       spin_unlock_irq(&ws->lock);
+
+       kfree(ws->name);
+       kfree(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_destroy);
+
+/**
+ * wakeup_source_add - Add given object to the list of wakeup sources.
+ * @ws: Wakeup source object to add to the list.
+ */
+void wakeup_source_add(struct wakeup_source *ws)
+{
+       if (WARN_ON(!ws))
+               return;
+
+       setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
+       ws->active = false;
+
+       spin_lock_irq(&events_lock);
+       list_add_rcu(&ws->entry, &wakeup_sources);
+       spin_unlock_irq(&events_lock);
+       synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_add);
+
+/**
+ * wakeup_source_remove - Remove given object from the wakeup sources list.
+ * @ws: Wakeup source object to remove from the list.
+ */
+void wakeup_source_remove(struct wakeup_source *ws)
+{
+       if (WARN_ON(!ws))
+               return;
+
+       spin_lock_irq(&events_lock);
+       list_del_rcu(&ws->entry);
+       spin_unlock_irq(&events_lock);
+       synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_remove);
+
+/**
+ * wakeup_source_register - Create wakeup source and add it to the list.
+ * @name: Name of the wakeup source to register.
+ */
+struct wakeup_source *wakeup_source_register(const char *name)
+{
+       struct wakeup_source *ws;
+
+       ws = wakeup_source_create(name);
+       if (ws)
+               wakeup_source_add(ws);
+
+       return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_register);
+
+/**
+ * wakeup_source_unregister - Remove wakeup source from the list and remove it.
+ * @ws: Wakeup source object to unregister.
+ */
+void wakeup_source_unregister(struct wakeup_source *ws)
+{
+       wakeup_source_remove(ws);
+       wakeup_source_destroy(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_unregister);
+
+/**
+ * device_wakeup_attach - Attach a wakeup source object to a device object.
+ * @dev: Device to handle.
+ * @ws: Wakeup source object to attach to @dev.
+ *
+ * This causes @dev to be treated as a wakeup device.
+ */
+static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
+{
+       spin_lock_irq(&dev->power.lock);
+       if (dev->power.wakeup) {
+               spin_unlock_irq(&dev->power.lock);
+               return -EEXIST;
+       }
+       dev->power.wakeup = ws;
+       spin_unlock_irq(&dev->power.lock);
+       return 0;
+}
+
+/**
+ * device_wakeup_enable - Enable given device to be a wakeup source.
+ * @dev: Device to handle.
+ *
+ * Create a wakeup source object, register it and attach it to @dev.
+ */
+int device_wakeup_enable(struct device *dev)
+{
+       struct wakeup_source *ws;
+       int ret;
+
+       if (!dev || !dev->power.can_wakeup)
+               return -EINVAL;
+
+       ws = wakeup_source_register(dev_name(dev));
+       if (!ws)
+               return -ENOMEM;
+
+       ret = device_wakeup_attach(dev, ws);
+       if (ret)
+               wakeup_source_unregister(ws);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_enable);
+
+/**
+ * device_wakeup_detach - Detach a device's wakeup source object from it.
+ * @dev: Device to detach the wakeup source object from.
+ *
+ * After it returns, @dev will not be treated as a wakeup device any more.
+ */
+static struct wakeup_source *device_wakeup_detach(struct device *dev)
+{
+       struct wakeup_source *ws;
+
+       spin_lock_irq(&dev->power.lock);
+       ws = dev->power.wakeup;
+       dev->power.wakeup = NULL;
+       spin_unlock_irq(&dev->power.lock);
+       return ws;
+}
+
+/**
+ * device_wakeup_disable - Do not regard a device as a wakeup source any more.
+ * @dev: Device to handle.
+ *
+ * Detach the @dev's wakeup source object from it, unregister this wakeup source
+ * object and destroy it.
+ */
+int device_wakeup_disable(struct device *dev)
+{
+       struct wakeup_source *ws;
+
+       if (!dev || !dev->power.can_wakeup)
+               return -EINVAL;
+
+       ws = device_wakeup_detach(dev);
+       if (ws)
+               wakeup_source_unregister(ws);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_disable);
+
+/**
+ * device_init_wakeup - Device wakeup initialization.
+ * @dev: Device to handle.
+ * @enable: Whether or not to enable @dev as a wakeup device.
+ *
+ * By default, most devices should leave wakeup disabled.  The exceptions are
+ * devices that everyone expects to be wakeup sources: keyboards, power buttons,
+ * possibly network interfaces, etc.
+ */
+int device_init_wakeup(struct device *dev, bool enable)
+{
+       int ret = 0;
+
+       if (enable) {
+               device_set_wakeup_capable(dev, true);
+               ret = device_wakeup_enable(dev);
+       } else {
+               device_set_wakeup_capable(dev, false);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(device_init_wakeup);
+
+/**
+ * device_set_wakeup_enable - Enable or disable a device to wake up the system.
+ * @dev: Device to handle.
+ */
+int device_set_wakeup_enable(struct device *dev, bool enable)
+{
+       if (!dev || !dev->power.can_wakeup)
+               return -EINVAL;
+
+       return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
+}
+EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
 
 /*
  * The functions below use the observation that each wakeup event starts a
@@ -55,118 +286,259 @@ static unsigned long events_timer_expires;
  * knowledge, however, may not be available to it, so it can simply specify time
  * to wait before the system can be suspended and pass it as the second
  * argument of pm_wakeup_event().
+ *
+ * It is valid to call pm_relax() after pm_wakeup_event(), in which case the
+ * "no suspend" period will be ended either by the pm_relax(), or by the timer
+ * function executed when the timer expires, whichever comes first.
  */
 
+/**
+ * wakup_source_activate - Mark given wakeup source as active.
+ * @ws: Wakeup source to handle.
+ *
+ * Update the @ws' statistics and, if @ws has just been activated, notify the PM
+ * core of the event by incrementing the counter of of wakeup events being
+ * processed.
+ */
+static void wakeup_source_activate(struct wakeup_source *ws)
+{
+       ws->active = true;
+       ws->active_count++;
+       ws->timer_expires = jiffies;
+       ws->last_time = ktime_get();
+
+       atomic_inc(&events_in_progress);
+}
+
+/**
+ * __pm_stay_awake - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the source of the event.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_stay_awake(struct wakeup_source *ws)
+{
+       unsigned long flags;
+
+       if (!ws)
+               return;
+
+       spin_lock_irqsave(&ws->lock, flags);
+       ws->event_count++;
+       if (!ws->active)
+               wakeup_source_activate(ws);
+       spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_stay_awake);
+
 /**
  * pm_stay_awake - Notify the PM core that a wakeup event is being processed.
  * @dev: Device the wakeup event is related to.
  *
- * Notify the PM core of a wakeup event (signaled by @dev) by incrementing the
- * counter of wakeup events being processed.  If @dev is not NULL, the counter
- * of wakeup events related to @dev is incremented too.
+ * Notify the PM core of a wakeup event (signaled by @dev) by calling
+ * __pm_stay_awake for the @dev's wakeup source object.
  *
  * Call this function after detecting of a wakeup event if pm_relax() is going
  * to be called directly after processing the event (and possibly passing it to
  * user space for further processing).
- *
- * It is safe to call this function from interrupt context.
  */
 void pm_stay_awake(struct device *dev)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&events_lock, flags);
-       if (dev)
-               dev->power.wakeup_count++;
+       if (!dev)
+               return;
 
-       events_in_progress++;
-       spin_unlock_irqrestore(&events_lock, flags);
+       spin_lock_irqsave(&dev->power.lock, flags);
+       __pm_stay_awake(dev->power.wakeup);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
 }
+EXPORT_SYMBOL_GPL(pm_stay_awake);
 
 /**
- * pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * wakup_source_deactivate - Mark given wakeup source as inactive.
+ * @ws: Wakeup source to handle.
  *
- * Notify the PM core that a wakeup event has been processed by decrementing
- * the counter of wakeup events being processed and incrementing the counter
- * of registered wakeup events.
+ * Update the @ws' statistics and notify the PM core that the wakeup source has
+ * become inactive by decrementing the counter of wakeup events being processed
+ * and incrementing the counter of registered wakeup events.
+ */
+static void wakeup_source_deactivate(struct wakeup_source *ws)
+{
+       ktime_t duration;
+       ktime_t now;
+
+       ws->relax_count++;
+       /*
+        * __pm_relax() may be called directly or from a timer function.
+        * If it is called directly right after the timer function has been
+        * started, but before the timer function calls __pm_relax(), it is
+        * possible that __pm_stay_awake() will be called in the meantime and
+        * will set ws->active.  Then, ws->active may be cleared immediately
+        * by the __pm_relax() called from the timer function, but in such a
+        * case ws->relax_count will be different from ws->active_count.
+        */
+       if (ws->relax_count != ws->active_count) {
+               ws->relax_count--;
+               return;
+       }
+
+       ws->active = false;
+
+       now = ktime_get();
+       duration = ktime_sub(now, ws->last_time);
+       ws->total_time = ktime_add(ws->total_time, duration);
+       if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
+               ws->max_time = duration;
+
+       del_timer(&ws->timer);
+
+       /*
+        * event_count has to be incremented before events_in_progress is
+        * modified, so that the callers of pm_check_wakeup_events() and
+        * pm_save_wakeup_count() don't see the old value of event_count and
+        * events_in_progress equal to zero at the same time.
+        */
+       atomic_inc(&event_count);
+       smp_mb__before_atomic_dec();
+       atomic_dec(&events_in_progress);
+}
+
+/**
+ * __pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @ws: Wakeup source object associated with the source of the event.
  *
  * Call this function for wakeup events whose processing started with calling
- * pm_stay_awake().
+ * __pm_stay_awake().
  *
  * It is safe to call it from interrupt context.
  */
-void pm_relax(void)
+void __pm_relax(struct wakeup_source *ws)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&events_lock, flags);
-       if (events_in_progress) {
-               events_in_progress--;
-               event_count++;
-       }
-       spin_unlock_irqrestore(&events_lock, flags);
+       if (!ws)
+               return;
+
+       spin_lock_irqsave(&ws->lock, flags);
+       if (ws->active)
+               wakeup_source_deactivate(ws);
+       spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_relax);
+
+/**
+ * pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @dev: Device that signaled the event.
+ *
+ * Execute __pm_relax() for the @dev's wakeup source object.
+ */
+void pm_relax(struct device *dev)
+{
+       unsigned long flags;
+
+       if (!dev)
+               return;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+       __pm_relax(dev->power.wakeup);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
 }
+EXPORT_SYMBOL_GPL(pm_relax);
 
 /**
  * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
+ * @data: Address of the wakeup source object associated with the event source.
  *
- * Decrease the counter of wakeup events being processed after it was increased
- * by pm_wakeup_event().
+ * Call __pm_relax() for the wakeup source whose address is stored in @data.
  */
 static void pm_wakeup_timer_fn(unsigned long data)
+{
+       __pm_relax((struct wakeup_source *)data);
+}
+
+/**
+ * __pm_wakeup_event - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the event source.
+ * @msec: Anticipated event processing time (in milliseconds).
+ *
+ * Notify the PM core of a wakeup event whose source is @ws that will take
+ * approximately @msec milliseconds to be processed by the kernel.  If @ws is
+ * not active, activate it.  If @msec is nonzero, set up the @ws' timer to
+ * execute pm_wakeup_timer_fn() in future.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
 {
        unsigned long flags;
+       unsigned long expires;
 
-       spin_lock_irqsave(&events_lock, flags);
-       if (events_timer_expires
-           && time_before_eq(events_timer_expires, jiffies)) {
-               events_in_progress--;
-               events_timer_expires = 0;
+       if (!ws)
+               return;
+
+       spin_lock_irqsave(&ws->lock, flags);
+
+       ws->event_count++;
+       if (!ws->active)
+               wakeup_source_activate(ws);
+
+       if (!msec) {
+               wakeup_source_deactivate(ws);
+               goto unlock;
        }
-       spin_unlock_irqrestore(&events_lock, flags);
+
+       expires = jiffies + msecs_to_jiffies(msec);
+       if (!expires)
+               expires = 1;
+
+       if (time_after(expires, ws->timer_expires)) {
+               mod_timer(&ws->timer, expires);
+               ws->timer_expires = expires;
+       }
+
+ unlock:
+       spin_unlock_irqrestore(&ws->lock, flags);
 }
+EXPORT_SYMBOL_GPL(__pm_wakeup_event);
+
 
 /**
  * pm_wakeup_event - Notify the PM core of a wakeup event.
  * @dev: Device the wakeup event is related to.
  * @msec: Anticipated event processing time (in milliseconds).
  *
- * Notify the PM core of a wakeup event (signaled by @dev) that will take
- * approximately @msec milliseconds to be processed by the kernel.  Increment
- * the counter of registered wakeup events and (if @msec is nonzero) set up
- * the wakeup events timer to execute pm_wakeup_timer_fn() in future (if the
- * timer has not been set up already, increment the counter of wakeup events
- * being processed).  If @dev is not NULL, the counter of wakeup events related
- * to @dev is incremented too.
- *
- * It is safe to call this function from interrupt context.
+ * Call __pm_wakeup_event() for the @dev's wakeup source object.
  */
 void pm_wakeup_event(struct device *dev, unsigned int msec)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&events_lock, flags);
-       event_count++;
-       if (dev)
-               dev->power.wakeup_count++;
-
-       if (msec) {
-               unsigned long expires;
+       if (!dev)
+               return;
 
-               expires = jiffies + msecs_to_jiffies(msec);
-               if (!expires)
-                       expires = 1;
+       spin_lock_irqsave(&dev->power.lock, flags);
+       __pm_wakeup_event(dev->power.wakeup, msec);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_wakeup_event);
 
-               if (!events_timer_expires
-                   || time_after(expires, events_timer_expires)) {
-                       if (!events_timer_expires)
-                               events_in_progress++;
+/**
+ * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
+ */
+static void pm_wakeup_update_hit_counts(void)
+{
+       unsigned long flags;
+       struct wakeup_source *ws;
 
-                       mod_timer(&events_timer, expires);
-                       events_timer_expires = expires;
-               }
+       rcu_read_lock();
+       list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+               spin_lock_irqsave(&ws->lock, flags);
+               if (ws->active)
+                       ws->hit_count++;
+               spin_unlock_irqrestore(&ws->lock, flags);
        }
-       spin_unlock_irqrestore(&events_lock, flags);
+       rcu_read_unlock();
 }
 
 /**
@@ -184,10 +556,13 @@ bool pm_check_wakeup_events(void)
 
        spin_lock_irqsave(&events_lock, flags);
        if (events_check_enabled) {
-               ret = (event_count == saved_event_count) && !events_in_progress;
+               ret = ((unsigned int)atomic_read(&event_count) == saved_count)
+                       && !atomic_read(&events_in_progress);
                events_check_enabled = ret;
        }
        spin_unlock_irqrestore(&events_lock, flags);
+       if (!ret)
+               pm_wakeup_update_hit_counts();
        return ret;
 }
 
@@ -202,24 +577,20 @@ bool pm_check_wakeup_events(void)
  * drop down to zero has been interrupted by a signal (and the current number
  * of wakeup events being processed is still nonzero).  Otherwise return true.
  */
-bool pm_get_wakeup_count(unsigned long *count)
+bool pm_get_wakeup_count(unsigned int *count)
 {
        bool ret;
 
-       spin_lock_irq(&events_lock);
        if (capable(CAP_SYS_ADMIN))
                events_check_enabled = false;
 
-       while (events_in_progress && !signal_pending(current)) {
-               spin_unlock_irq(&events_lock);
-
-               schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-               spin_lock_irq(&events_lock);
+       while (atomic_read(&events_in_progress) && !signal_pending(current)) {
+               pm_wakeup_update_hit_counts();
+               schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
        }
-       *count = event_count;
-       ret = !events_in_progress;
-       spin_unlock_irq(&events_lock);
+
+       ret = !atomic_read(&events_in_progress);
+       *count = atomic_read(&event_count);
        return ret;
 }
 
@@ -232,16 +603,102 @@ bool pm_get_wakeup_count(unsigned long *count)
  * old number of registered wakeup events to be used by pm_check_wakeup_events()
  * and return true.  Otherwise return false.
  */
-bool pm_save_wakeup_count(unsigned long count)
+bool pm_save_wakeup_count(unsigned int count)
 {
        bool ret = false;
 
        spin_lock_irq(&events_lock);
-       if (count == event_count && !events_in_progress) {
-               saved_event_count = count;
+       if (count == (unsigned int)atomic_read(&event_count)
+           && !atomic_read(&events_in_progress)) {
+               saved_count = count;
                events_check_enabled = true;
                ret = true;
        }
        spin_unlock_irq(&events_lock);
+       if (!ret)
+               pm_wakeup_update_hit_counts();
+       return ret;
+}
+
+static struct dentry *wakeup_sources_stats_dentry;
+
+/**
+ * print_wakeup_source_stats - Print wakeup source statistics information.
+ * @m: seq_file to print the statistics into.
+ * @ws: Wakeup source object to print the statistics for.
+ */
+static int print_wakeup_source_stats(struct seq_file *m,
+                                    struct wakeup_source *ws)
+{
+       unsigned long flags;
+       ktime_t total_time;
+       ktime_t max_time;
+       unsigned long active_count;
+       ktime_t active_time;
+       int ret;
+
+       spin_lock_irqsave(&ws->lock, flags);
+
+       total_time = ws->total_time;
+       max_time = ws->max_time;
+       active_count = ws->active_count;
+       if (ws->active) {
+               active_time = ktime_sub(ktime_get(), ws->last_time);
+               total_time = ktime_add(total_time, active_time);
+               if (active_time.tv64 > max_time.tv64)
+                       max_time = active_time;
+       } else {
+               active_time = ktime_set(0, 0);
+       }
+
+       ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t"
+                       "%lld\t\t%lld\t\t%lld\t\t%lld\n",
+                       ws->name, active_count, ws->event_count, ws->hit_count,
+                       ktime_to_ms(active_time), ktime_to_ms(total_time),
+                       ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
+
+       spin_unlock_irqrestore(&ws->lock, flags);
+
        return ret;
 }
+
+/**
+ * wakeup_sources_stats_show - Print wakeup sources statistics information.
+ * @m: seq_file to print the statistics into.
+ */
+static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
+{
+       struct wakeup_source *ws;
+
+       seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t"
+               "active_since\ttotal_time\tmax_time\tlast_change\n");
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(ws, &wakeup_sources, entry)
+               print_wakeup_source_stats(m, ws);
+       rcu_read_unlock();
+
+       return 0;
+}
+
+static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wakeup_sources_stats_show, NULL);
+}
+
+static const struct file_operations wakeup_sources_stats_fops = {
+       .owner = THIS_MODULE,
+       .open = wakeup_sources_stats_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int __init wakeup_sources_debugfs_init(void)
+{
+       wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
+                       S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops);
+       return 0;
+}
+
+postcore_initcall(wakeup_sources_debugfs_init);
index 9fc630ce1ddb4b46f93dd2c35a459849399efa8b..f6f37a05a0c3a5664503040bcdfaae32516d6e6c 100644 (file)
@@ -45,7 +45,8 @@ static ssize_t show_##name(struct sys_device *dev,            \
        return sprintf(buf, "%d\n", topology_##name(cpu));      \
 }
 
-#if defined(topology_thread_cpumask) || defined(topology_core_cpumask)
+#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
+    defined(topology_book_cpumask)
 static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
 {
        ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
@@ -114,6 +115,14 @@ define_siblings_show_func(core_cpumask);
 define_one_ro_named(core_siblings, show_core_cpumask);
 define_one_ro_named(core_siblings_list, show_core_cpumask_list);
 
+#ifdef CONFIG_SCHED_BOOK
+define_id_show_func(book_id);
+define_one_ro(book_id);
+define_siblings_show_func(book_cpumask);
+define_one_ro_named(book_siblings, show_book_cpumask);
+define_one_ro_named(book_siblings_list, show_book_cpumask_list);
+#endif
+
 static struct attribute *default_attrs[] = {
        &attr_physical_package_id.attr,
        &attr_core_id.attr,
@@ -121,6 +130,11 @@ static struct attribute *default_attrs[] = {
        &attr_thread_siblings_list.attr,
        &attr_core_siblings.attr,
        &attr_core_siblings_list.attr,
+#ifdef CONFIG_SCHED_BOOK
+       &attr_book_id.attr,
+       &attr_book_siblings.attr,
+       &attr_book_siblings_list.attr,
+#endif
        NULL
 };
 
index 4e2c367fec11df739ff4b19abdc5ebe1c1cd42e9..1f286ab461d3d62471dbaa5323cd468b1080a842 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/reboot.h>
@@ -54,6 +54,7 @@
 #define DAC960_GAM_MINOR       252
 
 
+static DEFINE_MUTEX(DAC960_mutex);
 static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];
 static int DAC960_ControllerCount;
 static struct proc_dir_entry *DAC960_ProcDirectoryEntry;
@@ -81,7 +82,7 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode)
        int drive_nr = (long)disk->private_data;
        int ret = -ENXIO;
 
-       lock_kernel();
+       mutex_lock(&DAC960_mutex);
        if (p->FirmwareType == DAC960_V1_Controller) {
                if (p->V1.LogicalDriveInformation[drive_nr].
                    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
@@ -99,7 +100,7 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode)
                goto out;
        ret = 0;
 out:
-       unlock_kernel();
+       mutex_unlock(&DAC960_mutex);
        return ret;
 }
 
@@ -6625,7 +6626,7 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
   long ErrorCode = 0;
   if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 
-  lock_kernel();
+  mutex_lock(&DAC960_mutex);
   switch (Request)
     {
     case DAC960_IOCTL_GET_CONTROLLER_COUNT:
@@ -7056,13 +7057,14 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
       default:
        ErrorCode = -ENOTTY;
     }
-  unlock_kernel();
+  mutex_unlock(&DAC960_mutex);
   return ErrorCode;
 }
 
 static const struct file_operations DAC960_gam_fops = {
        .owner          = THIS_MODULE,
-       .unlocked_ioctl = DAC960_gam_ioctl
+       .unlocked_ioctl = DAC960_gam_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice DAC960_gam_dev = {
index de277689da6153fac725e54e50f752e7a6ee5978..4b9359a6f6ca45c4cd5f8803b5e7cdb9ba496678 100644 (file)
@@ -488,4 +488,21 @@ config BLK_DEV_HD
 
          If unsure, say N.
 
+config BLK_DEV_RBD
+       tristate "Rados block device (RBD)"
+       depends on INET && EXPERIMENTAL && BLOCK
+       select CEPH_LIB
+       select LIBCRC32C
+       select CRYPTO_AES
+       select CRYPTO
+       default n
+       help
+         Say Y here if you want include the Rados block device, which stripes
+         a block device over objects stored in the Ceph distributed object
+         store.
+
+         More information at http://ceph.newdream.net/.
+
+         If unsure, say N.
+
 endif # BLK_DEV
index aff5ac925c34332f235e523164f7f85cd76b6751..d7f463d6312d6494c3ef795c5b96ff11fa0ec801 100644 (file)
@@ -37,5 +37,6 @@ obj-$(CONFIG_BLK_DEV_HD)      += hd.o
 
 obj-$(CONFIG_XEN_BLKDEV_FRONTEND)      += xen-blkfront.o
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
+obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 
 swim_mod-objs  := swim.o swim_asm.o
index 76f114f0bba32f5d0396ac9b2a1ec2a88963f7c1..4b852c9622660f761bf60278926006660e30e821 100644 (file)
@@ -60,7 +60,7 @@
 #include <linux/hdreg.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/amifdreg.h>
 #include <linux/amifd.h>
 #include <linux/buffer_head.h>
 #define FD_HD_3        0x55555555  /* high-density 3.5" (1760K) drive */
 #define FD_DD_5        0xaaaaaaaa  /* double-density 5.25" (440K) drive */
 
+static DEFINE_MUTEX(amiflop_mutex);
 static unsigned long int fd_def_df0 = FD_DD_3;     /* default for df0 if it doesn't identify */
 
 module_param(fd_def_df0, ulong, 0);
@@ -1506,9 +1507,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&amiflop_mutex);
        ret = fd_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
+       mutex_unlock(&amiflop_mutex);
 
        return ret;
 }
@@ -1555,11 +1556,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
        int old_dev;
        unsigned long flags;
 
-       lock_kernel();
+       mutex_lock(&amiflop_mutex);
        old_dev = fd_device[drive];
 
        if (fd_ref[drive] && old_dev != system) {
-               unlock_kernel();
+               mutex_unlock(&amiflop_mutex);
                return -EBUSY;
        }
 
@@ -1575,7 +1576,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
                        rel_fdc();
 
                        if (wrprot) {
-                               unlock_kernel();
+                               mutex_unlock(&amiflop_mutex);
                                return -EROFS;
                        }
                }
@@ -1594,7 +1595,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
        printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
               unit[drive].type->name, data_types[system].name);
 
-       unlock_kernel();
+       mutex_unlock(&amiflop_mutex);
        return 0;
 }
 
@@ -1603,7 +1604,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
        struct amiga_floppy_struct *p = disk->private_data;
        int drive = p - unit;
 
-       lock_kernel();
+       mutex_lock(&amiflop_mutex);
        if (unit[drive].dirty == 1) {
                del_timer (flush_track_timer + drive);
                non_int_flush_track (drive);
@@ -1617,7 +1618,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
 /* the mod_use counter is handled this way */
        floppy_off (drive | 0x40000000);
 #endif
-       unlock_kernel();
+       mutex_unlock(&amiflop_mutex);
        return 0;
 }
 
index a946929735a5818e525c14e97b9011913f9e54f9..f21c237a9e5e124a07c205c9770379831df6d8a4 100644 (file)
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/netdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "aoe.h"
 
+static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
 
 static ssize_t aoedisk_show_state(struct device *dev,
@@ -125,16 +126,16 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)
        struct aoedev *d = bdev->bd_disk->private_data;
        ulong flags;
 
-       lock_kernel();
+       mutex_lock(&aoeblk_mutex);
        spin_lock_irqsave(&d->lock, flags);
        if (d->flags & DEVFL_UP) {
                d->nopen++;
                spin_unlock_irqrestore(&d->lock, flags);
-               unlock_kernel();
+               mutex_unlock(&aoeblk_mutex);
                return 0;
        }
        spin_unlock_irqrestore(&d->lock, flags);
-       unlock_kernel();
+       mutex_unlock(&aoeblk_mutex);
        return -ENODEV;
 }
 
index 4a1b9e7464aa51e0d529ba920bbc597d5f9a381d..146296ca4965a8e44123928d2406820b949a1488 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/skbuff.h>
 #include "aoe.h"
 
@@ -37,6 +37,7 @@ struct ErrMsg {
        char *msg;
 };
 
+static DEFINE_MUTEX(aoechr_mutex);
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
 static struct completion emsgs_comp;
@@ -183,16 +184,16 @@ aoechr_open(struct inode *inode, struct file *filp)
 {
        int n, i;
 
-       lock_kernel();
+       mutex_lock(&aoechr_mutex);
        n = iminor(inode);
        filp->private_data = (void *) (unsigned long) n;
 
        for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
                if (chardevs[i].minor == n) {
-                       unlock_kernel();
+                       mutex_unlock(&aoechr_mutex);
                        return 0;
                }
-       unlock_kernel();
+       mutex_unlock(&aoechr_mutex);
        return -EINVAL;
 }
 
@@ -265,6 +266,7 @@ static const struct file_operations aoe_fops = {
        .open = aoechr_open,
        .release = aoechr_rel,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static char *aoe_devnode(struct device *dev, mode_t *mode)
index aceb964765246f9448c7ec65a8369a0d6106b89f..8c021bb7a9918422ec5fb8397ca9e0d3fa877368 100644 (file)
@@ -67,7 +67,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atafd.h>
 #include <asm/atafdreg.h>
@@ -79,6 +79,7 @@
 
 #undef DEBUG
 
+static DEFINE_MUTEX(ataflop_mutex);
 static struct request_queue *floppy_queue;
 static struct request *fd_request;
 
@@ -1671,9 +1672,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ataflop_mutex);
        ret = fd_locked_ioctl(bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ataflop_mutex);
 
        return ret;
 }
@@ -1854,9 +1855,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ataflop_mutex);
        ret = floppy_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&ataflop_mutex);
 
        return ret;
 }
@@ -1864,14 +1865,14 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
 static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
        struct atari_floppy_struct *p = disk->private_data;
-       lock_kernel();
+       mutex_lock(&ataflop_mutex);
        if (p->ref < 0)
                p->ref = 0;
        else if (!p->ref--) {
                printk(KERN_ERR "floppy_release with fd_ref == 0");
                p->ref = 0;
        }
-       unlock_kernel();
+       mutex_unlock(&ataflop_mutex);
        return 0;
 }
 
index 1c7f63792ff8ada51626f8316064bcb5220e6c7f..82bfd5bb4a973f316de41fb6fd05bd41226c322a 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 #include <linux/buffer_head.h> /* invalidate_bh_lrus() */
 #include <linux/slab.h>
@@ -55,6 +55,7 @@ struct brd_device {
 /*
  * Look up and return a brd's page for a given sector.
  */
+static DEFINE_MUTEX(brd_mutex);
 static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
 {
        pgoff_t idx;
@@ -402,7 +403,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
         * ram device BLKFLSBUF has special semantics, we want to actually
         * release and destroy the ramdisk data.
         */
-       lock_kernel();
+       mutex_lock(&brd_mutex);
        mutex_lock(&bdev->bd_mutex);
        error = -EBUSY;
        if (bdev->bd_openers <= 1) {
@@ -419,7 +420,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
                error = 0;
        }
        mutex_unlock(&bdev->bd_mutex);
-       unlock_kernel();
+       mutex_unlock(&brd_mutex);
 
        return error;
 }
index 31064df1370a96320f548d1ce5f191eaf2e97051..c484c96e22a68442d0d413519edcddf0b89c6603 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -66,6 +65,7 @@ MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
 MODULE_VERSION("3.6.26");
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(cciss_mutex);
 static int cciss_allow_hpsa;
 module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(cciss_allow_hpsa,
@@ -297,6 +297,8 @@ static void enqueue_cmd_and_start_io(ctlr_info_t *h,
        spin_lock_irqsave(&h->lock, flags);
        addQ(&h->reqQ, c);
        h->Qdepth++;
+       if (h->Qdepth > h->maxQsinceinit)
+               h->maxQsinceinit = h->Qdepth;
        start_io(h);
        spin_unlock_irqrestore(&h->lock, flags);
 }
@@ -1057,9 +1059,9 @@ static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&cciss_mutex);
        ret = cciss_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&cciss_mutex);
 
        return ret;
 }
@@ -1072,13 +1074,13 @@ static int cciss_release(struct gendisk *disk, fmode_t mode)
        ctlr_info_t *h;
        drive_info_struct *drv;
 
-       lock_kernel();
+       mutex_lock(&cciss_mutex);
        h = get_host(disk);
        drv = get_drv(disk);
        dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name);
        drv->usage_count--;
        h->usage_count--;
-       unlock_kernel();
+       mutex_unlock(&cciss_mutex);
        return 0;
 }
 
@@ -1086,9 +1088,9 @@ static int do_ioctl(struct block_device *bdev, fmode_t mode,
                    unsigned cmd, unsigned long arg)
 {
        int ret;
-       lock_kernel();
+       mutex_lock(&cciss_mutex);
        ret = cciss_ioctl(bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&cciss_mutex);
        return ret;
 }
 
@@ -4519,6 +4521,12 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
        misc_fw_support = readl(&cfgtable->misc_fw_support);
        use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 
+       /* The doorbell reset seems to cause lockups on some Smart
+        * Arrays (e.g. P410, P410i, maybe others).  Until this is
+        * fixed or at least isolated, avoid the doorbell reset.
+        */
+       use_doorbell = 0;
+
        rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
                goto unmap_cfgtable;
@@ -4712,6 +4720,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        h->scatter_list = kmalloc(h->max_commands *
                                                sizeof(struct scatterlist *),
                                                GFP_KERNEL);
+       if (!h->scatter_list)
+               goto clean4;
+
        for (k = 0; k < h->nr_cmds; k++) {
                h->scatter_list[k] = kmalloc(sizeof(struct scatterlist) *
                                                        h->maxsgentries,
@@ -4781,7 +4792,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 clean4:
        kfree(h->cmd_pool_bits);
        /* Free up sg elements */
-       for (k = 0; k < h->nr_cmds; k++)
+       for (k-- ; k >= 0; k--)
                kfree(h->scatter_list[k]);
        kfree(h->scatter_list);
        cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
index d53b0291c44ba0f175b8546c118b6eaffcac3a1d..946dad4caef37c63615d151fecabc8a7ac5e0d4e 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
@@ -68,6 +68,7 @@ MODULE_LICENSE("GPL");
 
 #define CPQARRAY_DMA_MASK      0xFFFFFFFF      /* 32 bit DMA */
 
+static DEFINE_MUTEX(cpqarray_mutex);
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
 
@@ -845,9 +846,9 @@ static int ida_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&cpqarray_mutex);
        ret = ida_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&cpqarray_mutex);
 
        return ret;
 }
@@ -859,10 +860,10 @@ static int ida_release(struct gendisk *disk, fmode_t mode)
 {
        ctlr_info_t *host;
 
-       lock_kernel();
+       mutex_lock(&cpqarray_mutex);
        host = get_host(disk);
        host->usage_count--;
-       unlock_kernel();
+       mutex_unlock(&cpqarray_mutex);
 
        return 0;
 }
@@ -1217,9 +1218,9 @@ static int ida_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&cpqarray_mutex);
        ret = ida_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
+       mutex_unlock(&cpqarray_mutex);
 
        return ret;
 }
index fa650dd85b9099073f1d3179aff32ed987a2541d..e4b56119866ed24b329605d8173d7499bd7d3063 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/types.h>
 #include <net/sock.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
@@ -64,6 +64,7 @@ struct after_state_chg_work {
        struct completion *done;
 };
 
+static DEFINE_MUTEX(drbd_main_mutex);
 int drbdd_init(struct drbd_thread *);
 int drbd_worker(struct drbd_thread *);
 int drbd_asender(struct drbd_thread *);
@@ -2536,7 +2537,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
        unsigned long flags;
        int rv = 0;
 
-       lock_kernel();
+       mutex_lock(&drbd_main_mutex);
        spin_lock_irqsave(&mdev->req_lock, flags);
        /* to have a stable mdev->state.role
         * and no race with updating open_cnt */
@@ -2551,7 +2552,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
        if (!rv)
                mdev->open_cnt++;
        spin_unlock_irqrestore(&mdev->req_lock, flags);
-       unlock_kernel();
+       mutex_unlock(&drbd_main_mutex);
 
        return rv;
 }
@@ -2559,9 +2560,9 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 static int drbd_release(struct gendisk *gd, fmode_t mode)
 {
        struct drbd_conf *mdev = gd->private_data;
-       lock_kernel();
+       mutex_lock(&drbd_main_mutex);
        mdev->open_cnt--;
-       unlock_kernel();
+       mutex_unlock(&drbd_main_mutex);
        return 0;
 }
 
index cf04c1b234ed192d1d6000deafc36430c0608651..3b57459bb745d962402e27d1c8107b26eb0154a2 100644 (file)
@@ -178,7 +178,6 @@ static int print_unex = 1;
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/jiffies.h>
 #include <linux/fcntl.h>
@@ -199,6 +198,7 @@ static int print_unex = 1;
  * It's been recommended that take about 1/4 of the default speed
  * in some more extreme cases.
  */
+static DEFINE_MUTEX(floppy_mutex);
 static int slow_floppy;
 
 #include <asm/dma.h>
@@ -3553,9 +3553,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&floppy_mutex);
        ret = fd_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
+       mutex_unlock(&floppy_mutex);
 
        return ret;
 }
@@ -3616,7 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
        int drive = (long)disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref = 0;
@@ -3627,7 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
        mutex_unlock(&open_lock);
-       unlock_kernel();
+       mutex_unlock(&floppy_mutex);
 
        return 0;
 }
@@ -3645,7 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
        int res = -EBUSY;
        char *tmp;
 
-       lock_kernel();
+       mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        old_dev = UDRS->fd_device;
        if (opened_bdev[drive] && opened_bdev[drive] != bdev)
@@ -3722,7 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
                        goto out;
        }
        mutex_unlock(&open_lock);
-       unlock_kernel();
+       mutex_unlock(&floppy_mutex);
        return 0;
 out:
        if (UDRS->fd_ref < 0)
@@ -3733,7 +3733,7 @@ out:
                opened_bdev[drive] = NULL;
 out2:
        mutex_unlock(&open_lock);
-       unlock_kernel();
+       mutex_unlock(&floppy_mutex);
        return res;
 }
 
index f3c636d237187df21879c0e8acc4a4c943e59ad2..a10c8c9b6b782320a131d65ebcdba6bcd01e102b 100644 (file)
@@ -67,7 +67,7 @@
 #include <linux/compat.h>
 #include <linux/suspend.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>         /* for invalidate_bdev() */
 #include <linux/completion.h>
@@ -77,6 +77,7 @@
 
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(loop_mutex);
 static LIST_HEAD(loop_devices);
 static DEFINE_MUTEX(loop_devices_mutex);
 
@@ -477,7 +478,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
        pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
 
        if (bio_rw(bio) == WRITE) {
-               bool barrier = (bio->bi_rw & REQ_HARDBARRIER);
+               bool barrier = !!(bio->bi_rw & REQ_HARDBARRIER);
                struct file *file = lo->lo_backing_file;
 
                if (barrier) {
@@ -1409,11 +1410,11 @@ static int lo_open(struct block_device *bdev, fmode_t mode)
 {
        struct loop_device *lo = bdev->bd_disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&loop_mutex);
        mutex_lock(&lo->lo_ctl_mutex);
        lo->lo_refcnt++;
        mutex_unlock(&lo->lo_ctl_mutex);
-       unlock_kernel();
+       mutex_unlock(&loop_mutex);
 
        return 0;
 }
@@ -1423,7 +1424,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
        struct loop_device *lo = disk->private_data;
        int err;
 
-       lock_kernel();
+       mutex_lock(&loop_mutex);
        mutex_lock(&lo->lo_ctl_mutex);
 
        if (--lo->lo_refcnt)
@@ -1448,7 +1449,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
 out:
        mutex_unlock(&lo->lo_ctl_mutex);
 out_unlocked:
-       lock_kernel();
+       mutex_unlock(&loop_mutex);
        return 0;
 }
 
index b82c5ce5e9dfaf3bcc1d81b68554de8cdff0493c..76fa3deaee84059d4431f7763981311210f16f06 100644 (file)
@@ -974,8 +974,7 @@ static int mg_probe(struct platform_device *plat_dev)
        host->breq->queuedata = host;
 
        /* mflash is random device, thanx for the noop */
-       elevator_exit(host->breq->elevator);
-       err = elevator_init(host->breq, "noop");
+       err = elevator_change(host->breq, "noop");
        if (err) {
                printk(KERN_ERR "%s:%d (elevator_init) fail\n",
                                __func__, __LINE__);
index 0daa422aa281c4a833299d86252d06abdc337fa4..a32fb41246f883a0a29fecca2cf70d17b0e7bae2 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -53,6 +53,7 @@
 #define DBG_BLKDEV      0x0100
 #define DBG_RX          0x0200
 #define DBG_TX          0x0400
+static DEFINE_MUTEX(nbd_mutex);
 static unsigned int debugflags;
 #endif /* NDEBUG */
 
@@ -717,11 +718,11 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
        dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
                        lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
-       lock_kernel();
+       mutex_lock(&nbd_mutex);
        mutex_lock(&lo->tx_lock);
        error = __nbd_ioctl(bdev, lo, cmd, arg);
        mutex_unlock(&lo->tx_lock);
-       unlock_kernel();
+       mutex_unlock(&nbd_mutex);
 
        return error;
 }
index 76f8565e1e8d072864e01362dd2ea4d5d42e59f1..62cec6afd7adf560f6792c68949f71fcc8e6f9ea 100644 (file)
@@ -138,9 +138,10 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pcd_mutex);
 static DEFINE_SPINLOCK(pcd_lock);
 
 module_param(verbose, bool, 0644);
@@ -227,9 +228,9 @@ static int pcd_block_open(struct block_device *bdev, fmode_t mode)
        struct pcd_unit *cd = bdev->bd_disk->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pcd_mutex);
        ret = cdrom_open(&cd->info, bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&pcd_mutex);
 
        return ret;
 }
@@ -237,9 +238,9 @@ static int pcd_block_open(struct block_device *bdev, fmode_t mode)
 static int pcd_block_release(struct gendisk *disk, fmode_t mode)
 {
        struct pcd_unit *cd = disk->private_data;
-       lock_kernel();
+       mutex_lock(&pcd_mutex);
        cdrom_release(&cd->info, mode);
-       unlock_kernel();
+       mutex_unlock(&pcd_mutex);
        return 0;
 }
 
@@ -249,9 +250,9 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
        struct pcd_unit *cd = bdev->bd_disk->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pcd_mutex);
        ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&pcd_mutex);
 
        return ret;
 }
index 985f0d4f1d1e2641c6c6d7f61e8dd76a95201921..c0ee1558b9bba105859f29f288bb4310e8ad4f3d 100644 (file)
@@ -153,10 +153,11 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/workqueue.h>
 
+static DEFINE_MUTEX(pd_mutex);
 static DEFINE_SPINLOCK(pd_lock);
 
 module_param(verbose, bool, 0);
@@ -736,14 +737,14 @@ static int pd_open(struct block_device *bdev, fmode_t mode)
 {
        struct pd_unit *disk = bdev->bd_disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&pd_mutex);
        disk->access++;
 
        if (disk->removable) {
                pd_special_command(disk, pd_media_check);
                pd_special_command(disk, pd_door_lock);
        }
-       unlock_kernel();
+       mutex_unlock(&pd_mutex);
        return 0;
 }
 
@@ -771,10 +772,10 @@ static int pd_ioctl(struct block_device *bdev, fmode_t mode,
 
        switch (cmd) {
        case CDROMEJECT:
-               lock_kernel();
+               mutex_lock(&pd_mutex);
                if (disk->access == 1)
                        pd_special_command(disk, pd_eject);
-               unlock_kernel();
+               mutex_unlock(&pd_mutex);
                return 0;
        default:
                return -EINVAL;
@@ -785,10 +786,10 @@ static int pd_release(struct gendisk *p, fmode_t mode)
 {
        struct pd_unit *disk = p->private_data;
 
-       lock_kernel();
+       mutex_lock(&pd_mutex);
        if (!--disk->access && disk->removable)
                pd_special_command(disk, pd_door_unlock);
-       unlock_kernel();
+       mutex_unlock(&pd_mutex);
 
        return 0;
 }
index 4457b494882a46c7ac42e85c7990dc12098b7ae0..635f25dd9e1082c9d1099c0ccca8142436e8f38d 100644 (file)
@@ -152,9 +152,10 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pf_mutex);
 static DEFINE_SPINLOCK(pf_spin_lock);
 
 module_param(verbose, bool, 0644);
@@ -302,7 +303,7 @@ static int pf_open(struct block_device *bdev, fmode_t mode)
        struct pf_unit *pf = bdev->bd_disk->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pf_mutex);
        pf_identify(pf);
 
        ret = -ENODEV;
@@ -318,7 +319,7 @@ static int pf_open(struct block_device *bdev, fmode_t mode)
        if (pf->removable)
                pf_lock(pf, 1);
 out:
-       unlock_kernel();
+       mutex_unlock(&pf_mutex);
        return ret;
 }
 
@@ -349,9 +350,9 @@ static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u
 
        if (pf->access != 1)
                return -EBUSY;
-       lock_kernel();
+       mutex_lock(&pf_mutex);
        pf_eject(pf);
-       unlock_kernel();
+       mutex_unlock(&pf_mutex);
 
        return 0;
 }
@@ -360,9 +361,9 @@ static int pf_release(struct gendisk *disk, fmode_t mode)
 {
        struct pf_unit *pf = disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&pf_mutex);
        if (pf->access <= 0) {
-               unlock_kernel();
+               mutex_unlock(&pf_mutex);
                return -EINVAL;
        }
 
@@ -371,7 +372,7 @@ static int pf_release(struct gendisk *disk, fmode_t mode)
        if (!pf->access && pf->removable)
                pf_lock(pf, 0);
 
-       unlock_kernel();
+       mutex_unlock(&pf_mutex);
        return 0;
 
 }
index c397b3ddba9b8676293bf773edfa90b29cf3101d..6b9a2000d56affdd7788ff26581ae587f3937f96 100644 (file)
@@ -162,7 +162,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 #include <linux/pg.h>
 #include <linux/device.h>
 #include <linux/sched.h>       /* current, TASK_* */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
@@ -193,6 +193,7 @@ module_param_array(drive3, int, NULL, 0);
 
 #define ATAPI_IDENTIFY         0x12
 
+static DEFINE_MUTEX(pg_mutex);
 static int pg_open(struct inode *inode, struct file *file);
 static int pg_release(struct inode *inode, struct file *file);
 static ssize_t pg_read(struct file *filp, char __user *buf,
@@ -234,6 +235,7 @@ static const struct file_operations pg_fops = {
        .write = pg_write,
        .open = pg_open,
        .release = pg_release,
+       .llseek = noop_llseek,
 };
 
 static void pg_init_units(void)
@@ -518,7 +520,7 @@ static int pg_open(struct inode *inode, struct file *file)
        struct pg *dev = &devices[unit];
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&pg_mutex);
        if ((unit >= PG_UNITS) || (!dev->present)) {
                ret = -ENODEV;
                goto out;
@@ -547,7 +549,7 @@ static int pg_open(struct inode *inode, struct file *file)
        file->private_data = dev;
 
 out:
-       unlock_kernel();
+       mutex_unlock(&pg_mutex);
        return ret;
 }
 
index bc5825fdeaabcfa297e9d00ffe1be1e8ade921fe..7179f79d746838f24640ac7c59fadb41a1c5f024 100644 (file)
@@ -146,7 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 #include <linux/mtio.h>
 #include <linux/device.h>
 #include <linux/sched.h>       /* current, TASK_*, schedule_timeout() */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 
@@ -189,6 +189,7 @@ module_param_array(drive3, int, NULL, 0);
 #define ATAPI_MODE_SENSE       0x1a
 #define ATAPI_LOG_SENSE                0x4d
 
+static DEFINE_MUTEX(pt_mutex);
 static int pt_open(struct inode *inode, struct file *file);
 static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static int pt_release(struct inode *inode, struct file *file);
@@ -239,6 +240,7 @@ static const struct file_operations pt_fops = {
        .unlocked_ioctl = pt_ioctl,
        .open = pt_open,
        .release = pt_release,
+       .llseek = noop_llseek,
 };
 
 /* sysfs class support */
@@ -650,9 +652,9 @@ static int pt_open(struct inode *inode, struct file *file)
        struct pt_unit *tape = pt + unit;
        int err;
 
-       lock_kernel();
+       mutex_lock(&pt_mutex);
        if (unit >= PT_UNITS || (!tape->present)) {
-               unlock_kernel();
+               mutex_unlock(&pt_mutex);
                return -ENODEV;
        }
 
@@ -681,12 +683,12 @@ static int pt_open(struct inode *inode, struct file *file)
        }
 
        file->private_data = tape;
-       unlock_kernel();
+       mutex_unlock(&pt_mutex);
        return 0;
 
 out:
        atomic_inc(&tape->available);
-       unlock_kernel();
+       mutex_unlock(&pt_mutex);
        return err;
 }
 
@@ -704,15 +706,15 @@ static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                switch (mtop.mt_op) {
 
                case MTREW:
-                       lock_kernel();
+                       mutex_lock(&pt_mutex);
                        pt_rewind(tape);
-                       unlock_kernel();
+                       mutex_unlock(&pt_mutex);
                        return 0;
 
                case MTWEOF:
-                       lock_kernel();
+                       mutex_lock(&pt_mutex);
                        pt_write_fm(tape);
-                       unlock_kernel();
+                       mutex_unlock(&pt_mutex);
                        return 0;
 
                default:
index b1cbeb59bb7622e61f75bc58f373cadf1e822218..ef58fccadad3ada40ad07f6891b2cd3de0234c17 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi_cmnd.h>
@@ -86,6 +85,7 @@
 
 #define ZONE(sector, pd) (((sector) + (pd)->offset) & ~((pd)->settings.size - 1))
 
+static DEFINE_MUTEX(pktcdvd_mutex);
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
 static struct proc_dir_entry *pkt_proc;
 static int pktdev_major;
@@ -2369,7 +2369,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
        pkt_shrink_pktlist(pd);
 }
 
-static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
+static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor)
 {
        if (dev_minor >= MAX_WRITERS)
                return NULL;
@@ -2383,7 +2383,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
 
        VPRINTK(DRIVER_NAME": entering open\n");
 
-       lock_kernel();
+       mutex_lock(&pktcdvd_mutex);
        mutex_lock(&ctl_mutex);
        pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
        if (!pd) {
@@ -2411,7 +2411,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
        }
 
        mutex_unlock(&ctl_mutex);
-       unlock_kernel();
+       mutex_unlock(&pktcdvd_mutex);
        return 0;
 
 out_dec:
@@ -2419,7 +2419,7 @@ out_dec:
 out:
        VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
        mutex_unlock(&ctl_mutex);
-       unlock_kernel();
+       mutex_unlock(&pktcdvd_mutex);
        return ret;
 }
 
@@ -2428,7 +2428,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode)
        struct pktcdvd_device *pd = disk->private_data;
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&pktcdvd_mutex);
        mutex_lock(&ctl_mutex);
        pd->refcnt--;
        BUG_ON(pd->refcnt < 0);
@@ -2437,7 +2437,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode)
                pkt_release_dev(pd, flush);
        }
        mutex_unlock(&ctl_mutex);
-       unlock_kernel();
+       mutex_unlock(&pktcdvd_mutex);
        return ret;
 }
 
@@ -2773,7 +2773,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
        VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
                MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
 
-       lock_kernel();
+       mutex_lock(&pktcdvd_mutex);
        switch (cmd) {
        case CDROMEJECT:
                /*
@@ -2798,7 +2798,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
                ret = -ENOTTY;
        }
-       unlock_kernel();
+       mutex_unlock(&pktcdvd_mutex);
 
        return ret;
 }
@@ -3046,6 +3046,7 @@ static const struct file_operations pkt_ctl_fops = {
        .compat_ioctl   = pkt_ctl_compat_ioctl,
 #endif
        .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice pkt_misc = {
index e9da874d04192b125561f4b71d8ba21ce55fadcc..03688c2da319c007f4923c4ffd989e4f9666b755 100644 (file)
@@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
                        memcpy(buf, dev->bounce_buf+offset, size);
                offset += size;
                flush_kernel_dcache_page(bvec->bv_page);
-               bvec_kunmap_irq(bvec, &flags);
+               bvec_kunmap_irq(buf, &flags);
                i++;
        }
 }
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
new file mode 100644 (file)
index 0000000..6ec9d53
--- /dev/null
@@ -0,0 +1,1841 @@
+/*
+   rbd.c -- Export ceph rados objects as a Linux block device
+
+
+   based on drivers/block/osdblk.c:
+
+   Copyright 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+   Instructions for use
+   --------------------
+
+   1) Map a Linux block device to an existing rbd image.
+
+      Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
+
+      $ echo "192.168.0.1 name=admin rbd foo" > /sys/class/rbd/add
+
+      The snapshot name can be "-" or omitted to map the image read/write.
+
+   2) List all active blkdev<->object mappings.
+
+      In this example, we have performed step #1 twice, creating two blkdevs,
+      mapped to two separate rados objects in the rados rbd pool
+
+      $ cat /sys/class/rbd/list
+      #id     major   client_name     pool    name    snap    KB
+      0       254     client4143      rbd     foo     -      1024000
+
+      The columns, in order, are:
+      - blkdev unique id
+      - blkdev assigned major
+      - rados client id
+      - rados pool name
+      - rados block device name
+      - mapped snapshot ("-" if none)
+      - device size in KB
+
+
+   3) Create a snapshot.
+
+      Usage: <blkdev id> <snapname>
+
+      $ echo "0 mysnap" > /sys/class/rbd/snap_create
+
+
+   4) Listing a snapshot.
+
+      $ cat /sys/class/rbd/snaps_list
+      #id     snap    KB
+      0       -       1024000 (*)
+      0       foo     1024000
+
+      The columns, in order, are:
+      - blkdev unique id
+      - snapshot name, '-' means none (active read/write version)
+      - size of device at time of snapshot
+      - the (*) indicates this is the active version
+
+   5) Rollback to snapshot.
+
+      Usage: <blkdev id> <snapname>
+
+      $ echo "0 mysnap" > /sys/class/rbd/snap_rollback
+
+
+   6) Mapping an image using snapshot.
+
+      A snapshot mapping is read-only. This is being done by passing
+      snap=<snapname> to the options when adding a device.
+
+      $ echo "192.168.0.1 name=admin,snap=mysnap rbd foo" > /sys/class/rbd/add
+
+
+   7) Remove an active blkdev<->rbd image mapping.
+
+      In this example, we remove the mapping with blkdev unique id 1.
+
+      $ echo 1 > /sys/class/rbd/remove
+
+
+   NOTE:  The actual creation and deletion of rados objects is outside the scope
+   of this driver.
+
+ */
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osd_client.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/decode.h>
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+
+#include "rbd_types.h"
+
+#define DRV_NAME "rbd"
+#define DRV_NAME_LONG "rbd (rados block device)"
+
+#define RBD_MINORS_PER_MAJOR   256             /* max minors per blkdev */
+
+#define RBD_MAX_MD_NAME_LEN    (96 + sizeof(RBD_SUFFIX))
+#define RBD_MAX_POOL_NAME_LEN  64
+#define RBD_MAX_SNAP_NAME_LEN  32
+#define RBD_MAX_OPT_LEN                1024
+
+#define RBD_SNAP_HEAD_NAME     "-"
+
+#define DEV_NAME_LEN           32
+
+/*
+ * block device image metadata (in-memory version)
+ */
+struct rbd_image_header {
+       u64 image_size;
+       char block_name[32];
+       __u8 obj_order;
+       __u8 crypt_type;
+       __u8 comp_type;
+       struct rw_semaphore snap_rwsem;
+       struct ceph_snap_context *snapc;
+       size_t snap_names_len;
+       u64 snap_seq;
+       u32 total_snaps;
+
+       char *snap_names;
+       u64 *snap_sizes;
+};
+
+/*
+ * an instance of the client.  multiple devices may share a client.
+ */
+struct rbd_client {
+       struct ceph_client      *client;
+       struct kref             kref;
+       struct list_head        node;
+};
+
+/*
+ * a single io request
+ */
+struct rbd_request {
+       struct request          *rq;            /* blk layer request */
+       struct bio              *bio;           /* cloned bio */
+       struct page             **pages;        /* list of used pages */
+       u64                     len;
+};
+
+/*
+ * a single device
+ */
+struct rbd_device {
+       int                     id;             /* blkdev unique id */
+
+       int                     major;          /* blkdev assigned major */
+       struct gendisk          *disk;          /* blkdev's gendisk and rq */
+       struct request_queue    *q;
+
+       struct ceph_client      *client;
+       struct rbd_client       *rbd_client;
+
+       char                    name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
+
+       spinlock_t              lock;           /* queue lock */
+
+       struct rbd_image_header header;
+       char                    obj[RBD_MAX_OBJ_NAME_LEN]; /* rbd image name */
+       int                     obj_len;
+       char                    obj_md_name[RBD_MAX_MD_NAME_LEN]; /* hdr nm. */
+       char                    pool_name[RBD_MAX_POOL_NAME_LEN];
+       int                     poolid;
+
+       char                    snap_name[RBD_MAX_SNAP_NAME_LEN];
+       u32 cur_snap;   /* index+1 of current snapshot within snap context
+                          0 - for the head */
+       int read_only;
+
+       struct list_head        node;
+};
+
+static spinlock_t node_lock;      /* protects client get/put */
+
+static struct class *class_rbd;          /* /sys/class/rbd */
+static DEFINE_MUTEX(ctl_mutex);          /* Serialize open/close/setup/teardown */
+static LIST_HEAD(rbd_dev_list);    /* devices */
+static LIST_HEAD(rbd_client_list);      /* clients */
+
+
+static int rbd_open(struct block_device *bdev, fmode_t mode)
+{
+       struct gendisk *disk = bdev->bd_disk;
+       struct rbd_device *rbd_dev = disk->private_data;
+
+       set_device_ro(bdev, rbd_dev->read_only);
+
+       if ((mode & FMODE_WRITE) && rbd_dev->read_only)
+               return -EROFS;
+
+       return 0;
+}
+
+static const struct block_device_operations rbd_bd_ops = {
+       .owner                  = THIS_MODULE,
+       .open                   = rbd_open,
+};
+
+/*
+ * Initialize an rbd client instance.
+ * We own *opt.
+ */
+static struct rbd_client *rbd_client_create(struct ceph_options *opt)
+{
+       struct rbd_client *rbdc;
+       int ret = -ENOMEM;
+
+       dout("rbd_client_create\n");
+       rbdc = kmalloc(sizeof(struct rbd_client), GFP_KERNEL);
+       if (!rbdc)
+               goto out_opt;
+
+       kref_init(&rbdc->kref);
+       INIT_LIST_HEAD(&rbdc->node);
+
+       rbdc->client = ceph_create_client(opt, rbdc);
+       if (IS_ERR(rbdc->client))
+               goto out_rbdc;
+       opt = NULL; /* Now rbdc->client is responsible for opt */
+
+       ret = ceph_open_session(rbdc->client);
+       if (ret < 0)
+               goto out_err;
+
+       spin_lock(&node_lock);
+       list_add_tail(&rbdc->node, &rbd_client_list);
+       spin_unlock(&node_lock);
+
+       dout("rbd_client_create created %p\n", rbdc);
+       return rbdc;
+
+out_err:
+       ceph_destroy_client(rbdc->client);
+out_rbdc:
+       kfree(rbdc);
+out_opt:
+       if (opt)
+               ceph_destroy_options(opt);
+       return ERR_PTR(ret);
+}
+
+/*
+ * Find a ceph client with specific addr and configuration.
+ */
+static struct rbd_client *__rbd_client_find(struct ceph_options *opt)
+{
+       struct rbd_client *client_node;
+
+       if (opt->flags & CEPH_OPT_NOSHARE)
+               return NULL;
+
+       list_for_each_entry(client_node, &rbd_client_list, node)
+               if (ceph_compare_options(opt, client_node->client) == 0)
+                       return client_node;
+       return NULL;
+}
+
+/*
+ * Get a ceph client with specific addr and configuration, if one does
+ * not exist create it.
+ */
+static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
+                         char *options)
+{
+       struct rbd_client *rbdc;
+       struct ceph_options *opt;
+       int ret;
+
+       ret = ceph_parse_options(&opt, options, mon_addr,
+                                mon_addr + strlen(mon_addr), NULL, NULL);
+       if (ret < 0)
+               return ret;
+
+       spin_lock(&node_lock);
+       rbdc = __rbd_client_find(opt);
+       if (rbdc) {
+               ceph_destroy_options(opt);
+
+               /* using an existing client */
+               kref_get(&rbdc->kref);
+               rbd_dev->rbd_client = rbdc;
+               rbd_dev->client = rbdc->client;
+               spin_unlock(&node_lock);
+               return 0;
+       }
+       spin_unlock(&node_lock);
+
+       rbdc = rbd_client_create(opt);
+       if (IS_ERR(rbdc))
+               return PTR_ERR(rbdc);
+
+       rbd_dev->rbd_client = rbdc;
+       rbd_dev->client = rbdc->client;
+       return 0;
+}
+
+/*
+ * Destroy ceph client
+ */
+static void rbd_client_release(struct kref *kref)
+{
+       struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
+
+       dout("rbd_release_client %p\n", rbdc);
+       spin_lock(&node_lock);
+       list_del(&rbdc->node);
+       spin_unlock(&node_lock);
+
+       ceph_destroy_client(rbdc->client);
+       kfree(rbdc);
+}
+
+/*
+ * Drop reference to ceph client node. If it's not referenced anymore, release
+ * it.
+ */
+static void rbd_put_client(struct rbd_device *rbd_dev)
+{
+       kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+       rbd_dev->rbd_client = NULL;
+       rbd_dev->client = NULL;
+}
+
+
+/*
+ * Create a new header structure, translate header format from the on-disk
+ * header.
+ */
+static int rbd_header_from_disk(struct rbd_image_header *header,
+                                struct rbd_image_header_ondisk *ondisk,
+                                int allocated_snaps,
+                                gfp_t gfp_flags)
+{
+       int i;
+       u32 snap_count = le32_to_cpu(ondisk->snap_count);
+       int ret = -ENOMEM;
+
+       init_rwsem(&header->snap_rwsem);
+
+       header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
+       header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
+                               snap_count *
+                                sizeof(struct rbd_image_snap_ondisk),
+                               gfp_flags);
+       if (!header->snapc)
+               return -ENOMEM;
+       if (snap_count) {
+               header->snap_names = kmalloc(header->snap_names_len,
+                                            GFP_KERNEL);
+               if (!header->snap_names)
+                       goto err_snapc;
+               header->snap_sizes = kmalloc(snap_count * sizeof(u64),
+                                            GFP_KERNEL);
+               if (!header->snap_sizes)
+                       goto err_names;
+       } else {
+               header->snap_names = NULL;
+               header->snap_sizes = NULL;
+       }
+       memcpy(header->block_name, ondisk->block_name,
+              sizeof(ondisk->block_name));
+
+       header->image_size = le64_to_cpu(ondisk->image_size);
+       header->obj_order = ondisk->options.order;
+       header->crypt_type = ondisk->options.crypt_type;
+       header->comp_type = ondisk->options.comp_type;
+
+       atomic_set(&header->snapc->nref, 1);
+       header->snap_seq = le64_to_cpu(ondisk->snap_seq);
+       header->snapc->num_snaps = snap_count;
+       header->total_snaps = snap_count;
+
+       if (snap_count &&
+           allocated_snaps == snap_count) {
+               for (i = 0; i < snap_count; i++) {
+                       header->snapc->snaps[i] =
+                               le64_to_cpu(ondisk->snaps[i].id);
+                       header->snap_sizes[i] =
+                               le64_to_cpu(ondisk->snaps[i].image_size);
+               }
+
+               /* copy snapshot names */
+               memcpy(header->snap_names, &ondisk->snaps[i],
+                       header->snap_names_len);
+       }
+
+       return 0;
+
+err_names:
+       kfree(header->snap_names);
+err_snapc:
+       kfree(header->snapc);
+       return ret;
+}
+
+static int snap_index(struct rbd_image_header *header, int snap_num)
+{
+       return header->total_snaps - snap_num;
+}
+
+static u64 cur_snap_id(struct rbd_device *rbd_dev)
+{
+       struct rbd_image_header *header = &rbd_dev->header;
+
+       if (!rbd_dev->cur_snap)
+               return 0;
+
+       return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)];
+}
+
+static int snap_by_name(struct rbd_image_header *header, const char *snap_name,
+                       u64 *seq, u64 *size)
+{
+       int i;
+       char *p = header->snap_names;
+
+       for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+               if (strcmp(snap_name, p) == 0)
+                       break;
+       }
+       if (i == header->total_snaps)
+               return -ENOENT;
+       if (seq)
+               *seq = header->snapc->snaps[i];
+
+       if (size)
+               *size = header->snap_sizes[i];
+
+       return i;
+}
+
+static int rbd_header_set_snap(struct rbd_device *dev,
+                              const char *snap_name,
+                              u64 *size)
+{
+       struct rbd_image_header *header = &dev->header;
+       struct ceph_snap_context *snapc = header->snapc;
+       int ret = -ENOENT;
+
+       down_write(&header->snap_rwsem);
+
+       if (!snap_name ||
+           !*snap_name ||
+           strcmp(snap_name, "-") == 0 ||
+           strcmp(snap_name, RBD_SNAP_HEAD_NAME) == 0) {
+               if (header->total_snaps)
+                       snapc->seq = header->snap_seq;
+               else
+                       snapc->seq = 0;
+               dev->cur_snap = 0;
+               dev->read_only = 0;
+               if (size)
+                       *size = header->image_size;
+       } else {
+               ret = snap_by_name(header, snap_name, &snapc->seq, size);
+               if (ret < 0)
+                       goto done;
+
+               dev->cur_snap = header->total_snaps - ret;
+               dev->read_only = 1;
+       }
+
+       ret = 0;
+done:
+       up_write(&header->snap_rwsem);
+       return ret;
+}
+
+static void rbd_header_free(struct rbd_image_header *header)
+{
+       kfree(header->snapc);
+       kfree(header->snap_names);
+       kfree(header->snap_sizes);
+}
+
+/*
+ * get the actual striped segment name, offset and length
+ */
+static u64 rbd_get_segment(struct rbd_image_header *header,
+                          const char *block_name,
+                          u64 ofs, u64 len,
+                          char *seg_name, u64 *segofs)
+{
+       u64 seg = ofs >> header->obj_order;
+
+       if (seg_name)
+               snprintf(seg_name, RBD_MAX_SEG_NAME_LEN,
+                        "%s.%012llx", block_name, seg);
+
+       ofs = ofs & ((1 << header->obj_order) - 1);
+       len = min_t(u64, len, (1 << header->obj_order) - ofs);
+
+       if (segofs)
+               *segofs = ofs;
+
+       return len;
+}
+
+/*
+ * bio helpers
+ */
+
+static void bio_chain_put(struct bio *chain)
+{
+       struct bio *tmp;
+
+       while (chain) {
+               tmp = chain;
+               chain = chain->bi_next;
+               bio_put(tmp);
+       }
+}
+
+/*
+ * zeros a bio chain, starting at specific offset
+ */
+static void zero_bio_chain(struct bio *chain, int start_ofs)
+{
+       struct bio_vec *bv;
+       unsigned long flags;
+       void *buf;
+       int i;
+       int pos = 0;
+
+       while (chain) {
+               bio_for_each_segment(bv, chain, i) {
+                       if (pos + bv->bv_len > start_ofs) {
+                               int remainder = max(start_ofs - pos, 0);
+                               buf = bvec_kmap_irq(bv, &flags);
+                               memset(buf + remainder, 0,
+                                      bv->bv_len - remainder);
+                               bvec_kunmap_irq(buf, &flags);
+                       }
+                       pos += bv->bv_len;
+               }
+
+               chain = chain->bi_next;
+       }
+}
+
+/*
+ * bio_chain_clone - clone a chain of bios up to a certain length.
+ * might return a bio_pair that will need to be released.
+ */
+static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
+                                  struct bio_pair **bp,
+                                  int len, gfp_t gfpmask)
+{
+       struct bio *tmp, *old_chain = *old, *new_chain = NULL, *tail = NULL;
+       int total = 0;
+
+       if (*bp) {
+               bio_pair_release(*bp);
+               *bp = NULL;
+       }
+
+       while (old_chain && (total < len)) {
+               tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+               if (!tmp)
+                       goto err_out;
+
+               if (total + old_chain->bi_size > len) {
+                       struct bio_pair *bp;
+
+                       /*
+                        * this split can only happen with a single paged bio,
+                        * split_bio will BUG_ON if this is not the case
+                        */
+                       dout("bio_chain_clone split! total=%d remaining=%d"
+                            "bi_size=%d\n",
+                            (int)total, (int)len-total,
+                            (int)old_chain->bi_size);
+
+                       /* split the bio. We'll release it either in the next
+                          call, or it will have to be released outside */
+                       bp = bio_split(old_chain, (len - total) / 512ULL);
+                       if (!bp)
+                               goto err_out;
+
+                       __bio_clone(tmp, &bp->bio1);
+
+                       *next = &bp->bio2;
+               } else {
+                       __bio_clone(tmp, old_chain);
+                       *next = old_chain->bi_next;
+               }
+
+               tmp->bi_bdev = NULL;
+               gfpmask &= ~__GFP_WAIT;
+               tmp->bi_next = NULL;
+
+               if (!new_chain) {
+                       new_chain = tail = tmp;
+               } else {
+                       tail->bi_next = tmp;
+                       tail = tmp;
+               }
+               old_chain = old_chain->bi_next;
+
+               total += tmp->bi_size;
+       }
+
+       BUG_ON(total < len);
+
+       if (tail)
+               tail->bi_next = NULL;
+
+       *old = old_chain;
+
+       return new_chain;
+
+err_out:
+       dout("bio_chain_clone with err\n");
+       bio_chain_put(new_chain);
+       return NULL;
+}
+
+/*
+ * helpers for osd request op vectors.
+ */
+static int rbd_create_rw_ops(struct ceph_osd_req_op **ops,
+                           int num_ops,
+                           int opcode,
+                           u32 payload_len)
+{
+       *ops = kzalloc(sizeof(struct ceph_osd_req_op) * (num_ops + 1),
+                      GFP_NOIO);
+       if (!*ops)
+               return -ENOMEM;
+       (*ops)[0].op = opcode;
+       /*
+        * op extent offset and length will be set later on
+        * in calc_raw_layout()
+        */
+       (*ops)[0].payload_len = payload_len;
+       return 0;
+}
+
+static void rbd_destroy_ops(struct ceph_osd_req_op *ops)
+{
+       kfree(ops);
+}
+
+/*
+ * Send ceph osd request
+ */
+static int rbd_do_request(struct request *rq,
+                         struct rbd_device *dev,
+                         struct ceph_snap_context *snapc,
+                         u64 snapid,
+                         const char *obj, u64 ofs, u64 len,
+                         struct bio *bio,
+                         struct page **pages,
+                         int num_pages,
+                         int flags,
+                         struct ceph_osd_req_op *ops,
+                         int num_reply,
+                         void (*rbd_cb)(struct ceph_osd_request *req,
+                                        struct ceph_msg *msg))
+{
+       struct ceph_osd_request *req;
+       struct ceph_file_layout *layout;
+       int ret;
+       u64 bno;
+       struct timespec mtime = CURRENT_TIME;
+       struct rbd_request *req_data;
+       struct ceph_osd_request_head *reqhead;
+       struct rbd_image_header *header = &dev->header;
+
+       ret = -ENOMEM;
+       req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
+       if (!req_data)
+               goto done;
+
+       dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs);
+
+       down_read(&header->snap_rwsem);
+
+       req = ceph_osdc_alloc_request(&dev->client->osdc, flags,
+                                     snapc,
+                                     ops,
+                                     false,
+                                     GFP_NOIO, pages, bio);
+       if (IS_ERR(req)) {
+               up_read(&header->snap_rwsem);
+               ret = PTR_ERR(req);
+               goto done_pages;
+       }
+
+       req->r_callback = rbd_cb;
+
+       req_data->rq = rq;
+       req_data->bio = bio;
+       req_data->pages = pages;
+       req_data->len = len;
+
+       req->r_priv = req_data;
+
+       reqhead = req->r_request->front.iov_base;
+       reqhead->snapid = cpu_to_le64(CEPH_NOSNAP);
+
+       strncpy(req->r_oid, obj, sizeof(req->r_oid));
+       req->r_oid_len = strlen(req->r_oid);
+
+       layout = &req->r_file_layout;
+       memset(layout, 0, sizeof(*layout));
+       layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+       layout->fl_stripe_count = cpu_to_le32(1);
+       layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+       layout->fl_pg_preferred = cpu_to_le32(-1);
+       layout->fl_pg_pool = cpu_to_le32(dev->poolid);
+       ceph_calc_raw_layout(&dev->client->osdc, layout, snapid,
+                            ofs, &len, &bno, req, ops);
+
+       ceph_osdc_build_request(req, ofs, &len,
+                               ops,
+                               snapc,
+                               &mtime,
+                               req->r_oid, req->r_oid_len);
+       up_read(&header->snap_rwsem);
+
+       ret = ceph_osdc_start_request(&dev->client->osdc, req, false);
+       if (ret < 0)
+               goto done_err;
+
+       if (!rbd_cb) {
+               ret = ceph_osdc_wait_request(&dev->client->osdc, req);
+               ceph_osdc_put_request(req);
+       }
+       return ret;
+
+done_err:
+       bio_chain_put(req_data->bio);
+       ceph_osdc_put_request(req);
+done_pages:
+       kfree(req_data);
+done:
+       if (rq)
+               blk_end_request(rq, ret, len);
+       return ret;
+}
+
+/*
+ * Ceph osd op callback
+ */
+static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
+{
+       struct rbd_request *req_data = req->r_priv;
+       struct ceph_osd_reply_head *replyhead;
+       struct ceph_osd_op *op;
+       __s32 rc;
+       u64 bytes;
+       int read_op;
+
+       /* parse reply */
+       replyhead = msg->front.iov_base;
+       WARN_ON(le32_to_cpu(replyhead->num_ops) == 0);
+       op = (void *)(replyhead + 1);
+       rc = le32_to_cpu(replyhead->result);
+       bytes = le64_to_cpu(op->extent.length);
+       read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ);
+
+       dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc);
+
+       if (rc == -ENOENT && read_op) {
+               zero_bio_chain(req_data->bio, 0);
+               rc = 0;
+       } else if (rc == 0 && read_op && bytes < req_data->len) {
+               zero_bio_chain(req_data->bio, bytes);
+               bytes = req_data->len;
+       }
+
+       blk_end_request(req_data->rq, rc, bytes);
+
+       if (req_data->bio)
+               bio_chain_put(req_data->bio);
+
+       ceph_osdc_put_request(req);
+       kfree(req_data);
+}
+
+/*
+ * Do a synchronous ceph osd operation
+ */
+static int rbd_req_sync_op(struct rbd_device *dev,
+                          struct ceph_snap_context *snapc,
+                          u64 snapid,
+                          int opcode,
+                          int flags,
+                          struct ceph_osd_req_op *orig_ops,
+                          int num_reply,
+                          const char *obj,
+                          u64 ofs, u64 len,
+                          char *buf)
+{
+       int ret;
+       struct page **pages;
+       int num_pages;
+       struct ceph_osd_req_op *ops = orig_ops;
+       u32 payload_len;
+
+       num_pages = calc_pages_for(ofs , len);
+       pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
+       if (IS_ERR(pages))
+               return PTR_ERR(pages);
+
+       if (!orig_ops) {
+               payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0);
+               ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+               if (ret < 0)
+                       goto done;
+
+               if ((flags & CEPH_OSD_FLAG_WRITE) && buf) {
+                       ret = ceph_copy_to_page_vector(pages, buf, ofs, len);
+                       if (ret < 0)
+                               goto done_ops;
+               }
+       }
+
+       ret = rbd_do_request(NULL, dev, snapc, snapid,
+                         obj, ofs, len, NULL,
+                         pages, num_pages,
+                         flags,
+                         ops,
+                         2,
+                         NULL);
+       if (ret < 0)
+               goto done_ops;
+
+       if ((flags & CEPH_OSD_FLAG_READ) && buf)
+               ret = ceph_copy_from_page_vector(pages, buf, ofs, ret);
+
+done_ops:
+       if (!orig_ops)
+               rbd_destroy_ops(ops);
+done:
+       ceph_release_page_vector(pages, num_pages);
+       return ret;
+}
+
+/*
+ * Do an asynchronous ceph osd operation
+ */
+static int rbd_do_op(struct request *rq,
+                    struct rbd_device *rbd_dev ,
+                    struct ceph_snap_context *snapc,
+                    u64 snapid,
+                    int opcode, int flags, int num_reply,
+                    u64 ofs, u64 len,
+                    struct bio *bio)
+{
+       char *seg_name;
+       u64 seg_ofs;
+       u64 seg_len;
+       int ret;
+       struct ceph_osd_req_op *ops;
+       u32 payload_len;
+
+       seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+       if (!seg_name)
+               return -ENOMEM;
+
+       seg_len = rbd_get_segment(&rbd_dev->header,
+                                 rbd_dev->header.block_name,
+                                 ofs, len,
+                                 seg_name, &seg_ofs);
+
+       payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0);
+
+       ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+       if (ret < 0)
+               goto done;
+
+       /* we've taken care of segment sizes earlier when we
+          cloned the bios. We should never have a segment
+          truncated at this point */
+       BUG_ON(seg_len < len);
+
+       ret = rbd_do_request(rq, rbd_dev, snapc, snapid,
+                            seg_name, seg_ofs, seg_len,
+                            bio,
+                            NULL, 0,
+                            flags,
+                            ops,
+                            num_reply,
+                            rbd_req_cb);
+done:
+       kfree(seg_name);
+       return ret;
+}
+
+/*
+ * Request async osd write
+ */
+static int rbd_req_write(struct request *rq,
+                        struct rbd_device *rbd_dev,
+                        struct ceph_snap_context *snapc,
+                        u64 ofs, u64 len,
+                        struct bio *bio)
+{
+       return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
+                        CEPH_OSD_OP_WRITE,
+                        CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+                        2,
+                        ofs, len, bio);
+}
+
+/*
+ * Request async osd read
+ */
+static int rbd_req_read(struct request *rq,
+                        struct rbd_device *rbd_dev,
+                        u64 snapid,
+                        u64 ofs, u64 len,
+                        struct bio *bio)
+{
+       return rbd_do_op(rq, rbd_dev, NULL,
+                        (snapid ? snapid : CEPH_NOSNAP),
+                        CEPH_OSD_OP_READ,
+                        CEPH_OSD_FLAG_READ,
+                        2,
+                        ofs, len, bio);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_read(struct rbd_device *dev,
+                         struct ceph_snap_context *snapc,
+                         u64 snapid,
+                         const char *obj,
+                         u64 ofs, u64 len,
+                         char *buf)
+{
+       return rbd_req_sync_op(dev, NULL,
+                              (snapid ? snapid : CEPH_NOSNAP),
+                              CEPH_OSD_OP_READ,
+                              CEPH_OSD_FLAG_READ,
+                              NULL,
+                              1, obj, ofs, len, buf);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
+                                    u64 snapid,
+                                    const char *obj)
+{
+       struct ceph_osd_req_op *ops;
+       int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0);
+       if (ret < 0)
+               return ret;
+
+       ops[0].snap.snapid = snapid;
+
+       ret = rbd_req_sync_op(dev, NULL,
+                              CEPH_NOSNAP,
+                              0,
+                              CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+                              ops,
+                              1, obj, 0, 0, NULL);
+
+       rbd_destroy_ops(ops);
+
+       if (ret < 0)
+               return ret;
+
+       return ret;
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_exec(struct rbd_device *dev,
+                            const char *obj,
+                            const char *cls,
+                            const char *method,
+                            const char *data,
+                            int len)
+{
+       struct ceph_osd_req_op *ops;
+       int cls_len = strlen(cls);
+       int method_len = strlen(method);
+       int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_CALL,
+                                   cls_len + method_len + len);
+       if (ret < 0)
+               return ret;
+
+       ops[0].cls.class_name = cls;
+       ops[0].cls.class_len = (__u8)cls_len;
+       ops[0].cls.method_name = method;
+       ops[0].cls.method_len = (__u8)method_len;
+       ops[0].cls.argc = 0;
+       ops[0].cls.indata = data;
+       ops[0].cls.indata_len = len;
+
+       ret = rbd_req_sync_op(dev, NULL,
+                              CEPH_NOSNAP,
+                              0,
+                              CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+                              ops,
+                              1, obj, 0, 0, NULL);
+
+       rbd_destroy_ops(ops);
+
+       dout("cls_exec returned %d\n", ret);
+       return ret;
+}
+
+/*
+ * block device queue callback
+ */
+static void rbd_rq_fn(struct request_queue *q)
+{
+       struct rbd_device *rbd_dev = q->queuedata;
+       struct request *rq;
+       struct bio_pair *bp = NULL;
+
+       rq = blk_fetch_request(q);
+
+       while (1) {
+               struct bio *bio;
+               struct bio *rq_bio, *next_bio = NULL;
+               bool do_write;
+               int size, op_size = 0;
+               u64 ofs;
+
+               /* peek at request from block layer */
+               if (!rq)
+                       break;
+
+               dout("fetched request\n");
+
+               /* filter out block requests we don't understand */
+               if ((rq->cmd_type != REQ_TYPE_FS)) {
+                       __blk_end_request_all(rq, 0);
+                       goto next;
+               }
+
+               /* deduce our operation (read, write) */
+               do_write = (rq_data_dir(rq) == WRITE);
+
+               size = blk_rq_bytes(rq);
+               ofs = blk_rq_pos(rq) * 512ULL;
+               rq_bio = rq->bio;
+               if (do_write && rbd_dev->read_only) {
+                       __blk_end_request_all(rq, -EROFS);
+                       goto next;
+               }
+
+               spin_unlock_irq(q->queue_lock);
+
+               dout("%s 0x%x bytes at 0x%llx\n",
+                    do_write ? "write" : "read",
+                    size, blk_rq_pos(rq) * 512ULL);
+
+               do {
+                       /* a bio clone to be passed down to OSD req */
+                       dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
+                       op_size = rbd_get_segment(&rbd_dev->header,
+                                                 rbd_dev->header.block_name,
+                                                 ofs, size,
+                                                 NULL, NULL);
+                       bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
+                                             op_size, GFP_ATOMIC);
+                       if (!bio) {
+                               spin_lock_irq(q->queue_lock);
+                               __blk_end_request_all(rq, -ENOMEM);
+                               goto next;
+                       }
+
+                       /* init OSD command: write or read */
+                       if (do_write)
+                               rbd_req_write(rq, rbd_dev,
+                                             rbd_dev->header.snapc,
+                                             ofs,
+                                             op_size, bio);
+                       else
+                               rbd_req_read(rq, rbd_dev,
+                                            cur_snap_id(rbd_dev),
+                                            ofs,
+                                            op_size, bio);
+
+                       size -= op_size;
+                       ofs += op_size;
+
+                       rq_bio = next_bio;
+               } while (size > 0);
+
+               if (bp)
+                       bio_pair_release(bp);
+
+               spin_lock_irq(q->queue_lock);
+next:
+               rq = blk_fetch_request(q);
+       }
+}
+
+/*
+ * a queue callback. Makes sure that we don't create a bio that spans across
+ * multiple osd objects. One exception would be with a single page bios,
+ * which we handle later at bio_chain_clone
+ */
+static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
+                         struct bio_vec *bvec)
+{
+       struct rbd_device *rbd_dev = q->queuedata;
+       unsigned int chunk_sectors = 1 << (rbd_dev->header.obj_order - 9);
+       sector_t sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev);
+       unsigned int bio_sectors = bmd->bi_size >> 9;
+       int max;
+
+       max =  (chunk_sectors - ((sector & (chunk_sectors - 1))
+                                + bio_sectors)) << 9;
+       if (max < 0)
+               max = 0; /* bio_add cannot handle a negative return */
+       if (max <= bvec->bv_len && bio_sectors == 0)
+               return bvec->bv_len;
+       return max;
+}
+
+static void rbd_free_disk(struct rbd_device *rbd_dev)
+{
+       struct gendisk *disk = rbd_dev->disk;
+
+       if (!disk)
+               return;
+
+       rbd_header_free(&rbd_dev->header);
+
+       if (disk->flags & GENHD_FL_UP)
+               del_gendisk(disk);
+       if (disk->queue)
+               blk_cleanup_queue(disk->queue);
+       put_disk(disk);
+}
+
+/*
+ * reload the ondisk the header 
+ */
+static int rbd_read_header(struct rbd_device *rbd_dev,
+                          struct rbd_image_header *header)
+{
+       ssize_t rc;
+       struct rbd_image_header_ondisk *dh;
+       int snap_count = 0;
+       u64 snap_names_len = 0;
+
+       while (1) {
+               int len = sizeof(*dh) +
+                         snap_count * sizeof(struct rbd_image_snap_ondisk) +
+                         snap_names_len;
+
+               rc = -ENOMEM;
+               dh = kmalloc(len, GFP_KERNEL);
+               if (!dh)
+                       return -ENOMEM;
+
+               rc = rbd_req_sync_read(rbd_dev,
+                                      NULL, CEPH_NOSNAP,
+                                      rbd_dev->obj_md_name,
+                                      0, len,
+                                      (char *)dh);
+               if (rc < 0)
+                       goto out_dh;
+
+               rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL);
+               if (rc < 0)
+                       goto out_dh;
+
+               if (snap_count != header->total_snaps) {
+                       snap_count = header->total_snaps;
+                       snap_names_len = header->snap_names_len;
+                       rbd_header_free(header);
+                       kfree(dh);
+                       continue;
+               }
+               break;
+       }
+
+out_dh:
+       kfree(dh);
+       return rc;
+}
+
+/*
+ * create a snapshot
+ */
+static int rbd_header_add_snap(struct rbd_device *dev,
+                              const char *snap_name,
+                              gfp_t gfp_flags)
+{
+       int name_len = strlen(snap_name);
+       u64 new_snapid;
+       int ret;
+       void *data, *data_start, *data_end;
+
+       /* we should create a snapshot only if we're pointing at the head */
+       if (dev->cur_snap)
+               return -EINVAL;
+
+       ret = ceph_monc_create_snapid(&dev->client->monc, dev->poolid,
+                                     &new_snapid);
+       dout("created snapid=%lld\n", new_snapid);
+       if (ret < 0)
+               return ret;
+
+       data = kmalloc(name_len + 16, gfp_flags);
+       if (!data)
+               return -ENOMEM;
+
+       data_start = data;
+       data_end = data + name_len + 16;
+
+       ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad);
+       ceph_encode_64_safe(&data, data_end, new_snapid, bad);
+
+       ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add",
+                               data_start, data - data_start);
+
+       kfree(data_start);
+
+       if (ret < 0)
+               return ret;
+
+       dev->header.snapc->seq =  new_snapid;
+
+       return 0;
+bad:
+       return -ERANGE;
+}
+
+/*
+ * only read the first part of the ondisk header, without the snaps info
+ */
+static int rbd_update_snaps(struct rbd_device *rbd_dev)
+{
+       int ret;
+       struct rbd_image_header h;
+       u64 snap_seq;
+
+       ret = rbd_read_header(rbd_dev, &h);
+       if (ret < 0)
+               return ret;
+
+       down_write(&rbd_dev->header.snap_rwsem);
+
+       snap_seq = rbd_dev->header.snapc->seq;
+
+       kfree(rbd_dev->header.snapc);
+       kfree(rbd_dev->header.snap_names);
+       kfree(rbd_dev->header.snap_sizes);
+
+       rbd_dev->header.total_snaps = h.total_snaps;
+       rbd_dev->header.snapc = h.snapc;
+       rbd_dev->header.snap_names = h.snap_names;
+       rbd_dev->header.snap_sizes = h.snap_sizes;
+       rbd_dev->header.snapc->seq = snap_seq;
+
+       up_write(&rbd_dev->header.snap_rwsem);
+
+       return 0;
+}
+
+static int rbd_init_disk(struct rbd_device *rbd_dev)
+{
+       struct gendisk *disk;
+       struct request_queue *q;
+       int rc;
+       u64 total_size = 0;
+
+       /* contact OSD, request size info about the object being mapped */
+       rc = rbd_read_header(rbd_dev, &rbd_dev->header);
+       if (rc)
+               return rc;
+
+       rc = rbd_header_set_snap(rbd_dev, rbd_dev->snap_name, &total_size);
+       if (rc)
+               return rc;
+
+       /* create gendisk info */
+       rc = -ENOMEM;
+       disk = alloc_disk(RBD_MINORS_PER_MAJOR);
+       if (!disk)
+               goto out;
+
+       sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id);
+       disk->major = rbd_dev->major;
+       disk->first_minor = 0;
+       disk->fops = &rbd_bd_ops;
+       disk->private_data = rbd_dev;
+
+       /* init rq */
+       rc = -ENOMEM;
+       q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
+       if (!q)
+               goto out_disk;
+       blk_queue_merge_bvec(q, rbd_merge_bvec);
+       disk->queue = q;
+
+       q->queuedata = rbd_dev;
+
+       rbd_dev->disk = disk;
+       rbd_dev->q = q;
+
+       /* finally, announce the disk to the world */
+       set_capacity(disk, total_size / 512ULL);
+       add_disk(disk);
+
+       pr_info("%s: added with size 0x%llx\n",
+               disk->disk_name, (unsigned long long)total_size);
+       return 0;
+
+out_disk:
+       put_disk(disk);
+out:
+       return rc;
+}
+
+/********************************************************************
+ * /sys/class/rbd/
+ *                   add       map rados objects to blkdev
+ *                   remove    unmap rados objects
+ *                   list      show mappings
+ *******************************************************************/
+
+static void class_rbd_release(struct class *cls)
+{
+       kfree(cls);
+}
+
+static ssize_t class_rbd_list(struct class *c,
+                             struct class_attribute *attr,
+                             char *data)
+{
+       int n = 0;
+       struct list_head *tmp;
+       int max = PAGE_SIZE;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       n += snprintf(data, max,
+                     "#id\tmajor\tclient_name\tpool\tname\tsnap\tKB\n");
+
+       list_for_each(tmp, &rbd_dev_list) {
+               struct rbd_device *rbd_dev;
+
+               rbd_dev = list_entry(tmp, struct rbd_device, node);
+               n += snprintf(data+n, max-n,
+                             "%d\t%d\tclient%lld\t%s\t%s\t%s\t%lld\n",
+                             rbd_dev->id,
+                             rbd_dev->major,
+                             ceph_client_id(rbd_dev->client),
+                             rbd_dev->pool_name,
+                             rbd_dev->obj, rbd_dev->snap_name,
+                             rbd_dev->header.image_size >> 10);
+               if (n == max)
+                       break;
+       }
+
+       mutex_unlock(&ctl_mutex);
+       return n;
+}
+
+static ssize_t class_rbd_add(struct class *c,
+                            struct class_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct ceph_osd_client *osdc;
+       struct rbd_device *rbd_dev;
+       ssize_t rc = -ENOMEM;
+       int irc, new_id = 0;
+       struct list_head *tmp;
+       char *mon_dev_name;
+       char *options;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       mon_dev_name = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+       if (!mon_dev_name)
+               goto err_out_mod;
+
+       options = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+       if (!options)
+               goto err_mon_dev;
+
+       /* new rbd_device object */
+       rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL);
+       if (!rbd_dev)
+               goto err_out_opt;
+
+       /* static rbd_device initialization */
+       spin_lock_init(&rbd_dev->lock);
+       INIT_LIST_HEAD(&rbd_dev->node);
+
+       /* generate unique id: find highest unique id, add one */
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       list_for_each(tmp, &rbd_dev_list) {
+               struct rbd_device *rbd_dev;
+
+               rbd_dev = list_entry(tmp, struct rbd_device, node);
+               if (rbd_dev->id >= new_id)
+                       new_id = rbd_dev->id + 1;
+       }
+
+       rbd_dev->id = new_id;
+
+       /* add to global list */
+       list_add_tail(&rbd_dev->node, &rbd_dev_list);
+
+       /* parse add command */
+       if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s "
+                  "%" __stringify(RBD_MAX_OPT_LEN) "s "
+                  "%" __stringify(RBD_MAX_POOL_NAME_LEN) "s "
+                  "%" __stringify(RBD_MAX_OBJ_NAME_LEN) "s"
+                  "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+                  mon_dev_name, options, rbd_dev->pool_name,
+                  rbd_dev->obj, rbd_dev->snap_name) < 4) {
+               rc = -EINVAL;
+               goto err_out_slot;
+       }
+
+       if (rbd_dev->snap_name[0] == 0)
+               rbd_dev->snap_name[0] = '-';
+
+       rbd_dev->obj_len = strlen(rbd_dev->obj);
+       snprintf(rbd_dev->obj_md_name, sizeof(rbd_dev->obj_md_name), "%s%s",
+                rbd_dev->obj, RBD_SUFFIX);
+
+       /* initialize rest of new object */
+       snprintf(rbd_dev->name, DEV_NAME_LEN, DRV_NAME "%d", rbd_dev->id);
+       rc = rbd_get_client(rbd_dev, mon_dev_name, options);
+       if (rc < 0)
+               goto err_out_slot;
+
+       mutex_unlock(&ctl_mutex);
+
+       /* pick the pool */
+       osdc = &rbd_dev->client->osdc;
+       rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name);
+       if (rc < 0)
+               goto err_out_client;
+       rbd_dev->poolid = rc;
+
+       /* register our block device */
+       irc = register_blkdev(0, rbd_dev->name);
+       if (irc < 0) {
+               rc = irc;
+               goto err_out_client;
+       }
+       rbd_dev->major = irc;
+
+       /* set up and announce blkdev mapping */
+       rc = rbd_init_disk(rbd_dev);
+       if (rc)
+               goto err_out_blkdev;
+
+       return count;
+
+err_out_blkdev:
+       unregister_blkdev(rbd_dev->major, rbd_dev->name);
+err_out_client:
+       rbd_put_client(rbd_dev);
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+err_out_slot:
+       list_del_init(&rbd_dev->node);
+       mutex_unlock(&ctl_mutex);
+
+       kfree(rbd_dev);
+err_out_opt:
+       kfree(options);
+err_mon_dev:
+       kfree(mon_dev_name);
+err_out_mod:
+       dout("Error adding device %s\n", buf);
+       module_put(THIS_MODULE);
+       return rc;
+}
+
+static struct rbd_device *__rbd_get_dev(unsigned long id)
+{
+       struct list_head *tmp;
+       struct rbd_device *rbd_dev;
+
+       list_for_each(tmp, &rbd_dev_list) {
+               rbd_dev = list_entry(tmp, struct rbd_device, node);
+               if (rbd_dev->id == id)
+                       return rbd_dev;
+       }
+       return NULL;
+}
+
+static ssize_t class_rbd_remove(struct class *c,
+                               struct class_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rbd_device *rbd_dev = NULL;
+       int target_id, rc;
+       unsigned long ul;
+
+       rc = strict_strtoul(buf, 10, &ul);
+       if (rc)
+               return rc;
+
+       /* convert to int; abort if we lost anything in the conversion */
+       target_id = (int) ul;
+       if (target_id != ul)
+               return -EINVAL;
+
+       /* remove object from list immediately */
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       rbd_dev = __rbd_get_dev(target_id);
+       if (rbd_dev)
+               list_del_init(&rbd_dev->node);
+
+       mutex_unlock(&ctl_mutex);
+
+       if (!rbd_dev)
+               return -ENOENT;
+
+       rbd_put_client(rbd_dev);
+
+       /* clean up and free blkdev */
+       rbd_free_disk(rbd_dev);
+       unregister_blkdev(rbd_dev->major, rbd_dev->name);
+       kfree(rbd_dev);
+
+       /* release module ref */
+       module_put(THIS_MODULE);
+
+       return count;
+}
+
+static ssize_t class_rbd_snaps_list(struct class *c,
+                             struct class_attribute *attr,
+                             char *data)
+{
+       struct rbd_device *rbd_dev = NULL;
+       struct list_head *tmp;
+       struct rbd_image_header *header;
+       int i, n = 0, max = PAGE_SIZE;
+       int ret;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       n += snprintf(data, max, "#id\tsnap\tKB\n");
+
+       list_for_each(tmp, &rbd_dev_list) {
+               char *names, *p;
+               struct ceph_snap_context *snapc;
+
+               rbd_dev = list_entry(tmp, struct rbd_device, node);
+               header = &rbd_dev->header;
+
+               down_read(&header->snap_rwsem);
+
+               names = header->snap_names;
+               snapc = header->snapc;
+
+               n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+                             rbd_dev->id, RBD_SNAP_HEAD_NAME,
+                             header->image_size >> 10,
+                             (!rbd_dev->cur_snap ? " (*)" : ""));
+               if (n == max)
+                       break;
+
+               p = names;
+               for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+                       n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+                             rbd_dev->id, p, header->snap_sizes[i] >> 10,
+                             (rbd_dev->cur_snap &&
+                              (snap_index(header, i) == rbd_dev->cur_snap) ?
+                              " (*)" : ""));
+                       if (n == max)
+                               break;
+               }
+
+               up_read(&header->snap_rwsem);
+       }
+
+
+       ret = n;
+       mutex_unlock(&ctl_mutex);
+       return ret;
+}
+
+static ssize_t class_rbd_snaps_refresh(struct class *c,
+                               struct class_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rbd_device *rbd_dev = NULL;
+       int target_id, rc;
+       unsigned long ul;
+       int ret = count;
+
+       rc = strict_strtoul(buf, 10, &ul);
+       if (rc)
+               return rc;
+
+       /* convert to int; abort if we lost anything in the conversion */
+       target_id = (int) ul;
+       if (target_id != ul)
+               return -EINVAL;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       rbd_dev = __rbd_get_dev(target_id);
+       if (!rbd_dev) {
+               ret = -ENOENT;
+               goto done;
+       }
+
+       rc = rbd_update_snaps(rbd_dev);
+       if (rc < 0)
+               ret = rc;
+
+done:
+       mutex_unlock(&ctl_mutex);
+       return ret;
+}
+
+static ssize_t class_rbd_snap_create(struct class *c,
+                               struct class_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rbd_device *rbd_dev = NULL;
+       int target_id, ret;
+       char *name;
+
+       name = kmalloc(RBD_MAX_SNAP_NAME_LEN + 1, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+
+       /* parse snaps add command */
+       if (sscanf(buf, "%d "
+                  "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+                  &target_id,
+                  name) != 2) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       rbd_dev = __rbd_get_dev(target_id);
+       if (!rbd_dev) {
+               ret = -ENOENT;
+               goto done_unlock;
+       }
+
+       ret = rbd_header_add_snap(rbd_dev,
+                                 name, GFP_KERNEL);
+       if (ret < 0)
+               goto done_unlock;
+
+       ret = rbd_update_snaps(rbd_dev);
+       if (ret < 0)
+               goto done_unlock;
+
+       ret = count;
+done_unlock:
+       mutex_unlock(&ctl_mutex);
+done:
+       kfree(name);
+       return ret;
+}
+
+static ssize_t class_rbd_rollback(struct class *c,
+                               struct class_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rbd_device *rbd_dev = NULL;
+       int target_id, ret;
+       u64 snapid;
+       char snap_name[RBD_MAX_SNAP_NAME_LEN];
+       u64 cur_ofs;
+       char *seg_name;
+
+       /* parse snaps add command */
+       if (sscanf(buf, "%d "
+                  "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+                  &target_id,
+                  snap_name) != 2) {
+               return -EINVAL;
+       }
+
+       ret = -ENOMEM;
+       seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+       if (!seg_name)
+               return ret;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       rbd_dev = __rbd_get_dev(target_id);
+       if (!rbd_dev) {
+               ret = -ENOENT;
+               goto done_unlock;
+       }
+
+       ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
+       if (ret < 0)
+               goto done_unlock;
+
+       dout("snapid=%lld\n", snapid);
+
+       cur_ofs = 0;
+       while (cur_ofs < rbd_dev->header.image_size) {
+               cur_ofs += rbd_get_segment(&rbd_dev->header,
+                                          rbd_dev->obj,
+                                          cur_ofs, (u64)-1,
+                                          seg_name, NULL);
+               dout("seg_name=%s\n", seg_name);
+
+               ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name);
+               if (ret < 0)
+                       pr_warning("could not roll back obj %s err=%d\n",
+                                  seg_name, ret);
+       }
+
+       ret = rbd_update_snaps(rbd_dev);
+       if (ret < 0)
+               goto done_unlock;
+
+       ret = count;
+
+done_unlock:
+       mutex_unlock(&ctl_mutex);
+       kfree(seg_name);
+
+       return ret;
+}
+
+static struct class_attribute class_rbd_attrs[] = {
+       __ATTR(add,             0200, NULL, class_rbd_add),
+       __ATTR(remove,          0200, NULL, class_rbd_remove),
+       __ATTR(list,            0444, class_rbd_list, NULL),
+       __ATTR(snaps_refresh,   0200, NULL, class_rbd_snaps_refresh),
+       __ATTR(snap_create,     0200, NULL, class_rbd_snap_create),
+       __ATTR(snaps_list,      0444, class_rbd_snaps_list, NULL),
+       __ATTR(snap_rollback,   0200, NULL, class_rbd_rollback),
+       __ATTR_NULL
+};
+
+/*
+ * create control files in sysfs
+ * /sys/class/rbd/...
+ */
+static int rbd_sysfs_init(void)
+{
+       int ret = -ENOMEM;
+
+       class_rbd = kzalloc(sizeof(*class_rbd), GFP_KERNEL);
+       if (!class_rbd)
+               goto out;
+
+       class_rbd->name = DRV_NAME;
+       class_rbd->owner = THIS_MODULE;
+       class_rbd->class_release = class_rbd_release;
+       class_rbd->class_attrs = class_rbd_attrs;
+
+       ret = class_register(class_rbd);
+       if (ret)
+               goto out_class;
+       return 0;
+
+out_class:
+       kfree(class_rbd);
+       class_rbd = NULL;
+       pr_err(DRV_NAME ": failed to create class rbd\n");
+out:
+       return ret;
+}
+
+static void rbd_sysfs_cleanup(void)
+{
+       if (class_rbd)
+               class_destroy(class_rbd);
+       class_rbd = NULL;
+}
+
+int __init rbd_init(void)
+{
+       int rc;
+
+       rc = rbd_sysfs_init();
+       if (rc)
+               return rc;
+       spin_lock_init(&node_lock);
+       pr_info("loaded " DRV_NAME_LONG "\n");
+       return 0;
+}
+
+void __exit rbd_exit(void)
+{
+       rbd_sysfs_cleanup();
+}
+
+module_init(rbd_init);
+module_exit(rbd_exit);
+
+MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
+MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
+MODULE_DESCRIPTION("rados block device");
+
+/* following authorship retained from original osdblk.c */
+MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/rbd_types.h b/drivers/block/rbd_types.h
new file mode 100644 (file)
index 0000000..fc6c678
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#ifndef CEPH_RBD_TYPES_H
+#define CEPH_RBD_TYPES_H
+
+#include <linux/types.h>
+
+/*
+ * rbd image 'foo' consists of objects
+ *   foo.rbd      - image metadata
+ *   foo.00000000
+ *   foo.00000001
+ *   ...          - data
+ */
+
+#define RBD_SUFFIX             ".rbd"
+#define RBD_DIRECTORY           "rbd_directory"
+#define RBD_INFO                "rbd_info"
+
+#define RBD_DEFAULT_OBJ_ORDER  22   /* 4MB */
+#define RBD_MIN_OBJ_ORDER       16
+#define RBD_MAX_OBJ_ORDER       30
+
+#define RBD_MAX_OBJ_NAME_LEN   96
+#define RBD_MAX_SEG_NAME_LEN   128
+
+#define RBD_COMP_NONE          0
+#define RBD_CRYPT_NONE         0
+
+#define RBD_HEADER_TEXT                "<<< Rados Block Device Image >>>\n"
+#define RBD_HEADER_SIGNATURE   "RBD"
+#define RBD_HEADER_VERSION     "001.005"
+
+struct rbd_info {
+       __le64 max_id;
+} __attribute__ ((packed));
+
+struct rbd_image_snap_ondisk {
+       __le64 id;
+       __le64 image_size;
+} __attribute__((packed));
+
+struct rbd_image_header_ondisk {
+       char text[40];
+       char block_name[24];
+       char signature[4];
+       char version[8];
+       struct {
+               __u8 order;
+               __u8 crypt_type;
+               __u8 comp_type;
+               __u8 unused;
+       } __attribute__((packed)) options;
+       __le64 image_size;
+       __le64 snap_seq;
+       __le32 snap_count;
+       __le32 reserved;
+       __le64 snap_names_len;
+       struct rbd_image_snap_ondisk snaps[0];
+} __attribute__((packed));
+
+
+#endif
index 2e46815876dfa087bd6f61fef9eee12cdf766512..75333d0a3327de785f520cdeddbb4a45b83f1a90 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/fd.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/hdreg.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -222,6 +222,7 @@ extern int swim_read_sector_header(struct swim __iomem *base,
 extern int swim_read_sector_data(struct swim __iomem *base,
                                 unsigned char *data);
 
+static DEFINE_MUTEX(swim_mutex);
 static inline void set_swim_mode(struct swim __iomem *base, int enable)
 {
        struct iwm __iomem *iwm_base;
@@ -666,9 +667,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&swim_mutex);
        ret = floppy_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&swim_mutex);
 
        return ret;
 }
@@ -678,7 +679,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
        struct floppy_state *fs = disk->private_data;
        struct swim __iomem *base = fs->swd->base;
 
-       lock_kernel();
+       mutex_lock(&swim_mutex);
        if (fs->ref_count < 0)
                fs->ref_count = 0;
        else if (fs->ref_count > 0)
@@ -686,7 +687,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
 
        if (fs->ref_count == 0)
                swim_motor(base, OFF);
-       unlock_kernel();
+       mutex_unlock(&swim_mutex);
 
        return 0;
 }
@@ -704,9 +705,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
        case FDEJECT:
                if (fs->ref_count != 1)
                        return -EBUSY;
-               lock_kernel();
+               mutex_lock(&swim_mutex);
                err = floppy_eject(fs);
-               unlock_kernel();
+               mutex_unlock(&swim_mutex);
                return err;
 
        case FDGETPRM:
index cc6a3864822cf72a7412fff054b07e520335e056..bf3a5b8592990ccf640b4221973ff84114b893df 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
@@ -36,6 +36,7 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 
+static DEFINE_MUTEX(swim3_mutex);
 static struct request_queue *swim3_queue;
 static struct gendisk *disks[2];
 static struct request *fd_req;
@@ -873,9 +874,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&swim3_mutex);
        ret = floppy_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
+       mutex_unlock(&swim3_mutex);
 
        return ret;
 }
@@ -953,9 +954,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&swim3_mutex);
        ret = floppy_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&swim3_mutex);
 
        return ret;
 }
@@ -964,13 +965,13 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
        struct floppy_state *fs = disk->private_data;
        struct swim3 __iomem *sw = fs->swim3;
-       lock_kernel();
+       mutex_lock(&swim3_mutex);
        if (fs->ref_count > 0 && --fs->ref_count == 0) {
                swim3_action(fs, MOTOR_OFF);
                out_8(&sw->control_bic, 0xff);
                swim3_select(fs, RELAX);
        }
-       unlock_kernel();
+       mutex_unlock(&swim3_mutex);
        return 0;
 }
 
index c48e148785827677b900e961f84b5d52b01e5acb..b5690a045a01076c782a575b4e846af64d0306c5 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <scsi/scsi.h>
 
 #define DRV_NAME "ub"
@@ -248,6 +248,7 @@ struct ub_completion {
        spinlock_t lock;
 };
 
+static DEFINE_MUTEX(ub_mutex);
 static inline void ub_init_completion(struct ub_completion *x)
 {
        x->done = 0;
@@ -1715,9 +1716,9 @@ static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ub_mutex);
        ret = ub_bd_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&ub_mutex);
 
        return ret;
 }
@@ -1730,9 +1731,9 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
        struct ub_lun *lun = disk->private_data;
        struct ub_dev *sc = lun->udev;
 
-       lock_kernel();
+       mutex_lock(&ub_mutex);
        ub_put(sc);
-       unlock_kernel();
+       mutex_unlock(&ub_mutex);
 
        return 0;
 }
@@ -1747,9 +1748,9 @@ static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
        void __user *usermem = (void __user *) arg;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ub_mutex);
        ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
-       unlock_kernel();
+       mutex_unlock(&ub_mutex);
 
        return ret;
 }
index f651e51a3319e0311f6a7bcc5e3d7e12d0e7d0e4..e2ff697697c27c7a26d7f66d24bafd94f10e1031 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/dma-mapping.h>
 #include <linux/completion.h>
 #include <linux/device.h>
@@ -73,6 +73,7 @@ enum {
        MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
 };
 
+static DEFINE_MUTEX(viodasd_mutex);
 static DEFINE_SPINLOCK(viodasd_spinlock);
 
 #define VIOMAXREQ              16
@@ -180,9 +181,9 @@ static int viodasd_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&viodasd_mutex);
        ret = viodasd_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&viodasd_mutex);
 
        return ret;
 }
@@ -196,7 +197,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode)
        struct viodasd_device *d = disk->private_data;
        HvLpEvent_Rc hvrc;
 
-       lock_kernel();
+       mutex_lock(&viodasd_mutex);
        /* Send the event to OS/400.  We DON'T expect a response */
        hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
                        HvLpEvent_Type_VirtualIo,
@@ -210,7 +211,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode)
        if (hvrc != 0)
                pr_warning("HV close call failed %d\n", (int)hvrc);
 
-       unlock_kernel();
+       mutex_unlock(&viodasd_mutex);
 
        return 0;
 }
index 2aafafca2b1374b11714546fb3c063044ed9200c..8320490226b78145f95c7e7801a15080419adc19 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/hdreg.h>
 #include <linux/virtio.h>
 #include <linux/virtio_blk.h>
@@ -202,6 +201,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
        struct virtio_blk *vblk = disk->private_data;
        struct request *req;
        struct bio *bio;
+       int err;
 
        bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES,
                           GFP_KERNEL);
@@ -215,11 +215,14 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
        }
 
        req->cmd_type = REQ_TYPE_SPECIAL;
-       return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+       err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+       blk_put_request(req);
+
+       return err;
 }
 
-static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode,
-                        unsigned cmd, unsigned long data)
+static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
+                            unsigned int cmd, unsigned long data)
 {
        struct gendisk *disk = bdev->bd_disk;
        struct virtio_blk *vblk = disk->private_data;
@@ -234,18 +237,6 @@ static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode,
                              (void __user *)data);
 }
 
-static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
-                            unsigned int cmd, unsigned long param)
-{
-       int ret;
-
-       lock_kernel();
-       ret = virtblk_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
-
-       return ret;
-}
-
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
index d5a3cd750561f29349e4850efde23a2463223bf6..4abd2bcd20fb8b069362e2684c8eed2dcd6a0620 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/blkpg.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -58,6 +58,7 @@
 
 #include "xd.h"
 
+static DEFINE_MUTEX(xd_mutex);
 static void __init do_xd_setup (int *integers);
 #ifdef MODULE
 static int xd[5] = { -1,-1,-1,-1, };
@@ -381,9 +382,9 @@ static int xd_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&xd_mutex);
        ret = xd_locked_ioctl(bdev, mode, cmd, param);
-       unlock_kernel();
+       mutex_unlock(&xd_mutex);
 
        return ret;
 }
index ac1b682edecb362831eb32e7fd09faaff69da428..3ff06f475eef47bc841b5c0877527ce9d47ea32b 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/cdrom.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 
 #include <xen/xen.h>
@@ -69,6 +69,7 @@ struct blk_shadow {
        unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
+static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
 #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
@@ -834,7 +835,7 @@ static int blkfront_probe(struct xenbus_device *dev,
                char *type;
                int len;
                /* no unplug has been done: do not hook devices != xen vbds */
-               if (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE) {
+               if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY) {
                        int major;
 
                        if (!VDEV_IS_EXTENDED(vdevice))
@@ -1201,7 +1202,7 @@ static int blkif_open(struct block_device *bdev, fmode_t mode)
        struct blkfront_info *info;
        int err = 0;
 
-       lock_kernel();
+       mutex_lock(&blkfront_mutex);
 
        info = disk->private_data;
        if (!info) {
@@ -1219,7 +1220,7 @@ static int blkif_open(struct block_device *bdev, fmode_t mode)
        mutex_unlock(&info->mutex);
 
 out:
-       unlock_kernel();
+       mutex_unlock(&blkfront_mutex);
        return err;
 }
 
@@ -1229,7 +1230,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
        struct block_device *bdev;
        struct xenbus_device *xbdev;
 
-       lock_kernel();
+       mutex_lock(&blkfront_mutex);
 
        bdev = bdget_disk(disk, 0);
        bdput(bdev);
@@ -1263,7 +1264,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
        }
 
 out:
-       unlock_kernel();
+       mutex_unlock(&blkfront_mutex);
        return 0;
 }
 
index 057413bb16e294d20d476d49ea4770b56a8e986c..6e968cd4893caea636246796fac124e7b34d83a6 100644 (file)
@@ -89,7 +89,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/ata.h>
 #include <linux/hdreg.h>
 #include <linux/platform_device.h>
@@ -214,6 +214,7 @@ struct ace_device {
        u16 cf_id[ATA_ID_WORDS];
 };
 
+static DEFINE_MUTEX(xsysace_mutex);
 static int ace_major;
 
 /* ---------------------------------------------------------------------
@@ -903,13 +904,13 @@ static int ace_open(struct block_device *bdev, fmode_t mode)
 
        dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
 
-       lock_kernel();
+       mutex_lock(&xsysace_mutex);
        spin_lock_irqsave(&ace->lock, flags);
        ace->users++;
        spin_unlock_irqrestore(&ace->lock, flags);
 
        check_disk_change(bdev);
-       unlock_kernel();
+       mutex_unlock(&xsysace_mutex);
 
        return 0;
 }
@@ -922,7 +923,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode)
 
        dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
 
-       lock_kernel();
+       mutex_lock(&xsysace_mutex);
        spin_lock_irqsave(&ace->lock, flags);
        ace->users--;
        if (ace->users == 0) {
@@ -930,7 +931,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode)
                ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
        }
        spin_unlock_irqrestore(&ace->lock, flags);
-       unlock_kernel();
+       mutex_unlock(&xsysace_mutex);
        return 0;
 }
 
index d75b2bb601adbb2a4eae42b5c259918fc7823df5..dcd4cfcf41264dac474df84616a0c7f6b44390b0 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/setup.h>
@@ -57,6 +57,7 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
 
 #define Z2RAM_CHUNK1024       ( Z2RAM_CHUNKSIZE >> 10 )
 
+static DEFINE_MUTEX(z2ram_mutex);
 static u_long *z2ram_map    = NULL;
 static u_long z2ram_size    = 0;
 static int z2_count         = 0;
@@ -154,7 +155,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
 
     device = MINOR(bdev->bd_dev);
 
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device != -1 && current_device != device )
     {
        rc = -EBUSY;
@@ -296,25 +297,25 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
        set_capacity(z2ram_gendisk, z2ram_size >> 9);
     }
 
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return 0;
 
 err_out_kfree:
     kfree(z2ram_map);
 err_out:
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return rc;
 }
 
 static int
 z2_release(struct gendisk *disk, fmode_t mode)
 {
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device == -1 ) {
-       unlock_kernel();
+       mutex_unlock(&z2ram_mutex);
        return 0;
     }
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     /*
      * FIXME: unmap memory
      */
index d52e90a5a61750494a6c740e4dd4565fb00f788e..4104b7feae6741c585af6d87db7c1333478e6891 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/skbuff.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -865,8 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
        info->p_dev = link;
        link->priv = info;
 
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ;
 
        return bluecard_config(link);
 }
@@ -886,7 +884,7 @@ static int bluecard_config(struct pcmcia_device *link)
        bluecard_info_t *info = link->priv;
        int i, n;
 
-       link->conf.ConfigIndex = 0x20;
+       link->config_index = 0x20;
 
        link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
        link->resource[0]->end = 64;
@@ -906,7 +904,7 @@ static int bluecard_config(struct pcmcia_device *link)
        if (i != 0)
                goto failed;
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                goto failed;
 
@@ -942,9 +940,7 @@ MODULE_DEVICE_TABLE(pcmcia, bluecard_ids);
 
 static struct pcmcia_driver bluecard_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "bluecard_cs",
-       },
+       .name           = "bluecard_cs",
        .probe          = bluecard_probe,
        .remove         = bluecard_detach,
        .id_table       = bluecard_ids,
index 7ab8f29d5e0dcb8df750bab81fc0bcce4494b12e..0c8a655874914d0604784d09c32c3b1651de03f5 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -657,11 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link)
        info->p_dev = link;
        link->priv = info;
 
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[0]->end = 8;
-
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+               CONF_AUTO_SET_IO;
 
        return bt3c_config(link);
 }
@@ -675,43 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int bt3c_check_config(struct pcmcia_device *p_dev,
-                            cistpl_cftable_entry_t *cf,
-                            cistpl_cftable_entry_t *dflt,
-                            unsigned int vcc,
-                            void *priv_data)
+static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
-       unsigned long try = (unsigned long) priv_data;
+       int *try = priv_data;
 
-       p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+       if (try == 0)
+               p_dev->io_lines = 16;
 
-       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-           (cf->io.win[0].base != 0)) {
-               p_dev->resource[0]->start = cf->io.win[0].base;
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -ENODEV;
+       if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+               return -EINVAL;
+
+       p_dev->resource[0]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
-                                     cistpl_cftable_entry_t *cf,
-                                     cistpl_cftable_entry_t *dflt,
-                                     unsigned int vcc,
                                      void *priv_data)
 {
        static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        int j;
 
-       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-               for (j = 0; j < 5; j++) {
-                       p_dev->resource[0]->start = base[j];
-                       p_dev->io_lines = base[j] ? 16 : 3;
-                       if (!pcmcia_request_io(p_dev))
-                               return 0;
-               }
+       if (p_dev->io_lines > 3)
+               return -ENODEV;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = 8;
+
+       for (j = 0; j < 5; j++) {
+               p_dev->resource[0]->start = base[j];
+               p_dev->io_lines = base[j] ? 16 : 3;
+               if (!pcmcia_request_io(p_dev))
+                       return 0;
        }
        return -ENODEV;
 }
@@ -742,7 +736,7 @@ found_port:
        if (i != 0)
                goto failed;
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                goto failed;
 
@@ -775,9 +769,7 @@ MODULE_DEVICE_TABLE(pcmcia, bt3c_ids);
 
 static struct pcmcia_driver bt3c_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "bt3c_cs",
-       },
+       .name           = "bt3c_cs",
        .probe          = bt3c_probe,
        .remove         = bt3c_detach,
        .id_table       = bt3c_ids,
index 54739b08c3083d413c70981fc0f0ca095cec0716..fd6305bf953e4084c9b7557a26acb002deb101fe 100644 (file)
@@ -92,6 +92,7 @@ static const struct file_operations btmrvl_hscfgcmd_fops = {
        .read   = btmrvl_hscfgcmd_read,
        .write  = btmrvl_hscfgcmd_write,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
@@ -130,6 +131,7 @@ static const struct file_operations btmrvl_psmode_fops = {
        .read   = btmrvl_psmode_read,
        .write  = btmrvl_psmode_write,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
@@ -173,6 +175,7 @@ static const struct file_operations btmrvl_pscmd_fops = {
        .read = btmrvl_pscmd_read,
        .write = btmrvl_pscmd_write,
        .open = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
@@ -211,6 +214,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
        .read   = btmrvl_gpiogap_read,
        .write  = btmrvl_gpiogap_write,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
@@ -252,6 +256,7 @@ static const struct file_operations btmrvl_hscmd_fops = {
        .read   = btmrvl_hscmd_read,
        .write  = btmrvl_hscmd_write,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
@@ -289,6 +294,7 @@ static const struct file_operations btmrvl_hsmode_fops = {
        .read   = btmrvl_hsmode_read,
        .write  = btmrvl_hsmode_write,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
@@ -306,6 +312,7 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_curpsmode_fops = {
        .read   = btmrvl_curpsmode_read,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
@@ -323,6 +330,7 @@ static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
 static const struct file_operations btmrvl_psstate_fops = {
        .read   = btmrvl_psstate_read,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
@@ -340,6 +348,7 @@ static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_hsstate_fops = {
        .read   = btmrvl_hsstate_read,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
@@ -358,6 +367,7 @@ static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_txdnldready_fops = {
        .read   = btmrvl_txdnldready_read,
        .open   = btmrvl_open_generic,
+       .llseek = default_llseek,
 };
 
 void btmrvl_debugfs_init(struct hci_dev *hdev)
index 1c4f5e863b032d21d8a765a4d3b97c1ca1bb73e4..f8a0708e23110446de1f8a4ccc5e344306b88820 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -586,11 +585,8 @@ static int btuart_probe(struct pcmcia_device *link)
        info->p_dev = link;
        link->priv = info;
 
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[0]->end = 8;
-
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+               CONF_AUTO_SET_IO;
 
        return btuart_config(link);
 }
@@ -604,43 +600,41 @@ static void btuart_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int btuart_check_config(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cf,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
        int *try = priv_data;
 
-       p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+       if (try == 0)
+               p_dev->io_lines = 16;
 
-       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-           (cf->io.win[0].base != 0)) {
-               p_dev->resource[0]->start = cf->io.win[0].base;
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -ENODEV;
+       if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+               return -EINVAL;
+
+       p_dev->resource[0]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
-                                       cistpl_cftable_entry_t *cf,
-                                       cistpl_cftable_entry_t *dflt,
-                                       unsigned int vcc,
                                        void *priv_data)
 {
        static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        int j;
 
-       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-               for (j = 0; j < 5; j++) {
-                       p_dev->resource[0]->start = base[j];
-                       p_dev->io_lines = base[j] ? 16 : 3;
-                       if (!pcmcia_request_io(p_dev))
-                               return 0;
-               }
+       if (p_dev->io_lines > 3)
+               return -ENODEV;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = 8;
+
+       for (j = 0; j < 5; j++) {
+               p_dev->resource[0]->start = base[j];
+               p_dev->io_lines = base[j] ? 16 : 3;
+               if (!pcmcia_request_io(p_dev))
+                       return 0;
        }
        return -ENODEV;
 }
@@ -671,7 +665,7 @@ found_port:
        if (i != 0)
                goto failed;
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                goto failed;
 
@@ -703,9 +697,7 @@ MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
 
 static struct pcmcia_driver btuart_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "btuart_cs",
-       },
+       .name           = "btuart_cs",
        .probe          = btuart_probe,
        .remove         = btuart_detach,
        .id_table       = btuart_ids,
index db7c8db695fc643cff089670b721ef801dd14090..26ee0cf88d20487c0c830b5dec0c753bbf11a3b8 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -572,11 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link)
        info->p_dev = link;
        link->priv = info;
 
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[0]->end = 8;
-
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
        return dtl1_config(link);
 }
@@ -591,18 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int dtl1_confcheck(struct pcmcia_device *p_dev,
-                         cistpl_cftable_entry_t *cf,
-                         cistpl_cftable_entry_t *dflt,
-                         unsigned int vcc,
-                         void *priv_data)
+static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
+       if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
                return -ENODEV;
 
-       p_dev->resource[0]->start = cf->io.win[0].base;
-       p_dev->resource[0]->end = cf->io.win[0].len;    /*yo */
-       p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
        return pcmcia_request_io(p_dev);
 }
 
@@ -620,7 +611,7 @@ static int dtl1_config(struct pcmcia_device *link)
        if (i != 0)
                goto failed;
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                goto failed;
 
@@ -656,9 +647,7 @@ MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
 
 static struct pcmcia_driver dtl1_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "dtl1_cs",
-       },
+       .name           = "dtl1_cs",
        .probe          = dtl1_probe,
        .remove         = dtl1_detach,
        .id_table       = dtl1_ids,
index 998833d93c13c724ffbc828ab0f62ad07e1c438c..17361bad46dd9e367a027c4506ceea7504d76af5 100644 (file)
@@ -256,9 +256,16 @@ static int hci_uart_tty_open(struct tty_struct *tty)
 
        BT_DBG("tty %p", tty);
 
+       /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+          the pointer */
        if (hu)
                return -EEXIST;
 
+       /* Error if the tty has no write op instead of leaving an exploitable
+          hole */
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
                BT_ERR("Can't allocate control structure");
                return -ENFILE;
index 3aa7b2a54b6f75b04014847e989bf7215dd41bc5..67c180c2c1e0fbf27951862e30a0787deba4d4a0 100644 (file)
@@ -282,6 +282,7 @@ static const struct file_operations vhci_fops = {
        .poll           = vhci_poll,
        .open           = vhci_open,
        .release        = vhci_release,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice vhci_miscdev= {
index 261107d1457c9a57599dbbb2db6c04a87c828a0a..3af6516919b740cd55f717e2786b89cde4ff83ea 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
@@ -81,6 +81,7 @@
 
 #define GDROM_DEFAULT_TIMEOUT  (HZ * 7)
 
+static DEFINE_MUTEX(gdrom_mutex);
 static const struct {
        int sense_key;
        const char * const text;
@@ -494,17 +495,17 @@ static struct cdrom_device_ops gdrom_ops = {
 static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
-       lock_kernel();
+       mutex_lock(&gdrom_mutex);
        ret = cdrom_open(gd.cd_info, bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&gdrom_mutex);
        return ret;
 }
 
 static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode)
 {
-       lock_kernel();
+       mutex_lock(&gdrom_mutex);
        cdrom_release(gd.cd_info, mode);
-       unlock_kernel();
+       mutex_unlock(&gdrom_mutex);
        return 0;
 }
 
@@ -518,9 +519,9 @@ static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&gdrom_mutex);
        ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gdrom_mutex);
 
        return ret;
 }
index 56bf9f44700c401f2a2556177c57f526aad868c7..be73a9b493a69970135663ffd4ed7a83cb568cb9 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
 
@@ -61,6 +61,7 @@
  */
 #define VIOCD_MAX_CD   HVMAXARCHITECTEDVIRTUALCDROMS
 
+static DEFINE_MUTEX(viocd_mutex);
 static const struct vio_error_entry viocd_err_table[] = {
        {0x0201, EINVAL, "Invalid Range"},
        {0x0202, EINVAL, "Invalid Token"},
@@ -156,9 +157,9 @@ static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
        struct disk_info *di = bdev->bd_disk->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&viocd_mutex);
        ret = cdrom_open(&di->viocd_info, bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&viocd_mutex);
 
        return ret;
 }
@@ -166,9 +167,9 @@ static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
 static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
 {
        struct disk_info *di = disk->private_data;
-       lock_kernel();
+       mutex_lock(&viocd_mutex);
        cdrom_release(&di->viocd_info, mode);
-       unlock_kernel();
+       mutex_unlock(&viocd_mutex);
        return 0;
 }
 
@@ -178,9 +179,9 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode,
        struct disk_info *di = bdev->bd_disk->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&viocd_mutex);
        ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&viocd_mutex);
 
        return ret;
 }
index 4b66c69eaf5790d104cf653dd48a14e5eb2940bf..5ddf67e76f8bbccf3242da3bc2e2373d2255648c 100644 (file)
@@ -57,7 +57,7 @@ config AGP_AMD
 
 config AGP_AMD64
        tristate "AMD Opteron/Athlon64 on-CPU GART support"
-       depends on AGP && X86 && K8_NB
+       depends on AGP && X86 && AMD_NB
        help
          This option gives you AGP support for the GLX component of
          X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
index 70312da4c968f9e4af7c39e9a5a649b4952f8bd3..42396df555567660d597ac524631e9020edfbea3 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/mmzone.h>
 #include <asm/page.h>          /* PAGE_SIZE */
 #include <asm/e820.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/gart.h>
 #include "agp.h"
 
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void)
        u32 temp;
        struct aper_size_info_32 *values;
 
-       dev = k8_northbridges[0];
+       dev = k8_northbridges.nb_misc[0];
        if (dev==NULL)
                return 0;
 
@@ -181,10 +181,14 @@ static int amd_8151_configure(void)
        unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
        int i;
 
+       if (!k8_northbridges.gart_supported)
+               return 0;
+
        /* Configure AGP regs in each x86-64 host bridge. */
-        for (i = 0; i < num_k8_northbridges; i++) {
+       for (i = 0; i < k8_northbridges.num; i++) {
                agp_bridge->gart_bus_addr =
-                               amd64_configure(k8_northbridges[i], gatt_bus);
+                               amd64_configure(k8_northbridges.nb_misc[i],
+                                               gatt_bus);
        }
        k8_flush_garts();
        return 0;
@@ -195,11 +199,15 @@ static void amd64_cleanup(void)
 {
        u32 tmp;
        int i;
-        for (i = 0; i < num_k8_northbridges; i++) {
-               struct pci_dev *dev = k8_northbridges[i];
+
+       if (!k8_northbridges.gart_supported)
+               return;
+
+       for (i = 0; i < k8_northbridges.num; i++) {
+               struct pci_dev *dev = k8_northbridges.nb_misc[i];
                /* disable gart translation */
                pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
-               tmp &= ~AMD64_GARTEN;
+               tmp &= ~GARTEN;
                pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp);
        }
 }
@@ -313,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
        if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
                return -1;
 
-       pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1);
+       gart_set_size_and_enable(nb, order);
        pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25);
 
        return 0;
 }
 
-static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
+static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
 {
        int i;
 
        if (cache_k8_northbridges() < 0)
                return -ENODEV;
 
+       if (!k8_northbridges.gart_supported)
+               return -ENODEV;
+
        i = 0;
-       for (i = 0; i < num_k8_northbridges; i++) {
-               struct pci_dev *dev = k8_northbridges[i];
+       for (i = 0; i < k8_northbridges.num; i++) {
+               struct pci_dev *dev = k8_northbridges.nb_misc[i];
                if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
                        dev_err(&dev->dev, "no usable aperture found\n");
 #ifdef __x86_64__
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
        }
 
        /* shadow x86-64 registers into ULi registers */
-       pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
+       pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+                              &httfea);
 
        /* if x86-64 aperture base is beyond 4G, exit here */
        if ((httfea & 0x7fff) >> (32 - 25)) {
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev)
        pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
 
        /* shadow x86-64 registers into NVIDIA registers */
-       pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
+       pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+                              &apbase);
 
        /* if x86-64 aperture base is beyond 4G, exit here */
        if ( (apbase & 0x7fff) >> (32 - 25) ) {
index d2abf51439836383fd9b03612a44bdf1779448fa..64255cef8a7db93f780c700d712c5fa4b7fe5907 100644 (file)
@@ -984,7 +984,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
 
        bridge->driver->cache_flush();
 #ifdef CONFIG_X86
-       set_memory_uc((unsigned long)table, 1 << page_order);
+       if (set_memory_uc((unsigned long)table, 1 << page_order))
+               printk(KERN_WARNING "Could not set GATT table memory to UC!");
+
        bridge->gatt_table = (void *)table;
 #else
        bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
index 710af89b176d0b8a7fcbed56dbb3a56b762e27f8..cd18493c952795317904229197016e40d7c408cd 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/smp.h>
 #include "agp.h"
 #include "intel-agp.h"
+#include <linux/intel-gtt.h>
 
 #include "intel-gtt.c"
 
@@ -805,6 +806,8 @@ static const struct intel_driver_description {
            "G45/G43", NULL, &intel_i965_driver },
        { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG,
            "B43", NULL, &intel_i965_driver },
+       { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG,
+           "B43", NULL, &intel_i965_driver },
        { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG,
            "G41", NULL, &intel_i965_driver },
        { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
@@ -815,11 +818,19 @@ static const struct intel_driver_description {
            "HD Graphics", NULL, &intel_i965_driver },
        { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
            "HD Graphics", NULL, &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
+           "Sandybridge", NULL, &intel_gen6_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
+           "Sandybridge", NULL, &intel_gen6_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
+           "Sandybridge", NULL, &intel_gen6_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
+           "Sandybridge", NULL, &intel_gen6_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
            "Sandybridge", NULL, &intel_gen6_driver },
-       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
            "Sandybridge", NULL, &intel_gen6_driver },
-       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG,
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
            "Sandybridge", NULL, &intel_gen6_driver },
        { 0, 0, NULL, NULL, NULL }
 };
@@ -1044,6 +1055,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
        ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
        ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
+       ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB),
        { }
 };
 
index 08d47532e60590f169f74995007e745623c4cd66..d09b1ab7e8abeac5bbdf0cc8a8dd5f333f9c22a3 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Common Intel AGPGART and GTT definitions.
  */
+#ifndef _INTEL_AGP_H
+#define _INTEL_AGP_H
 
 /* Intel registers */
 #define INTEL_APSIZE   0xb4
 #define PCI_DEVICE_ID_INTEL_Q33_IG          0x29D2
 #define PCI_DEVICE_ID_INTEL_B43_HB          0x2E40
 #define PCI_DEVICE_ID_INTEL_B43_IG          0x2E42
+#define PCI_DEVICE_ID_INTEL_B43_1_HB        0x2E90
+#define PCI_DEVICE_ID_INTEL_B43_1_IG        0x2E92
 #define PCI_DEVICE_ID_INTEL_GM45_HB         0x2A40
 #define PCI_DEVICE_ID_INTEL_GM45_IG         0x2A42
 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB        0x2E00
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB         0x0062
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB    0x006a
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG          0x0046
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB  0x0100
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG  0x0102
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB  0x0104
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG  0x0106
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG  0x0126
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB             0x0100  /* Desktop */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG         0x0102
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG         0x0112
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG    0x0122
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB           0x0104  /* Mobile */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG       0x0106
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG       0x0116
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG  0x0126
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB           0x0108  /* Server */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG           0x010A
 
 /* cover 915 and 945 variants */
 #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
 
 #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
-               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB)
 
 #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
                IS_SNB)
+
+#endif
index d22ffb811bf2cea4001a97d485327d668ff9d85a..75e0a3497888d295d25dd414bda8a2ce69eee724 100644 (file)
@@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] =
         .type = INTEL_AGP_CACHED_MEMORY}
 };
 
+#define INTEL_AGP_UNCACHED_MEMORY              0
+#define INTEL_AGP_CACHED_MEMORY_LLC            1
+#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT       2
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC        3
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT   4
+
+static struct gatt_mask intel_gen6_masks[] =
+{
+       {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
+        .type = INTEL_AGP_UNCACHED_MEMORY },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
+};
+
 static struct _intel_private {
        struct pci_dev *pcidev; /* device one */
        u8 __iomem *registers;
@@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
                                        off_t pg_start, int mask_type)
 {
        int i, j;
-       u32 cache_bits = 0;
-
-       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
-           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
-       {
-               cache_bits = GEN6_PTE_LLC_MLC;
-       }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
                return 0;
 }
 
+static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
+                                       int type)
+{
+       unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
+       unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;
+
+       if (type_mask == AGP_USER_UNCACHED_MEMORY)
+               return INTEL_AGP_UNCACHED_MEMORY;
+       else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
+               return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
+                             INTEL_AGP_CACHED_MEMORY_LLC_MLC;
+       else /* set 'normal'/'cached' to LLC by default */
+               return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
+                             INTEL_AGP_CACHED_MEMORY_LLC;
+}
+
+
 static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
                                int type)
 {
@@ -588,8 +618,7 @@ static void intel_i830_init_gtt_entries(void)
                        gtt_entries = 0;
                        break;
                }
-       } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
-                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
+       } else if (IS_SNB) {
                /*
                 * SandyBridge has new memory control reg at 0x50.w
                 */
@@ -1068,11 +1097,11 @@ static void intel_i9xx_setup_flush(void)
                intel_i915_setup_chipset_flush();
        }
 
-       if (intel_private.ifp_resource.start) {
+       if (intel_private.ifp_resource.start)
                intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
-               if (!intel_private.i9xx_flush_page)
-                       dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
-       }
+       if (!intel_private.i9xx_flush_page)
+               dev_err(&intel_private.pcidev->dev,
+                       "can't ioremap flush page - no chipset flushing\n");
 }
 
 static int intel_i9xx_configure(void)
@@ -1163,7 +1192,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
 
        mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-       if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+       if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
            mask_type != INTEL_AGP_CACHED_MEMORY)
                goto out_err;
 
@@ -1333,8 +1362,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
 static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
                                            dma_addr_t addr, int type)
 {
-       /* Shift high bits down */
-       addr |= (addr >> 28) & 0xff;
+       /* gen6 has bit11-4 for physical addr bit39-32 */
+       addr |= (addr >> 28) & 0xff0;
 
        /* Type checking must be done elsewhere */
        return addr | bridge->driver->masks[type].mask;
@@ -1359,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
                break;
        case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
        case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
+       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB:
                *gtt_offset = MB(2);
 
                pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
@@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
        .fetch_size             = intel_i9xx_fetch_size,
        .cleanup                = intel_i915_cleanup,
        .mask_memory            = intel_gen6_mask_memory,
-       .masks                  = intel_i810_masks,
+       .masks                  = intel_gen6_masks,
        .agp_enable             = intel_i810_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i965_create_gatt_table,
@@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
        .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_destroy_pages      = agp_generic_destroy_pages,
-       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
+       .agp_type_to_mask_type  = intel_gen6_type_to_mask_type,
        .chipset_flush          = intel_i915_chipset_flush,
 #ifdef USE_PCI_DMA_API
        .agp_map_page           = intel_agp_map_page,
index 033e1505fca9fe3ea2fee9b2b064578ad45637f4..3022801669b148b35bc9174c19a7bbf559ec7cd6 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
@@ -126,6 +126,7 @@ struct apm_user {
 /*
  * Local variables
  */
+static DEFINE_MUTEX(apm_mutex);
 static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
 static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
 static int apm_disabled;
@@ -274,7 +275,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
        if (!as->suser || !as->writer)
                return -EPERM;
 
-       lock_kernel();
+       mutex_lock(&apm_mutex);
        switch (cmd) {
        case APM_IOC_SUSPEND:
                mutex_lock(&state_lock);
@@ -335,7 +336,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
                mutex_unlock(&state_lock);
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&apm_mutex);
 
        return err;
 }
@@ -370,7 +371,7 @@ static int apm_open(struct inode * inode, struct file * filp)
 {
        struct apm_user *as;
 
-       lock_kernel();
+       mutex_lock(&apm_mutex);
        as = kzalloc(sizeof(*as), GFP_KERNEL);
        if (as) {
                /*
@@ -390,7 +391,7 @@ static int apm_open(struct inode * inode, struct file * filp)
 
                filp->private_data = as;
        }
-       unlock_kernel();
+       mutex_unlock(&apm_mutex);
 
        return as ? 0 : -ENOMEM;
 }
@@ -402,6 +403,7 @@ static const struct file_operations apm_bios_fops = {
        .unlocked_ioctl = apm_ioctl,
        .open           = apm_open,
        .release        = apm_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice apm_device = {
index f4ae0e0fb631b522f1b02a0a4ea68e2f98df0897..e7ba774beda6b8598a47dd77faf52e5283437037 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/wait.h>
@@ -60,6 +60,7 @@
 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
 #endif
 
+static DEFINE_MUTEX(ac_mutex);
 static char *applicom_pci_devnames[] = {
        "PCI board",
        "PCI2000IBS / PCI2000CAN",
@@ -707,7 +708,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        if (IS_ERR(adgl))
                return PTR_ERR(adgl);
 
-       lock_kernel();  
+       mutex_lock(&ac_mutex);  
        IndexCard = adgl->num_card-1;
         
        if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
@@ -717,7 +718,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        warncount--;
                }
                kfree(adgl);
-               unlock_kernel();
+               mutex_unlock(&ac_mutex);
                return -EINVAL;
        }
 
@@ -835,7 +836,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        }
        Dummy = readb(apbs[IndexCard].RamIO + VERS);
        kfree(adgl);
-       unlock_kernel();
+       mutex_unlock(&ac_mutex);
        return 0;
 }
 
index 836d4f0a876f5ca53b03f8314acea1a0f23f5ca3..44660f1c484932cc24421372558b5e8ed0049147 100644 (file)
@@ -222,6 +222,7 @@ static const struct file_operations bfin_otp_fops = {
        .unlocked_ioctl = bfin_otp_ioctl,
        .read           = bfin_otp_read,
        .write          = bfin_otp_write,
+       .llseek         = default_llseek,
 };
 
 static struct miscdevice bfin_otp_misc_device = {
index d5fa113afe3729760b00b5ee6cd048d20a169c27..f6718f05dad4a4ca16465967dd8779984637238e 100644 (file)
@@ -186,6 +186,7 @@ static const struct file_operations briq_panel_fops = {
        .write          = briq_panel_write,
        .open           = briq_panel_open,
        .release        = briq_panel_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice briq_panel_miscdev = {
index 91917133ae0ad7de08d58a9379e943c9ecef2988..a4a6c2f044b539e8472a8398ed712e3191febac3 100644 (file)
@@ -155,6 +155,7 @@ static const struct file_operations bsr_fops = {
        .owner = THIS_MODULE,
        .mmap  = bsr_mmap,
        .open  = bsr_open,
+       .llseek = noop_llseek,
 };
 
 static void bsr_cleanup_devs(void)
index 4d830dc482efd7466295d24702da85e65ac045f8..0cf1e5fad9ababdfebca61e37ae7b919318b3a6c 100644 (file)
@@ -169,7 +169,8 @@ static const struct file_operations cs5535_gpio_fops = {
        .owner  = THIS_MODULE,
        .write  = cs5535_gpio_write,
        .read   = cs5535_gpio_read,
-       .open   = cs5535_gpio_open
+       .open   = cs5535_gpio_open,
+       .llseek = no_llseek,
 };
 
 static int __init cs5535_gpio_init(void)
index 170693c93c73d275fceb2c310c41df8a323c9297..ed8303f9890c346ef136d54ec2b999cce3ee5e5d 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
@@ -32,6 +32,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(rtc_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* Send 8 bits. */
@@ -164,9 +165,9 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        struct rtc_time rtc_tm;
 
                        memset(&rtc_tm, 0, sizeof (struct rtc_time));
-                       lock_kernel();
+                       mutex_lock(&rtc_mutex);
                        get_rtc_time(&rtc_tm);
-                       unlock_kernel();
+                       mutex_unlock(&rtc_mutex);
                        if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
                                return -EFAULT;
                        return 0;
@@ -218,7 +219,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        mon = bin2bcd(mon);
                        yrs = bin2bcd(yrs);
 
-                       lock_kernel();
+                       mutex_lock(&rtc_mutex);
                        local_irq_save(flags);
                        CMOS_WRITE(yrs, RTC_YEAR);
                        CMOS_WRITE(mon, RTC_MONTH);
@@ -227,7 +228,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        CMOS_WRITE(min, RTC_MINUTES);
                        CMOS_WRITE(sec, RTC_SECONDS);
                        local_irq_restore(flags);
-                       unlock_kernel();
+                       mutex_unlock(&rtc_mutex);
 
                        /* Notice that at this point, the RTC is updated but
                         * the kernel is still running with the old time.
@@ -247,10 +248,10 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
                                return -EFAULT;
 
-                       lock_kernel();
+                       mutex_lock(&rtc_mutex);
                        tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
                        ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
-                       unlock_kernel();
+                       mutex_unlock(&rtc_mutex);
                        return 0;
                }
                default:
@@ -288,6 +289,7 @@ get_rtc_status(char *buf)
 static const struct file_operations rtc_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = rtc_ioctl,
+       .llseek         = noop_llseek,
 };
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
index dbee8688f75ceafddfd80a5be5b7dcf8affd7140..aab9605f0b43291974c67855caf920c5656c8b0d 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/proc_fs.h>
 #include <linux/capability.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,6 +34,7 @@
 #define CFG_CPU                        2
 #define CFG_1SHOT              1
 
+static DEFINE_MUTEX(ds1620_mutex);
 static const char *fan_state[] = { "off", "on", "on (hardwired)" };
 
 /*
@@ -210,7 +211,6 @@ static void ds1620_read_state(struct therm *therm)
 
 static int ds1620_open(struct inode *inode, struct file *file)
 {
-       cycle_kernel_lock();
        return nonseekable_open(inode, file);
 }
 
@@ -321,9 +321,9 @@ ds1620_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ds1620_mutex);
        ret = ds1620_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ds1620_mutex);
 
        return ret;
 }
@@ -357,6 +357,7 @@ static const struct file_operations ds1620_fops = {
        .open           = ds1620_open,
        .read           = ds1620_read,
        .unlocked_ioctl = ds1620_unlocked_ioctl,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice ds1620_miscdev = {
index 8a1b28a10ef0af184e4ff4e03e9eaaf4783f97ca..052797b32bd3ff484dca016c1b48a66d99cef6f8 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>     /* For put_user and get_user */
@@ -94,6 +94,7 @@
        } \
 }
 
+static DEFINE_MUTEX(dsp56k_mutex);
 static struct dsp56k_device {
        unsigned long in_use;
        long maxio, timeout;
@@ -330,9 +331,9 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
                        if (len > DSP56K_MAX_BINARY_LENGTH) {
                                return -EINVAL;
                        }
-                       lock_kernel();
+                       mutex_lock(&dsp56k_mutex);
                        r = dsp56k_upload(bin, len);
-                       unlock_kernel();
+                       mutex_unlock(&dsp56k_mutex);
                        if (r < 0) {
                                return r;
                        }
@@ -342,16 +343,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
                case DSP56K_SET_TX_WSIZE:
                        if (arg > 4 || arg < 1)
                                return -EINVAL;
-                       lock_kernel();
+                       mutex_lock(&dsp56k_mutex);
                        dsp56k.tx_wsize = (int) arg;
-                       unlock_kernel();
+                       mutex_unlock(&dsp56k_mutex);
                        break;
                case DSP56K_SET_RX_WSIZE:
                        if (arg > 4 || arg < 1)
                                return -EINVAL;
-                       lock_kernel();
+                       mutex_lock(&dsp56k_mutex);
                        dsp56k.rx_wsize = (int) arg;
-                       unlock_kernel();
+                       mutex_unlock(&dsp56k_mutex);
                        break;
                case DSP56K_HOST_FLAGS:
                {
@@ -363,7 +364,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
                        if(get_user(out, &hf->out) < 0)
                                return -EFAULT;
 
-                       lock_kernel();
+                       mutex_lock(&dsp56k_mutex);
                        if ((dir & 0x1) && (out & 0x1))
                                dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
                        else if (dir & 0x1)
@@ -378,16 +379,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
                        if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
-                       unlock_kernel();
+                       mutex_unlock(&dsp56k_mutex);
                        return put_user(status, &hf->status);
                }
                case DSP56K_HOST_CMD:
                        if (arg > 31 || arg < 0)
                                return -EINVAL;
-                       lock_kernel();
+                       mutex_lock(&dsp56k_mutex);
                        dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
                                                             DSP56K_CVR_HC);
-                       unlock_kernel();
+                       mutex_unlock(&dsp56k_mutex);
                        break;
                default:
                        return -EINVAL;
@@ -427,7 +428,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
        int dev = iminor(inode) & 0x0f;
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&dsp56k_mutex);
        switch(dev)
        {
        case DSP56K_DEV_56001:
@@ -454,7 +455,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
                ret = -ENODEV;
        }
 out:
-       unlock_kernel();
+       mutex_unlock(&dsp56k_mutex);
        return ret;
 }
 
@@ -482,6 +483,7 @@ static const struct file_operations dsp56k_fops = {
        .unlocked_ioctl = dsp56k_ioctl,
        .open           = dsp56k_open,
        .release        = dsp56k_release,
+       .llseek         = noop_llseek,
 };
 
 
index e3859d4eaead6e67552cdc3d2f24412a8a31067b..85156dd0caee0baebf051299a84db12476dbf322 100644 (file)
@@ -57,7 +57,7 @@
 #include <linux/ioport.h>      /* for request_region */
 #include <linux/delay.h>       /* for loops_per_jiffy */
 #include <linux/sched.h>
-#include <linux/smp_lock.h>    /* cycle_kernel_lock() */
+#include <linux/mutex.h>
 #include <asm/io.h>            /* for inb_p, outb_p, inb, outb, etc. */
 #include <asm/uaccess.h>       /* for get_user, etc. */
 #include <linux/wait.h>                /* for wait_queue */
@@ -73,6 +73,7 @@
 #define TRACE_RET ((void) 0)
 #endif                         /* TRACING */
 
+static DEFINE_MUTEX(dtlk_mutex);
 static void dtlk_timer_tick(unsigned long data);
 
 static int dtlk_major;
@@ -105,6 +106,7 @@ static const struct file_operations dtlk_fops =
        .unlocked_ioctl = dtlk_ioctl,
        .open           = dtlk_open,
        .release        = dtlk_release,
+       .llseek         = no_llseek,
 };
 
 /* local prototypes */
@@ -275,9 +277,9 @@ static long dtlk_ioctl(struct file *file,
        switch (cmd) {
 
        case DTLK_INTERROGATE:
-               lock_kernel();
+               mutex_lock(&dtlk_mutex);
                sp = dtlk_interrogate();
-               unlock_kernel();
+               mutex_unlock(&dtlk_mutex);
                if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
                        return -EINVAL;
                return 0;
@@ -296,7 +298,6 @@ static int dtlk_open(struct inode *inode, struct file *file)
 {
        TRACE_TEXT("(dtlk_open");
 
-       cycle_kernel_lock();
        nonseekable_open(inode, file);
        switch (iminor(inode)) {
        case DTLK_MINOR:
index 82b5a88a82d77d5351d1b1d413c4b123a382544f..0e941b57482e7d1021d409320e9184148888412b 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/miscdevice.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #ifdef CONFIG_PPC_PMAC
@@ -28,6 +28,7 @@
 
 #define NVRAM_SIZE     8192
 
+static DEFINE_MUTEX(nvram_mutex);
 static ssize_t nvram_len;
 
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
@@ -120,9 +121,9 @@ static long nvram_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned l
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&nvram_mutex);
        ret = nvram_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&nvram_mutex);
 
        return ret;
 }
index b6c2cc167c11fd39ce485f72281c79fa4e98bdd7..f773a9dd14f38ea2e1b5b2d3adcfd11f472f9ea3 100644 (file)
@@ -52,7 +52,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
@@ -66,6 +66,7 @@
  *     ioctls.
  */
 
+static DEFINE_MUTEX(gen_rtc_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
 
 /*
@@ -337,9 +338,9 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&gen_rtc_mutex);
        ret = gen_rtc_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gen_rtc_mutex);
 
        return ret;
 }
@@ -352,16 +353,16 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
 
 static int gen_rtc_open(struct inode *inode, struct file *file)
 {
-       lock_kernel();
+       mutex_lock(&gen_rtc_mutex);
        if (gen_rtc_status & RTC_IS_OPEN) {
-               unlock_kernel();
+               mutex_unlock(&gen_rtc_mutex);
                return -EBUSY;
        }
 
        gen_rtc_status |= RTC_IS_OPEN;
        gen_rtc_irq_data = 0;
        irq_active = 0;
-       unlock_kernel();
+       mutex_unlock(&gen_rtc_mutex);
 
        return 0;
 }
@@ -497,6 +498,7 @@ static const struct file_operations gen_rtc_fops = {
        .unlocked_ioctl = gen_rtc_unlocked_ioctl,
        .open           = gen_rtc_open,
        .release        = gen_rtc_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice rtc_gen_dev =
index e0249722d25f1c8b9dd05fa6705187afc8e23256..f953c96efc86499165f6006d1c6b97ee1e430884 100644 (file)
@@ -159,7 +159,7 @@ static void hangcheck_fire(unsigned long data)
                if (hangcheck_dump_tasks) {
                        printk(KERN_CRIT "Hangcheck: Task state:\n");
 #ifdef CONFIG_MAGIC_SYSRQ
-                       handle_sysrq('t', NULL);
+                       handle_sysrq('t');
 #endif  /* CONFIG_MAGIC_SYSRQ */
                }
                if (hangcheck_reboot) {
index a0a1829d3198fc19ccab2748718dbee2f814db86..a4eee324eb1ece730780079d0d968b316330a1e6 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/bcd.h>
 #include <linux/seq_file.h>
 #include <linux/bitops.h>
+#include <linux/compat.h>
 #include <linux/clocksource.h>
 #include <linux/slab.h>
 
@@ -67,6 +68,7 @@
 #define        read_counter(MC)        readl(MC)
 #endif
 
+static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
 static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
 /* This clocksource driver currently only works on ia64 */
@@ -250,7 +252,7 @@ static int hpet_open(struct inode *inode, struct file *file)
        if (file->f_mode & FMODE_WRITE)
                return -EINVAL;
 
-       lock_kernel();
+       mutex_lock(&hpet_mutex);
        spin_lock_irq(&hpet_lock);
 
        for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
@@ -264,7 +266,7 @@ static int hpet_open(struct inode *inode, struct file *file)
 
        if (!devp) {
                spin_unlock_irq(&hpet_lock);
-               unlock_kernel();
+               mutex_unlock(&hpet_mutex);
                return -EBUSY;
        }
 
@@ -272,7 +274,7 @@ static int hpet_open(struct inode *inode, struct file *file)
        devp->hd_irqdata = 0;
        devp->hd_flags |= HPET_OPEN;
        spin_unlock_irq(&hpet_lock);
-       unlock_kernel();
+       mutex_unlock(&hpet_mutex);
 
        hpet_timer_set_irq(devp);
 
@@ -429,22 +431,6 @@ static int hpet_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
-
-static long hpet_ioctl(struct file *file, unsigned int cmd,
-                       unsigned long arg)
-{
-       struct hpet_dev *devp;
-       int ret;
-
-       devp = file->private_data;
-       lock_kernel();
-       ret = hpet_ioctl_common(devp, cmd, arg, 0);
-       unlock_kernel();
-
-       return ret;
-}
-
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
        struct hpet_timer __iomem *timer;
@@ -553,7 +539,8 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
 }
 
 static int
-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
+                 struct hpet_info *info)
 {
        struct hpet_timer __iomem *timer;
        struct hpet __iomem *hpet;
@@ -594,23 +581,15 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
                break;
        case HPET_INFO:
                {
-                       struct hpet_info info;
-
                        if (devp->hd_ireqfreq)
-                               info.hi_ireqfreq =
+                               info->hi_ireqfreq =
                                        hpet_time_div(hpetp, devp->hd_ireqfreq);
                        else
-                               info.hi_ireqfreq = 0;
-                       info.hi_flags =
+                               info->hi_ireqfreq = 0;
+                       info->hi_flags =
                            readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
-                       info.hi_hpet = hpetp->hp_which;
-                       info.hi_timer = devp - hpetp->hp_dev;
-                       if (kernel)
-                               memcpy((void *)arg, &info, sizeof(info));
-                       else
-                               if (copy_to_user((void __user *)arg, &info,
-                                                sizeof(info)))
-                                       err = -EFAULT;
+                       info->hi_hpet = hpetp->hp_which;
+                       info->hi_timer = devp - hpetp->hp_dev;
                        break;
                }
        case HPET_EPI:
@@ -636,7 +615,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
                devp->hd_flags &= ~HPET_PERIODIC;
                break;
        case HPET_IRQFREQ:
-               if (!kernel && (arg > hpet_max_freq) &&
+               if ((arg > hpet_max_freq) &&
                    !capable(CAP_SYS_RESOURCE)) {
                        err = -EACCES;
                        break;
@@ -653,12 +632,63 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
        return err;
 }
 
+static long
+hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct hpet_info info;
+       int err;
+
+       mutex_lock(&hpet_mutex);
+       err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+       mutex_unlock(&hpet_mutex);
+
+       if ((cmd == HPET_INFO) && !err &&
+           (copy_to_user((void __user *)arg, &info, sizeof(info))))
+               err = -EFAULT;
+
+       return err;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_hpet_info {
+       compat_ulong_t hi_ireqfreq;     /* Hz */
+       compat_ulong_t hi_flags;        /* information */
+       unsigned short hi_hpet;
+       unsigned short hi_timer;
+};
+
+static long
+hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct hpet_info info;
+       int err;
+
+       mutex_lock(&hpet_mutex);
+       err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+       mutex_unlock(&hpet_mutex);
+
+       if ((cmd == HPET_INFO) && !err) {
+               struct compat_hpet_info __user *u = compat_ptr(arg);
+               if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
+                   put_user(info.hi_flags, &u->hi_flags) ||
+                   put_user(info.hi_hpet, &u->hi_hpet) ||
+                   put_user(info.hi_timer, &u->hi_timer))
+                       err = -EFAULT;
+       }
+
+       return err;
+}
+#endif
+
 static const struct file_operations hpet_fops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
        .read = hpet_read,
        .poll = hpet_poll,
        .unlocked_ioctl = hpet_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = hpet_compat_ioctl,
+#endif
        .open = hpet_open,
        .release = hpet_release,
        .fasync = hpet_fasync,
index fa27d1676ee5e0405cc5497bec6c703ade6e10b2..3afd62e856ebfea311eba94c496ac6628f586458 100644 (file)
@@ -651,7 +651,7 @@ int hvc_poll(struct hvc_struct *hp)
                                        if (sysrq_pressed)
                                                continue;
                                } else if (sysrq_pressed) {
-                                       handle_sysrq(buf[i], tty);
+                                       handle_sysrq(buf[i]);
                                        sysrq_pressed = 0;
                                        continue;
                                }
index 1f4b6de65a2dcac06a565aa7777359e1e873b444..a2bc885ce60a8e2bab93a815ab6ffc7d86640220 100644 (file)
@@ -403,7 +403,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
                        hp->sysrq = 1;
                        continue;
                } else if (hp->sysrq) {
-                       handle_sysrq(c, hp->tty);
+                       handle_sysrq(c);
                        hp->sysrq = 0;
                        continue;
                }
index 3d9c61e5acbf2adb354a70e0a8ba532568ef06d0..788da05190ccf865ab47f0e53848c70faa8f5d33 100644 (file)
@@ -170,6 +170,7 @@ static const struct file_operations rng_chrdev_ops = {
        .owner          = THIS_MODULE,
        .open           = rng_dev_open,
        .read           = rng_dev_read,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice rng_miscdev = {
index 1acdb25095112ef538072e8d153a889476d1359f..a3f5e381e74647268517a22c6f65d7c641277f3d 100644 (file)
@@ -387,7 +387,7 @@ static int n2rng_init_control(struct n2rng *np)
 
 static int n2rng_data_read(struct hwrng *rng, u32 *data)
 {
-       struct n2rng *np = rng->priv;
+       struct n2rng *np = (struct n2rng *) rng->priv;
        unsigned long ra = __pa(&np->test_data);
        int len;
 
index 4cd8b227c11f378336d46601318eae5471f6ec66..3bc0eef88717136342564976a8e18aa534732284 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/dmi.h>
 #include <linux/capability.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -56,6 +56,7 @@
 
 #define I8K_TEMPERATURE_BUG    1
 
+static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
 
 MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
@@ -399,9 +400,9 @@ static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&i8k_mutex);
        ret = i8k_ioctl_unlocked(fp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&i8k_mutex);
 
        return ret;
 }
index 07f3ea38b5828eda0a16ceed8b23fdbdee891d79..64a439ce2f892fe61a70375bd0c7cfeb8d65bdbc 100644 (file)
@@ -98,7 +98,7 @@
 #include <linux/major.h>
 #include <linux/wait.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+static DEFINE_MUTEX(ip2_mutex);
 static const struct file_operations ip2mem_proc_fops;
 static const struct file_operations ip2_proc_fops;
 
@@ -236,6 +237,7 @@ static const struct file_operations ip2_ipl = {
        .write          = ip2_ipl_write,
        .unlocked_ioctl = ip2_ipl_ioctl,
        .open           = ip2_ipl_open,
+       .llseek         = noop_llseek,
 }; 
 
 static unsigned long irq_counter;
@@ -1650,7 +1652,7 @@ ip2_close( PTTY tty, struct file *pFile )
        /* disable DSS reporting */
        i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
                                CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-       if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
+       if (tty->termios->c_cflag & HUPCL) {
                i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
                pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
                i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
@@ -2897,7 +2899,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
        printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
 #endif
 
-       lock_kernel();
+       mutex_lock(&ip2_mutex);
 
        switch ( iplminor ) {
        case 0:     // IPL device
@@ -2930,6 +2932,8 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
                                if ( pCh )
                                {
                                        rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
+                                       if (rc)
+                                               rc = -EFAULT;
                                } else {
                                        rc = -ENODEV;
                                }
@@ -2959,7 +2963,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
                rc = -ENODEV;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&ip2_mutex);
        return rc;
 }
 
@@ -2980,7 +2984,6 @@ ip2_ipl_open( struct inode *pInode, struct file *pFile )
 #ifdef IP2DEBUG_IPL
        printk (KERN_DEBUG "IP2IPL: open\n" );
 #endif
-       cycle_kernel_lock();
        return 0;
 }
 
index d8ec92a38980b451d70d454e04d20bf931d9f858..1fc8876af1f529ef945cbf0df553cfc76490e454 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
 
 struct ipmi_file_private
 {
@@ -59,6 +58,7 @@ struct ipmi_file_private
        unsigned int         default_retry_time_ms;
 };
 
+static DEFINE_MUTEX(ipmi_mutex);
 static void file_receive_handler(struct ipmi_recv_msg *msg,
                                 void                 *handler_data)
 {
@@ -102,9 +102,9 @@ static int ipmi_fasync(int fd, struct file *file, int on)
        struct ipmi_file_private *priv = file->private_data;
        int                      result;
 
-       lock_kernel(); /* could race against open() otherwise */
+       mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
        result = fasync_helper(fd, file, on, &priv->fasync_queue);
-       unlock_kernel();
+       mutex_unlock(&ipmi_mutex);
 
        return (result);
 }
@@ -125,7 +125,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
        if (!priv)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&ipmi_mutex);
        priv->file = file;
 
        rv = ipmi_create_user(if_num,
@@ -150,7 +150,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
        priv->default_retry_time_ms = 0;
 
 out:
-       unlock_kernel();
+       mutex_unlock(&ipmi_mutex);
        return rv;
 }
 
@@ -639,9 +639,9 @@ static long ipmi_unlocked_ioctl(struct file   *file,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ipmi_mutex);
        ret = ipmi_ioctl(file, cmd, data);
-       unlock_kernel();
+       mutex_unlock(&ipmi_mutex);
 
        return ret;
 }
@@ -850,6 +850,7 @@ static const struct file_operations ipmi_fops = {
        .release        = ipmi_release,
        .fasync         = ipmi_fasync,
        .poll           = ipmi_poll,
+       .llseek         = noop_llseek,
 };
 
 #define DEVICE_NAME     "ipmidev"
index 3822b4f49c84a360145a085e329fe0b76df4d47c..7bd7c45b53efc849225f7f0a604c41f2f0a4fded 100644 (file)
@@ -305,6 +305,9 @@ static int num_force_kipmid;
 #ifdef CONFIG_PCI
 static int pci_registered;
 #endif
+#ifdef CONFIG_ACPI
+static int pnp_registered;
+#endif
 #ifdef CONFIG_PPC_OF
 static int of_registered;
 #endif
@@ -2126,7 +2129,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 {
        struct acpi_device *acpi_dev;
        struct smi_info *info;
-       struct resource *res;
+       struct resource *res, *res_second;
        acpi_handle handle;
        acpi_status status;
        unsigned long long tmp;
@@ -2182,13 +2185,13 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
        info->io.addr_data = res->start;
 
        info->io.regspacing = DEFAULT_REGSPACING;
-       res = pnp_get_resource(dev,
+       res_second = pnp_get_resource(dev,
                               (info->io.addr_type == IPMI_IO_ADDR_SPACE) ?
                                        IORESOURCE_IO : IORESOURCE_MEM,
                               1);
-       if (res) {
-               if (res->start > info->io.addr_data)
-                       info->io.regspacing = res->start - info->io.addr_data;
+       if (res_second) {
+               if (res_second->start > info->io.addr_data)
+                       info->io.regspacing = res_second->start - info->io.addr_data;
        }
        info->io.regsize = DEFAULT_REGSPACING;
        info->io.regshift = 0;
@@ -3359,6 +3362,7 @@ static __devinit int init_ipmi_si(void)
 
 #ifdef CONFIG_ACPI
        pnp_register_driver(&ipmi_pnp_driver);
+       pnp_registered = 1;
 #endif
 
 #ifdef CONFIG_DMI
@@ -3526,7 +3530,8 @@ static __exit void cleanup_ipmi_si(void)
                pci_unregister_driver(&ipmi_pci_driver);
 #endif
 #ifdef CONFIG_ACPI
-       pnp_unregister_driver(&ipmi_pnp_driver);
+       if (pnp_registered)
+               pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
 #ifdef CONFIG_PPC_OF
index 654d566ca57c676ae6b6aa4cd2edb3f66d20f448..f4d334f2536ee3f74b0a95e58aa05b590396dc9b 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #define        WDIOC_GET_PRETIMEOUT     _IOW(WATCHDOG_IOCTL_BASE, 22, int)
 #endif
 
+static DEFINE_MUTEX(ipmi_watchdog_mutex);
 static int nowayout = WATCHDOG_NOWAYOUT;
 
 static ipmi_user_t watchdog_user;
@@ -748,9 +749,9 @@ static long ipmi_unlocked_ioctl(struct file *file,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ipmi_watchdog_mutex);
        ret = ipmi_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ipmi_watchdog_mutex);
 
        return ret;
 }
@@ -844,7 +845,6 @@ static int ipmi_open(struct inode *ino, struct file *filep)
                if (test_and_set_bit(0, &ipmi_wdog_open))
                        return -EBUSY;
 
-               cycle_kernel_lock();
 
                /*
                 * Don't start the timer now, let it start on the
@@ -909,6 +909,7 @@ static const struct file_operations ipmi_wdog_fops = {
        .open    = ipmi_open,
        .release = ipmi_close,
        .fasync  = ipmi_fasync,
+       .llseek  = no_llseek,
 };
 
 static struct miscdevice ipmi_wdog_miscdev = {
index be28391adb79b7de338594ad0a9cd5d865de5fdf..667abd23ad6ab91b81fa957f3c80260e9c7735a6 100644 (file)
@@ -704,6 +704,7 @@ static const struct file_operations stli_fsiomem = {
        .read           = stli_memread,
        .write          = stli_memwrite,
        .unlocked_ioctl = stli_memioctl,
+       .llseek         = default_llseek,
 };
 
 /*****************************************************************************/
index 938a3a2738866c71e42b7d8112b29966cdf3417c..97c3edb95ae747a3ff2832f48e6daf098fad83bf 100644 (file)
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <linux/parport.h>
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
 
+static DEFINE_MUTEX(lp_mutex);
 static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
@@ -493,7 +494,7 @@ static int lp_open(struct inode * inode, struct file * file)
        unsigned int minor = iminor(inode);
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&lp_mutex);
        if (minor >= LP_NO) {
                ret = -ENXIO;
                goto out;
@@ -554,7 +555,7 @@ static int lp_open(struct inode * inode, struct file * file)
        lp_release_parport (&lp_table[minor]);
        lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 out:
-       unlock_kernel();
+       mutex_unlock(&lp_mutex);
        return ret;
 }
 
@@ -680,7 +681,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
        int ret;
 
        minor = iminor(file->f_path.dentry->d_inode);
-       lock_kernel();
+       mutex_lock(&lp_mutex);
        switch (cmd) {
        case LPSETTIMEOUT:
                if (copy_from_user(&par_timeout, (void __user *)arg,
@@ -694,7 +695,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
                ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&lp_mutex);
 
        return ret;
 }
@@ -709,7 +710,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
        int ret;
 
        minor = iminor(file->f_path.dentry->d_inode);
-       lock_kernel();
+       mutex_lock(&lp_mutex);
        switch (cmd) {
        case LPSETTIMEOUT:
                tc = compat_ptr(arg);
@@ -730,7 +731,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
                ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&lp_mutex);
 
        return ret;
 }
@@ -748,6 +749,7 @@ static const struct file_operations lp_fops = {
 #ifdef CONFIG_PARPORT_1284
        .read           = lp_read,
 #endif
+       .llseek         = noop_llseek,
 };
 
 /* --- support for console on the line printer ----------------- */
index 83bef4efe37636869f418756462516d00a4f3ccd..1aeaaba680d22e1e943995efeff6b0ed671c5fe8 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -42,6 +41,7 @@
 #else
 #define DBG(fmt...)
 #endif
+static DEFINE_MUTEX(mbcs_mutex);
 static int mbcs_major;
 
 static LIST_HEAD(soft_list);
@@ -385,19 +385,19 @@ static int mbcs_open(struct inode *ip, struct file *fp)
        struct mbcs_soft *soft;
        int minor;
 
-       lock_kernel();
+       mutex_lock(&mbcs_mutex);
        minor = iminor(ip);
 
        /* Nothing protects access to this list... */
        list_for_each_entry(soft, &soft_list, list) {
                if (soft->nasid == minor) {
                        fp->private_data = soft->cxdev;
-                       unlock_kernel();
+                       mutex_unlock(&mbcs_mutex);
                        return 0;
                }
        }
 
-       unlock_kernel();
+       mutex_unlock(&mbcs_mutex);
        return -ENODEV;
 }
 
index a398ecdbd758058104e81223f1cbdfe7057e9a4b..e985b1c2730e800db599ad445371a8b100eee506 100644 (file)
@@ -788,10 +788,11 @@ static const struct file_operations zero_fops = {
 /*
  * capabilities for /dev/zero
  * - permits private mappings, "copies" are taken of the source of zeros
+ * - no writeback happens
  */
 static struct backing_dev_info zero_bdi = {
        .name           = "char/mem",
-       .capabilities   = BDI_CAP_MAP_COPY,
+       .capabilities   = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static const struct file_operations full_fops = {
@@ -804,6 +805,7 @@ static const struct file_operations full_fops = {
 static const struct file_operations oldmem_fops = {
        .read   = read_oldmem,
        .open   = open_oldmem,
+       .llseek = default_llseek,
 };
 #endif
 
@@ -830,6 +832,7 @@ static ssize_t kmsg_write(struct file *file, const char __user *buf,
 
 static const struct file_operations kmsg_fops = {
        .write = kmsg_write,
+       .llseek = noop_llseek,
 };
 
 static const struct memdev {
@@ -881,6 +884,7 @@ static int memory_open(struct inode *inode, struct file *filp)
 
 static const struct file_operations memory_fops = {
        .open = memory_open,
+       .llseek = noop_llseek,
 };
 
 static char *mem_devnode(struct device *dev, mode_t *mode)
index abdafd48898029324d21153637bb3af4925e0fe3..778273c93242f5efbd1629a0f7c9d102ed907b4a 100644 (file)
@@ -162,6 +162,7 @@ static struct class *misc_class;
 static const struct file_operations misc_fops = {
        .owner          = THIS_MODULE,
        .open           = misc_open,
+       .llseek         = noop_llseek,
 };
 
 /**
index ea7c99fa978f9e8d2877ba8a783daeef5214cc5c..c070b53984e45f77a2805e0428027fbe594622bd 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/math64.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -59,6 +59,7 @@ extern unsigned long sn_rtc_cycles_per_second;
 
 #define rtc_time()              (*RTC_COUNTER_ADDR)
 
+static DEFINE_MUTEX(mmtimer_mutex);
 static long mmtimer_ioctl(struct file *file, unsigned int cmd,
                                                unsigned long arg);
 static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +73,7 @@ static const struct file_operations mmtimer_fops = {
        .owner = THIS_MODULE,
        .mmap = mmtimer_mmap,
        .unlocked_ioctl = mmtimer_ioctl,
+       .llseek = noop_llseek,
 };
 
 /*
@@ -371,7 +373,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
 {
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&mmtimer_mutex);
 
        switch (cmd) {
        case MMTIMER_GETOFFSET: /* offset of the counter */
@@ -414,7 +416,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
                ret = -ENOTTY;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&mmtimer_mutex);
        return ret;
 }
 
index ecb89d798e3553bffe2044cd27e0ed7aa608729b..966a95bc974b2c0489c7c4f33b52d1b3872238a0 100644 (file)
@@ -316,7 +316,8 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma)
 
 static const struct file_operations fetchop_fops = {
        .owner = THIS_MODULE,
-       .mmap = fetchop_mmap
+       .mmap = fetchop_mmap,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice fetchop_miscdev = {
@@ -327,7 +328,8 @@ static struct miscdevice fetchop_miscdev = {
 
 static const struct file_operations cached_fops = {
        .owner = THIS_MODULE,
-       .mmap = cached_mmap
+       .mmap = cached_mmap,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice cached_miscdev = {
@@ -338,7 +340,8 @@ static struct miscdevice cached_miscdev = {
 
 static const struct file_operations uncached_fops = {
        .owner = THIS_MODULE,
-       .mmap = uncached_mmap
+       .mmap = uncached_mmap,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice uncached_miscdev = {
index a4ec50c950722410e9cd6dc99b72b76edf11fb2b..1d82d5838f0c38c416947d7f95b17d204d0a93b1 100644 (file)
@@ -56,7 +56,7 @@
 #include <linux/serial.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
 #include "smapi.h"
@@ -73,6 +73,7 @@ MODULE_LICENSE("GPL");
 * checks are made against other devices (ie. superio) for conflicts.
 * We'll depend on users using the tpctl utility to do that for now
 */
+static DEFINE_MUTEX(mwave_mutex);
 int mwave_debug = 0;
 int mwave_3780i_irq = 0;
 int mwave_3780i_io = 0;
@@ -101,7 +102,6 @@ static int mwave_open(struct inode *inode, struct file *file)
        PRINTK_2(TRACE_MWAVE,
                "mwavedd::mwave_open, exit return retval %x\n", retval);
 
-       cycle_kernel_lock();
        return retval;
 }
 
@@ -136,9 +136,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                        PRINTK_1(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
                                " calling tp3780I_ResetDSP\n");
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_ResetDSP(&pDrvData->rBDData);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
                                " retval %x from tp3780I_ResetDSP\n",
@@ -149,9 +149,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                        PRINTK_1(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
                                " calling tp3780I_StartDSP\n");
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_StartDSP(&pDrvData->rBDData);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
                                " retval %x from tp3780I_StartDSP\n",
@@ -165,10 +165,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                "mwavedd::mwave_ioctl,"
                                " IOCTL_MW_DSP_ABILITIES calling"
                                " tp3780I_QueryAbilities\n");
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
                                        &rAbilities);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
                                " retval %x from tp3780I_QueryAbilities\n",
@@ -199,13 +199,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rReadData.ulDataLength, ioarg, pusBuffer);
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                        iocmd,
                                        pusBuffer,
                                        rReadData.ulDataLength,
                                        rReadData.usDspAddress);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -223,12 +223,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rReadData.ulDataLength / 2, ioarg,
                                pusBuffer);
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                iocmd, pusBuffer,
                                rReadData.ulDataLength / 2,
                                rReadData.usDspAddress);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -246,12 +246,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rWriteData.ulDataLength, ioarg,
                                pusBuffer);
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                        iocmd, pusBuffer,
                                        rWriteData.ulDataLength,
                                        rWriteData.usDspAddress);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -269,12 +269,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rWriteData.ulDataLength, ioarg,
                                pusBuffer);
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
                                        iocmd, pusBuffer,
                                        rWriteData.ulDataLength,
                                        rWriteData.usDspAddress);
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -295,10 +295,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                ipcnum,
                                pDrvData->IPCs[ipcnum].usIntCount);
 
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        pDrvData->IPCs[ipcnum].bIsHere = FALSE;
                        pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
        
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -323,7 +323,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                ipcnum,
                                pDrvData->IPCs[ipcnum].usIntCount);
        
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
                                DECLARE_WAITQUEUE(wait, current);
 
@@ -364,7 +364,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                        " processing\n",
                                        ipcnum);
                        }
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -383,14 +383,14 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
-                       lock_kernel();
+                       mutex_lock(&mwave_mutex);
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
                                pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
                                if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
                                        wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
                                }
                        }
-                       unlock_kernel();
+                       mutex_unlock(&mwave_mutex);
                }
                        break;
        
@@ -479,7 +479,8 @@ static const struct file_operations mwave_fops = {
        .write          = mwave_write,
        .unlocked_ioctl = mwave_ioctl,
        .open           = mwave_open,
-       .release        = mwave_close
+       .release        = mwave_close,
+       .llseek         = default_llseek,
 };
 
 
index 66d2917b003f6361080e063323d88dca49fd623f..166f1e7aaa7ee844c4a36b8950cb9f343e0f5c82 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/system.h>
 
+static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
 static int nvram_open_cnt;     /* #times opened */
 static int nvram_open_mode;    /* special open modes */
@@ -308,7 +309,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
                if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
 
-               lock_kernel();
+               mutex_lock(&nvram_mutex);
                spin_lock_irq(&rtc_lock);
 
                for (i = 0; i < NVRAM_BYTES; ++i)
@@ -316,7 +317,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
                __nvram_set_checksum();
 
                spin_unlock_irq(&rtc_lock);
-               unlock_kernel();
+               mutex_unlock(&nvram_mutex);
                return 0;
 
        case NVRAM_SETCKS:
@@ -325,11 +326,11 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
                if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
 
-               lock_kernel();
+               mutex_lock(&nvram_mutex);
                spin_lock_irq(&rtc_lock);
                __nvram_set_checksum();
                spin_unlock_irq(&rtc_lock);
-               unlock_kernel();
+               mutex_unlock(&nvram_mutex);
                return 0;
 
        default:
index 2604246501e499eda6568527e4c64d8b5a13bc48..8994ce32e6c70046c2658d69a4bc4e828636c43a 100644 (file)
@@ -182,6 +182,7 @@ static int button_read (struct file *filp, char __user *buffer,
 static const struct file_operations button_fops = {
        .owner          = THIS_MODULE,
        .read           = button_read,
+       .llseek         = noop_llseek,
 };
 
 /* 
index 043a1c7b86beefb3438976f3512230b9571278c3..a12f52400dbc5ed6ef65885ff7dc80052ed49ad6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
@@ -41,6 +40,7 @@
 
 #define        NWFLASH_VERSION "6.4"
 
+static DEFINE_MUTEX(flash_mutex);
 static void kick_open(void);
 static int get_flash_id(void);
 static int erase_block(int nBlock);
@@ -96,7 +96,7 @@ static int get_flash_id(void)
 
 static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
-       lock_kernel();
+       mutex_lock(&flash_mutex);
        switch (cmd) {
        case CMD_WRITE_DISABLE:
                gbWriteBase64Enable = 0;
@@ -114,10 +114,10 @@ static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
        default:
                gbWriteBase64Enable = 0;
                gbWriteEnable = 0;
-               unlock_kernel();
+               mutex_unlock(&flash_mutex);
                return -EINVAL;
        }
-       unlock_kernel();
+       mutex_unlock(&flash_mutex);
        return 0;
 }
 
@@ -282,7 +282,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
 {
        loff_t ret;
 
-       lock_kernel();
+       mutex_lock(&flash_mutex);
        if (flashdebug)
                printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
                       (unsigned int) offset, orig);
@@ -317,7 +317,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
        default:
                ret = -EINVAL;
        }
-       unlock_kernel();
+       mutex_unlock(&flash_mutex);
        return ret;
 }
 
index 8ecbcc174c150b5deccde7ca3f5ab0c199781b0f..b304ec05250124e55183fe59f55d1f99e9e33356 100644 (file)
@@ -234,6 +234,7 @@ static const struct file_operations pc8736x_gpio_fileops = {
        .open   = pc8736x_gpio_open,
        .write  = nsc_gpio_write,
        .read   = nsc_gpio_read,
+       .llseek = no_llseek,
 };
 
 static void __init pc8736x_init_shadow(void)
index ec73d9f6d9ed92c9fa527718ff44871bd7d64669..6835c23e9a51a7a2799e4fd46cd92bba20f3ad97 100644 (file)
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/bitrev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -55,7 +54,7 @@
                           __func__ , ## args);         \
        } while (0)
 
-static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cmm_mutex);
 
 #define        T_1SEC          (HZ)
 #define        T_10MSEC        msecs_to_jiffies(10)
@@ -1418,7 +1417,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
               iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 #endif
 
-       lock_kernel();
+       mutex_lock(&cmm_mutex);
        rc = -ENODEV;
        link = dev_table[iminor(inode)];
        if (!pcmcia_dev_present(link)) {
@@ -1626,7 +1625,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                rc = -ENOTTY;
        }
 out:
-       unlock_kernel();
+       mutex_unlock(&cmm_mutex);
        return rc;
 }
 
@@ -1640,7 +1639,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
        if (minor >= CM4000_MAX_DEV)
                return -ENODEV;
 
-       lock_kernel();
+       mutex_lock(&cmm_mutex);
        link = dev_table[minor];
        if (link == NULL || !pcmcia_dev_present(link)) {
                ret = -ENODEV;
@@ -1685,7 +1684,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
        DEBUGP(2, dev, "<- cmm_open\n");
        ret = nonseekable_open(inode, filp);
 out:
-       unlock_kernel();
+       mutex_unlock(&cmm_mutex);
        return ret;
 }
 
@@ -1742,20 +1741,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
-static int cm4000_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cfg,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (!cfg->io.nwin)
-               return -ENODEV;
-
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
-       p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-       p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
        return pcmcia_request_io(p_dev);
 }
 
@@ -1763,13 +1750,13 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
 {
        struct cm4000_dev *dev;
 
+       link->config_flags |= CONF_AUTO_SET_IO;
+
        /* read the config-tuples */
        if (pcmcia_loop_config(link, cm4000_config_check, NULL))
                goto cs_release;
 
-       link->conf.IntType = 00000002;
-
-       if (pcmcia_request_configuration(link, &link->conf))
+       if (pcmcia_enable_device(link))
                goto cs_release;
 
        dev = link->priv;
@@ -1829,7 +1816,6 @@ static int cm4000_probe(struct pcmcia_device *link)
 
        dev->p_dev = link;
        link->priv = dev;
-       link->conf.IntType = INT_MEMORY_AND_IO;
        dev_table[i] = link;
 
        init_waitqueue_head(&dev->devq);
@@ -1880,6 +1866,7 @@ static const struct file_operations cm4000_fops = {
        .unlocked_ioctl = cmm_ioctl,
        .open   = cmm_open,
        .release= cmm_close,
+       .llseek = no_llseek,
 };
 
 static struct pcmcia_device_id cm4000_ids[] = {
@@ -1891,9 +1878,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids);
 
 static struct pcmcia_driver cm4000_driver = {
        .owner    = THIS_MODULE,
-       .drv      = {
-               .name = "cm4000_cs",
-               },
+       .name     = "cm4000_cs",
        .probe    = cm4000_probe,
        .remove   = cm4000_detach,
        .suspend  = cm4000_suspend,
@@ -1905,8 +1890,6 @@ static int __init cmm_init(void)
 {
        int rc;
 
-       printk(KERN_INFO "%s\n", version);
-
        cmm_class = class_create(THIS_MODULE, "cardman_4000");
        if (IS_ERR(cmm_class))
                return PTR_ERR(cmm_class);
@@ -1931,7 +1914,6 @@ static int __init cmm_init(void)
 
 static void __exit cmm_exit(void)
 {
-       printk(KERN_INFO MODULE_NAME ": unloading\n");
        pcmcia_unregister_driver(&cm4000_driver);
        unregister_chrdev(major, DEVICE_NAME);
        class_destroy(cmm_class);
index 815cde1d0570e86d4ba0e8970ef60248997a3302..5d8d59e865f4b15cea3194ec8ef23c8f5d07c736 100644 (file)
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -49,8 +48,7 @@
                           __func__ , ## args);         \
        } while (0)
 
-static char *version =
-"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cm4040_mutex);
 
 #define        CCID_DRIVER_BULK_DEFAULT_TIMEOUT        (150*HZ)
 #define        CCID_DRIVER_ASYNC_POWERUP_TIMEOUT       (35*HZ)
@@ -444,7 +442,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
        if (minor >= CM_MAX_DEV)
                return -ENODEV;
 
-       lock_kernel();
+       mutex_lock(&cm4040_mutex);
        link = dev_table[minor];
        if (link == NULL || !pcmcia_dev_present(link)) {
                ret = -ENODEV;
@@ -473,7 +471,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
        DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
        ret = nonseekable_open(inode, filp);
 out:
-       unlock_kernel();
+       mutex_unlock(&cm4040_mutex);
        return ret;
 }
 
@@ -516,26 +514,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
        return;
 }
 
-static int cm4040_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cfg,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       int rc;
-       if (!cfg->io.nwin)
-               return -ENODEV;
-
-       /* Get the IOaddr */
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
-       p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-       p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-       rc = pcmcia_request_io(p_dev);
-
-       dev_printk(KERN_INFO, &p_dev->dev,
-                  "pcmcia_request_io returned 0x%x\n", rc);
-       return rc;
+       return pcmcia_request_io(p_dev);
 }
 
 
@@ -544,15 +525,15 @@ static int reader_config(struct pcmcia_device *link, int devno)
        struct reader_dev *dev;
        int fail_rc;
 
+       link->config_flags |= CONF_AUTO_SET_IO;
+
        if (pcmcia_loop_config(link, cm4040_config_check, NULL))
                goto cs_release;
 
-       link->conf.IntType = 00000002;
-
-       fail_rc = pcmcia_request_configuration(link, &link->conf);
+       fail_rc = pcmcia_enable_device(link);
        if (fail_rc != 0) {
                dev_printk(KERN_INFO, &link->dev,
-                          "pcmcia_request_configuration failed 0x%x\n",
+                          "pcmcia_enable_device failed 0x%x\n",
                           fail_rc);
                goto cs_release;
        }
@@ -599,7 +580,6 @@ static int reader_probe(struct pcmcia_device *link)
        link->priv = dev;
        dev->p_dev = link;
 
-       link->conf.IntType = INT_MEMORY_AND_IO;
        dev_table[i] = link;
 
        init_waitqueue_head(&dev->devq);
@@ -650,6 +630,7 @@ static const struct file_operations reader_fops = {
        .open           = cm4040_open,
        .release        = cm4040_close,
        .poll           = cm4040_poll,
+       .llseek         = no_llseek,
 };
 
 static struct pcmcia_device_id cm4040_ids[] = {
@@ -662,9 +643,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4040_ids);
 
 static struct pcmcia_driver reader_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "cm4040_cs",
-       },
+       .name           = "cm4040_cs",
        .probe          = reader_probe,
        .remove         = reader_detach,
        .id_table       = cm4040_ids,
@@ -674,7 +653,6 @@ static int __init cm4040_init(void)
 {
        int rc;
 
-       printk(KERN_INFO "%s\n", version);
        cmx_class = class_create(THIS_MODULE, "cardman_4040");
        if (IS_ERR(cmx_class))
                return PTR_ERR(cmx_class);
@@ -699,7 +677,6 @@ static int __init cm4040_init(void)
 
 static void __exit cm4040_exit(void)
 {
-       printk(KERN_INFO MODULE_NAME ": unloading\n");
        pcmcia_unregister_driver(&reader_driver);
        unregister_chrdev(major, DEVICE_NAME);
        class_destroy(cmx_class);
index 67bdb05798b1943c8c2242f85494f70c6e2c7e3c..94b8eb4d691d6b95fd0f32ffeea780dc28a6121c 100644 (file)
@@ -32,7 +32,6 @@
 #include <pcmcia/device_id.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/ds.h>
-#include <pcmcia/cs.h>
 
 static struct pcmcia_device_id ipw_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
@@ -76,23 +75,18 @@ static void signalled_reboot_callback(void *callback_data)
        schedule_work(&ipw->work_reboot);
 }
 
-static int ipwireless_probe(struct pcmcia_device *p_dev,
-                           cistpl_cftable_entry_t *cfg,
-                           cistpl_cftable_entry_t *dflt,
-                           unsigned int vcc,
-                           void *priv_data)
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
 {
        struct ipw_dev *ipw = priv_data;
        struct resource *io_resource;
        int ret;
 
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
        p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
 
        /* 0x40 causes it to generate level mode interrupts. */
        /* 0x04 enables IREQ pin. */
-       p_dev->conf.ConfigIndex = cfg->index | 0x44;
+       p_dev->config_index |= 0x44;
        p_dev->io_lines = 16;
        ret = pcmcia_request_io(p_dev);
        if (ret)
@@ -102,65 +96,49 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
                                resource_size(p_dev->resource[0]),
                                IPWIRELESS_PCCARD_NAME);
 
-       if (cfg->mem.nwin == 0)
-               return 0;
-
-       ipw->request_common_memory.Attributes =
+       p_dev->resource[2]->flags |=
                WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-       ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
-       ipw->request_common_memory.Size = cfg->mem.win[0].len;
-       if (ipw->request_common_memory.Size < 0x1000)
-               ipw->request_common_memory.Size = 0x1000;
-       ipw->request_common_memory.AccessSpeed = 0;
-
-       ret = pcmcia_request_window(p_dev, &ipw->request_common_memory,
-                               &ipw->handle_common_memory);
 
+       ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
        if (ret != 0)
                goto exit1;
 
-       ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
-                               cfg->mem.win[0].card_addr);
-
+       ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
        if (ret != 0)
                goto exit2;
 
-       ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
+       ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
 
-       ipw->common_memory = ioremap(ipw->request_common_memory.Base,
-                               ipw->request_common_memory.Size);
-       request_mem_region(ipw->request_common_memory.Base,
-                       ipw->request_common_memory.Size,
+       ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+                               resource_size(p_dev->resource[2]));
+       request_mem_region(p_dev->resource[2]->start,
+                       resource_size(p_dev->resource[2]),
                        IPWIRELESS_PCCARD_NAME);
 
-       ipw->request_attr_memory.Attributes =
-               WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-       ipw->request_attr_memory.Base = 0;
-       ipw->request_attr_memory.Size = 0;      /* this used to be 0x1000 */
-       ipw->request_attr_memory.AccessSpeed = 0;
-
-       ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory,
-                               &ipw->handle_attr_memory);
-
+       p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
+                                       WIN_ENABLE;
+       p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
+       ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
        if (ret != 0)
                goto exit2;
 
-       ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
+       ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
        if (ret != 0)
                goto exit3;
 
-       ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
-                               ipw->request_attr_memory.Size);
-       request_mem_region(ipw->request_attr_memory.Base,
-                       ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
+       ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+                               resource_size(p_dev->resource[3]));
+       request_mem_region(p_dev->resource[3]->start,
+                       resource_size(p_dev->resource[3]),
+                       IPWIRELESS_PCCARD_NAME);
 
        return 0;
 
 exit3:
 exit2:
        if (ipw->common_memory) {
-               release_mem_region(ipw->request_common_memory.Base,
-                               ipw->request_common_memory.Size);
+               release_mem_region(p_dev->resource[2]->start,
+                               resource_size(p_dev->resource[2]));
                iounmap(ipw->common_memory);
        }
 exit1:
@@ -175,14 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
        int ret = 0;
 
        ipw->is_v2_card = 0;
+       link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
+               CONF_ENABLE_IRQ;
 
        ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
        if (ret != 0)
                return ret;
 
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
        ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
@@ -201,13 +178,9 @@ static int config_ipwireless(struct ipw_dev *ipw)
                        (unsigned int) link->irq);
        if (ipw->attr_memory && ipw->common_memory)
                printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-                       ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
-                       ipw->request_attr_memory.Base,
-                       ipw->request_attr_memory.Base
-                       + ipw->request_attr_memory.Size - 1,
-                       ipw->request_common_memory.Base,
-                       ipw->request_common_memory.Base
-                       + ipw->request_common_memory.Size - 1);
+                       ": attr memory %pR, common memory %pR\n",
+                       link->resource[3],
+                       link->resource[2]);
 
        ipw->network = ipwireless_network_create(ipw->hardware);
        if (!ipw->network)
@@ -223,25 +196,23 @@ static int config_ipwireless(struct ipw_dev *ipw)
         * Do the RequestConfiguration last, because it enables interrupts.
         * Then we don't get any interrupts before we're ready for them.
         */
-       ret = pcmcia_request_configuration(link, &link->conf);
-
+       ret = pcmcia_enable_device(link);
        if (ret != 0)
                goto exit;
 
        return 0;
 
 exit:
-       if (ipw->attr_memory) {
-               release_mem_region(ipw->request_attr_memory.Base,
-                               ipw->request_attr_memory.Size);
-               iounmap(ipw->attr_memory);
-
-       }
        if (ipw->common_memory) {
-               release_mem_region(ipw->request_common_memory.Base,
-                               ipw->request_common_memory.Size);
+               release_mem_region(link->resource[2]->start,
+                               resource_size(link->resource[2]));
                iounmap(ipw->common_memory);
        }
+       if (ipw->attr_memory) {
+               release_mem_region(link->resource[3]->start,
+                               resource_size(link->resource[3]));
+               iounmap(ipw->attr_memory);
+       }
        pcmcia_disable_device(link);
        return -1;
 }
@@ -249,13 +220,13 @@ exit:
 static void release_ipwireless(struct ipw_dev *ipw)
 {
        if (ipw->common_memory) {
-               release_mem_region(ipw->request_common_memory.Base,
-                               ipw->request_common_memory.Size);
+               release_mem_region(ipw->link->resource[2]->start,
+                               resource_size(ipw->link->resource[2]));
                iounmap(ipw->common_memory);
        }
        if (ipw->attr_memory) {
-               release_mem_region(ipw->request_attr_memory.Base,
-                               ipw->request_attr_memory.Size);
+               release_mem_region(ipw->link->resource[3]->start,
+                               resource_size(ipw->link->resource[3]));
                iounmap(ipw->attr_memory);
        }
        pcmcia_disable_device(ipw->link);
@@ -324,7 +295,7 @@ static struct pcmcia_driver me = {
        .owner          = THIS_MODULE,
        .probe          = ipwireless_attach,
        .remove         = ipwireless_detach,
-       .drv = { .name  = IPWIRELESS_PCCARD_NAME },
+       .name           = IPWIRELESS_PCCARD_NAME,
        .id_table       = ipw_ids
 };
 
@@ -336,9 +307,6 @@ static int __init init_ipwireless(void)
 {
        int ret;
 
-       printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
-              IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
-
        ret = ipwireless_tty_init();
        if (ret != 0)
                return ret;
@@ -355,9 +323,6 @@ static int __init init_ipwireless(void)
  */
 static void __exit exit_ipwireless(void)
 {
-       printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
-                       IPWIRELESS_PCMCIA_VERSION " removed\n");
-
        pcmcia_unregister_driver(&me);
        ipwireless_tty_release();
 }
index c207be87b597fe3cecfec61da71d8fdf3386b36f..f2cbb116bccb51d2c3c548cf5053b782fb84f9de 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -45,13 +44,9 @@ struct ipw_dev {
        struct pcmcia_device *link;
        int is_v2_card;
 
-       window_handle_t handle_attr_memory;
        void __iomem *attr_memory;
-       win_req_t request_attr_memory;
 
-       window_handle_t handle_common_memory;
        void __iomem *common_memory;
-       win_req_t request_common_memory;
 
        /* Reference to attribute memory, containing CIS data */
        void *attribute_memory;
index 3e163d4cab15b034d14153d5dcb2d1f6bdeae36e..747b2d63786093058213b5aea75724a9cc68960e 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
index 9ecd6bef5d3b5457ec5bcc6566db7621c1d791f3..be18100576075a7b476c5be534640349679ff280 100644 (file)
@@ -70,7 +70,6 @@
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -550,9 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
 
     /* Initialize the struct pcmcia_device structure */
 
-    link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     ret = mgslpc_config(link);
     if (ret)
            return ret;
@@ -565,20 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link)
 /* Card has been inserted.
  */
 
-static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
-                         cistpl_cftable_entry_t *cfg,
-                         cistpl_cftable_entry_t *dflt,
-                         unsigned int vcc,
-                         void *priv_data)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (!cfg->io.nwin)
-               return -ENODEV;
-
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
-       p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-       p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
        return pcmcia_request_io(p_dev);
 }
 
@@ -590,32 +574,24 @@ static int mgslpc_config(struct pcmcia_device *link)
     if (debug_level >= DEBUG_LEVEL_INFO)
            printk("mgslpc_config(0x%p)\n", link);
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
     if (ret != 0)
            goto failed;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 8;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_index = 8;
+    link->config_regs = PRESENT_OPTION;
 
     ret = pcmcia_request_irq(link, mgslpc_isr);
     if (ret)
            goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
     info->io_base = link->resource[0]->start;
     info->irq_level = link->irq;
-
-    dev_info(&link->dev, "index 0x%02x:",
-           link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-           printk(", irq %d", link->irq);
-    if (link->resource[0])
-           printk(", io %pR", link->resource[0]);
-    printk("\n");
     return 0;
 
 failed:
@@ -2797,9 +2773,7 @@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);
 
 static struct pcmcia_driver mgslpc_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "synclink_cs",
-       },
+       .name           = "synclink_cs",
        .probe          = mgslpc_probe,
        .remove         = mgslpc_detach,
        .id_table       = mgslpc_ids,
@@ -2835,8 +2809,6 @@ static void synclink_cs_cleanup(void)
 {
        int rc;
 
-       printk("Unloading %s: version %s\n", driver_name, driver_version);
-
        while(mgslpc_device_list)
                mgslpc_remove_device(mgslpc_device_list);
 
@@ -2859,8 +2831,6 @@ static int __init synclink_cs_init(void)
            BREAKPOINT();
     }
 
-    printk("%s %s\n", driver_name, driver_version);
-
     if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
            return rc;
 
@@ -4127,6 +4097,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        if (cmd != SIOCWANDEV)
                return hdlc_ioctl(dev, ifr, cmd);
 
+       memset(&new_line, 0, size);
+
        switch(ifr->ifr_settings.type) {
        case IF_GET_IFACE: /* return current sync_serial_settings */
 
index 02abfddce45a192ceccae3d71f3008ba7d329767..723152d978a9482ac3c1e48c2724894a9d6cceb4 100644 (file)
@@ -67,7 +67,7 @@
 #include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/ppdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
@@ -97,6 +97,7 @@ struct pp_struct {
 /* ROUND_UP macro from fs/select.c */
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 
+static DEFINE_MUTEX(pp_do_mutex);
 static inline void pp_enable_irq (struct pp_struct *pp)
 {
        struct parport *port = pp->pdev->port;
@@ -630,9 +631,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&pp_do_mutex);
        ret = pp_do_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&pp_do_mutex);
        return ret;
 }
 
@@ -641,7 +642,6 @@ static int pp_open (struct inode * inode, struct file * file)
        unsigned int minor = iminor(inode);
        struct pp_struct *pp;
 
-       cycle_kernel_lock();
        if (minor >= PARPORT_MAX)
                return -ENXIO;
 
index caef35a468908046be61975611ea7728661ed32c..5a1aa64f4e76c5b9178dbb9d3ef4fe9285ed8791 100644 (file)
@@ -1165,6 +1165,7 @@ const struct file_operations random_fops = {
        .poll  = random_poll,
        .unlocked_ioctl = random_ioctl,
        .fasync = random_fasync,
+       .llseek = noop_llseek,
 };
 
 const struct file_operations urandom_fops = {
@@ -1172,6 +1173,7 @@ const struct file_operations urandom_fops = {
        .write = random_write,
        .unlocked_ioctl = random_ioctl,
        .fasync = random_fasync,
+       .llseek = noop_llseek,
 };
 
 /***************************************************************
index b38942f6bf3140684be8ffadfcbac7381201baa5..bfe25ea9766b94caf11ffbc5ca4fb3b766c2c188 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
+#include <linux/compat.h>
 
 #include <asm/uaccess.h>
 
@@ -55,7 +55,6 @@ static int raw_open(struct inode *inode, struct file *filp)
                return 0;
        }
 
-       lock_kernel();
        mutex_lock(&raw_mutex);
 
        /*
@@ -82,7 +81,6 @@ static int raw_open(struct inode *inode, struct file *filp)
                        bdev->bd_inode->i_mapping;
        filp->private_data = bdev;
        mutex_unlock(&raw_mutex);
-       unlock_kernel();
        return 0;
 
 out2:
@@ -91,7 +89,6 @@ out1:
        blkdev_put(bdev, filp->f_mode);
 out:
        mutex_unlock(&raw_mutex);
-       unlock_kernel();
        return err;
 }
 
@@ -125,20 +122,84 @@ static long
 raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
 {
        struct block_device *bdev = filp->private_data;
-       int ret;
+       return blkdev_ioctl(bdev, 0, command, arg);
+}
+
+static int bind_set(int number, u64 major, u64 minor)
+{
+       dev_t dev = MKDEV(major, minor);
+       struct raw_device_data *rawdev;
+       int err = 0;
 
-       lock_kernel();
-       ret = blkdev_ioctl(bdev, 0, command, arg);
-       unlock_kernel();
+       if (number <= 0 || number >= MAX_RAW_MINORS)
+               return -EINVAL;
 
-       return ret;
+       if (MAJOR(dev) != major || MINOR(dev) != minor)
+               return -EINVAL;
+
+       rawdev = &raw_devices[number];
+
+       /*
+        * This is like making block devices, so demand the
+        * same capability
+        */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       /*
+        * For now, we don't need to check that the underlying
+        * block device is present or not: we can do that when
+        * the raw device is opened.  Just check that the
+        * major/minor numbers make sense.
+        */
+
+       if (MAJOR(dev) == 0 && dev != 0)
+               return -EINVAL;
+
+       mutex_lock(&raw_mutex);
+       if (rawdev->inuse) {
+               mutex_unlock(&raw_mutex);
+               return -EBUSY;
+       }
+       if (rawdev->binding) {
+               bdput(rawdev->binding);
+               module_put(THIS_MODULE);
+       }
+       if (!dev) {
+               /* unbind */
+               rawdev->binding = NULL;
+               device_destroy(raw_class, MKDEV(RAW_MAJOR, number));
+       } else {
+               rawdev->binding = bdget(dev);
+               if (rawdev->binding == NULL) {
+                       err = -ENOMEM;
+               } else {
+                       dev_t raw = MKDEV(RAW_MAJOR, number);
+                       __module_get(THIS_MODULE);
+                       device_destroy(raw_class, raw);
+                       device_create(raw_class, NULL, raw, NULL,
+                                     "raw%d", number);
+               }
+       }
+       mutex_unlock(&raw_mutex);
+       return err;
 }
 
-static void bind_device(struct raw_config_request *rq)
+static int bind_get(int number, dev_t *dev)
 {
-       device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-       device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
-                     "raw%d", rq->raw_minor);
+       struct raw_device_data *rawdev;
+       struct block_device *bdev;
+
+       if (number <= 0 || number >= MAX_RAW_MINORS)
+               return -EINVAL;
+
+       rawdev = &raw_devices[number];
+
+       mutex_lock(&raw_mutex);
+       bdev = rawdev->binding;
+       *dev = bdev ? bdev->bd_dev : 0;
+       mutex_unlock(&raw_mutex);
+       return 0;
 }
 
 /*
@@ -149,105 +210,78 @@ static long raw_ctl_ioctl(struct file *filp, unsigned int command,
                          unsigned long arg)
 {
        struct raw_config_request rq;
-       struct raw_device_data *rawdev;
-       int err = 0;
+       dev_t dev;
+       int err;
 
-       lock_kernel();
        switch (command) {
        case RAW_SETBIND:
+               if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+                       return -EFAULT;
+
+               return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
        case RAW_GETBIND:
+               if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+                       return -EFAULT;
 
-               /* First, find out which raw minor we want */
+               err = bind_get(rq.raw_minor, &dev);
+               if (err)
+                       return err;
 
-               if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) {
-                       err = -EFAULT;
-                       goto out;
-               }
+               rq.block_major = MAJOR(dev);
+               rq.block_minor = MINOR(dev);
 
-               if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
-                       err = -EINVAL;
-                       goto out;
-               }
-               rawdev = &raw_devices[rq.raw_minor];
-
-               if (command == RAW_SETBIND) {
-                       dev_t dev;
-
-                       /*
-                        * This is like making block devices, so demand the
-                        * same capability
-                        */
-                       if (!capable(CAP_SYS_ADMIN)) {
-                               err = -EPERM;
-                               goto out;
-                       }
-
-                       /*
-                        * For now, we don't need to check that the underlying
-                        * block device is present or not: we can do that when
-                        * the raw device is opened.  Just check that the
-                        * major/minor numbers make sense.
-                        */
-
-                       dev = MKDEV(rq.block_major, rq.block_minor);
-                       if ((rq.block_major == 0 && rq.block_minor != 0) ||
-                                       MAJOR(dev) != rq.block_major ||
-                                       MINOR(dev) != rq.block_minor) {
-                               err = -EINVAL;
-                               goto out;
-                       }
-
-                       mutex_lock(&raw_mutex);
-                       if (rawdev->inuse) {
-                               mutex_unlock(&raw_mutex);
-                               err = -EBUSY;
-                               goto out;
-                       }
-                       if (rawdev->binding) {
-                               bdput(rawdev->binding);
-                               module_put(THIS_MODULE);
-                       }
-                       if (rq.block_major == 0 && rq.block_minor == 0) {
-                               /* unbind */
-                               rawdev->binding = NULL;
-                               device_destroy(raw_class,
-                                               MKDEV(RAW_MAJOR, rq.raw_minor));
-                       } else {
-                               rawdev->binding = bdget(dev);
-                               if (rawdev->binding == NULL)
-                                       err = -ENOMEM;
-                               else {
-                                       __module_get(THIS_MODULE);
-                                       bind_device(&rq);
-                               }
-                       }
-                       mutex_unlock(&raw_mutex);
-               } else {
-                       struct block_device *bdev;
-
-                       mutex_lock(&raw_mutex);
-                       bdev = rawdev->binding;
-                       if (bdev) {
-                               rq.block_major = MAJOR(bdev->bd_dev);
-                               rq.block_minor = MINOR(bdev->bd_dev);
-                       } else {
-                               rq.block_major = rq.block_minor = 0;
-                       }
-                       mutex_unlock(&raw_mutex);
-                       if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) {
-                               err = -EFAULT;
-                               goto out;
-                       }
-               }
-               break;
-       default:
-               err = -EINVAL;
-               break;
+               if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
+                       return -EFAULT;
+
+               return 0;
        }
-out:
-       unlock_kernel();
-       return err;
+
+       return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+struct raw32_config_request {
+       compat_int_t    raw_minor;
+       compat_u64      block_major;
+       compat_u64      block_minor;
+};
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct raw32_config_request __user *user_req = compat_ptr(arg);
+       struct raw32_config_request rq;
+       dev_t dev;
+       int err = 0;
+
+       switch (cmd) {
+       case RAW_SETBIND:
+               if (copy_from_user(&rq, user_req, sizeof(rq)))
+                       return -EFAULT;
+
+               return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
+       case RAW_GETBIND:
+               if (copy_from_user(&rq, user_req, sizeof(rq)))
+                       return -EFAULT;
+
+               err = bind_get(rq.raw_minor, &dev);
+               if (err)
+                       return err;
+
+               rq.block_major = MAJOR(dev);
+               rq.block_minor = MINOR(dev);
+
+               if (copy_to_user(user_req, &rq, sizeof(rq)))
+                       return -EFAULT;
+
+               return 0;
+       }
+
+       return -EINVAL;
 }
+#endif
 
 static const struct file_operations raw_fops = {
        .read           = do_sync_read,
@@ -258,13 +292,18 @@ static const struct file_operations raw_fops = {
        .open           = raw_open,
        .release        = raw_release,
        .unlocked_ioctl = raw_ioctl,
+       .llseek         = default_llseek,
        .owner          = THIS_MODULE,
 };
 
 static const struct file_operations raw_ctl_fops = {
        .unlocked_ioctl = raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = raw_ctl_compat_ioctl,
+#endif
        .open           = raw_open,
        .owner          = THIS_MODULE,
+       .llseek         = noop_llseek,
 };
 
 static struct cdev raw_cdev;
index d58c2eb07f07aaad25a568095ccaab7d3e53f686..5e33293d24e399d60f45301fdf3ad9e73f00dd9b 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
@@ -122,6 +122,7 @@ more than 512 ports.... */
 
 
 /* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
 static struct Conf
  RIOConf = {
        /* locator */ "RIO Config here",
@@ -241,6 +242,7 @@ static struct real_driver rio_real_driver = {
 static const struct file_operations rio_fw_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = rio_fw_ioctl,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice rio_fw_device = {
@@ -566,9 +568,9 @@ static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        func_enter();
 
        /* The "dev" argument isn't used. */
-       lock_kernel();
+       mutex_lock(&rio_fw_mutex);
        rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-       unlock_kernel();
+       mutex_unlock(&rio_fw_mutex);
 
        func_exit();
        return rc;
index 79c3bc69165afb919f8084cf274c4d2310def8c2..7c79d243acc9b3fac68d6b4062fc9a43bb93eb65 100644 (file)
@@ -1244,6 +1244,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
                }
                info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
                configure_r_port(tty, info, NULL);
+               mutex_unlock(&info->port.mutex);
                return 0;
        }
 
index 99e5272e3c53e1ef1aa32f0733b1bbf0e9f2487e..0bc135b9b16fa680d0111aa932eb4cc39ce36ee8 100644 (file)
@@ -67,6 +67,7 @@ static const struct file_operations scx200_gpio_fileops = {
        .read    = nsc_gpio_read,
        .open    = scx200_gpio_open,
        .release = scx200_gpio_release,
+       .llseek  = no_llseek,
 };
 
 static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
index 32b74de18f5face7e590ac25fc955aef373c6247..5816b39ff5a9cf43cbba56579d9b0b2d021f8883 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/sn/io.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/module.h>
@@ -34,6 +34,7 @@
 #define SCDRV_BUFSZ    2048
 #define SCDRV_TIMEOUT  1000
 
+static DEFINE_MUTEX(scdrv_mutex);
 static irqreturn_t
 scdrv_interrupt(int irq, void *subch_data)
 {
@@ -105,7 +106,7 @@ scdrv_open(struct inode *inode, struct file *file)
        file->private_data = sd;
 
        /* hook this subchannel up to the system controller interrupt */
-       lock_kernel();
+       mutex_lock(&scdrv_mutex);
        rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
                         IRQF_SHARED | IRQF_DISABLED,
                         SYSCTL_BASENAME, sd);
@@ -113,10 +114,10 @@ scdrv_open(struct inode *inode, struct file *file)
                ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
                kfree(sd);
                printk("%s: irq request failed (%d)\n", __func__, rv);
-               unlock_kernel();
+               mutex_unlock(&scdrv_mutex);
                return -EBUSY;
        }
-       unlock_kernel();
+       mutex_unlock(&scdrv_mutex);
        return 0;
 }
 
@@ -357,6 +358,7 @@ static const struct file_operations scdrv_fops = {
        .poll =         scdrv_poll,
        .open =         scdrv_open,
        .release =      scdrv_release,
+       .llseek =       noop_llseek,
 };
 
 static struct class *snsc_class;
index f2167f8e5aab631acbf56cd91338bdd60644942e..8ef16490810c6abb92e17022ebc42c9e6e5d1025 100644 (file)
@@ -608,6 +608,7 @@ static unsigned int sc26198_baudtable[] = {
 static const struct file_operations    stl_fsiomem = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = stl_memioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct class *stallion_class;
index 5b24db4ff7f102f1b2af7b154f1690cf71b29c39..e53f16865397c491fa4afac65988c49b0f391ff9 100644 (file)
@@ -397,6 +397,7 @@ static struct real_driver sx_real_driver = {
 static const struct file_operations sx_fw_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = sx_fw_ioctl,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice sx_fw_device = {
index fef80cfcab5c8caf231b4435d423095dfb90815e..e63b830c86cc0778cb45827dc46a7e207488b586 100644 (file)
@@ -691,8 +691,10 @@ static int open(struct tty_struct *tty, struct file *filp)
        if (info->port.count == 1) {
                /* 1st open on this device, init hardware */
                retval = startup(info);
-               if (retval < 0)
+               if (retval < 0) {
+                       mutex_unlock(&info->port.mutex);
                        goto cleanup;
+               }
        }
        mutex_unlock(&info->port.mutex);
        retval = block_til_ready(tty, filp, info);
index 878ac0c2cc6864a84c7df230c5c12efee1944607..f3019f53e8752becb85b459cc6ad5bc902b986ab 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <linux/tty.h>
 #include <linux/mount.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
@@ -76,7 +75,7 @@ static int __init sysrq_always_enabled_setup(char *str)
 __setup("sysrq_always_enabled", sysrq_always_enabled_setup);
 
 
-static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
+static void sysrq_handle_loglevel(int key)
 {
        int i;
 
@@ -93,7 +92,7 @@ static struct sysrq_key_op sysrq_loglevel_op = {
 };
 
 #ifdef CONFIG_VT
-static void sysrq_handle_SAK(int key, struct tty_struct *tty)
+static void sysrq_handle_SAK(int key)
 {
        struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
        schedule_work(SAK_work);
@@ -109,7 +108,7 @@ static struct sysrq_key_op sysrq_SAK_op = {
 #endif
 
 #ifdef CONFIG_VT
-static void sysrq_handle_unraw(int key, struct tty_struct *tty)
+static void sysrq_handle_unraw(int key)
 {
        struct kbd_struct *kbd = &kbd_table[fg_console];
 
@@ -126,7 +125,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
 #define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
 #endif /* CONFIG_VT */
 
-static void sysrq_handle_crash(int key, struct tty_struct *tty)
+static void sysrq_handle_crash(int key)
 {
        char *killer = NULL;
 
@@ -141,7 +140,7 @@ static struct sysrq_key_op sysrq_crash_op = {
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
-static void sysrq_handle_reboot(int key, struct tty_struct *tty)
+static void sysrq_handle_reboot(int key)
 {
        lockdep_off();
        local_irq_enable();
@@ -154,7 +153,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
        .enable_mask    = SYSRQ_ENABLE_BOOT,
 };
 
-static void sysrq_handle_sync(int key, struct tty_struct *tty)
+static void sysrq_handle_sync(int key)
 {
        emergency_sync();
 }
@@ -165,7 +164,7 @@ static struct sysrq_key_op sysrq_sync_op = {
        .enable_mask    = SYSRQ_ENABLE_SYNC,
 };
 
-static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
+static void sysrq_handle_show_timers(int key)
 {
        sysrq_timer_list_show();
 }
@@ -176,7 +175,7 @@ static struct sysrq_key_op sysrq_show_timers_op = {
        .action_msg     = "Show clockevent devices & pending hrtimers (no others)",
 };
 
-static void sysrq_handle_mountro(int key, struct tty_struct *tty)
+static void sysrq_handle_mountro(int key)
 {
        emergency_remount();
 }
@@ -188,7 +187,7 @@ static struct sysrq_key_op sysrq_mountro_op = {
 };
 
 #ifdef CONFIG_LOCKDEP
-static void sysrq_handle_showlocks(int key, struct tty_struct *tty)
+static void sysrq_handle_showlocks(int key)
 {
        debug_show_all_locks();
 }
@@ -226,7 +225,7 @@ static void sysrq_showregs_othercpus(struct work_struct *dummy)
 
 static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
 
-static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
+static void sysrq_handle_showallcpus(int key)
 {
        /*
         * Fall back to the workqueue based printing if the
@@ -252,7 +251,7 @@ static struct sysrq_key_op sysrq_showallcpus_op = {
 };
 #endif
 
-static void sysrq_handle_showregs(int key, struct tty_struct *tty)
+static void sysrq_handle_showregs(int key)
 {
        struct pt_regs *regs = get_irq_regs();
        if (regs)
@@ -266,7 +265,7 @@ static struct sysrq_key_op sysrq_showregs_op = {
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
-static void sysrq_handle_showstate(int key, struct tty_struct *tty)
+static void sysrq_handle_showstate(int key)
 {
        show_state();
 }
@@ -277,7 +276,7 @@ static struct sysrq_key_op sysrq_showstate_op = {
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
-static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
+static void sysrq_handle_showstate_blocked(int key)
 {
        show_state_filter(TASK_UNINTERRUPTIBLE);
 }
@@ -291,7 +290,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = {
 #ifdef CONFIG_TRACING
 #include <linux/ftrace.h>
 
-static void sysrq_ftrace_dump(int key, struct tty_struct *tty)
+static void sysrq_ftrace_dump(int key)
 {
        ftrace_dump(DUMP_ALL);
 }
@@ -305,7 +304,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = {
 #define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
 #endif
 
-static void sysrq_handle_showmem(int key, struct tty_struct *tty)
+static void sysrq_handle_showmem(int key)
 {
        show_mem();
 }
@@ -330,7 +329,7 @@ static void send_sig_all(int sig)
        }
 }
 
-static void sysrq_handle_term(int key, struct tty_struct *tty)
+static void sysrq_handle_term(int key)
 {
        send_sig_all(SIGTERM);
        console_loglevel = 8;
@@ -349,7 +348,7 @@ static void moom_callback(struct work_struct *ignored)
 
 static DECLARE_WORK(moom_work, moom_callback);
 
-static void sysrq_handle_moom(int key, struct tty_struct *tty)
+static void sysrq_handle_moom(int key)
 {
        schedule_work(&moom_work);
 }
@@ -361,7 +360,7 @@ static struct sysrq_key_op sysrq_moom_op = {
 };
 
 #ifdef CONFIG_BLOCK
-static void sysrq_handle_thaw(int key, struct tty_struct *tty)
+static void sysrq_handle_thaw(int key)
 {
        emergency_thaw_all();
 }
@@ -373,7 +372,7 @@ static struct sysrq_key_op sysrq_thaw_op = {
 };
 #endif
 
-static void sysrq_handle_kill(int key, struct tty_struct *tty)
+static void sysrq_handle_kill(int key)
 {
        send_sig_all(SIGKILL);
        console_loglevel = 8;
@@ -385,7 +384,7 @@ static struct sysrq_key_op sysrq_kill_op = {
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
 
-static void sysrq_handle_unrt(int key, struct tty_struct *tty)
+static void sysrq_handle_unrt(int key)
 {
        normalize_rt_tasks();
 }
@@ -493,7 +492,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
                 sysrq_key_table[i] = op_p;
 }
 
-void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, bool check_mask)
 {
        struct sysrq_key_op *op_p;
        int orig_log_level;
@@ -520,7 +519,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
                if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
                        printk("%s\n", op_p->action_msg);
                        console_loglevel = orig_log_level;
-                       op_p->handler(key, tty);
+                       op_p->handler(key);
                } else {
                        printk("This sysrq operation is disabled.\n");
                }
@@ -545,10 +544,10 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
        spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
 }
 
-void handle_sysrq(int key, struct tty_struct *tty)
+void handle_sysrq(int key)
 {
        if (sysrq_on())
-               __handle_sysrq(key, tty, 1);
+               __handle_sysrq(key, true);
 }
 EXPORT_SYMBOL(handle_sysrq);
 
@@ -597,7 +596,7 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
 
        default:
                if (sysrq_down && value && value != 2)
-                       __handle_sysrq(sysrq_xlate[code], NULL, 1);
+                       __handle_sysrq(sysrq_xlate[code], true);
                break;
        }
 
@@ -765,7 +764,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
 
                if (get_user(c, buf))
                        return -EFAULT;
-               __handle_sysrq(c, NULL, 0);
+               __handle_sysrq(c, false);
        }
 
        return count;
@@ -773,6 +772,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
 
 static const struct file_operations proc_sysrq_trigger_operations = {
        .write          = write_sysrq_trigger,
+       .llseek         = noop_llseek,
 };
 
 static void sysrq_init_procfs(void)
index cad4eb65f13de1cc22e0301c9c30c22227d7804b..ad264185eb10a0fb43d1c67ed86a7cbab9b70381 100644 (file)
@@ -261,6 +261,7 @@ static const struct file_operations tb0219_fops = {
        .write          = tanbac_tb0219_write,
        .open           = tanbac_tb0219_open,
        .release        = tanbac_tb0219_release,
+       .llseek         = no_llseek,
 };
 
 static void tb0219_restart(char *command)
index 80ea6bcfffdc4136c07a79483d4ad65d11556302..0c964cdcc223ca7e710534470ee069d75497b802 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <linux/sysfs.h>
 #include <linux/device.h>
@@ -206,7 +206,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
 {
        int result;
 
-       lock_kernel();
+       mutex_lock(&tlclk_mutex);
        if (test_and_set_bit(0, &useflags)) {
                result = -EBUSY;
                /* this legacy device is always one per system and it doesn't
@@ -229,7 +229,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
                inb(TLCLK_REG6);        /* Clear interrupt events */
 
 out:
-       unlock_kernel();
+       mutex_unlock(&tlclk_mutex);
        return result;
 }
 
@@ -267,6 +267,7 @@ static const struct file_operations tlclk_fops = {
        .read = tlclk_read,
        .open = tlclk_open,
        .release = tlclk_release,
+       .llseek = noop_llseek,
 
 };
 
index f8bc79f6de34875cba7ac1e74e9110ff3c236d53..014c9d90d297ba57f1f83c7abbe1768042971b6b 100644 (file)
@@ -68,7 +68,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/toshiba.h>
 
 #define TOSH_MINOR_DEV 181
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
 MODULE_DESCRIPTION("Toshiba laptop SMM driver");
 MODULE_SUPPORTED_DEVICE("toshiba");
 
+static DEFINE_MUTEX(tosh_mutex);
 static int tosh_fn;
 module_param_named(fn, tosh_fn, int, 0);
 MODULE_PARM_DESC(fn, "User specified Fn key detection port");
@@ -95,6 +96,7 @@ static long tosh_ioctl(struct file *, unsigned int,
 static const struct file_operations tosh_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = tosh_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice tosh_device = {
@@ -274,16 +276,16 @@ static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                                return -EINVAL;
 
                        /* do we need to emulate the fan ? */
-                       lock_kernel();
+                       mutex_lock(&tosh_mutex);
                        if (tosh_fan==1) {
                                if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
                                        err = tosh_emulate_fan(&regs);
-                                       unlock_kernel();
+                                       mutex_unlock(&tosh_mutex);
                                        break;
                                }
                        }
                        err = tosh_smm(&regs);
-                       unlock_kernel();
+                       mutex_unlock(&tosh_mutex);
                        break;
                default:
                        return -EINVAL;
index 05ad4a17a28f238ecc197e67051f60a50faad769..7c4133582dbae484f449d49f97b2ee0f179a9891 100644 (file)
@@ -47,6 +47,16 @@ enum tpm_duration {
 #define TPM_MAX_PROTECTED_ORDINAL 12
 #define TPM_PROTECTED_ORDINAL_MASK 0xFF
 
+/*
+ * Bug workaround - some TPM's don't flush the most
+ * recently changed pcr on suspend, so force the flush
+ * with an extend to the selected _unused_ non-volatile pcr.
+ */
+static int tpm_suspend_pcr;
+module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
+MODULE_PARM_DESC(suspend_pcr,
+                "PCR to use for dummy writes to faciltate flush on suspend.");
+
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
 static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
@@ -1077,18 +1087,6 @@ static struct tpm_input_header savestate_header = {
        .ordinal = TPM_ORD_SAVESTATE
 };
 
-/* Bug workaround - some TPM's don't flush the most
- * recently changed pcr on suspend, so force the flush
- * with an extend to the selected _unused_ non-volatile pcr.
- */
-static int tpm_suspend_pcr;
-static int __init tpm_suspend_setup(char *str)
-{
-       get_option(&str, &tpm_suspend_pcr);
-       return 1;
-}
-__setup("tpm_suspend_pcr=", tpm_suspend_setup);
-
 /*
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
index 949067a0bd4743151515382b07ccf7aecad11316..613c852ee0feced279c50f6850e9e30c7c870111 100644 (file)
@@ -355,7 +355,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
                if (*stp == '\0')
                        stp = NULL;
 
-               if (tty_line >= 0 && tty_line <= p->num && p->ops &&
+               if (tty_line >= 0 && tty_line < p->num && p->ops &&
                    p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
                        res = tty_driver_kref_get(p);
                        *line = tty_line;
index c7072ba14f48130d8f04977232bb38ed8dbe067e..493b47a0d511bd1a01dcd8985b76666f66a03971 100644 (file)
@@ -52,6 +52,7 @@ static const struct file_operations uv_mmtimer_fops = {
        .owner = THIS_MODULE,
        .mmap = uv_mmtimer_mmap,
        .unlocked_ioctl = uv_mmtimer_ioctl,
+       .llseek = noop_llseek,
 };
 
 /**
index 42f7fa442ff80653c3cbabf9c80bd1b2e05de28d..ad6e64a2912d6fe61d06d7c20135e76a92bc9e1c 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -64,6 +64,7 @@
 #define VIOTAPE_KERN_WARN      KERN_WARNING "viotape: "
 #define VIOTAPE_KERN_INFO      KERN_INFO "viotape: "
 
+static DEFINE_MUTEX(proc_viotape_mutex);
 static int viotape_numdev;
 
 /*
@@ -684,9 +685,9 @@ static long viotap_unlocked_ioctl(struct file *file,
 {
        long rc;
 
-       lock_kernel();
+       mutex_lock(&proc_viotape_mutex);
        rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&proc_viotape_mutex);
        return rc;
 }
 
@@ -700,7 +701,7 @@ static int viotap_open(struct inode *inode, struct file *file)
        if (op == NULL)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&proc_viotape_mutex);
        get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        /* Note: We currently only support one mode! */
@@ -731,7 +732,7 @@ static int viotap_open(struct inode *inode, struct file *file)
 
 free_op:
        free_op_struct(op);
-       unlock_kernel();
+       mutex_unlock(&proc_viotape_mutex);
        return ret;
 }
 
@@ -804,6 +805,7 @@ const struct file_operations viotap_fops = {
        .unlocked_ioctl =       viotap_unlocked_ioctl,
        .open =                 viotap_open,
        .release =              viotap_release,
+       .llseek =               noop_llseek,
 };
 
 /* Handle interrupt events for tape */
index 942a9826bd23ed64b83095fcdeb65ed059c9ce02..6c1b676643a9ef43fe3984bb8495996960cf4337 100644 (file)
@@ -48,6 +48,9 @@ struct ports_driver_data {
        /* Used for exporting per-port information to debugfs */
        struct dentry *debugfs_dir;
 
+       /* List of all the devices we're handling */
+       struct list_head portdevs;
+
        /* Number of devices this driver is handling */
        unsigned int index;
 
@@ -108,6 +111,9 @@ struct port_buffer {
  * ports for that device (vdev->priv).
  */
 struct ports_device {
+       /* Next portdev in the list, head is in the pdrvdata struct */
+       struct list_head list;
+
        /*
         * Workqueue handlers where we process deferred work after
         * notification
@@ -178,15 +184,21 @@ struct port {
        struct console cons;
 
        /* Each port associates with a separate char device */
-       struct cdev cdev;
+       struct cdev *cdev;
        struct device *dev;
 
+       /* Reference-counting to handle port hot-unplugs and file operations */
+       struct kref kref;
+
        /* A waitqueue for poll() or blocking read operations */
        wait_queue_head_t waitqueue;
 
        /* The 'name' of the port that we expose via sysfs properties */
        char *name;
 
+       /* We can notify apps of host connect / disconnect events via SIGIO */
+       struct fasync_struct *async_queue;
+
        /* The 'id' to identify the port with the Host */
        u32 id;
 
@@ -221,6 +233,41 @@ out:
        return port;
 }
 
+static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
+                                                dev_t dev)
+{
+       struct port *port;
+       unsigned long flags;
+
+       spin_lock_irqsave(&portdev->ports_lock, flags);
+       list_for_each_entry(port, &portdev->ports, list)
+               if (port->cdev->dev == dev)
+                       goto out;
+       port = NULL;
+out:
+       spin_unlock_irqrestore(&portdev->ports_lock, flags);
+
+       return port;
+}
+
+static struct port *find_port_by_devt(dev_t dev)
+{
+       struct ports_device *portdev;
+       struct port *port;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pdrvdata_lock, flags);
+       list_for_each_entry(portdev, &pdrvdata.portdevs, list) {
+               port = find_port_by_devt_in_portdev(portdev, dev);
+               if (port)
+                       goto out;
+       }
+       port = NULL;
+out:
+       spin_unlock_irqrestore(&pdrvdata_lock, flags);
+       return port;
+}
+
 static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
 {
        struct port *port;
@@ -410,7 +457,10 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
 static ssize_t send_control_msg(struct port *port, unsigned int event,
                                unsigned int value)
 {
-       return __send_control_msg(port->portdev, port->id, event, value);
+       /* Did the port get unplugged before userspace closed it? */
+       if (port->portdev)
+               return __send_control_msg(port->portdev, port->id, event, value);
+       return 0;
 }
 
 /* Callers must take the port->outvq_lock */
@@ -459,9 +509,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
 
        /*
         * Wait till the host acknowledges it pushed out the data we
-        * sent.  This is done for ports in blocking mode or for data
-        * from the hvc_console; the tty operations are performed with
-        * spinlocks held so we can't sleep here.
+        * sent.  This is done for data from the hvc_console; the tty
+        * operations are performed with spinlocks held so we can't
+        * sleep here.  An alternative would be to copy the data to a
+        * buffer and relax the spinning requirement.  The downside is
+        * we need to kmalloc a GFP_ATOMIC buffer each time the
+        * console driver writes something out.
         */
        while (!virtqueue_get_buf(out_vq, &len))
                cpu_relax();
@@ -522,6 +575,10 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
 /* The condition that must be true for polling to end */
 static bool will_read_block(struct port *port)
 {
+       if (!port->guest_connected) {
+               /* Port got hot-unplugged. Let's exit. */
+               return false;
+       }
        return !port_has_data(port) && port->host_connected;
 }
 
@@ -572,6 +629,9 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
                if (ret < 0)
                        return ret;
        }
+       /* Port got hot-unplugged. */
+       if (!port->guest_connected)
+               return -ENODEV;
        /*
         * We could've received a disconnection message while we were
         * waiting for more data.
@@ -596,6 +656,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
        ssize_t ret;
        bool nonblock;
 
+       /* Userspace could be out to fool us */
+       if (!count)
+               return 0;
+
        port = filp->private_data;
 
        nonblock = filp->f_flags & O_NONBLOCK;
@@ -609,6 +673,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
                if (ret < 0)
                        return ret;
        }
+       /* Port got hot-unplugged. */
+       if (!port->guest_connected)
+               return -ENODEV;
 
        count = min((size_t)(32 * 1024), count);
 
@@ -622,6 +689,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
                goto free_buf;
        }
 
+       /*
+        * We now ask send_buf() to not spin for generic ports -- we
+        * can re-use the same code path that non-blocking file
+        * descriptors take for blocking file descriptors since the
+        * wait is already done and we're certain the write will go
+        * through to the host.
+        */
+       nonblock = true;
        ret = send_buf(port, buf, count, nonblock);
 
        if (nonblock && ret > 0)
@@ -641,8 +716,12 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
        port = filp->private_data;
        poll_wait(filp, &port->waitqueue, wait);
 
+       if (!port->guest_connected) {
+               /* Port got unplugged */
+               return POLLHUP;
+       }
        ret = 0;
-       if (port->inbuf)
+       if (!will_read_block(port))
                ret |= POLLIN | POLLRDNORM;
        if (!will_write_block(port))
                ret |= POLLOUT;
@@ -652,6 +731,8 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
        return ret;
 }
 
+static void remove_port(struct kref *kref);
+
 static int port_fops_release(struct inode *inode, struct file *filp)
 {
        struct port *port;
@@ -672,6 +753,16 @@ static int port_fops_release(struct inode *inode, struct file *filp)
        reclaim_consumed_buffers(port);
        spin_unlock_irq(&port->outvq_lock);
 
+       /*
+        * Locks aren't necessary here as a port can't be opened after
+        * unplug, and if a port isn't unplugged, a kref would already
+        * exist for the port.  Plus, taking ports_lock here would
+        * create a dependency on other locks taken by functions
+        * inside remove_port if we're the last holder of the port,
+        * creating many problems.
+        */
+       kref_put(&port->kref, remove_port);
+
        return 0;
 }
 
@@ -679,22 +770,31 @@ static int port_fops_open(struct inode *inode, struct file *filp)
 {
        struct cdev *cdev = inode->i_cdev;
        struct port *port;
+       int ret;
 
-       port = container_of(cdev, struct port, cdev);
+       port = find_port_by_devt(cdev->dev);
        filp->private_data = port;
 
+       /* Prevent against a port getting hot-unplugged at the same time */
+       spin_lock_irq(&port->portdev->ports_lock);
+       kref_get(&port->kref);
+       spin_unlock_irq(&port->portdev->ports_lock);
+
        /*
         * Don't allow opening of console port devices -- that's done
         * via /dev/hvc
         */
-       if (is_console_port(port))
-               return -ENXIO;
+       if (is_console_port(port)) {
+               ret = -ENXIO;
+               goto out;
+       }
 
        /* Allow only one process to open a particular port at a time */
        spin_lock_irq(&port->inbuf_lock);
        if (port->guest_connected) {
                spin_unlock_irq(&port->inbuf_lock);
-               return -EMFILE;
+               ret = -EMFILE;
+               goto out;
        }
 
        port->guest_connected = true;
@@ -709,10 +809,23 @@ static int port_fops_open(struct inode *inode, struct file *filp)
        reclaim_consumed_buffers(port);
        spin_unlock_irq(&port->outvq_lock);
 
+       nonseekable_open(inode, filp);
+
        /* Notify host of port being opened */
        send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1);
 
        return 0;
+out:
+       kref_put(&port->kref, remove_port);
+       return ret;
+}
+
+static int port_fops_fasync(int fd, struct file *filp, int mode)
+{
+       struct port *port;
+
+       port = filp->private_data;
+       return fasync_helper(fd, filp, mode, &port->async_queue);
 }
 
 /*
@@ -728,6 +841,8 @@ static const struct file_operations port_fops = {
        .write = port_fops_write,
        .poll  = port_fops_poll,
        .release = port_fops_release,
+       .fasync = port_fops_fasync,
+       .llseek = no_llseek,
 };
 
 /*
@@ -986,6 +1101,12 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
        return nr_added_bufs;
 }
 
+static void send_sigio_to_port(struct port *port)
+{
+       if (port->async_queue && port->guest_connected)
+               kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
+}
+
 static int add_port(struct ports_device *portdev, u32 id)
 {
        char debugfs_name[16];
@@ -1000,6 +1121,7 @@ static int add_port(struct ports_device *portdev, u32 id)
                err = -ENOMEM;
                goto fail;
        }
+       kref_init(&port->kref);
 
        port->portdev = portdev;
        port->id = id;
@@ -1007,6 +1129,7 @@ static int add_port(struct ports_device *portdev, u32 id)
        port->name = NULL;
        port->inbuf = NULL;
        port->cons.hvc = NULL;
+       port->async_queue = NULL;
 
        port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
 
@@ -1017,14 +1140,20 @@ static int add_port(struct ports_device *portdev, u32 id)
        port->in_vq = portdev->in_vqs[port->id];
        port->out_vq = portdev->out_vqs[port->id];
 
-       cdev_init(&port->cdev, &port_fops);
+       port->cdev = cdev_alloc();
+       if (!port->cdev) {
+               dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n");
+               err = -ENOMEM;
+               goto free_port;
+       }
+       port->cdev->ops = &port_fops;
 
        devt = MKDEV(portdev->chr_major, id);
-       err = cdev_add(&port->cdev, devt, 1);
+       err = cdev_add(port->cdev, devt, 1);
        if (err < 0) {
                dev_err(&port->portdev->vdev->dev,
                        "Error %d adding cdev for port %u\n", err, id);
-               goto free_port;
+               goto free_cdev;
        }
        port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
                                  devt, port, "vport%up%u",
@@ -1089,7 +1218,7 @@ free_inbufs:
 free_device:
        device_destroy(pdrvdata.class, port->dev->devt);
 free_cdev:
-       cdev_del(&port->cdev);
+       cdev_del(port->cdev);
 free_port:
        kfree(port);
 fail:
@@ -1098,21 +1227,45 @@ fail:
        return err;
 }
 
-/* Remove all port-specific data. */
-static int remove_port(struct port *port)
+/* No users remain, remove all port-specific data. */
+static void remove_port(struct kref *kref)
+{
+       struct port *port;
+
+       port = container_of(kref, struct port, kref);
+
+       sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+       device_destroy(pdrvdata.class, port->dev->devt);
+       cdev_del(port->cdev);
+
+       kfree(port->name);
+
+       debugfs_remove(port->debugfs_file);
+
+       kfree(port);
+}
+
+/*
+ * Port got unplugged.  Remove port from portdev's list and drop the
+ * kref reference.  If no userspace has this port opened, it will
+ * result in immediate removal the port.
+ */
+static void unplug_port(struct port *port)
 {
        struct port_buffer *buf;
 
+       spin_lock_irq(&port->portdev->ports_lock);
+       list_del(&port->list);
+       spin_unlock_irq(&port->portdev->ports_lock);
+
        if (port->guest_connected) {
                port->guest_connected = false;
                port->host_connected = false;
                wake_up_interruptible(&port->waitqueue);
-               send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-       }
 
-       spin_lock_irq(&port->portdev->ports_lock);
-       list_del(&port->list);
-       spin_unlock_irq(&port->portdev->ports_lock);
+               /* Let the app know the port is going down. */
+               send_sigio_to_port(port);
+       }
 
        if (is_console_port(port)) {
                spin_lock_irq(&pdrvdata_lock);
@@ -1131,9 +1284,6 @@ static int remove_port(struct port *port)
                hvc_remove(port->cons.hvc);
 #endif
        }
-       sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
-       device_destroy(pdrvdata.class, port->dev->devt);
-       cdev_del(&port->cdev);
 
        /* Remove unused data this port might have received. */
        discard_port_data(port);
@@ -1144,12 +1294,19 @@ static int remove_port(struct port *port)
        while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
                free_buf(buf);
 
-       kfree(port->name);
-
-       debugfs_remove(port->debugfs_file);
+       /*
+        * We should just assume the device itself has gone off --
+        * else a close on an open port later will try to send out a
+        * control message.
+        */
+       port->portdev = NULL;
 
-       kfree(port);
-       return 0;
+       /*
+        * Locks around here are not necessary - a port can't be
+        * opened after we removed the port struct from ports_list
+        * above.
+        */
+       kref_put(&port->kref, remove_port);
 }
 
 /* Any private messages that the Host and Guest want to share */
@@ -1188,7 +1345,7 @@ static void handle_control_message(struct ports_device *portdev,
                add_port(portdev, cpkt->id);
                break;
        case VIRTIO_CONSOLE_PORT_REMOVE:
-               remove_port(port);
+               unplug_port(port);
                break;
        case VIRTIO_CONSOLE_CONSOLE_PORT:
                if (!cpkt->value)
@@ -1230,6 +1387,12 @@ static void handle_control_message(struct ports_device *portdev,
                spin_lock_irq(&port->outvq_lock);
                reclaim_consumed_buffers(port);
                spin_unlock_irq(&port->outvq_lock);
+
+               /*
+                * If the guest is connected, it'll be interested in
+                * knowing the host connection state changed.
+                */
+               send_sigio_to_port(port);
                break;
        case VIRTIO_CONSOLE_PORT_NAME:
                /*
@@ -1326,6 +1489,9 @@ static void in_intr(struct virtqueue *vq)
 
        wake_up_interruptible(&port->waitqueue);
 
+       /* Send a SIGIO indicating new data in case the process asked for it */
+       send_sigio_to_port(port);
+
        if (is_console_port(port) && hvc_poll(port->cons.hvc))
                hvc_kick();
 }
@@ -1562,6 +1728,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
                add_port(portdev, 0);
        }
 
+       spin_lock_irq(&pdrvdata_lock);
+       list_add_tail(&portdev->list, &pdrvdata.portdevs);
+       spin_unlock_irq(&pdrvdata_lock);
+
        __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
                           VIRTIO_CONSOLE_DEVICE_READY, 1);
        return 0;
@@ -1585,23 +1755,41 @@ static void virtcons_remove(struct virtio_device *vdev)
 {
        struct ports_device *portdev;
        struct port *port, *port2;
-       struct port_buffer *buf;
-       unsigned int len;
 
        portdev = vdev->priv;
 
+       spin_lock_irq(&pdrvdata_lock);
+       list_del(&portdev->list);
+       spin_unlock_irq(&pdrvdata_lock);
+
+       /* Disable interrupts for vqs */
+       vdev->config->reset(vdev);
+       /* Finish up work that's lined up */
        cancel_work_sync(&portdev->control_work);
 
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
-               remove_port(port);
+               unplug_port(port);
 
        unregister_chrdev(portdev->chr_major, "virtio-portsdev");
 
-       while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
-               free_buf(buf);
+       /*
+        * When yanking out a device, we immediately lose the
+        * (device-side) queues.  So there's no point in keeping the
+        * guest side around till we drop our final reference.  This
+        * also means that any ports which are in an open state will
+        * have to just stop using the port, as the vqs are going
+        * away.
+        */
+       if (use_multiport(portdev)) {
+               struct port_buffer *buf;
+               unsigned int len;
 
-       while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
-               free_buf(buf);
+               while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
+                       free_buf(buf);
+
+               while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
+                       free_buf(buf);
+       }
 
        vdev->config->del_vqs(vdev);
        kfree(portdev->in_vqs);
@@ -1648,6 +1836,7 @@ static int __init init(void)
                           PTR_ERR(pdrvdata.debugfs_dir));
        }
        INIT_LIST_HEAD(&pdrvdata.consoles);
+       INIT_LIST_HEAD(&pdrvdata.portdevs);
 
        return register_virtio_driver(&virtio_console);
 }
index 50590c7f2c01ac4c2a71595e94fbebe930081079..281aada7b4a110a2d9f47d5e3e780596a36c298e 100644 (file)
@@ -906,22 +906,16 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
                         * bottom of buffer
                         */
                        old_origin += (old_rows - new_rows) * old_row_size;
-                       end = vc->vc_scr_end;
                } else {
                        /*
                         * Cursor is in no man's land, copy 1/2 screenful
                         * from the top and bottom of cursor position
                         */
                        old_origin += (vc->vc_y - new_rows/2) * old_row_size;
-                       end = old_origin + (old_row_size * new_rows);
                }
-       } else
-               /*
-                * Cursor near the top, copy contents from the top of buffer
-                */
-               end = (old_rows > new_rows) ? old_origin +
-                       (old_row_size * new_rows) :
-                       vc->vc_scr_end;
+       }
+
+       end = old_origin + old_row_size * min(old_rows, new_rows);
 
        update_attr(vc);
 
@@ -3075,8 +3069,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
 
                old_was_color = vc->vc_can_do_color;
                vc->vc_sw->con_deinit(vc);
-               if (!vc->vc_origin)
-                       vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+               vc->vc_origin = (unsigned long)vc->vc_screenbuf;
                visual_init(vc, i, 0);
                set_origin(vc);
                update_attr(vc);
index 2bbeaaea46e9b7765ce983374fb125b7dd5422c9..38df8c19e74cc56903d5985cdbee7d52df3dc0d9 100644 (file)
@@ -533,11 +533,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        case KIOCSOUND:
                if (!perm)
                        goto eperm;
-               /* FIXME: This is an old broken API but we need to keep it
-                  supported and somehow separate the historic advertised
-                  tick rate from any real one */
+               /*
+                * The use of PIT_TICK_RATE is historic, it used to be
+                * the platform-dependent CLOCK_TICK_RATE between 2.6.12
+                * and 2.6.36, which was a minor but unfortunate ABI
+                * change.
+                */
                if (arg)
-                       arg = CLOCK_TICK_RATE / arg;
+                       arg = PIT_TICK_RATE / arg;
                kd_mksound(arg, 0);
                break;
 
@@ -553,11 +556,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                 */
                ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
                count = ticks ? (arg & 0xffff) : 0;
-               /* FIXME: This is an old broken API but we need to keep it
-                  supported and somehow separate the historic advertised
-                  tick rate from any real one */
                if (count)
-                       count = CLOCK_TICK_RATE / count;
+                       count = PIT_TICK_RATE / count;
                kd_mksound(count, ticks);
                break;
        }
index b663d573aad99ed5257f9ab324d566309e70ac37..9f2272e6de1c160e1566eb5b01c63f45ddb2a129 100644 (file)
@@ -81,7 +81,6 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #define HWICAP_DEVICES 1
 
 /* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(hwicap_mutex);
 static bool probed_devices[HWICAP_DEVICES];
 static struct mutex icap_sem;
 
@@ -502,7 +502,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
        struct hwicap_drvdata *drvdata;
        int status;
 
-       lock_kernel();
+       mutex_lock(&hwicap_mutex);
        drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
 
        status = mutex_lock_interruptible(&drvdata->sem);
@@ -528,7 +528,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
  error:
        mutex_unlock(&drvdata->sem);
  out:
-       unlock_kernel();
+       mutex_unlock(&hwicap_mutex);
        return status;
 }
 
@@ -567,6 +567,7 @@ static const struct file_operations hwicap_fops = {
        .read = hwicap_read,
        .open = hwicap_open,
        .release = hwicap_release,
+       .llseek = noop_llseek,
 };
 
 static int __devinit hwicap_setup(struct device *dev, int id,
index c2408bbe9c2eed3521f4eb21a86c1e9671774534..f508690eb95859ef80e217f68db827daba606f29 100644 (file)
@@ -80,7 +80,7 @@
  * Limiting Performance Impact
  * ---------------------------
  * C states, especially those with large exit latencies, can have a real
- * noticable impact on workloads, which is not acceptable for most sysadmins,
+ * noticeable impact on workloads, which is not acceptable for most sysadmins,
  * and in addition, less performance has a power price of its own.
  *
  * As a general rule of thumb, menu assumes that the following heuristic
index 8661c84a105d86751e1990636f6dbcdeb4962cf3..b98c67664ae72b7638bdf06365fd0789eb76245e 100644 (file)
@@ -39,6 +39,10 @@ static DEFINE_SPINLOCK(dca_lock);
 
 static LIST_HEAD(dca_domains);
 
+static BLOCKING_NOTIFIER_HEAD(dca_provider_chain);
+
+static int dca_providers_blocked;
+
 static struct pci_bus *dca_pci_rc_from_dev(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -70,6 +74,60 @@ static void dca_free_domain(struct dca_domain *domain)
        kfree(domain);
 }
 
+static int dca_provider_ioat_ver_3_0(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
+               ((pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG0) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG1) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG2) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG3) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG4) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG5) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG6) ||
+               (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG7)));
+}
+
+static void unregister_dca_providers(void)
+{
+       struct dca_provider *dca, *_dca;
+       struct list_head unregistered_providers;
+       struct dca_domain *domain;
+       unsigned long flags;
+
+       blocking_notifier_call_chain(&dca_provider_chain,
+                                    DCA_PROVIDER_REMOVE, NULL);
+
+       INIT_LIST_HEAD(&unregistered_providers);
+
+       spin_lock_irqsave(&dca_lock, flags);
+
+       if (list_empty(&dca_domains)) {
+               spin_unlock_irqrestore(&dca_lock, flags);
+               return;
+       }
+
+       /* at this point only one domain in the list is expected */
+       domain = list_first_entry(&dca_domains, struct dca_domain, node);
+       if (!domain)
+               return;
+
+       list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) {
+               list_del(&dca->node);
+               list_add(&dca->node, &unregistered_providers);
+       }
+
+       dca_free_domain(domain);
+
+       spin_unlock_irqrestore(&dca_lock, flags);
+
+       list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) {
+               dca_sysfs_remove_provider(dca);
+               list_del(&dca->node);
+       }
+}
+
 static struct dca_domain *dca_find_domain(struct pci_bus *rc)
 {
        struct dca_domain *domain;
@@ -90,9 +148,13 @@ static struct dca_domain *dca_get_domain(struct device *dev)
        domain = dca_find_domain(rc);
 
        if (!domain) {
-               domain = dca_allocate_domain(rc);
-               if (domain)
-                       list_add(&domain->node, &dca_domains);
+               if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) {
+                       dca_providers_blocked = 1;
+               } else {
+                       domain = dca_allocate_domain(rc);
+                       if (domain)
+                               list_add(&domain->node, &dca_domains);
+               }
        }
 
        return domain;
@@ -293,8 +355,6 @@ void free_dca_provider(struct dca_provider *dca)
 }
 EXPORT_SYMBOL_GPL(free_dca_provider);
 
-static BLOCKING_NOTIFIER_HEAD(dca_provider_chain);
-
 /**
  * register_dca_provider - register a dca provider
  * @dca - struct created by alloc_dca_provider()
@@ -306,6 +366,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
        unsigned long flags;
        struct dca_domain *domain;
 
+       spin_lock_irqsave(&dca_lock, flags);
+       if (dca_providers_blocked) {
+               spin_unlock_irqrestore(&dca_lock, flags);
+               return -ENODEV;
+       }
+       spin_unlock_irqrestore(&dca_lock, flags);
+
        err = dca_sysfs_add_provider(dca, dev);
        if (err)
                return err;
@@ -313,7 +380,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
        spin_lock_irqsave(&dca_lock, flags);
        domain = dca_get_domain(dev);
        if (!domain) {
-               spin_unlock_irqrestore(&dca_lock, flags);
+               if (dca_providers_blocked) {
+                       spin_unlock_irqrestore(&dca_lock, flags);
+                       dca_sysfs_remove_provider(dca);
+                       unregister_dca_providers();
+               } else {
+                       spin_unlock_irqrestore(&dca_lock, flags);
+               }
                return -ENODEV;
        }
        list_add(&dca->node, &domain->dca_providers);
index 557e2272e5b3195a70525c5c955fa6c4dab0ba0b..ae2b8714d19058cfc3371d7b7cc587b56fb2afbc 100644 (file)
@@ -157,6 +157,7 @@ static const struct file_operations coh901318_debugfs_status_operations = {
        .owner          = THIS_MODULE,
        .open           = coh901318_debugfs_open,
        .read           = coh901318_debugfs_read,
+       .llseek         = default_llseek,
 };
 
 
index 216f9d383b5b7b1b0a4d2062c388518a7270de55..effd140fc042b827617bebce013dae190c7b4d76 100644 (file)
@@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
        dma->device_issue_pending = ioat2_issue_pending;
        dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
        dma->device_free_chan_resources = ioat2_free_chan_resources;
-       dma->device_tx_status = ioat_tx_status;
+       dma->device_tx_status = ioat_dma_tx_status;
 
        err = ioat_probe(device);
        if (err)
index 86c5ae9fde34d3cf0f3f372a33739ccb4286fdf3..411d5bf50fc43cab437dff34d3d9f25dd9928fe0 100644 (file)
@@ -162,7 +162,7 @@ static int mv_is_err_intr(u32 intr_cause)
 
 static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
 {
-       u32 val = (1 << (1 + (chan->idx * 16)));
+       u32 val = ~(1 << (chan->idx * 16));
        dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
        __raw_writel(val, XOR_INTR_CAUSE(chan));
 }
index fb64cf36ba61d0e786ecfeb802f43909ade4f2f2..eb6b54dbb8064a9a5d2e71eb3261132195ff6f8d 100644 (file)
@@ -580,7 +580,6 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
 
        sh_chan = to_sh_chan(chan);
        param = chan->private;
-       slave_addr = param->config->addr;
 
        /* Someone calling slave DMA on a public channel? */
        if (!param || !sg_len) {
@@ -589,6 +588,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
                return NULL;
        }
 
+       slave_addr = param->config->addr;
+
        /*
         * if (param != NULL), this is a successfully requested slave channel,
         * therefore param->config != NULL too.
index 70bb350de9964a813b6e4627e6c4a709e23ff930..9dbb28b9559f7d794dd7f6899a5ff52056ce4017 100644 (file)
@@ -39,7 +39,7 @@ config EDAC_DEBUG
          there're four debug levels (x=0,1,2,3 from low to high).
          Usually you should select 'N'.
 
- config EDAC_DECODE_MCE
+config EDAC_DECODE_MCE
        tristate "Decode MCEs in human-readable form (only on AMD for now)"
        depends on CPU_SUP_AMD && X86_MCE
        default y
@@ -51,6 +51,16 @@ config EDAC_DEBUG
          which occur really early upon boot, before the module infrastructure
          has been initialized.
 
+config EDAC_MCE_INJ
+       tristate "Simple MCE injection interface over /sysfs"
+       depends on EDAC_DECODE_MCE
+       default n
+       help
+         This is a simple interface to inject MCEs over /sysfs and test
+         the MCE decoding code in EDAC.
+
+         This is currently AMD-only.
+
 config EDAC_MM_EDAC
        tristate "Main Memory EDAC (Error Detection And Correction) reporting"
        help
@@ -66,13 +76,13 @@ config EDAC_MCE
 
 config EDAC_AMD64
        tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-       depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
+       depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE
        help
          Support for error detection and correction on the AMD 64
          Families of Memory Controllers (K8, F10h and F11h)
 
 config EDAC_AMD64_ERROR_INJECTION
-       bool "Sysfs Error Injection facilities"
+       bool "Sysfs HW Error injection facilities"
        depends on EDAC_AMD64
        help
          Recent Opterons (Family 10h and later) provide for Memory Error
index ca6b1bb24ccc8e76109b13f38e1237eec98ec09e..32c7bc93c525ef1613d1c116b14b0e1a0e0f4f8a 100644 (file)
@@ -17,6 +17,9 @@ ifdef CONFIG_PCI
 edac_core-objs += edac_pci.o edac_pci_sysfs.o
 endif
 
+obj-$(CONFIG_EDAC_MCE_INJ)             += mce_amd_inj.o
+
+edac_mce_amd-objs                      := mce_amd.o
 obj-$(CONFIG_EDAC_DECODE_MCE)          += edac_mce_amd.o
 
 obj-$(CONFIG_EDAC_AMD76X)              += amd76x_edac.o
index 670239ab7511aea7f902449c33e675efe3202a0a..8521401bbd751406e6f2752e10868f63c7e3b48a 100644 (file)
@@ -1,5 +1,5 @@
 #include "amd64_edac.h"
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 static struct edac_pci_ctl_info *amd64_ctl_pci;
 
@@ -2071,23 +2071,20 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
                amd64_handle_ce(mci, info);
        else if (ecc_type == 1)
                amd64_handle_ue(mci, info);
-
-       /*
-        * If main error is CE then overflow must be CE.  If main error is UE
-        * then overflow is unknown.  We'll call the overflow a CE - if
-        * panic_on_ue is set then we're already panic'ed and won't arrive
-        * here. Else, then apparently someone doesn't think that UE's are
-        * catastrophic.
-        */
-       if (info->nbsh & K8_NBSH_OVERFLOW)
-               edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR " Error Overflow");
 }
 
-void amd64_decode_bus_error(int node_id, struct err_regs *regs)
+void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
 {
        struct mem_ctl_info *mci = mci_lookup[node_id];
+       struct err_regs regs;
+
+       regs.nbsl  = (u32) m->status;
+       regs.nbsh  = (u32)(m->status >> 32);
+       regs.nbeal = (u32) m->addr;
+       regs.nbeah = (u32)(m->addr >> 32);
+       regs.nbcfg = nbcfg;
 
-       __amd64_decode_bus_error(mci, regs);
+       __amd64_decode_bus_error(mci, &regs);
 
        /*
         * Check the UE bit of the NB status high register, if set generate some
@@ -2096,7 +2093,7 @@ void amd64_decode_bus_error(int node_id, struct err_regs *regs)
         *
         * FIXME: this should go somewhere else, if at all.
         */
-       if (regs->nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
+       if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
                edac_mc_handle_ue_no_info(mci, "UE bit is set");
 
 }
@@ -2937,7 +2934,7 @@ static int __init amd64_edac_init(void)
         * to finish initialization of the MC instances.
         */
        err = -ENODEV;
-       for (nb = 0; nb < num_k8_northbridges; nb++) {
+       for (nb = 0; nb < k8_northbridges.num; nb++) {
                if (!pvt_lookup[nb])
                        continue;
 
index 613b9381e71a658e76fd312beb0e1d05e5f10616..044aee4f944da6ae9a709584ae243c3e97c151a9 100644 (file)
@@ -72,7 +72,7 @@
 #include <linux/edac.h>
 #include <asm/msr.h>
 #include "edac_core.h"
-#include "edac_mce_amd.h"
+#include "mce_amd.h"
 
 #define amd64_printk(level, fmt, arg...) \
        edac_printk(level, "amd64", fmt, ##arg)
@@ -482,11 +482,10 @@ extern const char *rrrr_msgs[16];
 extern const char *to_msgs[2];
 extern const char *pp_msgs[4];
 extern const char *ii_msgs[4];
-extern const char *ext_msgs[32];
 extern const char *htlink_msgs[8];
 
 #ifdef CONFIG_EDAC_DEBUG
-#define NUM_DBG_ATTRS 9
+#define NUM_DBG_ATTRS 5
 #else
 #define NUM_DBG_ATTRS 0
 #endif
index 59cf2cf6e11ec3fc9628b5f6b32aa525ae3a80cf..e3562288f4ce80589ab0680f4fc179335da80822 100644 (file)
 #include "amd64_edac.h"
 
-/*
- * accept a hex value and store it into the virtual error register file, field:
- * nbeal and nbeah. Assume virtual error values have already been set for: NBSL,
- * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and
- * CHANNEL
- */
-static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,
-                               size_t count)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       unsigned long long value;
-       int ret = 0;
-
-       ret = strict_strtoull(data, 16, &value);
-       if (ret != -EINVAL) {
-               debugf0("received NBEA= 0x%llx\n", value);
-
-               /* place the value into the virtual error packet */
-               pvt->ctl_error_info.nbeal = (u32) value;
-               value >>= 32;
-               pvt->ctl_error_info.nbeah = (u32) value;
-
-               /* Process the Mapping request */
-               /* TODO: Add race prevention */
-               amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1);
-
-               return count;
-       }
-       return ret;
-}
-
-/* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */
-static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       u64 value;
-
-       value = pvt->ctl_error_info.nbeah;
-       value <<= 32;
-       value |= pvt->ctl_error_info.nbeal;
-
-       return sprintf(data, "%llx\n", value);
-}
-
-/* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */
-static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data,
-                               size_t count)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       unsigned long value;
-       int ret = 0;
-
-       ret = strict_strtoul(data, 16, &value);
-       if (ret != -EINVAL) {
-               debugf0("received NBSL= 0x%lx\n", value);
-
-               pvt->ctl_error_info.nbsl = (u32) value;
-
-               return count;
-       }
-       return ret;
-}
-
-/* display back what the last NBSL value written */
-static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       u32 value;
-
-       value = pvt->ctl_error_info.nbsl;
-
-       return sprintf(data, "%x\n", value);
-}
-
-/* store the NBSH (MCA NB Status High) value user desires */
-static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data,
-                               size_t count)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       unsigned long value;
-       int ret = 0;
-
-       ret = strict_strtoul(data, 16, &value);
-       if (ret != -EINVAL) {
-               debugf0("received NBSH= 0x%lx\n", value);
-
-               pvt->ctl_error_info.nbsh = (u32) value;
-
-               return count;
-       }
-       return ret;
-}
-
-/* display back what the last NBSH value written */
-static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       u32 value;
-
-       value = pvt->ctl_error_info.nbsh;
-
-       return sprintf(data, "%x\n", value);
+#define EDAC_DCT_ATTR_SHOW(reg)                                                \
+static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data)        \
+{                                                                      \
+       struct amd64_pvt *pvt = mci->pvt_info;                          \
+               return sprintf(data, "0x%016llx\n", (u64)pvt->reg);     \
 }
 
-/* accept and store the NBCFG (MCA NB Configuration) value user desires */
-static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci,
-                                       const char *data, size_t count)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       unsigned long value;
-       int ret = 0;
-
-       ret = strict_strtoul(data, 16, &value);
-       if (ret != -EINVAL) {
-               debugf0("received NBCFG= 0x%lx\n", value);
-
-               pvt->ctl_error_info.nbcfg = (u32) value;
-
-               return count;
-       }
-       return ret;
-}
-
-/* various show routines for the controls of a MCI */
-static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg);
-}
-
-
-static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       return sprintf(data, "%x\n", pvt->dhar);
-}
-
-
-static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       return sprintf(data, "%x\n", pvt->dbam0);
-}
-
-
-static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       return sprintf(data, "%llx\n", pvt->top_mem);
-}
-
-
-static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       return sprintf(data, "%llx\n", pvt->top_mem2);
-}
+EDAC_DCT_ATTR_SHOW(dhar);
+EDAC_DCT_ATTR_SHOW(dbam0);
+EDAC_DCT_ATTR_SHOW(top_mem);
+EDAC_DCT_ATTR_SHOW(top_mem2);
 
 static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
 {
@@ -180,38 +29,6 @@ static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
  */
 struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
 
-       {
-               .attr = {
-                       .name = "nbea_ctl",
-                       .mode = (S_IRUGO | S_IWUSR)
-               },
-               .show = amd64_nbea_show,
-               .store = amd64_nbea_store,
-       },
-       {
-               .attr = {
-                       .name = "nbsl_ctl",
-                       .mode = (S_IRUGO | S_IWUSR)
-               },
-               .show = amd64_nbsl_show,
-               .store = amd64_nbsl_store,
-       },
-       {
-               .attr = {
-                       .name = "nbsh_ctl",
-                       .mode = (S_IRUGO | S_IWUSR)
-               },
-               .show = amd64_nbsh_show,
-               .store = amd64_nbsh_store,
-       },
-       {
-               .attr = {
-                       .name = "nbcfg_ctl",
-                       .mode = (S_IRUGO | S_IWUSR)
-               },
-               .show = amd64_nbcfg_show,
-               .store = amd64_nbcfg_store,
-       },
        {
                .attr = {
                        .name = "dhar",
@@ -225,7 +42,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
                        .name = "dbam",
                        .mode = (S_IRUGO)
                },
-               .show = amd64_dbam_show,
+               .show = amd64_dbam0_show,
                .store = NULL,
        },
        {
@@ -233,7 +50,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
                        .name = "topmem",
                        .mode = (S_IRUGO)
                },
-               .show = amd64_topmem_show,
+               .show = amd64_top_mem_show,
                .store = NULL,
        },
        {
@@ -241,7 +58,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
                        .name = "topmem2",
                        .mode = (S_IRUGO)
                },
-               .show = amd64_topmem2_show,
+               .show = amd64_top_mem2_show,
                .store = NULL,
        },
        {
index 070968178a24a80703708dd50ba363301ad71aac..2941dca91aae3f949a04a29b02f32eed5a107bb8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 
 #include "edac_core.h"
 #include "edac_module.h"
@@ -235,7 +236,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
        debugf1("%s()\n", __func__);
 
        /* get the /sys/devices/system/edac reference */
-       edac_class = edac_get_edac_class();
+       edac_class = edac_get_sysfs_class();
        if (edac_class == NULL) {
                debugf1("%s() no edac_class error\n", __func__);
                err = -ENODEV;
@@ -255,7 +256,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
 
        if (!try_module_get(edac_dev->owner)) {
                err = -ENODEV;
-               goto err_out;
+               goto err_mod_get;
        }
 
        /* register */
@@ -282,6 +283,9 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
 err_kobj_reg:
        module_put(edac_dev->owner);
 
+err_mod_get:
+       edac_put_sysfs_class();
+
 err_out:
        return err;
 }
@@ -290,12 +294,11 @@ err_out:
  * edac_device_unregister_sysfs_main_kobj:
  *     the '..../edac/<name>' kobject
  */
-void edac_device_unregister_sysfs_main_kobj(
-                                       struct edac_device_ctl_info *edac_dev)
+void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
 {
        debugf0("%s()\n", __func__);
        debugf4("%s() name of kobject is: %s\n",
-               __func__, kobject_name(&edac_dev->kobj));
+               __func__, kobject_name(&dev->kobj));
 
        /*
         * Unregister the edac device's kobject and
@@ -304,7 +307,8 @@ void edac_device_unregister_sysfs_main_kobj(
         *   a) module_put() this module
         *   b) 'kfree' the memory
         */
-       kobject_put(&edac_dev->kobj);
+       kobject_put(&dev->kobj);
+       edac_put_sysfs_class();
 }
 
 /* edac_dev -> instance information */
index 3630308e7b811a66f398193eae71cc12f5d7383f..6b21e25f7a84cc99ad6ea710b788745992d1170f 100644 (file)
@@ -339,6 +339,9 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
 {
        int status;
 
+       if (mci->op_state != OP_RUNNING_POLL)
+               return;
+
        status = cancel_delayed_work(&mci->work);
        if (status == 0) {
                debugf0("%s() not canceled, flush the queue\n",
index 8aad94d10c0cced51d10746f22b5086068c48d74..a4135860149b5592e6e73e8036796f63e6f045d4 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include <linux/bug.h>
 
 #include "edac_core.h"
@@ -1011,13 +1012,13 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
  */
 int edac_sysfs_setup_mc_kset(void)
 {
-       int err = 0;
+       int err = -EINVAL;
        struct sysdev_class *edac_class;
 
        debugf1("%s()\n", __func__);
 
        /* get the /sys/devices/system/edac class reference */
-       edac_class = edac_get_edac_class();
+       edac_class = edac_get_sysfs_class();
        if (edac_class == NULL) {
                debugf1("%s() no edac_class error=%d\n", __func__, err);
                goto fail_out;
@@ -1028,15 +1029,16 @@ int edac_sysfs_setup_mc_kset(void)
        if (!mc_kset) {
                err = -ENOMEM;
                debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
-               goto fail_out;
+               goto fail_kset;
        }
 
        debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
 
        return 0;
 
+fail_kset:
+       edac_put_sysfs_class();
 
-       /* error unwind stack */
 fail_out:
        return err;
 }
@@ -1049,5 +1051,6 @@ fail_out:
 void edac_sysfs_teardown_mc_kset(void)
 {
        kset_unregister(mc_kset);
+       edac_put_sysfs_class();
 }
 
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
deleted file mode 100644 (file)
index bae9351..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-#include <linux/module.h>
-#include "edac_mce_amd.h"
-
-static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct err_regs *regs);
-
-void amd_report_gart_errors(bool v)
-{
-       report_gart_errors = v;
-}
-EXPORT_SYMBOL_GPL(amd_report_gart_errors);
-
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *))
-{
-       nb_bus_decoder = f;
-}
-EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
-
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *))
-{
-       if (nb_bus_decoder) {
-               WARN_ON(nb_bus_decoder != f);
-
-               nb_bus_decoder = NULL;
-       }
-}
-EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
-
-/*
- * string representation for the different MCA reported error types, see F3x48
- * or MSR0000_0411.
- */
-const char *tt_msgs[] = {        /* transaction type */
-       "instruction",
-       "data",
-       "generic",
-       "reserved"
-};
-EXPORT_SYMBOL_GPL(tt_msgs);
-
-const char *ll_msgs[] = {      /* cache level */
-       "L0",
-       "L1",
-       "L2",
-       "L3/generic"
-};
-EXPORT_SYMBOL_GPL(ll_msgs);
-
-const char *rrrr_msgs[] = {
-       "generic",
-       "generic read",
-       "generic write",
-       "data read",
-       "data write",
-       "inst fetch",
-       "prefetch",
-       "evict",
-       "snoop",
-       "reserved RRRR= 9",
-       "reserved RRRR= 10",
-       "reserved RRRR= 11",
-       "reserved RRRR= 12",
-       "reserved RRRR= 13",
-       "reserved RRRR= 14",
-       "reserved RRRR= 15"
-};
-EXPORT_SYMBOL_GPL(rrrr_msgs);
-
-const char *pp_msgs[] = {      /* participating processor */
-       "local node originated (SRC)",
-       "local node responded to request (RES)",
-       "local node observed as 3rd party (OBS)",
-       "generic"
-};
-EXPORT_SYMBOL_GPL(pp_msgs);
-
-const char *to_msgs[] = {
-       "no timeout",
-       "timed out"
-};
-EXPORT_SYMBOL_GPL(to_msgs);
-
-const char *ii_msgs[] = {      /* memory or i/o */
-       "mem access",
-       "reserved",
-       "i/o access",
-       "generic"
-};
-EXPORT_SYMBOL_GPL(ii_msgs);
-
-/*
- * Map the 4 or 5 (family-specific) bits of Extended Error code to the
- * string table.
- */
-const char *ext_msgs[] = {
-       "K8 ECC error",                                 /* 0_0000b */
-       "CRC error on link",                            /* 0_0001b */
-       "Sync error packets on link",                   /* 0_0010b */
-       "Master Abort during link operation",           /* 0_0011b */
-       "Target Abort during link operation",           /* 0_0100b */
-       "Invalid GART PTE entry during table walk",     /* 0_0101b */
-       "Unsupported atomic RMW command received",      /* 0_0110b */
-       "WDT error: NB transaction timeout",            /* 0_0111b */
-       "ECC/ChipKill ECC error",                       /* 0_1000b */
-       "SVM DEV Error",                                /* 0_1001b */
-       "Link Data error",                              /* 0_1010b */
-       "Link/L3/Probe Filter Protocol error",          /* 0_1011b */
-       "NB Internal Arrays Parity error",              /* 0_1100b */
-       "DRAM Address/Control Parity error",            /* 0_1101b */
-       "Link Transmission error",                      /* 0_1110b */
-       "GART/DEV Table Walk Data error"                /* 0_1111b */
-       "Res 0x100 error",                              /* 1_0000b */
-       "Res 0x101 error",                              /* 1_0001b */
-       "Res 0x102 error",                              /* 1_0010b */
-       "Res 0x103 error",                              /* 1_0011b */
-       "Res 0x104 error",                              /* 1_0100b */
-       "Res 0x105 error",                              /* 1_0101b */
-       "Res 0x106 error",                              /* 1_0110b */
-       "Res 0x107 error",                              /* 1_0111b */
-       "Res 0x108 error",                              /* 1_1000b */
-       "Res 0x109 error",                              /* 1_1001b */
-       "Res 0x10A error",                              /* 1_1010b */
-       "Res 0x10B error",                              /* 1_1011b */
-       "ECC error in L3 Cache Data",                   /* 1_1100b */
-       "L3 Cache Tag error",                           /* 1_1101b */
-       "L3 Cache LRU Parity error",                    /* 1_1110b */
-       "Probe Filter error"                            /* 1_1111b */
-};
-EXPORT_SYMBOL_GPL(ext_msgs);
-
-static void amd_decode_dc_mce(u64 mc0_status)
-{
-       u32 ec  = mc0_status & 0xffff;
-       u32 xec = (mc0_status >> 16) & 0xf;
-
-       pr_emerg("Data Cache Error");
-
-       if (xec == 1 && TLB_ERROR(ec))
-               pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
-       else if (xec == 0) {
-               if (mc0_status & (1ULL << 40))
-                       pr_cont(" during Data Scrub.\n");
-               else if (TLB_ERROR(ec))
-                       pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
-               else if (MEM_ERROR(ec)) {
-                       u8 ll   = ec & 0x3;
-                       u8 tt   = (ec >> 2) & 0x3;
-                       u8 rrrr = (ec >> 4) & 0xf;
-
-                       /* see F10h BKDG (31116), Table 92. */
-                       if (ll == 0x1) {
-                               if (tt != 0x1)
-                                       goto wrong_dc_mce;
-
-                               pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
-
-                       } else if (ll == 0x2 && rrrr == 0x3)
-                               pr_cont(" during L1 linefill from L2.\n");
-                       else
-                               goto wrong_dc_mce;
-               } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
-                       pr_cont(" during system linefill.\n");
-               else
-                       goto wrong_dc_mce;
-       } else
-               goto wrong_dc_mce;
-
-       return;
-
-wrong_dc_mce:
-       pr_warning("Corrupted DC MCE info?\n");
-}
-
-static void amd_decode_ic_mce(u64 mc1_status)
-{
-       u32 ec  = mc1_status & 0xffff;
-       u32 xec = (mc1_status >> 16) & 0xf;
-
-       pr_emerg("Instruction Cache Error");
-
-       if (xec == 1 && TLB_ERROR(ec))
-               pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
-       else if (xec == 0) {
-               if (TLB_ERROR(ec))
-                       pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
-               else if (BUS_ERROR(ec)) {
-                       if (boot_cpu_data.x86 == 0xf &&
-                           (mc1_status & (1ULL << 58)))
-                               pr_cont(" during system linefill.\n");
-                       else
-                               pr_cont(" during attempted NB data read.\n");
-               } else if (MEM_ERROR(ec)) {
-                       u8 ll   = ec & 0x3;
-                       u8 rrrr = (ec >> 4) & 0xf;
-
-                       if (ll == 0x2)
-                               pr_cont(" during a linefill from L2.\n");
-                       else if (ll == 0x1) {
-
-                               switch (rrrr) {
-                               case 0x5:
-                                       pr_cont(": Parity error during "
-                                              "data load.\n");
-                                       break;
-
-                               case 0x7:
-                                       pr_cont(": Copyback Parity/Victim"
-                                               " error.\n");
-                                       break;
-
-                               case 0x8:
-                                       pr_cont(": Tag Snoop error.\n");
-                                       break;
-
-                               default:
-                                       goto wrong_ic_mce;
-                                       break;
-                               }
-                       }
-               } else
-                       goto wrong_ic_mce;
-       } else
-               goto wrong_ic_mce;
-
-       return;
-
-wrong_ic_mce:
-       pr_warning("Corrupted IC MCE info?\n");
-}
-
-static void amd_decode_bu_mce(u64 mc2_status)
-{
-       u32 ec = mc2_status & 0xffff;
-       u32 xec = (mc2_status >> 16) & 0xf;
-
-       pr_emerg("Bus Unit Error");
-
-       if (xec == 0x1)
-               pr_cont(" in the write data buffers.\n");
-       else if (xec == 0x3)
-               pr_cont(" in the victim data buffers.\n");
-       else if (xec == 0x2 && MEM_ERROR(ec))
-               pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
-       else if (xec == 0x0) {
-               if (TLB_ERROR(ec))
-                       pr_cont(": %s error in a Page Descriptor Cache or "
-                               "Guest TLB.\n", TT_MSG(ec));
-               else if (BUS_ERROR(ec))
-                       pr_cont(": %s/ECC error in data read from NB: %s.\n",
-                               RRRR_MSG(ec), PP_MSG(ec));
-               else if (MEM_ERROR(ec)) {
-                       u8 rrrr = (ec >> 4) & 0xf;
-
-                       if (rrrr >= 0x7)
-                               pr_cont(": %s error during data copyback.\n",
-                                       RRRR_MSG(ec));
-                       else if (rrrr <= 0x1)
-                               pr_cont(": %s parity/ECC error during data "
-                                       "access from L2.\n", RRRR_MSG(ec));
-                       else
-                               goto wrong_bu_mce;
-               } else
-                       goto wrong_bu_mce;
-       } else
-               goto wrong_bu_mce;
-
-       return;
-
-wrong_bu_mce:
-       pr_warning("Corrupted BU MCE info?\n");
-}
-
-static void amd_decode_ls_mce(u64 mc3_status)
-{
-       u32 ec  = mc3_status & 0xffff;
-       u32 xec = (mc3_status >> 16) & 0xf;
-
-       pr_emerg("Load Store Error");
-
-       if (xec == 0x0) {
-               u8 rrrr = (ec >> 4) & 0xf;
-
-               if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
-                       goto wrong_ls_mce;
-
-               pr_cont(" during %s.\n", RRRR_MSG(ec));
-       }
-       return;
-
-wrong_ls_mce:
-       pr_warning("Corrupted LS MCE info?\n");
-}
-
-void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
-{
-       u32 ec  = ERROR_CODE(regs->nbsl);
-
-       if (!handle_errors)
-               return;
-
-       /*
-        * GART TLB error reporting is disabled by default. Bail out early.
-        */
-       if (TLB_ERROR(ec) && !report_gart_errors)
-               return;
-
-       pr_emerg("Northbridge Error, node %d", node_id);
-
-       /*
-        * F10h, revD can disable ErrCpu[3:0] so check that first and also the
-        * value encoding has changed so interpret those differently
-        */
-       if ((boot_cpu_data.x86 == 0x10) &&
-           (boot_cpu_data.x86_model > 7)) {
-               if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
-                       pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
-       } else {
-               u8 assoc_cpus = regs->nbsh & 0xf;
-
-               if (assoc_cpus > 0)
-                       pr_cont(", core: %d", fls(assoc_cpus) - 1);
-
-               pr_cont("\n");
-       }
-
-       pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl));
-
-       if (BUS_ERROR(ec) && nb_bus_decoder)
-               nb_bus_decoder(node_id, regs);
-}
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
-
-static void amd_decode_fr_mce(u64 mc5_status)
-{
-       /* we have only one error signature so match all fields at once. */
-       if ((mc5_status & 0xffff) == 0x0f0f)
-               pr_emerg(" FR Error: CPU Watchdog timer expire.\n");
-       else
-               pr_warning("Corrupted FR MCE info?\n");
-}
-
-static inline void amd_decode_err_code(unsigned int ec)
-{
-       if (TLB_ERROR(ec)) {
-               pr_emerg("Transaction: %s, Cache Level %s\n",
-                        TT_MSG(ec), LL_MSG(ec));
-       } else if (MEM_ERROR(ec)) {
-               pr_emerg("Transaction: %s, Type: %s, Cache Level: %s",
-                        RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
-       } else if (BUS_ERROR(ec)) {
-               pr_emerg("Transaction type: %s(%s), %s, Cache Level: %s, "
-                        "Participating Processor: %s\n",
-                         RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
-                         PP_MSG(ec));
-       } else
-               pr_warning("Huh? Unknown MCE error 0x%x\n", ec);
-}
-
-static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
-                          void *data)
-{
-       struct mce *m = (struct mce *)data;
-       struct err_regs regs;
-       int node, ecc;
-
-       pr_emerg("MC%d_STATUS: ", m->bank);
-
-       pr_cont("%sorrected error, report: %s, MiscV: %svalid, "
-                "CPU context corrupt: %s",
-                ((m->status & MCI_STATUS_UC) ? "Unc"  : "C"),
-                ((m->status & MCI_STATUS_EN) ? "yes"  : "no"),
-                ((m->status & MCI_STATUS_MISCV) ? ""  : "in"),
-                ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
-
-       /* do the two bits[14:13] together */
-       ecc = (m->status >> 45) & 0x3;
-       if (ecc)
-               pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
-
-       pr_cont("\n");
-
-       switch (m->bank) {
-       case 0:
-               amd_decode_dc_mce(m->status);
-               break;
-
-       case 1:
-               amd_decode_ic_mce(m->status);
-               break;
-
-       case 2:
-               amd_decode_bu_mce(m->status);
-               break;
-
-       case 3:
-               amd_decode_ls_mce(m->status);
-               break;
-
-       case 4:
-               regs.nbsl  = (u32) m->status;
-               regs.nbsh  = (u32)(m->status >> 32);
-               regs.nbeal = (u32) m->addr;
-               regs.nbeah = (u32)(m->addr >> 32);
-               node       = amd_get_nb_id(m->extcpu);
-
-               amd_decode_nb_mce(node, &regs, 1);
-               break;
-
-       case 5:
-               amd_decode_fr_mce(m->status);
-               break;
-
-       default:
-               break;
-       }
-
-       amd_decode_err_code(m->status & 0xffff);
-
-       return NOTIFY_STOP;
-}
-
-static struct notifier_block amd_mce_dec_nb = {
-       .notifier_call  = amd_decode_mce,
-};
-
-static int __init mce_amd_init(void)
-{
-       /*
-        * We can decode MCEs for Opteron and later CPUs:
-        */
-       if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
-           (boot_cpu_data.x86 >= 0xf))
-               atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-
-       return 0;
-}
-early_initcall(mce_amd_init);
-
-#ifdef MODULE
-static void __exit mce_amd_exit(void)
-{
-       atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-}
-
-MODULE_DESCRIPTION("AMD MCE decoder");
-MODULE_ALIAS("edac-mce-amd");
-MODULE_LICENSE("GPL");
-module_exit(mce_amd_exit);
-#endif
index 7e1374afd967256054be17b687954151576d60ae..be4b075c30984c1b408246a306664c0a6bb626f0 100644 (file)
@@ -26,15 +26,6 @@ EXPORT_SYMBOL_GPL(edac_debug_level);
 /* scope is to module level only */
 struct workqueue_struct *edac_workqueue;
 
-/*
- * sysfs object: /sys/devices/system/edac
- *     need to export to other files in this modules
- */
-static struct sysdev_class edac_class = {
-       .name = "edac",
-};
-static int edac_class_valid;
-
 /*
  * edac_op_state_to_string()
  */
@@ -54,60 +45,6 @@ char *edac_op_state_to_string(int opstate)
        return "UNKNOWN";
 }
 
-/*
- * edac_get_edac_class()
- *
- *     return pointer to the edac class of 'edac'
- */
-struct sysdev_class *edac_get_edac_class(void)
-{
-       struct sysdev_class *classptr = NULL;
-
-       if (edac_class_valid)
-               classptr = &edac_class;
-
-       return classptr;
-}
-
-/*
- * edac_register_sysfs_edac_name()
- *
- *     register the 'edac' into /sys/devices/system
- *
- * return:
- *     0  success
- *     !0 error
- */
-static int edac_register_sysfs_edac_name(void)
-{
-       int err;
-
-       /* create the /sys/devices/system/edac directory */
-       err = sysdev_class_register(&edac_class);
-
-       if (err) {
-               debugf1("%s() error=%d\n", __func__, err);
-               return err;
-       }
-
-       edac_class_valid = 1;
-       return 0;
-}
-
-/*
- * sysdev_class_unregister()
- *
- *     unregister the 'edac' from /sys/devices/system
- */
-static void edac_unregister_sysfs_edac_name(void)
-{
-       /* only if currently registered, then unregister it */
-       if (edac_class_valid)
-               sysdev_class_unregister(&edac_class);
-
-       edac_class_valid = 0;
-}
-
 /*
  * edac_workqueue_setup
  *     initialize the edac work queue for polling operations
@@ -153,22 +90,12 @@ static int __init edac_init(void)
         */
        edac_pci_clear_parity_errors();
 
-       /*
-        * perform the registration of the /sys/devices/system/edac class object
-        */
-       if (edac_register_sysfs_edac_name()) {
-               edac_printk(KERN_ERR, EDAC_MC,
-                       "Error initializing 'edac' kobject\n");
-               err = -ENODEV;
-               goto error;
-       }
-
        /*
         * now set up the mc_kset under the edac class object
         */
        err = edac_sysfs_setup_mc_kset();
        if (err)
-               goto sysfs_setup_fail;
+               goto error;
 
        /* Setup/Initialize the workq for this core */
        err = edac_workqueue_setup();
@@ -183,9 +110,6 @@ static int __init edac_init(void)
 workq_fail:
        edac_sysfs_teardown_mc_kset();
 
-sysfs_setup_fail:
-       edac_unregister_sysfs_edac_name();
-
 error:
        return err;
 }
@@ -201,7 +125,6 @@ static void __exit edac_exit(void)
        /* tear down the various subsystems */
        edac_workqueue_teardown();
        edac_sysfs_teardown_mc_kset();
-       edac_unregister_sysfs_edac_name();
 }
 
 /*
index 233d4798c3aa2ecf18f3875d45a138b8bc2f2fe8..17aabb7b90ecff1ac09a7344ea9fe17a86fb9c8a 100644 (file)
@@ -42,7 +42,6 @@ extern void edac_device_unregister_sysfs_main_kobj(
                                struct edac_device_ctl_info *edac_dev);
 extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
 extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
-extern struct sysdev_class *edac_get_edac_class(void);
 
 /* edac core workqueue: single CPU mode */
 extern struct workqueue_struct *edac_workqueue;
index c39697df9cb41e87c8177c76bab788b85567003e..023b01cb5175c70a15804faba0c356ecacfb1809 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/edac.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
 
@@ -354,7 +354,7 @@ static int edac_pci_main_kobj_setup(void)
        /* First time, so create the main kobject and its
         * controls and atributes
         */
-       edac_class = edac_get_edac_class();
+       edac_class = edac_get_sysfs_class();
        if (edac_class == NULL) {
                debugf1("%s() no edac_class\n", __func__);
                err = -ENODEV;
@@ -368,7 +368,7 @@ static int edac_pci_main_kobj_setup(void)
        if (!try_module_get(THIS_MODULE)) {
                debugf1("%s() try_module_get() failed\n", __func__);
                err = -ENODEV;
-               goto decrement_count_fail;
+               goto mod_get_fail;
        }
 
        edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
@@ -403,6 +403,9 @@ kobject_init_and_add_fail:
 kzalloc_fail:
        module_put(THIS_MODULE);
 
+mod_get_fail:
+       edac_put_sysfs_class();
+
 decrement_count_fail:
        /* if are on this error exit, nothing to tear down */
        atomic_dec(&edac_pci_sysfs_refcount);
@@ -429,6 +432,7 @@ static void edac_pci_main_kobj_teardown(void)
                        __func__);
                kobject_put(edac_pci_top_main_kobj);
        }
+       edac_put_sysfs_class();
 }
 
 /*
index 20b428aa155e144413aeaeed2928b059ebd659d4..aab970760b755b4a5e3f848829bcbd74b3122a37 100644 (file)
@@ -3,10 +3,13 @@
  *
  * Author: Dave Jiang <djiang@mvista.com>
  *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
+ * 2007 (c) MontaVista Software, Inc.
+ * 2010 (c) Advanced Micro Devices Inc.
+ *         Borislav Petkov <borislav.petkov@amd.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
  *
  */
 #include <linux/module.h>
@@ -23,6 +26,8 @@ EXPORT_SYMBOL_GPL(edac_handlers);
 int edac_err_assert = 0;
 EXPORT_SYMBOL_GPL(edac_err_assert);
 
+static atomic_t edac_class_valid = ATOMIC_INIT(0);
+
 /*
  * called to determine if there is an EDAC driver interested in
  * knowing an event (such as NMI) occurred
@@ -44,3 +49,41 @@ void edac_atomic_assert_error(void)
        edac_err_assert++;
 }
 EXPORT_SYMBOL_GPL(edac_atomic_assert_error);
+
+/*
+ * sysfs object: /sys/devices/system/edac
+ *     need to export to other files
+ */
+struct sysdev_class edac_class = {
+       .name = "edac",
+};
+EXPORT_SYMBOL_GPL(edac_class);
+
+/* return pointer to the 'edac' node in sysfs */
+struct sysdev_class *edac_get_sysfs_class(void)
+{
+       int err = 0;
+
+       if (atomic_read(&edac_class_valid))
+               goto out;
+
+       /* create the /sys/devices/system/edac directory */
+       err = sysdev_class_register(&edac_class);
+       if (err) {
+               printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
+               return NULL;
+       }
+
+out:
+       atomic_inc(&edac_class_valid);
+       return &edac_class;
+}
+EXPORT_SYMBOL_GPL(edac_get_sysfs_class);
+
+void edac_put_sysfs_class(void)
+{
+       /* last user unregisters it */
+       if (atomic_dec_and_test(&edac_class_valid))
+               sysdev_class_unregister(&edac_class);
+}
+EXPORT_SYMBOL_GPL(edac_put_sysfs_class);
index e0187d16dd7c53fd240b58d62005e4c17df14bc4..0fd5b85a0f756745bd1074ae673e89d6c81a237a 100644 (file)
@@ -1140,6 +1140,7 @@ static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
        ATTR_COUNTER(0),
        ATTR_COUNTER(1),
        ATTR_COUNTER(2),
+       { .attr = { .name = NULL } }
 };
 
 static struct mcidev_sysfs_group i7core_udimm_counters = {
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
new file mode 100644 (file)
index 0000000..c018109
--- /dev/null
@@ -0,0 +1,680 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "mce_amd.h"
+
+static struct amd_decoder_ops *fam_ops;
+
+static u8 nb_err_cpumask = 0xf;
+
+static bool report_gart_errors;
+static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+
+void amd_report_gart_errors(bool v)
+{
+       report_gart_errors = v;
+}
+EXPORT_SYMBOL_GPL(amd_report_gart_errors);
+
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+       nb_bus_decoder = f;
+}
+EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
+
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+       if (nb_bus_decoder) {
+               WARN_ON(nb_bus_decoder != f);
+
+               nb_bus_decoder = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
+
+/*
+ * string representation for the different MCA reported error types, see F3x48
+ * or MSR0000_0411.
+ */
+
+/* transaction type */
+const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
+EXPORT_SYMBOL_GPL(tt_msgs);
+
+/* cache level */
+const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
+EXPORT_SYMBOL_GPL(ll_msgs);
+
+/* memory transaction type */
+const char *rrrr_msgs[] = {
+       "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
+};
+EXPORT_SYMBOL_GPL(rrrr_msgs);
+
+/* participating processor */
+const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
+EXPORT_SYMBOL_GPL(pp_msgs);
+
+/* request timeout */
+const char *to_msgs[] = { "no timeout",        "timed out" };
+EXPORT_SYMBOL_GPL(to_msgs);
+
+/* memory or i/o */
+const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
+EXPORT_SYMBOL_GPL(ii_msgs);
+
+static const char *f10h_nb_mce_desc[] = {
+       "HT link data error",
+       "Protocol error (link, L3, probe filter, etc.)",
+       "Parity error in NB-internal arrays",
+       "Link Retry due to IO link transmission error",
+       "L3 ECC data cache error",
+       "ECC error in L3 cache tag",
+       "L3 LRU parity bits error",
+       "ECC Error in the Probe Filter directory"
+};
+
+static bool f12h_dc_mce(u16 ec)
+{
+       bool ret = false;
+
+       if (MEM_ERROR(ec)) {
+               u8 ll = ec & 0x3;
+               ret = true;
+
+               if (ll == LL_L2)
+                       pr_cont("during L1 linefill from L2.\n");
+               else if (ll == LL_L1)
+                       pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
+               else
+                       ret = false;
+       }
+       return ret;
+}
+
+static bool f10h_dc_mce(u16 ec)
+{
+       u8 r4  = (ec >> 4) & 0xf;
+       u8 ll  = ec & 0x3;
+
+       if (r4 == R4_GEN && ll == LL_L1) {
+               pr_cont("during data scrub.\n");
+               return true;
+       }
+       return f12h_dc_mce(ec);
+}
+
+static bool k8_dc_mce(u16 ec)
+{
+       if (BUS_ERROR(ec)) {
+               pr_cont("during system linefill.\n");
+               return true;
+       }
+
+       return f10h_dc_mce(ec);
+}
+
+static bool f14h_dc_mce(u16 ec)
+{
+       u8 r4    = (ec >> 4) & 0xf;
+       u8 ll    = ec & 0x3;
+       u8 tt    = (ec >> 2) & 0x3;
+       u8 ii    = tt;
+       bool ret = true;
+
+       if (MEM_ERROR(ec)) {
+
+               if (tt != TT_DATA || ll != LL_L1)
+                       return false;
+
+               switch (r4) {
+               case R4_DRD:
+               case R4_DWR:
+                       pr_cont("Data/Tag parity error due to %s.\n",
+                               (r4 == R4_DRD ? "load/hw prf" : "store"));
+                       break;
+               case R4_EVICT:
+                       pr_cont("Copyback parity error on a tag miss.\n");
+                       break;
+               case R4_SNOOP:
+                       pr_cont("Tag parity error during snoop.\n");
+                       break;
+               default:
+                       ret = false;
+               }
+       } else if (BUS_ERROR(ec)) {
+
+               if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
+                       return false;
+
+               pr_cont("System read data error on a ");
+
+               switch (r4) {
+               case R4_RD:
+                       pr_cont("TLB reload.\n");
+                       break;
+               case R4_DWR:
+                       pr_cont("store.\n");
+                       break;
+               case R4_DRD:
+                       pr_cont("load.\n");
+                       break;
+               default:
+                       ret = false;
+               }
+       } else {
+               ret = false;
+       }
+
+       return ret;
+}
+
+static void amd_decode_dc_mce(struct mce *m)
+{
+       u16 ec = m->status & 0xffff;
+       u8 xec = (m->status >> 16) & 0xf;
+
+       pr_emerg(HW_ERR "Data Cache Error: ");
+
+       /* TLB error signatures are the same across families */
+       if (TLB_ERROR(ec)) {
+               u8 tt = (ec >> 2) & 0x3;
+
+               if (tt == TT_DATA) {
+                       pr_cont("%s TLB %s.\n", LL_MSG(ec),
+                               (xec ? "multimatch" : "parity error"));
+                       return;
+               }
+               else
+                       goto wrong_dc_mce;
+       }
+
+       if (!fam_ops->dc_mce(ec))
+               goto wrong_dc_mce;
+
+       return;
+
+wrong_dc_mce:
+       pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+}
+
+static bool k8_ic_mce(u16 ec)
+{
+       u8 ll    = ec & 0x3;
+       u8 r4    = (ec >> 4) & 0xf;
+       bool ret = true;
+
+       if (!MEM_ERROR(ec))
+               return false;
+
+       if (ll == 0x2)
+               pr_cont("during a linefill from L2.\n");
+       else if (ll == 0x1) {
+               switch (r4) {
+               case R4_IRD:
+                       pr_cont("Parity error during data load.\n");
+                       break;
+
+               case R4_EVICT:
+                       pr_cont("Copyback Parity/Victim error.\n");
+                       break;
+
+               case R4_SNOOP:
+                       pr_cont("Tag Snoop error.\n");
+                       break;
+
+               default:
+                       ret = false;
+                       break;
+               }
+       } else
+               ret = false;
+
+       return ret;
+}
+
+static bool f14h_ic_mce(u16 ec)
+{
+       u8 ll    = ec & 0x3;
+       u8 tt    = (ec >> 2) & 0x3;
+       u8 r4  = (ec >> 4) & 0xf;
+       bool ret = true;
+
+       if (MEM_ERROR(ec)) {
+               if (tt != 0 || ll != 1)
+                       ret = false;
+
+               if (r4 == R4_IRD)
+                       pr_cont("Data/tag array parity error for a tag hit.\n");
+               else if (r4 == R4_SNOOP)
+                       pr_cont("Tag error during snoop/victimization.\n");
+               else
+                       ret = false;
+       }
+       return ret;
+}
+
+static void amd_decode_ic_mce(struct mce *m)
+{
+       u16 ec = m->status & 0xffff;
+       u8 xec = (m->status >> 16) & 0xf;
+
+       pr_emerg(HW_ERR "Instruction Cache Error: ");
+
+       if (TLB_ERROR(ec))
+               pr_cont("%s TLB %s.\n", LL_MSG(ec),
+                       (xec ? "multimatch" : "parity error"));
+       else if (BUS_ERROR(ec)) {
+               bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
+
+               pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
+       } else if (fam_ops->ic_mce(ec))
+               ;
+       else
+               pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+}
+
+static void amd_decode_bu_mce(struct mce *m)
+{
+       u32 ec = m->status & 0xffff;
+       u32 xec = (m->status >> 16) & 0xf;
+
+       pr_emerg(HW_ERR "Bus Unit Error");
+
+       if (xec == 0x1)
+               pr_cont(" in the write data buffers.\n");
+       else if (xec == 0x3)
+               pr_cont(" in the victim data buffers.\n");
+       else if (xec == 0x2 && MEM_ERROR(ec))
+               pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
+       else if (xec == 0x0) {
+               if (TLB_ERROR(ec))
+                       pr_cont(": %s error in a Page Descriptor Cache or "
+                               "Guest TLB.\n", TT_MSG(ec));
+               else if (BUS_ERROR(ec))
+                       pr_cont(": %s/ECC error in data read from NB: %s.\n",
+                               RRRR_MSG(ec), PP_MSG(ec));
+               else if (MEM_ERROR(ec)) {
+                       u8 rrrr = (ec >> 4) & 0xf;
+
+                       if (rrrr >= 0x7)
+                               pr_cont(": %s error during data copyback.\n",
+                                       RRRR_MSG(ec));
+                       else if (rrrr <= 0x1)
+                               pr_cont(": %s parity/ECC error during data "
+                                       "access from L2.\n", RRRR_MSG(ec));
+                       else
+                               goto wrong_bu_mce;
+               } else
+                       goto wrong_bu_mce;
+       } else
+               goto wrong_bu_mce;
+
+       return;
+
+wrong_bu_mce:
+       pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+}
+
+static void amd_decode_ls_mce(struct mce *m)
+{
+       u16 ec = m->status & 0xffff;
+       u8 xec = (m->status >> 16) & 0xf;
+
+       if (boot_cpu_data.x86 == 0x14) {
+               pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+                        " please report on LKML.\n");
+               return;
+       }
+
+       pr_emerg(HW_ERR "Load Store Error");
+
+       if (xec == 0x0) {
+               u8 r4 = (ec >> 4) & 0xf;
+
+               if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
+                       goto wrong_ls_mce;
+
+               pr_cont(" during %s.\n", RRRR_MSG(ec));
+       } else
+               goto wrong_ls_mce;
+
+       return;
+
+wrong_ls_mce:
+       pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+}
+
+static bool k8_nb_mce(u16 ec, u8 xec)
+{
+       bool ret = true;
+
+       switch (xec) {
+       case 0x1:
+               pr_cont("CRC error detected on HT link.\n");
+               break;
+
+       case 0x5:
+               pr_cont("Invalid GART PTE entry during GART table walk.\n");
+               break;
+
+       case 0x6:
+               pr_cont("Unsupported atomic RMW received from an IO link.\n");
+               break;
+
+       case 0x0:
+       case 0x8:
+               if (boot_cpu_data.x86 == 0x11)
+                       return false;
+
+               pr_cont("DRAM ECC error detected on the NB.\n");
+               break;
+
+       case 0xd:
+               pr_cont("Parity error on the DRAM addr/ctl signals.\n");
+               break;
+
+       default:
+               ret = false;
+               break;
+       }
+
+       return ret;
+}
+
+static bool f10h_nb_mce(u16 ec, u8 xec)
+{
+       bool ret = true;
+       u8 offset = 0;
+
+       if (k8_nb_mce(ec, xec))
+               return true;
+
+       switch(xec) {
+       case 0xa ... 0xc:
+               offset = 10;
+               break;
+
+       case 0xe:
+               offset = 11;
+               break;
+
+       case 0xf:
+               if (TLB_ERROR(ec))
+                       pr_cont("GART Table Walk data error.\n");
+               else if (BUS_ERROR(ec))
+                       pr_cont("DMA Exclusion Vector Table Walk error.\n");
+               else
+                       ret = false;
+
+               goto out;
+               break;
+
+       case 0x1c ... 0x1f:
+               offset = 24;
+               break;
+
+       default:
+               ret = false;
+
+               goto out;
+               break;
+       }
+
+       pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
+
+out:
+       return ret;
+}
+
+static bool nb_noop_mce(u16 ec, u8 xec)
+{
+       return false;
+}
+
+void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+{
+       u8 xec   = (m->status >> 16) & 0x1f;
+       u16 ec   = m->status & 0xffff;
+       u32 nbsh = (u32)(m->status >> 32);
+
+       pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
+
+       /*
+        * F10h, revD can disable ErrCpu[3:0] so check that first and also the
+        * value encoding has changed so interpret those differently
+        */
+       if ((boot_cpu_data.x86 == 0x10) &&
+           (boot_cpu_data.x86_model > 7)) {
+               if (nbsh & K8_NBSH_ERR_CPU_VAL)
+                       pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
+       } else {
+               u8 assoc_cpus = nbsh & nb_err_cpumask;
+
+               if (assoc_cpus > 0)
+                       pr_cont(", core: %d", fls(assoc_cpus) - 1);
+       }
+
+       switch (xec) {
+       case 0x2:
+               pr_cont("Sync error (sync packets on HT link detected).\n");
+               return;
+
+       case 0x3:
+               pr_cont("HT Master abort.\n");
+               return;
+
+       case 0x4:
+               pr_cont("HT Target abort.\n");
+               return;
+
+       case 0x7:
+               pr_cont("NB Watchdog timeout.\n");
+               return;
+
+       case 0x9:
+               pr_cont("SVM DMA Exclusion Vector error.\n");
+               return;
+
+       default:
+               break;
+       }
+
+       if (!fam_ops->nb_mce(ec, xec))
+               goto wrong_nb_mce;
+
+       if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+               if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
+                       nb_bus_decoder(node_id, m, nbcfg);
+
+       return;
+
+wrong_nb_mce:
+       pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+}
+EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
+
+static void amd_decode_fr_mce(struct mce *m)
+{
+       if (boot_cpu_data.x86 == 0xf ||
+           boot_cpu_data.x86 == 0x11)
+               goto wrong_fr_mce;
+
+       /* we have only one error signature so match all fields at once. */
+       if ((m->status & 0xffff) == 0x0f0f) {
+               pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
+               return;
+       }
+
+wrong_fr_mce:
+       pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+}
+
+static inline void amd_decode_err_code(u16 ec)
+{
+       if (TLB_ERROR(ec)) {
+               pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
+                        TT_MSG(ec), LL_MSG(ec));
+       } else if (MEM_ERROR(ec)) {
+               pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
+                        RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
+       } else if (BUS_ERROR(ec)) {
+               pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
+                        "Participating Processor: %s\n",
+                         RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
+                         PP_MSG(ec));
+       } else
+               pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
+}
+
+/*
+ * Filter out unwanted MCE signatures here.
+ */
+static bool amd_filter_mce(struct mce *m)
+{
+       u8 xec = (m->status >> 16) & 0x1f;
+
+       /*
+        * NB GART TLB error reporting is disabled by default.
+        */
+       if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
+               return true;
+
+       return false;
+}
+
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
+{
+       struct mce *m = (struct mce *)data;
+       int node, ecc;
+
+       if (amd_filter_mce(m))
+               return NOTIFY_STOP;
+
+       pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
+
+       pr_cont("%sorrected error, other errors lost: %s, "
+                "CPU context corrupt: %s",
+                ((m->status & MCI_STATUS_UC) ? "Unc"  : "C"),
+                ((m->status & MCI_STATUS_OVER) ? "yes"  : "no"),
+                ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
+
+       /* do the two bits[14:13] together */
+       ecc = (m->status >> 45) & 0x3;
+       if (ecc)
+               pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
+
+       pr_cont("\n");
+
+       switch (m->bank) {
+       case 0:
+               amd_decode_dc_mce(m);
+               break;
+
+       case 1:
+               amd_decode_ic_mce(m);
+               break;
+
+       case 2:
+               amd_decode_bu_mce(m);
+               break;
+
+       case 3:
+               amd_decode_ls_mce(m);
+               break;
+
+       case 4:
+               node = amd_get_nb_id(m->extcpu);
+               amd_decode_nb_mce(node, m, 0);
+               break;
+
+       case 5:
+               amd_decode_fr_mce(m);
+               break;
+
+       default:
+               break;
+       }
+
+       amd_decode_err_code(m->status & 0xffff);
+
+       return NOTIFY_STOP;
+}
+EXPORT_SYMBOL_GPL(amd_decode_mce);
+
+static struct notifier_block amd_mce_dec_nb = {
+       .notifier_call  = amd_decode_mce,
+};
+
+static int __init mce_amd_init(void)
+{
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+               return 0;
+
+       if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
+           (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
+               return 0;
+
+       fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
+       if (!fam_ops)
+               return -ENOMEM;
+
+       switch (boot_cpu_data.x86) {
+       case 0xf:
+               fam_ops->dc_mce = k8_dc_mce;
+               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->nb_mce = k8_nb_mce;
+               break;
+
+       case 0x10:
+               fam_ops->dc_mce = f10h_dc_mce;
+               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->nb_mce = f10h_nb_mce;
+               break;
+
+       case 0x11:
+               fam_ops->dc_mce = k8_dc_mce;
+               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->nb_mce = f10h_nb_mce;
+               break;
+
+       case 0x12:
+               fam_ops->dc_mce = f12h_dc_mce;
+               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->nb_mce = nb_noop_mce;
+               break;
+
+       case 0x14:
+               nb_err_cpumask  = 0x3;
+               fam_ops->dc_mce = f14h_dc_mce;
+               fam_ops->ic_mce = f14h_ic_mce;
+               fam_ops->nb_mce = nb_noop_mce;
+               break;
+
+       default:
+               printk(KERN_WARNING "Huh? What family is that: %d?!\n",
+                                   boot_cpu_data.x86);
+               kfree(fam_ops);
+               return -EINVAL;
+       }
+
+       pr_info("MCE: In-kernel MCE decoding enabled.\n");
+
+       atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+
+       return 0;
+}
+early_initcall(mce_amd_init);
+
+#ifdef MODULE
+static void __exit mce_amd_exit(void)
+{
+       atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+       kfree(fam_ops);
+}
+
+MODULE_DESCRIPTION("AMD MCE decoder");
+MODULE_ALIAS("edac-mce-amd");
+MODULE_LICENSE("GPL");
+module_exit(mce_amd_exit);
+#endif
similarity index 65%
rename from drivers/edac/edac_mce_amd.h
rename to drivers/edac/mce_amd.h
index df23ee065f7981fe9f4084b461efa1de0f5d6836..35f6e0e3b297de16ad5e7c0ccac18dae0c388590 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef _EDAC_MCE_AMD_H
 #define _EDAC_MCE_AMD_H
 
+#include <linux/notifier.h>
+
 #include <asm/mce.h>
 
+#define BIT_64(n)                      (U64_C(1) << (n))
+
 #define ERROR_CODE(x)                  ((x) & 0xffff)
 #define EXT_ERROR_CODE(x)              (((x) >> 16) & 0x1f)
-#define EXT_ERR_MSG(x)                 ext_msgs[EXT_ERROR_CODE(x)]
 
 #define LOW_SYNDROME(x)                        (((x) >> 15) & 0xff)
 #define HIGH_SYNDROME(x)               (((x) >> 24) & 0xff)
 #define II_MSG(x)                      ii_msgs[II(x)]
 #define LL(x)                          (((x) >> 0) & 0x3)
 #define LL_MSG(x)                      ll_msgs[LL(x)]
-#define RRRR(x)                                (((x) >> 4) & 0xf)
-#define RRRR_MSG(x)                    rrrr_msgs[RRRR(x)]
 #define TO(x)                          (((x) >> 8) & 0x1)
 #define TO_MSG(x)                      to_msgs[TO(x)]
 #define PP(x)                          (((x) >> 9) & 0x3)
 #define PP_MSG(x)                      pp_msgs[PP(x)]
 
+#define RRRR(x)                                (((x) >> 4) & 0xf)
+#define RRRR_MSG(x)                    ((RRRR(x) < 9) ?  rrrr_msgs[RRRR(x)] : "Wrong R4!")
+
 #define K8_NBSH                                0x4C
 
 #define K8_NBSH_VALID_BIT              BIT(31)
 #define K8_NBSH_UECC                   BIT(13)
 #define K8_NBSH_ERR_SCRUBER            BIT(8)
 
+enum tt_ids {
+       TT_INSTR = 0,
+       TT_DATA,
+       TT_GEN,
+       TT_RESV,
+};
+
+enum ll_ids {
+       LL_RESV = 0,
+       LL_L1,
+       LL_L2,
+       LL_LG,
+};
+
+enum ii_ids {
+       II_MEM = 0,
+       II_RESV,
+       II_IO,
+       II_GEN,
+};
+
+enum rrrr_ids {
+       R4_GEN  = 0,
+       R4_RD,
+       R4_WR,
+       R4_DRD,
+       R4_DWR,
+       R4_IRD,
+       R4_PREF,
+       R4_EVICT,
+       R4_SNOOP,
+};
+
 extern const char *tt_msgs[];
 extern const char *ll_msgs[];
 extern const char *rrrr_msgs[];
 extern const char *pp_msgs[];
 extern const char *to_msgs[];
 extern const char *ii_msgs[];
-extern const char *ext_msgs[];
 
 /*
  * relevant NB regs
@@ -60,10 +96,19 @@ struct err_regs {
        u32 nbeal;
 };
 
+/*
+ * per-family decoder ops
+ */
+struct amd_decoder_ops {
+       bool (*dc_mce)(u16);
+       bool (*ic_mce)(u16);
+       bool (*nb_mce)(u16, u8);
+};
 
 void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_decode_nb_mce(int, struct err_regs *, int);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_decode_nb_mce(int, struct mce *, u32);
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
 
 #endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
new file mode 100644 (file)
index 0000000..8d0688f
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * A simple MCE injection facility for testing the MCE decoding code. This
+ * driver should be built as module so that it can be loaded on production
+ * kernels for testing purposes.
+ *
+ * This file may be distributed under the terms of the GNU General Public
+ * License version 2.
+ *
+ * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ *                     Advanced Micro Devices Inc.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
+#include <linux/edac.h>
+#include <asm/mce.h>
+
+#include "mce_amd.h"
+
+struct edac_mce_attr {
+       struct attribute attr;
+       ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
+       ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
+                        const char *buf, size_t count);
+};
+
+#define EDAC_MCE_ATTR(_name, _mode, _show, _store)                     \
+static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+static struct kobject *mce_kobj;
+
+/*
+ * Collect all the MCi_XXX settings
+ */
+static struct mce i_mce;
+
+#define MCE_INJECT_STORE(reg)                                          \
+static ssize_t edac_inject_##reg##_store(struct kobject *kobj,         \
+                                        struct edac_mce_attr *attr,    \
+                                        const char *data, size_t count)\
+{                                                                      \
+       int ret = 0;                                                    \
+       unsigned long value;                                            \
+                                                                       \
+       ret = strict_strtoul(data, 16, &value);                         \
+       if (ret < 0)                                                    \
+               printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \
+                                                                       \
+       i_mce.reg = value;                                              \
+                                                                       \
+       return count;                                                   \
+}
+
+MCE_INJECT_STORE(status);
+MCE_INJECT_STORE(misc);
+MCE_INJECT_STORE(addr);
+
+#define MCE_INJECT_SHOW(reg)                                           \
+static ssize_t edac_inject_##reg##_show(struct kobject *kobj,          \
+                                       struct edac_mce_attr *attr,     \
+                                       char *buf)                      \
+{                                                                      \
+       return sprintf(buf, "0x%016llx\n", i_mce.reg);                  \
+}
+
+MCE_INJECT_SHOW(status);
+MCE_INJECT_SHOW(misc);
+MCE_INJECT_SHOW(addr);
+
+EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
+EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
+EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
+
+/*
+ * This denotes into which bank we're injecting and triggers
+ * the injection, at the same time.
+ */
+static ssize_t edac_inject_bank_store(struct kobject *kobj,
+                                     struct edac_mce_attr *attr,
+                                     const char *data, size_t count)
+{
+       int ret = 0;
+       unsigned long value;
+
+       ret = strict_strtoul(data, 10, &value);
+       if (ret < 0) {
+               printk(KERN_ERR "Invalid bank value!\n");
+               return -EINVAL;
+       }
+
+       if (value > 5) {
+               printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+               return -EINVAL;
+       }
+
+       i_mce.bank = value;
+
+       amd_decode_mce(NULL, 0, &i_mce);
+
+       return count;
+}
+
+static ssize_t edac_inject_bank_show(struct kobject *kobj,
+                                    struct edac_mce_attr *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", i_mce.bank);
+}
+
+EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+
+static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
+                                              &mce_attr_addr, &mce_attr_bank
+};
+
+static int __init edac_init_mce_inject(void)
+{
+       struct sysdev_class *edac_class = NULL;
+       int i, err = 0;
+
+       edac_class = edac_get_sysfs_class();
+       if (!edac_class)
+               return -EINVAL;
+
+       mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj);
+       if (!mce_kobj) {
+               printk(KERN_ERR "Error creating a mce kset.\n");
+               err = -ENOMEM;
+               goto err_mce_kobj;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
+               err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
+               if (err) {
+                       printk(KERN_ERR "Error creating %s in sysfs.\n",
+                                       sysfs_attrs[i]->attr.name);
+                       goto err_sysfs_create;
+               }
+       }
+       return 0;
+
+err_sysfs_create:
+       while (i-- >= 0)
+               sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+       kobject_del(mce_kobj);
+
+err_mce_kobj:
+       edac_put_sysfs_class();
+
+       return err;
+}
+
+static void __exit edac_exit_mce_inject(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
+               sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+       kobject_del(mce_kobj);
+
+       edac_put_sysfs_class();
+}
+
+module_init(edac_init_mce_inject);
+module_exit(edac_exit_mce_inject);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("AMD Inc.");
+MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
index ca7ca56661e018c5ecfd9d4c56321f4dea901f93..b42a0bde8494bf0dec8cc2e20d34dfc3e7c046b5 100644 (file)
@@ -81,6 +81,10 @@ static int close_transaction(struct fw_transaction *transaction,
        spin_lock_irqsave(&card->lock, flags);
        list_for_each_entry(t, &card->transaction_list, link) {
                if (t == transaction) {
+                       if (!del_timer(&t->split_timeout_timer)) {
+                               spin_unlock_irqrestore(&card->lock, flags);
+                               goto timed_out;
+                       }
                        list_del_init(&t->link);
                        card->tlabel_mask &= ~(1ULL << t->tlabel);
                        break;
@@ -89,11 +93,11 @@ static int close_transaction(struct fw_transaction *transaction,
        spin_unlock_irqrestore(&card->lock, flags);
 
        if (&t->link != &card->transaction_list) {
-               del_timer_sync(&t->split_timeout_timer);
                t->callback(card, rcode, NULL, 0, t->callback_data);
                return 0;
        }
 
+ timed_out:
        return -ENOENT;
 }
 
@@ -921,6 +925,10 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
        spin_lock_irqsave(&card->lock, flags);
        list_for_each_entry(t, &card->transaction_list, link) {
                if (t->node_id == source && t->tlabel == tlabel) {
+                       if (!del_timer(&t->split_timeout_timer)) {
+                               spin_unlock_irqrestore(&card->lock, flags);
+                               goto timed_out;
+                       }
                        list_del_init(&t->link);
                        card->tlabel_mask &= ~(1ULL << t->tlabel);
                        break;
@@ -929,6 +937,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
        spin_unlock_irqrestore(&card->lock, flags);
 
        if (&t->link == &card->transaction_list) {
+ timed_out:
                fw_notify("Unsolicited response (source %x, tlabel %x)\n",
                          source, tlabel);
                return;
@@ -963,8 +972,6 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
                break;
        }
 
-       del_timer_sync(&t->split_timeout_timer);
-
        /*
         * The response handler may be executed while the request handler
         * is still pending.  Cancel the request handler.
index da17d409a244b0af97249341855dfe301b506ab3..33f8421c71cc05001c57bbf275b61679fded72eb 100644 (file)
@@ -579,7 +579,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
                if (!peer) {
                        fw_notify("No peer for ARP packet from %016llx\n",
                                  (unsigned long long)peer_guid);
-                       goto failed_proto;
+                       goto no_peer;
                }
 
                /*
@@ -656,7 +656,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 
        return 0;
 
failed_proto:
no_peer:
        net->stats.rx_errors++;
        net->stats.rx_dropped++;
 
@@ -664,7 +664,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
        if (netif_queue_stopped(net))
                netif_wake_queue(net);
 
-       return 0;
+       return -ENOENT;
 }
 
 static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
@@ -701,7 +701,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                        fw_error("out of memory\n");
                        net->stats.rx_dropped++;
 
-                       return -1;
+                       return -ENOMEM;
                }
                skb_reserve(skb, (net->hard_header_len + 15) & ~15);
                memcpy(skb_put(skb, len), buf, len);
@@ -726,8 +726,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
        spin_lock_irqsave(&dev->lock, flags);
 
        peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
-       if (!peer)
-               goto bad_proto;
+       if (!peer) {
+               retval = -ENOENT;
+               goto fail;
+       }
 
        pd = fwnet_pd_find(peer, datagram_label);
        if (pd == NULL) {
@@ -741,7 +743,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                                  dg_size, buf, fg_off, len);
                if (pd == NULL) {
                        retval = -ENOMEM;
-                       goto bad_proto;
+                       goto fail;
                }
                peer->pdg_size++;
        } else {
@@ -755,9 +757,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                        pd = fwnet_pd_new(net, peer, datagram_label,
                                          dg_size, buf, fg_off, len);
                        if (pd == NULL) {
-                               retval = -ENOMEM;
                                peer->pdg_size--;
-                               goto bad_proto;
+                               retval = -ENOMEM;
+                               goto fail;
                        }
                } else {
                        if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
@@ -768,7 +770,8 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                                 */
                                fwnet_pd_delete(pd);
                                peer->pdg_size--;
-                               goto bad_proto;
+                               retval = -ENOMEM;
+                               goto fail;
                        }
                }
        } /* new datagram or add to existing one */
@@ -794,14 +797,13 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
        spin_unlock_irqrestore(&dev->lock, flags);
 
        return 0;
-
- bad_proto:
+ fail:
        spin_unlock_irqrestore(&dev->lock, flags);
 
        if (netif_queue_stopped(net))
                netif_wake_queue(net);
 
-       return 0;
+       return retval;
 }
 
 static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
index 8528b10763eddcd2253a5dca8e1222969bb76c1b..bf184fb59a5e4329ca11a391cefdc011ea050dfd 100644 (file)
@@ -405,6 +405,7 @@ static const struct file_operations nosy_ops = {
        .poll =                 nosy_poll,
        .open =                 nosy_open,
        .release =              nosy_release,
+       .llseek =               noop_llseek,
 };
 
 #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
index 7f03540cabe8b3932021545a6db05aebb3f729b1..9dcb17d51aee737bcbb4ac478807c04311588d6c 100644 (file)
@@ -263,6 +263,7 @@ static const struct {
        {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
        {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
        {PCI_VENDOR_ID_VIA,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
+       {PCI_VENDOR_ID_RICOH,   PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
        {PCI_VENDOR_ID_APPLE,   PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
 };
 
@@ -694,7 +695,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
        log_ar_at_event('R', p.speed, p.header, evt);
 
        /*
-        * The OHCI bus reset handler synthesizes a phy packet with
+        * Several controllers, notably from NEC and VIA, forget to
+        * write ack_complete status at PHY packet reception.
+        */
+       if (evt == OHCI1394_evt_no_status &&
+           (p.header[0] & 0xff) == (OHCI1394_phy_tcode << 4))
+               p.ack = ACK_COMPLETE;
+
+       /*
+        * The OHCI bus reset handler synthesizes a PHY packet with
         * the new generation number when a bus reset happens (see
         * section 8.4.2.3).  This helps us determine when a request
         * was received and make sure we send the response in the same
@@ -2831,7 +2840,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
                               const struct pci_device_id *ent)
 {
        struct fw_ohci *ohci;
-       u32 bus_options, max_receive, link_speed, version, link_enh;
+       u32 bus_options, max_receive, link_speed, version;
        u64 guid;
        int i, err, n_ir, n_it;
        size_t size;
@@ -2885,23 +2894,6 @@ static int __devinit pci_probe(struct pci_dev *dev,
        if (param_quirks)
                ohci->quirks = param_quirks;
 
-       /* TI OHCI-Lynx and compatible: set recommended configuration bits. */
-       if (dev->vendor == PCI_VENDOR_ID_TI) {
-               pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh);
-
-               /* adjust latency of ATx FIFO: use 1.7 KB threshold */
-               link_enh &= ~TI_LinkEnh_atx_thresh_mask;
-               link_enh |= TI_LinkEnh_atx_thresh_1_7K;
-
-               /* use priority arbitration for asynchronous responses */
-               link_enh |= TI_LinkEnh_enab_unfair;
-
-               /* required for aPhyEnhanceEnable to work */
-               link_enh |= TI_LinkEnh_enab_accel;
-
-               pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh);
-       }
-
        ar_context_init(&ohci->ar_request_ctx, ohci,
                        OHCI1394_AsReqRcvContextControlSet);
 
index 0e6c5a466908d58156f4fe7dd978c469efb94aad..ef5e7336da68ddf6af413ecd0cc616a812ae1490 100644 (file)
 
 #define OHCI1394_phy_tcode             0xe
 
-/* TI extensions */
-
-#define PCI_CFG_TI_LinkEnh             0xf4
-#define  TI_LinkEnh_enab_accel         0x00000002
-#define  TI_LinkEnh_enab_unfair                0x00000080
-#define  TI_LinkEnh_atx_thresh_mask    0x00003000
-#define  TI_LinkEnh_atx_thresh_1_7K    0x00001000
-
 #endif /* _FIREWIRE_OHCI_H */
index 9f76171717e50302dc4e895a4988cb15f7e7023f..bfae4b309791103e48b2bb704300d1cd84da9750 100644 (file)
@@ -450,7 +450,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
 
        if (&orb->link != &lu->orb_list) {
                orb->callback(orb, &status);
-               kref_put(&orb->kref, free_orb);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        } else {
                fw_error("status write for unknown orb\n");
        }
@@ -472,20 +472,28 @@ static void complete_transaction(struct fw_card *card, int rcode,
         * So this callback only sets the rcode if it hasn't already
         * been set and only does the cleanup if the transaction
         * failed and we didn't already get a status write.
+        *
+        * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
+        * OXUF936QSE firmwares occasionally respond after Split_Timeout and
+        * complete the ORB just fine.  Note, we also get RCODE_CANCELLED
+        * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
         */
        spin_lock_irqsave(&card->lock, flags);
 
        if (orb->rcode == -1)
                orb->rcode = rcode;
-       if (orb->rcode != RCODE_COMPLETE) {
+
+       if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
                list_del(&orb->link);
                spin_unlock_irqrestore(&card->lock, flags);
+
                orb->callback(orb, NULL);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        } else {
                spin_unlock_irqrestore(&card->lock, flags);
        }
 
-       kref_put(&orb->kref, free_orb);
+       kref_put(&orb->kref, free_orb); /* transaction callback reference */
 }
 
 static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
@@ -501,9 +509,8 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
        list_add_tail(&orb->link, &lu->orb_list);
        spin_unlock_irqrestore(&device->card->lock, flags);
 
-       /* Take a ref for the orb list and for the transaction callback. */
-       kref_get(&orb->kref);
-       kref_get(&orb->kref);
+       kref_get(&orb->kref); /* transaction callback reference */
+       kref_get(&orb->kref); /* orb callback reference */
 
        fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
                        node_id, generation, device->max_speed, offset,
@@ -525,11 +532,11 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 
        list_for_each_entry_safe(orb, next, &list, link) {
                retval = 0;
-               if (fw_cancel_transaction(device->card, &orb->t) == 0)
-                       continue;
+               fw_cancel_transaction(device->card, &orb->t);
 
                orb->rcode = RCODE_CANCELLED;
                orb->callback(orb, NULL);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        }
 
        return retval;
index 280c9b5ad9e375afafd3116cc75d8b6fc3eb12fd..88a3ae6cd02306784184fd3f31399da88840defd 100644 (file)
@@ -125,7 +125,7 @@ config ISCSI_IBFT_FIND
 config ISCSI_IBFT
        tristate "iSCSI Boot Firmware Table Attributes module"
        select ISCSI_BOOT_SYSFS
-       depends on ISCSI_IBFT_FIND && SCSI
+       depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL
        default n
        help
          This option enables support for detection and exposing of iSCSI
index b42f42ca70c3c9454bb00ff7cf2e8505f74e482d..823559ab0e243610ca8e5ff3b5983aca3d53b7bb 100644 (file)
@@ -459,17 +459,33 @@ static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
        return err;
 }
 
-static int sx150x_init_hw(struct sx150x_chip *chip,
-                       struct sx150x_platform_data *pdata)
+static int sx150x_reset(struct sx150x_chip *chip)
 {
-       int err = 0;
+       int err;
 
-       err = i2c_smbus_write_word_data(chip->client,
+       err = i2c_smbus_write_byte_data(chip->client,
                                        chip->dev_cfg->reg_reset,
-                                       0x3412);
+                                       0x12);
        if (err < 0)
                return err;
 
+       err = i2c_smbus_write_byte_data(chip->client,
+                                       chip->dev_cfg->reg_reset,
+                                       0x34);
+       return err;
+}
+
+static int sx150x_init_hw(struct sx150x_chip *chip,
+                       struct sx150x_platform_data *pdata)
+{
+       int err = 0;
+
+       if (pdata->reset_during_probe) {
+               err = sx150x_reset(chip);
+               if (err < 0)
+                       return err;
+       }
+
        err = sx150x_i2c_write(chip->client,
                        chip->dev_cfg->reg_misc,
                        0x01);
index 1be6288780de9aad04b54aaa3976e770be8c229e..7e10c935a047553d7c9203acf00aa807b9853de4 100644 (file)
@@ -322,6 +322,9 @@ static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
                goto out_freeirq;
        }
 
+       if (pdata->setup)
+               pdata->setup(tc35892, tc35892_gpio->chip.base);
+
        platform_set_drvdata(pdev, tc35892_gpio);
 
        return 0;
@@ -338,9 +341,14 @@ out_free:
 static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
 {
        struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
+       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
+       struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
        int irq = platform_get_irq(pdev, 0);
        int ret;
 
+       if (pdata->remove)
+               pdata->remove(tc35892, tc35892_gpio->chip.base);
+
        ret = gpiochip_remove(&tc35892_gpio->chip);
        if (ret < 0) {
                dev_err(tc35892_gpio->dev,
index 4cab0c6397e34654086f57433e1de471d1d87b30..7af443672626d7429fdff1bdcbe1d2d44f5d4b48 100644 (file)
@@ -73,7 +73,8 @@ source "drivers/gpu/drm/radeon/Kconfig"
 
 config DRM_I810
        tristate "Intel I810"
-       depends on DRM && AGP && AGP_INTEL
+       # BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
+       depends on DRM && AGP && AGP_INTEL && BKL
        help
          Choose this option if you have an Intel I810 graphics card.  If M is
          selected, the module will be called i810.  AGP support is required
@@ -86,6 +87,8 @@ choice
 
 config DRM_I830
        tristate "i830 driver"
+       # BKL usage in order to avoid AB-BA deadlocks, i830 may get removed
+       depends on BKL
        help
          Choose this option if you have a system that has Intel 830M, 845G,
          852GM, 855GM or 865G integrated graphics.  If M is selected, the
index 55d03ed050006c3de3a2b7470c4ededeafbc8871..529a0dbe9fc65960e62bc7840320754fb61393e8 100644 (file)
@@ -98,8 +98,8 @@ EXPORT_SYMBOL(drm_buffer_alloc);
  *   user_data: A pointer the data that is copied to the buffer.
  *   size: The Number of bytes to copy.
  */
-extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
-               void __user *user_data, int size)
+int drm_buffer_copy_from_user(struct drm_buffer *buf,
+                             void __user *user_data, int size)
 {
        int nr_pages = size / PAGE_SIZE + 1;
        int idx;
@@ -163,7 +163,7 @@ void *drm_buffer_read_object(struct drm_buffer *buf,
 {
        int idx = drm_buffer_index(buf);
        int page = drm_buffer_page(buf);
-       void *obj = 0;
+       void *obj = NULL;
 
        if (idx + objsize <= PAGE_SIZE) {
                obj = &buf->data[page][idx];
index 7e31d4348340b10c9c4b39b0612e119335dc444c..dcbeb98f195a7addf665e0134af9ee799280a279 100644 (file)
@@ -34,6 +34,9 @@
 #include "drm_crtc_helper.h"
 #include "drm_fb_helper.h"
 
+static bool drm_kms_helper_poll = true;
+module_param_named(poll, drm_kms_helper_poll, bool, 0600);
+
 static void drm_mode_validate_flag(struct drm_connector *connector,
                                   int flags)
 {
@@ -99,8 +102,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                        connector->status = connector_status_disconnected;
                if (connector->funcs->force)
                        connector->funcs->force(connector);
-       } else
-               connector->status = connector->funcs->detect(connector);
+       } else {
+               connector->status = connector->funcs->detect(connector, true);
+               drm_kms_helper_poll_enable(dev);
+       }
 
        if (connector->status == connector_status_disconnected) {
                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
@@ -110,11 +115,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
        }
 
        count = (*connector_funcs->get_modes)(connector);
-       if (!count) {
+       if (count == 0 && connector->status == connector_status_connected)
                count = drm_add_modes_noedid(connector, 1024, 768);
-               if (!count)
-                       return 0;
-       }
+       if (count == 0)
+               goto prune;
 
        drm_mode_connector_list_update(connector);
 
@@ -633,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                mode_changed = true;
 
        if (mode_changed) {
-               old_fb = set->crtc->fb;
-               set->crtc->fb = set->fb;
                set->crtc->enabled = (set->mode != NULL);
                if (set->mode != NULL) {
                        DRM_DEBUG_KMS("attempting to set mode from"
                                        " userspace\n");
                        drm_mode_debug_printmodeline(set->mode);
+                       old_fb = set->crtc->fb;
+                       set->crtc->fb = set->fb;
                        if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
                                                      set->x, set->y,
                                                      old_fb)) {
@@ -840,6 +844,9 @@ static void output_poll_execute(struct work_struct *work)
        enum drm_connector_status old_status, status;
        bool repoll = false, changed = false;
 
+       if (!drm_kms_helper_poll)
+               return;
+
        mutex_lock(&dev->mode_config.mutex);
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 
@@ -859,7 +866,7 @@ static void output_poll_execute(struct work_struct *work)
                    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
                        continue;
 
-               status = connector->funcs->detect(connector);
+               status = connector->funcs->detect(connector, false);
                if (old_status != status)
                        changed = true;
        }
@@ -890,6 +897,9 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
        bool poll = false;
        struct drm_connector *connector;
 
+       if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
+               return;
+
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (connector->polled)
                        poll = true;
@@ -919,8 +929,10 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
 {
        if (!dev->mode_config.poll_enabled)
                return;
+
        /* kill timer and schedule immediate execution, this doesn't block */
        cancel_delayed_work(&dev->mode_config.output_poll_work);
-       queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
+       if (drm_kms_helper_poll)
+               queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
 }
 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
index 90288ec7c28420133d0deea13e3ba2f1f98d413c..ff6690f4fc87a2593c4e350bad8aaf030daee164 100644 (file)
@@ -55,6 +55,9 @@
 static int drm_version(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 
+#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
+       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0}
+
 /** Ioctl table */
 static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
@@ -281,7 +284,8 @@ EXPORT_SYMBOL(drm_exit);
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
        .owner = THIS_MODULE,
-       .open = drm_stub_open
+       .open = drm_stub_open,
+       .llseek = noop_llseek,
 };
 
 static int __init drm_core_init(void)
@@ -421,6 +425,7 @@ long drm_ioctl(struct file *filp,
        int retcode = -EINVAL;
        char stack_kdata[128];
        char *kdata = NULL;
+       unsigned int usize, asize;
 
        dev = file_priv->minor->dev;
        atomic_inc(&dev->ioctl_count);
@@ -436,11 +441,18 @@ long drm_ioctl(struct file *filp,
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
                goto err_i1;
        if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
-           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+               u32 drv_size;
                ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+               drv_size = _IOC_SIZE(ioctl->cmd_drv);
+               usize = asize = _IOC_SIZE(cmd);
+               if (drv_size > asize)
+                       asize = drv_size;
+       }
        else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
                ioctl = &drm_ioctls[nr];
                cmd = ioctl->cmd;
+               usize = asize = _IOC_SIZE(cmd);
        } else
                goto err_i1;
 
@@ -460,10 +472,10 @@ long drm_ioctl(struct file *filp,
                retcode = -EACCES;
        } else {
                if (cmd & (IOC_IN | IOC_OUT)) {
-                       if (_IOC_SIZE(cmd) <= sizeof(stack_kdata)) {
+                       if (asize <= sizeof(stack_kdata)) {
                                kdata = stack_kdata;
                        } else {
-                               kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+                               kdata = kmalloc(asize, GFP_KERNEL);
                                if (!kdata) {
                                        retcode = -ENOMEM;
                                        goto err_i1;
@@ -473,11 +485,13 @@ long drm_ioctl(struct file *filp,
 
                if (cmd & IOC_IN) {
                        if (copy_from_user(kdata, (void __user *)arg,
-                                          _IOC_SIZE(cmd)) != 0) {
+                                          usize) != 0) {
                                retcode = -EFAULT;
                                goto err_i1;
                        }
-               }
+               } else
+                       memset(kdata, 0, usize);
+
                if (ioctl->flags & DRM_UNLOCKED)
                        retcode = func(dev, kdata, file_priv);
                else {
@@ -488,7 +502,7 @@ long drm_ioctl(struct file *filp,
 
                if (cmd & IOC_OUT) {
                        if (copy_to_user((void __user *)arg, kdata,
-                                        _IOC_SIZE(cmd)) != 0)
+                                        usize) != 0)
                                retcode = -EFAULT;
                }
        }
index de82e201d6826d8ac0e422b22a2d0a93f8312d82..6a5e403f9aa160b54caad1bca22ba93dd27415e6 100644 (file)
@@ -94,10 +94,11 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn
        int i;
        enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
        struct drm_fb_helper_cmdline_mode *cmdline_mode;
-       struct drm_connector *connector = fb_helper_conn->connector;
+       struct drm_connector *connector;
 
        if (!fb_helper_conn)
                return false;
+       connector = fb_helper_conn->connector;
 
        cmdline_mode = &fb_helper_conn->cmdline_mode;
        if (!mode_option)
@@ -369,7 +370,7 @@ static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
 }
 static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
 
-static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
+static void drm_fb_helper_sysrq(int dummy1)
 {
        schedule_work(&drm_fb_helper_restore_work);
 }
index 3a652a65546f16781542b7613865a8c1e692b60c..b744dad5c237f5371d571d13dc35d46a2fc95e2c 100644 (file)
@@ -41,6 +41,7 @@
 
 /* from BKL pushdown: note that nothing else serializes idr_find() */
 DEFINE_MUTEX(drm_global_mutex);
+EXPORT_SYMBOL(drm_global_mutex);
 
 static int drm_open_helper(struct inode *inode, struct file *filp,
                           struct drm_device * dev);
index bf92d07510df740d856c173e7dcce292659fe6f7..5663d2719063de9231ca6cc153b63b30422e17aa 100644 (file)
@@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev,
                return -ENOMEM;
 
        kref_init(&obj->refcount);
-       kref_init(&obj->handlecount);
+       atomic_set(&obj->handle_count, 0);
        obj->size = size;
 
        atomic_inc(&dev->object_count);
@@ -462,28 +462,6 @@ drm_gem_object_free(struct kref *kref)
 }
 EXPORT_SYMBOL(drm_gem_object_free);
 
-/**
- * Called after the last reference to the object has been lost.
- * Must be called without holding struct_mutex
- *
- * Frees the object
- */
-void
-drm_gem_object_free_unlocked(struct kref *kref)
-{
-       struct drm_gem_object *obj = (struct drm_gem_object *) kref;
-       struct drm_device *dev = obj->dev;
-
-       if (dev->driver->gem_free_object_unlocked != NULL)
-               dev->driver->gem_free_object_unlocked(obj);
-       else if (dev->driver->gem_free_object != NULL) {
-               mutex_lock(&dev->struct_mutex);
-               dev->driver->gem_free_object(obj);
-               mutex_unlock(&dev->struct_mutex);
-       }
-}
-EXPORT_SYMBOL(drm_gem_object_free_unlocked);
-
 static void drm_gem_object_ref_bug(struct kref *list_kref)
 {
        BUG();
@@ -496,12 +474,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref)
  * called before drm_gem_object_free or we'll be touching
  * freed memory
  */
-void
-drm_gem_object_handle_free(struct kref *kref)
+void drm_gem_object_handle_free(struct drm_gem_object *obj)
 {
-       struct drm_gem_object *obj = container_of(kref,
-                                                 struct drm_gem_object,
-                                                 handlecount);
        struct drm_device *dev = obj->dev;
 
        /* Remove any name for this object */
@@ -528,6 +502,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
        struct drm_gem_object *obj = vma->vm_private_data;
 
        drm_gem_object_reference(obj);
+
+       mutex_lock(&obj->dev->struct_mutex);
+       drm_vm_open_locked(vma);
+       mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_open);
 
@@ -535,7 +513,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
 
-       drm_gem_object_unreference_unlocked(obj);
+       mutex_lock(&obj->dev->struct_mutex);
+       drm_vm_close_locked(vma);
+       drm_gem_object_unreference(obj);
+       mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
index 2ef2c78272434dcb6b32dc17fd96e34dd7a8d959..974e970ce3f81ce014170b90ad1b8adc8a1dd5a9 100644 (file)
@@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data)
 
        seq_printf(m, "%6d %8zd %7d %8d\n",
                   obj->name, obj->size,
-                  atomic_read(&obj->handlecount.refcount),
+                  atomic_read(&obj->handle_count),
                   atomic_read(&obj->refcount.refcount));
        return 0;
 }
index e2f70a516c34412112078131203309c3656622d7..9bf93bc9a32c27798791684ab73512a046e92a9c 100644 (file)
@@ -92,7 +92,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
                }
 
                /* Contention */
+               mutex_unlock(&drm_global_mutex);
                schedule();
+               mutex_lock(&drm_global_mutex);
                if (signal_pending(current)) {
                        ret = -EINTR;
                        break;
index da99edc50888f2168c510054305e1c847e1fbefb..a6bfc302ed909ecf136888953b329d5acbdf65a3 100644 (file)
@@ -285,21 +285,21 @@ void drm_mm_put_block(struct drm_mm_node *cur)
 
 EXPORT_SYMBOL(drm_mm_put_block);
 
-static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size,
-                             unsigned alignment)
+static int check_free_hole(unsigned long start, unsigned long end,
+                          unsigned long size, unsigned alignment)
 {
        unsigned wasted = 0;
 
-       if (entry->size < size)
+       if (end - start < size)
                return 0;
 
        if (alignment) {
-               register unsigned tmp = entry->start % alignment;
+               unsigned tmp = start % alignment;
                if (tmp)
                        wasted = alignment - tmp;
        }
 
-       if (entry->size >= size + wasted) {
+       if (end >= start + size + wasted) {
                return 1;
        }
 
@@ -320,7 +320,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
        best_size = ~0UL;
 
        list_for_each_entry(entry, &mm->free_stack, free_stack) {
-               if (!check_free_mm_node(entry, size, alignment))
+               if (!check_free_hole(entry->start, entry->start + entry->size,
+                                    size, alignment))
                        continue;
 
                if (!best_match)
@@ -353,10 +354,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
        best_size = ~0UL;
 
        list_for_each_entry(entry, &mm->free_stack, free_stack) {
-               if (entry->start > end || (entry->start+entry->size) < start)
-                       continue;
+               unsigned long adj_start = entry->start < start ?
+                       start : entry->start;
+               unsigned long adj_end = entry->start + entry->size > end ?
+                       end : entry->start + entry->size;
 
-               if (!check_free_mm_node(entry, size, alignment))
+               if (!check_free_hole(adj_start, adj_end, size, alignment))
                        continue;
 
                if (!best_match)
@@ -449,7 +452,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
        node->free_stack.prev = prev_free;
        node->free_stack.next = next_free;
 
-       if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) {
+       if (check_free_hole(node->start, node->start + node->size,
+                           mm->scan_size, mm->scan_alignment)) {
                mm->scan_hit_start = node->start;
                mm->scan_hit_size = node->size;
 
index f1f473ea97d3bc3c7af129fe7e364c33e6a02de8..949326d2a8e5b6b3609d002daa75795c7cff6566 100644 (file)
@@ -251,7 +251,10 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
                drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
                /* Fill in HSync values */
                drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
-               drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC;
+               drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
+               /* Fill in VSync values */
+               drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
+               drm_mode->vsync_end = drm_mode->vsync_start + vsync;
        }
        /* 15/13. Find pixel clock frequency (kHz for xf86) */
        drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod;
index e20f78b542a756644a29693c8da5927dd72f5a7d..f5bd9e590c801b50b0d3629ddbadd6c54a69923a 100644 (file)
@@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
        dev->hose = pdev->sysdata;
 #endif
 
+       mutex_lock(&drm_global_mutex);
+
        if ((ret = drm_fill_in_dev(dev, ent, driver))) {
                printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
                goto err_g2;
@@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                 driver->name, driver->major, driver->minor, driver->patchlevel,
                 driver->date, pci_name(pdev), dev->primary->index);
 
+       mutex_unlock(&drm_global_mutex);
        return 0;
 
 err_g4:
@@ -210,6 +213,7 @@ err_g2:
        pci_disable_device(pdev);
 err_g1:
        kfree(dev);
+       mutex_unlock(&drm_global_mutex);
        return ret;
 }
 EXPORT_SYMBOL(drm_get_pci_dev);
index 460e9a3afa8d4bd43ac752cbf2e1bae3e0f2b832..92d1d0fb7b7581821756ebcdf01089f55037198c 100644 (file)
@@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev,
        dev->platformdev = platdev;
        dev->dev = &platdev->dev;
 
+       mutex_lock(&drm_global_mutex);
+
        ret = drm_fill_in_dev(dev, NULL, driver);
 
        if (ret) {
@@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev,
 
        list_add_tail(&dev->driver_item, &driver->device_list);
 
+       mutex_unlock(&drm_global_mutex);
+
        DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
                 driver->date, dev->primary->index);
@@ -100,6 +104,7 @@ err_g2:
                drm_put_minor(&dev->control);
 err_g1:
        kfree(dev);
+       mutex_unlock(&drm_global_mutex);
        return ret;
 }
 EXPORT_SYMBOL(drm_get_platform_dev);
index 86118a742231b42fd711f18b64deb182a8d60d3a..85da4c40694cc8a99c2b3224e31af548b76e198a 100644 (file)
@@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device,
        struct drm_connector *connector = to_drm_connector(device);
        enum drm_connector_status status;
 
-       status = connector->funcs->detect(connector);
+       status = connector->funcs->detect(connector, true);
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        drm_get_connector_status_name(status));
 }
index 3778360eceea0cc44d2f2213090d5e1ed2e670f4..5df450683aab8649511aaa96aaa759452b022fc0 100644 (file)
@@ -138,7 +138,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                                break;
                }
 
-               if (!agpmem)
+               if (&agpmem->head == &dev->agp->memory)
                        goto vm_fault_error;
 
                /*
@@ -433,15 +433,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
        mutex_unlock(&dev->struct_mutex);
 }
 
-/**
- * \c close method for all virtual memory types.
- *
- * \param vma virtual memory area.
- *
- * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
- * free it.
- */
-static void drm_vm_close(struct vm_area_struct *vma)
+void drm_vm_close_locked(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
        struct drm_device *dev = priv->minor->dev;
@@ -451,7 +443,6 @@ static void drm_vm_close(struct vm_area_struct *vma)
                  vma->vm_start, vma->vm_end - vma->vm_start);
        atomic_dec(&dev->vma_count);
 
-       mutex_lock(&dev->struct_mutex);
        list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
                if (pt->vma == vma) {
                        list_del(&pt->head);
@@ -459,6 +450,23 @@ static void drm_vm_close(struct vm_area_struct *vma)
                        break;
                }
        }
+}
+
+/**
+ * \c close method for all virtual memory types.
+ *
+ * \param vma virtual memory area.
+ *
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
+static void drm_vm_close(struct vm_area_struct *vma)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_vm_close_locked(vma);
        mutex_unlock(&dev->struct_mutex);
 }
 
index 0e6c131313d95b48e62a6dab63730049c7332355..ff33e53bbbf80dfbd470a444c854dc5ae158e32b 100644 (file)
@@ -116,9 +116,10 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations i810_buffer_fops = {
        .open = drm_open,
        .release = drm_release,
-       .unlocked_ioctl = drm_ioctl,
+       .unlocked_ioctl = i810_ioctl,
        .mmap = i810_mmap_buffers,
        .fasync = drm_fasync,
+       .llseek = noop_llseek,
 };
 
 static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
@@ -1255,21 +1256,21 @@ long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 }
 
 struct drm_ioctl_desc i810_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
 };
 
 int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
index b4250b2cac1ff446d1a1f5e67a77fd1a1572ded6..fe69914ce507b3df89ed8193fb32ca58c4a73c0c 100644 (file)
@@ -63,6 +63,7 @@ static struct drm_driver driver = {
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
+                .llseek = noop_llseek,
        },
 
        .pci_driver = {
index 5168862c92271e5d7fddfb48d3470f4f70113d92..ca6f31ff0eecc54a2868878c97b98c7cf6a71bb2 100644 (file)
@@ -118,9 +118,10 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations i830_buffer_fops = {
        .open = drm_open,
        .release = drm_release,
-       .unlocked_ioctl = drm_ioctl,
+       .unlocked_ioctl = i830_ioctl,
        .mmap = i830_mmap_buffers,
        .fasync = drm_fasync,
+       .llseek = noop_llseek,
 };
 
 static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
@@ -1524,20 +1525,20 @@ long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 }
 
 struct drm_ioctl_desc i830_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
 };
 
 int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
index a5c66aa82f0c1cd9246b8ea3c66c29f0bc7cd1e2..5b6298b24e249960bcf6053cb4d29c4573a285d3 100644 (file)
@@ -74,6 +74,7 @@ static struct drm_driver driver = {
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
+                .llseek = noop_llseek,
        },
 
        .pci_driver = {
index 92d5605a34d11a6fcecbbae4149220c44ac86740..048149748fdc9457f48ee5884f74d5cb849e43c0 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include "drmP.h"
 #include "drm.h"
+#include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 
@@ -121,6 +122,54 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
        return 0;
 }
 
+static int i915_gem_pageflip_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       unsigned long flags;
+       struct intel_crtc *crtc;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+               const char *pipe = crtc->pipe ? "B" : "A";
+               const char *plane = crtc->plane ? "B" : "A";
+               struct intel_unpin_work *work;
+
+               spin_lock_irqsave(&dev->event_lock, flags);
+               work = crtc->unpin_work;
+               if (work == NULL) {
+                       seq_printf(m, "No flip due on pipe %s (plane %s)\n",
+                                  pipe, plane);
+               } else {
+                       if (!work->pending) {
+                               seq_printf(m, "Flip queued on pipe %s (plane %s)\n",
+                                          pipe, plane);
+                       } else {
+                               seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n",
+                                          pipe, plane);
+                       }
+                       if (work->enable_stall_check)
+                               seq_printf(m, "Stall check enabled, ");
+                       else
+                               seq_printf(m, "Stall check waiting for page flip ioctl, ");
+                       seq_printf(m, "%d prepares\n", work->pending);
+
+                       if (work->old_fb_obj) {
+                               struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj);
+                               if(obj_priv)
+                                       seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
+                       }
+                       if (work->pending_flip_obj) {
+                               struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj);
+                               if(obj_priv)
+                                       seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
+                       }
+               }
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+       }
+
+       return 0;
+}
+
 static int i915_gem_request_info(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -733,6 +782,7 @@ static const struct file_operations i915_wedged_fops = {
        .open = i915_wedged_open,
        .read = i915_wedged_read,
        .write = i915_wedged_write,
+       .llseek = default_llseek,
 };
 
 /* As the drm_debugfs_init() routines are called before dev->dev_private is
@@ -777,6 +827,7 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
        {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
        {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
+       {"i915_gem_pageflip", i915_gem_pageflip_info, 0},
        {"i915_gem_request", i915_gem_request_info, 0},
        {"i915_gem_seqno", i915_gem_seqno_info, 0},
        {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
index 44af317731b67071c3fa9ec13280975ae7f7d639..2dd2c93ebfa35dace7916b38c6df18c835161978 100644 (file)
@@ -620,8 +620,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                ret = copy_from_user(cliprects, batch->cliprects,
                                     batch->num_cliprects *
                                     sizeof(struct drm_clip_rect));
-               if (ret != 0)
+               if (ret != 0) {
+                       ret = -EFAULT;
                        goto fail_free;
+               }
        }
 
        mutex_lock(&dev->struct_mutex);
@@ -662,8 +664,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                return -ENOMEM;
 
        ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
-       if (ret != 0)
+       if (ret != 0) {
+               ret = -EFAULT;
                goto fail_batch_free;
+       }
 
        if (cmdbuf->num_cliprects) {
                cliprects = kcalloc(cmdbuf->num_cliprects,
@@ -676,8 +680,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                ret = copy_from_user(cliprects, cmdbuf->cliprects,
                                     cmdbuf->num_cliprects *
                                     sizeof(struct drm_clip_rect));
-               if (ret != 0)
+               if (ret != 0) {
+                       ret = -EFAULT;
                        goto fail_clip_free;
+               }
        }
 
        mutex_lock(&dev->struct_mutex);
@@ -885,7 +891,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
        int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
        u32 temp_lo, temp_hi = 0;
        u64 mchbar_addr;
-       int ret = 0;
+       int ret;
 
        if (IS_I965G(dev))
                pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
@@ -895,22 +901,23 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
        /* If ACPI doesn't have it, assume we need to allocate it ourselves */
 #ifdef CONFIG_PNP
        if (mchbar_addr &&
-           pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
-               ret = 0;
-               goto out;
-       }
+           pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
+               return 0;
 #endif
 
        /* Get some space for it */
-       ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
+       dev_priv->mch_res.name = "i915 MCHBAR";
+       dev_priv->mch_res.flags = IORESOURCE_MEM;
+       ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
+                                    &dev_priv->mch_res,
                                     MCHBAR_SIZE, MCHBAR_SIZE,
                                     PCIBIOS_MIN_MEM,
-                                    0,   pcibios_align_resource,
+                                    0, pcibios_align_resource,
                                     dev_priv->bridge_dev);
        if (ret) {
                DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
                dev_priv->mch_res.start = 0;
-               goto out;
+               return ret;
        }
 
        if (IS_I965G(dev))
@@ -919,8 +926,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
 
        pci_write_config_dword(dev_priv->bridge_dev, reg,
                               lower_32_bits(dev_priv->mch_res.start));
-out:
-       return ret;
+       return 0;
 }
 
 /* Setup MCHBAR if possible, return true if we should disable it again */
@@ -1781,9 +1787,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
                }
        }
 
-       div_u64(diff, diff1);
+       diff = div_u64(diff, diff1);
        ret = ((m * diff) + c);
-       div_u64(ret, 10);
+       ret = div_u64(ret, 10);
 
        dev_priv->last_count1 = total_count;
        dev_priv->last_time1 = now;
@@ -1852,7 +1858,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
        /* More magic constants... */
        diff = diff * 1181;
-       div_u64(diff, diffms * 10);
+       diff = div_u64(diff, diffms * 10);
        dev_priv->gfx_power = diff;
 }
 
@@ -2082,6 +2088,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto free_priv;
        }
 
+       /* overlay on gen2 is broken and can't address above 1G */
+       if (IS_GEN2(dev))
+               dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
+
        dev_priv->regs = ioremap(base, size);
        if (!dev_priv->regs) {
                DRM_ERROR("failed to map registers\n");
@@ -2221,6 +2231,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        dev_priv->mchdev_lock = &mchdev_lock;
        spin_unlock(&mchdev_lock);
 
+       /* XXX Prevent module unload due to memory corruption bugs. */
+       __module_get(THIS_MODULE);
+
        return 0;
 
 out_workqueue_free:
@@ -2367,46 +2380,46 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
 }
 
 struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
-       DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
-       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
-       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 00befce8fbb7f503b5ed5311c8acac81f1c00fcd..895ab896e336c660c279622a6b79bfe138a24a5d 100644 (file)
@@ -61,91 +61,86 @@ extern int intel_agp_enabled;
        .driver_data = (unsigned long) info }
 
 static const struct intel_device_info intel_i830_info = {
-       .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+       .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_845g_info = {
-       .is_i8xx = 1,
+       .gen = 2, .is_i8xx = 1,
 };
 
 static const struct intel_device_info intel_i85x_info = {
-       .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
+       .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
        .cursor_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i865g_info = {
-       .is_i8xx = 1,
+       .gen = 2, .is_i8xx = 1,
 };
 
 static const struct intel_device_info intel_i915g_info = {
-       .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
+       .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
 };
 static const struct intel_device_info intel_i915gm_info = {
-       .is_i9xx = 1,  .is_mobile = 1,
+       .gen = 3, .is_i9xx = 1,  .is_mobile = 1,
        .cursor_needs_physical = 1,
 };
 static const struct intel_device_info intel_i945g_info = {
-       .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
+       .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
 };
 static const struct intel_device_info intel_i945gm_info = {
-       .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
+       .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
        .has_hotplug = 1, .cursor_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i965g_info = {
-       .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
+       .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1,
+       .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_i965gm_info = {
-       .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
-       .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
-       .has_hotplug = 1,
+       .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
+       .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_g33_info = {
-       .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_hotplug = 1,
+       .gen = 3, .is_g33 = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_g45_info = {
-       .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_pipe_cxsr = 1,
-       .has_hotplug = 1,
+       .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_pipe_cxsr = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_gm45_info = {
-       .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
+       .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
        .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
-       .has_pipe_cxsr = 1,
-       .has_hotplug = 1,
+       .has_pipe_cxsr = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_pineview_info = {
-       .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
-       .need_gfx_hws = 1,
-       .has_hotplug = 1,
+       .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_ironlake_d_info = {
-       .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_pipe_cxsr = 1,
-       .has_hotplug = 1,
+       .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
-       .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
-       .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
-       .has_hotplug = 1,
+       .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
-       .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_hotplug = 1, .is_gen6 = 1,
+       .gen = 6, .is_i965g = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
-       .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
-       .has_hotplug = 1, .is_gen6 = 1,
+       .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {              /* aka */
@@ -175,13 +170,18 @@ static const struct pci_device_id pciidlist[] = {         /* aka */
        INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),              /* G45_G */
        INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),              /* G41_G */
        INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),              /* B43_G */
+       INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),              /* B43_G.1 */
        INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
        INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
        INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
        INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
        INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
+       INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
+       INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
        INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
+       INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
        INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
+       INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
        {0, 0, 0}
 };
 
@@ -548,6 +548,7 @@ static struct drm_driver driver = {
 #ifdef CONFIG_COMPAT
                 .compat_ioctl = i915_compat_ioctl,
 #endif
+                .llseek = noop_llseek,
        },
 
        .pci_driver = {
index 047cd7ce7e1b31ec981f9069fdfbfb412e9dd8ea..af4a263cf25782a6906f80a1d0783841000ac9b1 100644 (file)
@@ -191,6 +191,7 @@ struct drm_i915_display_funcs {
 };
 
 struct intel_device_info {
+       u8 gen;
        u8 is_mobile : 1;
        u8 is_i8xx : 1;
        u8 is_i85x : 1;
@@ -206,7 +207,6 @@ struct intel_device_info {
        u8 is_broadwater : 1;
        u8 is_crestline : 1;
        u8 is_ironlake : 1;
-       u8 is_gen6 : 1;
        u8 has_fbc : 1;
        u8 has_rc6 : 1;
        u8 has_pipe_cxsr : 1;
@@ -1162,7 +1162,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
 #define IS_845G(dev)           ((dev)->pci_device == 0x2562)
 #define IS_I85X(dev)           (INTEL_INFO(dev)->is_i85x)
 #define IS_I865G(dev)          ((dev)->pci_device == 0x2572)
-#define IS_GEN2(dev)           (INTEL_INFO(dev)->is_i8xx)
 #define IS_I915G(dev)          (INTEL_INFO(dev)->is_i915g)
 #define IS_I915GM(dev)         ((dev)->pci_device == 0x2592)
 #define IS_I945G(dev)          ((dev)->pci_device == 0x2772)
@@ -1181,27 +1180,13 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
 #define IS_IRONLAKE_M(dev)     ((dev)->pci_device == 0x0046)
 #define IS_IRONLAKE(dev)       (INTEL_INFO(dev)->is_ironlake)
 #define IS_I9XX(dev)           (INTEL_INFO(dev)->is_i9xx)
-#define IS_GEN6(dev)           (INTEL_INFO(dev)->is_gen6)
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 
-#define IS_GEN3(dev)   (IS_I915G(dev) ||                       \
-                        IS_I915GM(dev) ||                      \
-                        IS_I945G(dev) ||                       \
-                        IS_I945GM(dev) ||                      \
-                        IS_G33(dev) || \
-                        IS_PINEVIEW(dev))
-#define IS_GEN4(dev)   ((dev)->pci_device == 0x2972 ||         \
-                        (dev)->pci_device == 0x2982 ||         \
-                        (dev)->pci_device == 0x2992 ||         \
-                        (dev)->pci_device == 0x29A2 ||         \
-                        (dev)->pci_device == 0x2A02 ||         \
-                        (dev)->pci_device == 0x2A12 ||         \
-                        (dev)->pci_device == 0x2E02 ||         \
-                        (dev)->pci_device == 0x2E12 ||         \
-                        (dev)->pci_device == 0x2E22 ||         \
-                        (dev)->pci_device == 0x2E32 ||         \
-                        (dev)->pci_device == 0x2A42 ||         \
-                        (dev)->pci_device == 0x2E42)
+#define IS_GEN2(dev)   (INTEL_INFO(dev)->gen == 2)
+#define IS_GEN3(dev)   (INTEL_INFO(dev)->gen == 3)
+#define IS_GEN4(dev)   (INTEL_INFO(dev)->gen == 4)
+#define IS_GEN5(dev)   (INTEL_INFO(dev)->gen == 5)
+#define IS_GEN6(dev)   (INTEL_INFO(dev)->gen == 6)
 
 #define HAS_BSD(dev)            (IS_IRONLAKE(dev) || IS_G4X(dev))
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
index df5a7135c2614c8de55e309c5dfad82efcf618ac..90b1d6753b9d493d3ed8d2c45153bf2047b54d8f 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
+#include <linux/intel-gtt.h>
 
 static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
 static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
@@ -135,12 +136,13 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
                return -ENOMEM;
 
        ret = drm_gem_handle_create(file_priv, obj, &handle);
+       /* drop reference from allocate - handle holds it now */
        drm_gem_object_unreference_unlocked(obj);
-       if (ret)
+       if (ret) {
                return ret;
+       }
 
        args->handle = handle;
-
        return 0;
 }
 
@@ -467,14 +469,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
                return -ENOENT;
        obj_priv = to_intel_bo(obj);
 
-       /* Bounds check source.
-        *
-        * XXX: This could use review for overflow issues...
-        */
-       if (args->offset > obj->size || args->size > obj->size ||
-           args->offset + args->size > obj->size) {
-               drm_gem_object_unreference_unlocked(obj);
-               return -EINVAL;
+       /* Bounds check source.  */
+       if (args->offset > obj->size || args->size > obj->size - args->offset) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (!access_ok(VERIFY_WRITE,
+                      (char __user *)(uintptr_t)args->data_ptr,
+                      args->size)) {
+               ret = -EFAULT;
+               goto err;
        }
 
        if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -486,8 +491,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
                                                        file_priv);
        }
 
+err:
        drm_gem_object_unreference_unlocked(obj);
-
        return ret;
 }
 
@@ -576,8 +581,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
 
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        remain = args->size;
-       if (!access_ok(VERIFY_READ, user_data, remain))
-               return -EFAULT;
 
 
        mutex_lock(&dev->struct_mutex);
@@ -930,14 +933,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                return -ENOENT;
        obj_priv = to_intel_bo(obj);
 
-       /* Bounds check destination.
-        *
-        * XXX: This could use review for overflow issues...
-        */
-       if (args->offset > obj->size || args->size > obj->size ||
-           args->offset + args->size > obj->size) {
-               drm_gem_object_unreference_unlocked(obj);
-               return -EINVAL;
+       /* Bounds check destination. */
+       if (args->offset > obj->size || args->size > obj->size - args->offset) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (!access_ok(VERIFY_READ,
+                      (char __user *)(uintptr_t)args->data_ptr,
+                      args->size)) {
+               ret = -EFAULT;
+               goto err;
        }
 
        /* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -971,8 +977,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                DRM_INFO("pwrite failed %d\n", ret);
 #endif
 
+err:
        drm_gem_object_unreference_unlocked(obj);
-
        return ret;
 }
 
@@ -2347,14 +2353,21 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 
        reg->obj = obj;
 
-       if (IS_GEN6(dev))
+       switch (INTEL_INFO(dev)->gen) {
+       case 6:
                sandybridge_write_fence_reg(reg);
-       else if (IS_I965G(dev))
+               break;
+       case 5:
+       case 4:
                i965_write_fence_reg(reg);
-       else if (IS_I9XX(dev))
+               break;
+       case 3:
                i915_write_fence_reg(reg);
-       else
+               break;
+       case 2:
                i830_write_fence_reg(reg);
+               break;
+       }
 
        trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
                        obj_priv->tiling_mode);
@@ -2377,22 +2390,26 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct drm_i915_fence_reg *reg =
                &dev_priv->fence_regs[obj_priv->fence_reg];
+       uint32_t fence_reg;
 
-       if (IS_GEN6(dev)) {
+       switch (INTEL_INFO(dev)->gen) {
+       case 6:
                I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
                             (obj_priv->fence_reg * 8), 0);
-       } else if (IS_I965G(dev)) {
+               break;
+       case 5:
+       case 4:
                I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
-       } else {
-               uint32_t fence_reg;
-
-               if (obj_priv->fence_reg < 8)
-                       fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
+               break;
+       case 3:
+               if (obj_priv->fence_reg >= 8)
+                       fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4;
                else
-                       fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg -
-                                                      8) * 4;
+       case 2:
+                       fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
 
                I915_WRITE(fence_reg, 0);
+               break;
        }
 
        reg->obj = NULL;
@@ -3243,6 +3260,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                  (int) reloc->offset,
                                  reloc->read_domains,
                                  reloc->write_domain);
+                       drm_gem_object_unreference(target_obj);
+                       i915_gem_object_unpin(obj);
                        return -EINVAL;
                }
                if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
@@ -3585,6 +3604,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                if (ret != 0) {
                        DRM_ERROR("copy %d cliprects failed: %d\n",
                                  args->num_cliprects, ret);
+                       ret = -EFAULT;
                        goto pre_mutex_err;
                }
        }
index 72cae3cccad8802641d973542ab6c440445b81db..5c428fa3e0b34049e94786184b646a98ee87c06d 100644 (file)
@@ -79,6 +79,7 @@ mark_free(struct drm_i915_gem_object *obj_priv,
           struct list_head *unwind)
 {
        list_add(&obj_priv->evict_list, unwind);
+       drm_gem_object_reference(&obj_priv->base);
        return drm_mm_scan_add_block(obj_priv->gtt_space);
 }
 
@@ -92,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct list_head eviction_list, unwind_list;
-       struct drm_i915_gem_object *obj_priv, *tmp_obj_priv;
+       struct drm_i915_gem_object *obj_priv;
        struct list_head *render_iter, *bsd_iter;
        int ret = 0;
 
@@ -165,6 +166,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
        list_for_each_entry(obj_priv, &unwind_list, evict_list) {
                ret = drm_mm_scan_remove_block(obj_priv->gtt_space);
                BUG_ON(ret);
+               drm_gem_object_unreference(&obj_priv->base);
        }
 
        /* We expect the caller to unpin, evict all and try again, or give up.
@@ -173,36 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
        return -ENOSPC;
 
 found:
+       /* drm_mm doesn't allow any other other operations while
+        * scanning, therefore store to be evicted objects on a
+        * temporary list. */
        INIT_LIST_HEAD(&eviction_list);
-       list_for_each_entry_safe(obj_priv, tmp_obj_priv,
-                                &unwind_list, evict_list) {
+       while (!list_empty(&unwind_list)) {
+               obj_priv = list_first_entry(&unwind_list,
+                                           struct drm_i915_gem_object,
+                                           evict_list);
                if (drm_mm_scan_remove_block(obj_priv->gtt_space)) {
-                       /* drm_mm doesn't allow any other other operations while
-                        * scanning, therefore store to be evicted objects on a
-                        * temporary list. */
                        list_move(&obj_priv->evict_list, &eviction_list);
+                       continue;
                }
+               list_del(&obj_priv->evict_list);
+               drm_gem_object_unreference(&obj_priv->base);
        }
 
        /* Unbinding will emit any required flushes */
-       list_for_each_entry_safe(obj_priv, tmp_obj_priv,
-                                &eviction_list, evict_list) {
-#if WATCH_LRU
-               DRM_INFO("%s: evicting %p\n", __func__, obj);
-#endif
-               ret = i915_gem_object_unbind(&obj_priv->base);
-               if (ret)
-                       return ret;
+       while (!list_empty(&eviction_list)) {
+               obj_priv = list_first_entry(&eviction_list,
+                                           struct drm_i915_gem_object,
+                                           evict_list);
+               if (ret == 0)
+                       ret = i915_gem_object_unbind(&obj_priv->base);
+               list_del(&obj_priv->evict_list);
+               drm_gem_object_unreference(&obj_priv->base);
        }
 
-       /* The just created free hole should be on the top of the free stack
-        * maintained by drm_mm, so this BUG_ON actually executes in O(1).
-        * Furthermore all accessed data has just recently been used, so it
-        * should be really fast, too. */
-       BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size,
-                                  alignment, 0));
-
-       return 0;
+       return ret;
 }
 
 int
index 16861b800feeb46577f35e616c3d891b6dff9f4e..744225ebb4b25d5988fab454441de95d7db94115 100644 (file)
@@ -887,6 +887,49 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
        queue_work(dev_priv->wq, &dev_priv->error_work);
 }
 
+static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_i915_gem_object *obj_priv;
+       struct intel_unpin_work *work;
+       unsigned long flags;
+       bool stall_detected;
+
+       /* Ignore early vblank irqs */
+       if (intel_crtc == NULL)
+               return;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       work = intel_crtc->unpin_work;
+
+       if (work == NULL || work->pending || !work->enable_stall_check) {
+               /* Either the pending flip IRQ arrived, or we're too early. Don't check */
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+               return;
+       }
+
+       /* Potential stall - if we see that the flip has happened, assume a missed interrupt */
+       obj_priv = to_intel_bo(work->pending_flip_obj);
+       if(IS_I965G(dev)) {
+               int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
+               stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset;
+       } else {
+               int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR;
+               stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset +
+                                                       crtc->y * crtc->fb->pitch +
+                                                       crtc->x * crtc->fb->bits_per_pixel/8);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       if (stall_detected) {
+               DRM_DEBUG_DRIVER("Pageflip stall detected\n");
+               intel_prepare_page_flip(dev, intel_crtc->plane);
+       }
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -1004,15 +1047,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                if (pipea_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 0);
-                       if (!dev_priv->flip_pending_is_done)
+                       if (!dev_priv->flip_pending_is_done) {
+                               i915_pageflip_stall_check(dev, 0);
                                intel_finish_page_flip(dev, 0);
+                       }
                }
 
                if (pipeb_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 1);
-                       if (!dev_priv->flip_pending_is_done)
+                       if (!dev_priv->flip_pending_is_done) {
+                               i915_pageflip_stall_check(dev, 1);
                                intel_finish_page_flip(dev, 1);
+                       }
                }
 
                if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
@@ -1303,17 +1350,25 @@ void i915_hangcheck_elapsed(unsigned long data)
                i915_seqno_passed(i915_get_gem_seqno(dev,
                                &dev_priv->render_ring),
                        i915_get_tail_request(dev)->seqno)) {
+               bool missed_wakeup = false;
+
                dev_priv->hangcheck_count = 0;
 
                /* Issue a wake-up to catch stuck h/w. */
-               if (dev_priv->render_ring.waiting_gem_seqno |
-                   dev_priv->bsd_ring.waiting_gem_seqno) {
-                       DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
-                       if (dev_priv->render_ring.waiting_gem_seqno)
-                               DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
-                       if (dev_priv->bsd_ring.waiting_gem_seqno)
-                               DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+               if (dev_priv->render_ring.waiting_gem_seqno &&
+                   waitqueue_active(&dev_priv->render_ring.irq_queue)) {
+                       DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
+                       missed_wakeup = true;
                }
+
+               if (dev_priv->bsd_ring.waiting_gem_seqno &&
+                   waitqueue_active(&dev_priv->bsd_ring.irq_queue)) {
+                       DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+                       missed_wakeup = true;
+               }
+
+               if (missed_wakeup)
+                       DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
                return;
        }
 
index 67e3ec1a6af9dc482870e842b3739a86581176ae..4f5e15577e89e3e6f7005cd92f9f87ab0636b4eb 100644 (file)
 
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
+# define MI_FLUSH_ENABLE                               (1 << 11)
 
 #define SCPD0          0x0209c /* 915+ only */
 #define IER            0x020a0
 #define  WM1_LP_SR_EN          (1<<31)
 #define  WM1_LP_LATENCY_SHIFT  24
 #define  WM1_LP_LATENCY_MASK   (0x7f<<24)
+#define  WM1_LP_FBC_LP1_MASK   (0xf<<20)
+#define  WM1_LP_FBC_LP1_SHIFT  20
 #define  WM1_LP_SR_MASK                (0x1ff<<8)
 #define  WM1_LP_SR_SHIFT       8
 #define  WM1_LP_CURSOR_MASK    (0x3f)
+#define WM2_LP_ILK             0x4510c
+#define  WM2_LP_EN             (1<<31)
+#define WM3_LP_ILK             0x45110
+#define  WM3_LP_EN             (1<<31)
+#define WM1S_LP_ILK            0x45120
+#define  WM1S_LP_EN            (1<<31)
 
 /* Memory latency timer register */
 #define MLTR_ILK               0x11222
index 2c6b98f2440eff4fdee79ba3c7c95a5bbdf07c4a..31f08581e93a46dbdc2ca1cfa563faec31e9ffc5 100644 (file)
@@ -789,16 +789,25 @@ int i915_save_state(struct drm_device *dev)
                dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
 
        /* Fences */
-       if (IS_I965G(dev)) {
+       switch (INTEL_INFO(dev)->gen) {
+       case 6:
+               for (i = 0; i < 16; i++)
+                       dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+               break;
+       case 5:
+       case 4:
                for (i = 0; i < 16; i++)
                        dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
-       } else {
-               for (i = 0; i < 8; i++)
-                       dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
-
+               break;
+       case 3:
                if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                        for (i = 0; i < 8; i++)
                                dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+       case 2:
+               for (i = 0; i < 8; i++)
+                       dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+               break;
+
        }
 
        return 0;
@@ -815,15 +824,24 @@ int i915_restore_state(struct drm_device *dev)
        I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
        /* Fences */
-       if (IS_I965G(dev)) {
+       switch (INTEL_INFO(dev)->gen) {
+       case 6:
+               for (i = 0; i < 16; i++)
+                       I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
+               break;
+       case 5:
+       case 4:
                for (i = 0; i < 16; i++)
                        I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
-       } else {
-               for (i = 0; i < 8; i++)
-                       I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
+               break;
+       case 3:
+       case 2:
                if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                        for (i = 0; i < 8; i++)
                                I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
+               for (i = 0; i < 8; i++)
+                       I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
+               break;
        }
 
        i915_restore_display(dev);
index 4b7735196cd5a516eb3bb34b9a843450da3f1fe4..197d4f32585a59b5b336328b470fa038bc922781 100644 (file)
@@ -188,7 +188,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
 
        if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
                     1000, 1))
-               DRM_ERROR("timed out waiting for FORCE_TRIGGER");
+               DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
 
        if (turn_off_dac) {
                I915_WRITE(PCH_ADPA, temp);
@@ -245,7 +245,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
                if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
                              CRT_HOTPLUG_FORCE_DETECT) == 0,
                             1000, 1))
-                       DRM_ERROR("timed out waiting for FORCE_DETECT to go off");
+                       DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off");
        }
 
        stat = I915_READ(PORT_HOTPLUG_STAT);
@@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
        return status;
 }
 
-static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
+static enum drm_connector_status
+intel_crt_detect(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
        if (intel_crt_detect_ddc(encoder))
                return connector_status_connected;
 
+       if (!force)
+               return connector->status;
+
        /* for pre-945g platforms use load detect */
        if (encoder->crtc && encoder->crtc->enabled) {
                status = intel_crt_load_detect(encoder->crtc, intel_encoder);
index 23157e1de3bec24339f21ed95fac72bd341ab0fb..979228594599a28ac7737762679f1c97fd5981bf 100644 (file)
@@ -990,15 +990,31 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
 
+       /* Clear existing vblank status. Note this will clear any other
+        * sticky status fields as well.
+        *
+        * This races with i915_driver_irq_handler() with the result
+        * that either function could miss a vblank event.  Here it is not
+        * fatal, as we will either wait upon the next vblank interrupt or
+        * timeout.  Generally speaking intel_wait_for_vblank() is only
+        * called during modeset at which time the GPU should be idle and
+        * should *not* be performing page flips and thus not waiting on
+        * vblanks...
+        * Currently, the result of us stealing a vblank from the irq
+        * handler is that a single frame will be skipped during swapbuffers.
+        */
+       I915_WRITE(pipestat_reg,
+                  I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS);
+
        /* Wait for vblank interrupt bit to set */
        if (wait_for((I915_READ(pipestat_reg) &
-                     PIPE_VBLANK_INTERRUPT_STATUS) == 0,
+                     PIPE_VBLANK_INTERRUPT_STATUS),
                     50, 0))
                DRM_DEBUG_KMS("vblank wait timed out\n");
 }
 
-/**
- * intel_wait_for_vblank_off - wait for vblank after disabling a pipe
+/*
+ * intel_wait_for_pipe_off - wait for pipe to turn off
  * @dev: drm device
  * @pipe: pipe to wait for
  *
@@ -1006,25 +1022,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
  * spinning on the vblank interrupt status bit, since we won't actually
  * see an interrupt when the pipe is disabled.
  *
- * So this function waits for the display line value to settle (it
- * usually ends up stopping at the start of the next frame).
+ * On Gen4 and above:
+ *   wait for the pipe register state bit to turn off
+ *
+ * Otherwise:
+ *   wait for the display line value to settle (it usually
+ *   ends up stopping at the start of the next frame).
+ *  
  */
-void intel_wait_for_vblank_off(struct drm_device *dev, int pipe)
+static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
-       unsigned long timeout = jiffies + msecs_to_jiffies(100);
-       u32 last_line;
-
-       /* Wait for the display line to settle */
-       do {
-               last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
-               mdelay(5);
-       } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
-                time_after(timeout, jiffies));
-
-       if (time_after(jiffies, timeout))
-               DRM_DEBUG_KMS("vblank wait timed out\n");
+
+       if (INTEL_INFO(dev)->gen >= 4) {
+               int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF);
+
+               /* Wait for the Pipe State to go off */
+               if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0,
+                            100, 0))
+                       DRM_DEBUG_KMS("pipe_off wait timed out\n");
+       } else {
+               u32 last_line;
+               int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
+               unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+               /* Wait for the display line to settle */
+               do {
+                       last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
+                       mdelay(5);
+               } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
+                        time_after(timeout, jiffies));
+               if (time_after(jiffies, timeout))
+                       DRM_DEBUG_KMS("pipe_off wait timed out\n");
+       }
 }
 
 /* Parameters have changed, update FBC info */
@@ -1486,7 +1516,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                        dspcntr &= ~DISPPLANE_TILED;
        }
 
-       if (IS_IRONLAKE(dev))
+       if (HAS_PCH_SPLIT(dev))
                /* must disable */
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
@@ -1495,20 +1525,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        Start = obj_priv->gtt_offset;
        Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
 
-       DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+                     Start, Offset, x, y, fb->pitch);
        I915_WRITE(dspstride, fb->pitch);
        if (IS_I965G(dev)) {
-               I915_WRITE(dspbase, Offset);
-               I915_READ(dspbase);
                I915_WRITE(dspsurf, Start);
-               I915_READ(dspsurf);
                I915_WRITE(dsptileoff, (y << 16) | x);
+               I915_WRITE(dspbase, Offset);
        } else {
                I915_WRITE(dspbase, Start + Offset);
-               I915_READ(dspbase);
        }
+       POSTING_READ(dspbase);
 
-       if ((IS_I965G(dev) || plane == 0))
+       if (IS_I965G(dev) || plane == 0)
                intel_update_fbc(crtc, &crtc->mode);
 
        intel_wait_for_vblank(dev, intel_crtc->pipe);
@@ -1522,7 +1551,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_framebuffer *intel_fb;
@@ -1530,13 +1558,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_gem_object *obj;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
-       unsigned long Start, Offset;
-       int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
-       int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
-       int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
-       u32 dspcntr;
        int ret;
 
        /* no fb bound */
@@ -1572,71 +1593,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return ret;
        }
 
-       dspcntr = I915_READ(dspcntr_reg);
-       /* Mask out pixel format bits in case we change it */
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               dspcntr |= DISPPLANE_8BPP;
-               break;
-       case 16:
-               if (crtc->fb->depth == 15)
-                       dspcntr |= DISPPLANE_15_16BPP;
-               else
-                       dspcntr |= DISPPLANE_16BPP;
-               break;
-       case 24:
-       case 32:
-               if (crtc->fb->depth == 30)
-                       dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
-               else
-                       dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-               break;
-       default:
-               DRM_ERROR("Unknown color depth\n");
+       ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y);
+       if (ret) {
                i915_gem_object_unpin(obj);
                mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-       if (IS_I965G(dev)) {
-               if (obj_priv->tiling_mode != I915_TILING_NONE)
-                       dspcntr |= DISPPLANE_TILED;
-               else
-                       dspcntr &= ~DISPPLANE_TILED;
-       }
-
-       if (HAS_PCH_SPLIT(dev))
-               /* must disable */
-               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
-       I915_WRITE(dspcntr_reg, dspcntr);
-
-       Start = obj_priv->gtt_offset;
-       Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
-
-       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
-                     Start, Offset, x, y, crtc->fb->pitch);
-       I915_WRITE(dspstride, crtc->fb->pitch);
-       if (IS_I965G(dev)) {
-               I915_WRITE(dspsurf, Start);
-               I915_WRITE(dsptileoff, (y << 16) | x);
-               I915_WRITE(dspbase, Offset);
-       } else {
-               I915_WRITE(dspbase, Start + Offset);
+               return ret;
        }
-       POSTING_READ(dspbase);
-
-       if ((IS_I965G(dev) || plane == 0))
-               intel_update_fbc(crtc, &crtc->mode);
-
-       intel_wait_for_vblank(dev, pipe);
 
        if (old_fb) {
                intel_fb = to_intel_framebuffer(old_fb);
                obj_priv = to_intel_bo(intel_fb->obj);
                i915_gem_object_unpin(intel_fb->obj);
        }
-       intel_increase_pllclock(crtc, true);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -1911,9 +1879,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
        int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
        int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
        int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
-       int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
-       int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
-       int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
        int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
        int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
        int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
@@ -1982,15 +1947,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                }
 
                /* Enable panel fitting for LVDS */
-               if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
-                   || HAS_eDP || intel_pch_has_edp(crtc)) {
-                       if (dev_priv->pch_pf_size) {
-                               temp = I915_READ(pf_ctl_reg);
-                               I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
-                               I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos);
-                               I915_WRITE(pf_win_size, dev_priv->pch_pf_size);
-                       } else
-                               I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
+               if (dev_priv->pch_pf_size &&
+                   (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
+                   || HAS_eDP || intel_pch_has_edp(crtc))) {
+                       /* Force use of hard-coded filter coefficients
+                        * as some pre-programmed values are broken,
+                        * e.g. x201.
+                        */
+                       I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
+                                  PF_ENABLE | PF_FILTER_MED_3x3);
+                       I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
+                                  dev_priv->pch_pf_pos);
+                       I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
+                                  dev_priv->pch_pf_size);
                }
 
                /* Enable CPU pipe */
@@ -2115,7 +2084,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                        I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
                        I915_READ(transconf_reg);
 
-                       if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0))
+                       if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1))
                                DRM_ERROR("failed to enable transcoder\n");
                }
 
@@ -2155,14 +2124,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                udelay(100);
 
                /* Disable PF */
-               temp = I915_READ(pf_ctl_reg);
-               if ((temp & PF_ENABLE) != 0) {
-                       I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
-                       I915_READ(pf_ctl_reg);
-               }
-               I915_WRITE(pf_win_size, 0);
-               POSTING_READ(pf_win_size);
-
+               I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
+               I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
 
                /* disable CPU FDI tx and PCH FDI rx */
                temp = I915_READ(fdi_tx_reg);
@@ -2379,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
                        I915_READ(dspbase_reg);
                }
 
-               /* Wait for vblank for the disable to take effect */
-               intel_wait_for_vblank_off(dev, pipe);
-
                /* Don't disable pipe A or pipe A PLLs if needed */
                if (pipeconf_reg == PIPEACONF &&
-                   (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+                   (dev_priv->quirks & QUIRK_PIPEA_FORCE)) {
+                       /* Wait for vblank for the disable to take effect */
+                       intel_wait_for_vblank(dev, pipe);
                        goto skip_pipe_off;
+               }
 
                /* Next, disable display pipes */
                temp = I915_READ(pipeconf_reg);
@@ -2394,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
                        I915_READ(pipeconf_reg);
                }
 
-               /* Wait for vblank for the disable to take effect. */
-               intel_wait_for_vblank_off(dev, pipe);
+               /* Wait for the pipe to turn off */
+               intel_wait_for_pipe_off(dev, pipe);
 
                temp = I915_READ(dpll_reg);
                if ((temp & DPLL_VCO_ENABLE) != 0) {
@@ -2421,6 +2384,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
        int pipe = intel_crtc->pipe;
        bool enabled;
 
+       if (intel_crtc->dpms_mode == mode)
+               return;
+
        intel_crtc->dpms_mode = mode;
        intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON;
 
@@ -2511,11 +2477,19 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                                  struct drm_display_mode *adjusted_mode)
 {
        struct drm_device *dev = crtc->dev;
+
        if (HAS_PCH_SPLIT(dev)) {
                /* FDI link clock is fixed at 2.7G */
                if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4)
                        return false;
        }
+
+       /* XXX some encoders set the crtcinfo, others don't.
+        * Obviously we need some form of conflict resolution here...
+        */
+       if (adjusted_mode->crtc_htotal == 0)
+               drm_mode_set_crtcinfo(adjusted_mode, 0);
+
        return true;
 }
 
@@ -2815,14 +2789,8 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
        /* Don't promote wm_size to unsigned... */
        if (wm_size > (long)wm->max_wm)
                wm_size = wm->max_wm;
-       if (wm_size <= 0) {
+       if (wm_size <= 0)
                wm_size = wm->default_wm;
-               DRM_ERROR("Insufficient FIFO for plane, expect flickering:"
-                         " entries required = %ld, available = %lu.\n",
-                         entries_required + wm->guard_size,
-                         wm->fifo_size);
-       }
-
        return wm_size;
 }
 
@@ -3436,8 +3404,7 @@ static void ironlake_update_wm(struct drm_device *dev,  int planea_clock,
                reg_value = I915_READ(WM1_LP_ILK);
                reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK |
                               WM1_LP_CURSOR_MASK);
-               reg_value |= WM1_LP_SR_EN |
-                            (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
+               reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
                             (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm;
 
                I915_WRITE(WM1_LP_ILK, reg_value);
@@ -3554,10 +3521,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
        bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
        bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
-       bool is_edp = false;
+       struct intel_encoder *has_edp_encoder = NULL;
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_encoder *encoder;
-       struct intel_encoder *intel_encoder = NULL;
        const intel_limit_t *limit;
        int ret;
        struct fdi_m_n m_n = {0};
@@ -3578,12 +3544,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        drm_vblank_pre_modeset(dev, pipe);
 
        list_for_each_entry(encoder, &mode_config->encoder_list, head) {
+               struct intel_encoder *intel_encoder;
 
-               if (!encoder || encoder->crtc != crtc)
+               if (encoder->crtc != crtc)
                        continue;
 
                intel_encoder = enc_to_intel_encoder(encoder);
-
                switch (intel_encoder->type) {
                case INTEL_OUTPUT_LVDS:
                        is_lvds = true;
@@ -3607,7 +3573,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        is_dp = true;
                        break;
                case INTEL_OUTPUT_EDP:
-                       is_edp = true;
+                       has_edp_encoder = intel_encoder;
                        break;
                }
 
@@ -3685,10 +3651,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                int lane = 0, link_bw, bpp;
                /* eDP doesn't require FDI link, so just set DP M/N
                   according to current link config */
-               if (is_edp) {
+               if (has_edp_encoder) {
                        target_clock = mode->clock;
-                       intel_edp_link_config(intel_encoder,
-                                       &lane, &link_bw);
+                       intel_edp_link_config(has_edp_encoder,
+                                             &lane, &link_bw);
                } else {
                        /* DP over FDI requires target mode clock
                           instead of link clock */
@@ -3709,7 +3675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                                temp |= PIPE_8BPC;
                        else
                                temp |= PIPE_6BPC;
-               } else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) {
+               } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) {
                        switch (dev_priv->edp_bpp/3) {
                        case 8:
                                temp |= PIPE_8BPC;
@@ -3782,7 +3748,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
                udelay(200);
 
-               if (is_edp) {
+               if (has_edp_encoder) {
                        if (dev_priv->lvds_use_ssc) {
                                temp |= DREF_SSC1_ENABLE;
                                I915_WRITE(PCH_DREF_CONTROL, temp);
@@ -3931,7 +3897,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                dpll_reg = pch_dpll_reg;
        }
 
-       if (!is_edp) {
+       if (!has_edp_encoder) {
                I915_WRITE(fp_reg, fp);
                I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
                I915_READ(dpll_reg);
@@ -4026,7 +3992,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       if (!is_edp) {
+       if (!has_edp_encoder) {
                I915_WRITE(fp_reg, fp);
                I915_WRITE(dpll_reg, dpll);
                I915_READ(dpll_reg);
@@ -4105,7 +4071,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                I915_WRITE(link_m1_reg, m_n.link_m);
                I915_WRITE(link_n1_reg, m_n.link_n);
 
-               if (is_edp) {
+               if (has_edp_encoder) {
                        ironlake_set_pll_edp(crtc, adjusted_mode->clock);
                } else {
                        /* enable FDI RX PLL too */
@@ -4911,15 +4877,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
        kfree(intel_crtc);
 }
 
-struct intel_unpin_work {
-       struct work_struct work;
-       struct drm_device *dev;
-       struct drm_gem_object *old_fb_obj;
-       struct drm_gem_object *pending_flip_obj;
-       struct drm_pending_vblank_event *event;
-       int pending;
-};
-
 static void intel_unpin_work_fn(struct work_struct *__work)
 {
        struct intel_unpin_work *work =
@@ -5007,7 +4964,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
 
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
-               intel_crtc->unpin_work->pending = 1;
+               if ((++intel_crtc->unpin_work->pending) > 1)
+                       DRM_ERROR("Prepared flip multiple times\n");
        } else {
                DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
        }
@@ -5026,9 +4984,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        unsigned long flags, offset;
-       int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int ret, pipesrc;
-       u32 flip_mask;
+       int pipe = intel_crtc->pipe;
+       u32 pf, pipesrc;
+       int ret;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
        if (work == NULL)
@@ -5077,42 +5035,73 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        atomic_inc(&obj_priv->pending_flip);
        work->pending_flip_obj = obj;
 
-       if (intel_crtc->plane)
-               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-       else
-               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-
        if (IS_GEN3(dev) || IS_GEN2(dev)) {
+               u32 flip_mask;
+
+               if (intel_crtc->plane)
+                       flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+               else
+                       flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+
                BEGIN_LP_RING(2);
                OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
                OUT_RING(0);
                ADVANCE_LP_RING();
        }
 
+       work->enable_stall_check = true;
+
        /* Offset into the new buffer for cases of shared fbs between CRTCs */
-       offset = obj_priv->gtt_offset;
-       offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
+       offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
 
        BEGIN_LP_RING(4);
-       if (IS_I965G(dev)) {
+       switch(INTEL_INFO(dev)->gen) {
+       case 2:
                OUT_RING(MI_DISPLAY_FLIP |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
                OUT_RING(fb->pitch);
-               OUT_RING(offset | obj_priv->tiling_mode);
-               pipesrc = I915_READ(pipesrc_reg); 
-               OUT_RING(pipesrc & 0x0fff0fff);
-       } else if (IS_GEN3(dev)) {
+               OUT_RING(obj_priv->gtt_offset + offset);
+               OUT_RING(MI_NOOP);
+               break;
+
+       case 3:
                OUT_RING(MI_DISPLAY_FLIP_I915 |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
                OUT_RING(fb->pitch);
-               OUT_RING(offset);
+               OUT_RING(obj_priv->gtt_offset + offset);
                OUT_RING(MI_NOOP);
-       } else {
+               break;
+
+       case 4:
+       case 5:
+               /* i965+ uses the linear or tiled offsets from the
+                * Display Registers (which do not change across a page-flip)
+                * so we need only reprogram the base address.
+                */
                OUT_RING(MI_DISPLAY_FLIP |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
                OUT_RING(fb->pitch);
-               OUT_RING(offset);
-               OUT_RING(MI_NOOP);
+               OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
+
+               /* XXX Enabling the panel-fitter across page-flip is so far
+                * untested on non-native modes, so ignore it for now.
+                * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
+                */
+               pf = 0;
+               pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+               OUT_RING(pf | pipesrc);
+               break;
+
+       case 6:
+               OUT_RING(MI_DISPLAY_FLIP |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch | obj_priv->tiling_mode);
+               OUT_RING(obj_priv->gtt_offset);
+
+               pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
+               pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+               OUT_RING(pf | pipesrc);
+               break;
        }
        ADVANCE_LP_RING();
 
@@ -5193,7 +5182,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
        intel_crtc->cursor_addr = 0;
-       intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
+       intel_crtc->dpms_mode = -1;
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
        intel_crtc->busy = false;
@@ -5701,6 +5690,9 @@ void intel_init_clock_gating(struct drm_device *dev)
                        I915_WRITE(DISP_ARB_CTL,
                                        (I915_READ(DISP_ARB_CTL) |
                                                DISP_FBC_WM_DIS));
+               I915_WRITE(WM3_LP_ILK, 0);
+               I915_WRITE(WM2_LP_ILK, 0);
+               I915_WRITE(WM1_LP_ILK, 0);
                }
                /*
                 * Based on the document from hardware guys the following bits
@@ -5722,8 +5714,7 @@ void intel_init_clock_gating(struct drm_device *dev)
                                   ILK_DPFC_DIS2 |
                                   ILK_CLK_FBC);
                }
-               if (IS_GEN6(dev))
-                       return;
+               return;
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
                I915_WRITE(RENCLK_GATE_D1, 0);
@@ -5784,11 +5775,9 @@ void intel_init_clock_gating(struct drm_device *dev)
                                OUT_RING(MI_FLUSH);
                                ADVANCE_LP_RING();
                        }
-               } else {
+               } else
                        DRM_DEBUG_KMS("Failed to allocate render context."
-                                     "Disable RC6\n");
-                       return;
-               }
+                                      "Disable RC6\n");
        }
 
        if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
index 9caccd03dccb6841fea4be4c5fa43f5e8822ee33..9ab8708ac6ba1370cea75680d6a660daa5f9b147 100644 (file)
@@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        uint32_t ch_data = ch_ctl + 4;
        int i;
        int recv_bytes;
-       uint32_t ctl;
        uint32_t status;
        uint32_t aux_clock_divider;
        int try, precharge;
@@ -263,41 +262,43 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        else
                precharge = 5;
 
+       if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) {
+               DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
+                         I915_READ(ch_ctl));
+               return -EBUSY;
+       }
+
        /* Must try at least 3 times according to DP spec */
        for (try = 0; try < 5; try++) {
                /* Load the send data into the aux channel data registers */
-               for (i = 0; i < send_bytes; i += 4) {
-                       uint32_t    d = pack_aux(send + i, send_bytes - i);
-       
-                       I915_WRITE(ch_data + i, d);
-               }
-       
-               ctl = (DP_AUX_CH_CTL_SEND_BUSY |
-                      DP_AUX_CH_CTL_TIME_OUT_400us |
-                      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-                      (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
-                      (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
-                      DP_AUX_CH_CTL_DONE |
-                      DP_AUX_CH_CTL_TIME_OUT_ERROR |
-                      DP_AUX_CH_CTL_RECEIVE_ERROR);
+               for (i = 0; i < send_bytes; i += 4)
+                       I915_WRITE(ch_data + i,
+                                  pack_aux(send + i, send_bytes - i));
        
                /* Send the command and wait for it to complete */
-               I915_WRITE(ch_ctl, ctl);
-               (void) I915_READ(ch_ctl);
+               I915_WRITE(ch_ctl,
+                          DP_AUX_CH_CTL_SEND_BUSY |
+                          DP_AUX_CH_CTL_TIME_OUT_400us |
+                          (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+                          (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+                          (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+                          DP_AUX_CH_CTL_DONE |
+                          DP_AUX_CH_CTL_TIME_OUT_ERROR |
+                          DP_AUX_CH_CTL_RECEIVE_ERROR);
                for (;;) {
-                       udelay(100);
                        status = I915_READ(ch_ctl);
                        if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
                                break;
+                       udelay(100);
                }
        
                /* Clear done status and any errors */
-               I915_WRITE(ch_ctl, (status |
-                               DP_AUX_CH_CTL_DONE |
-                               DP_AUX_CH_CTL_TIME_OUT_ERROR |
-                               DP_AUX_CH_CTL_RECEIVE_ERROR));
-               (void) I915_READ(ch_ctl);
-               if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0)
+               I915_WRITE(ch_ctl,
+                          status |
+                          DP_AUX_CH_CTL_DONE |
+                          DP_AUX_CH_CTL_TIME_OUT_ERROR |
+                          DP_AUX_CH_CTL_RECEIVE_ERROR);
+               if (status & DP_AUX_CH_CTL_DONE)
                        break;
        }
 
@@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        /* Unload any bytes sent back from the other side */
        recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
                      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
-
        if (recv_bytes > recv_size)
                recv_bytes = recv_size;
        
-       for (i = 0; i < recv_bytes; i += 4) {
-               uint32_t    d = I915_READ(ch_data + i);
-
-               unpack_aux(d, recv + i, recv_bytes - i);
-       }
+       for (i = 0; i < recv_bytes; i += 4)
+               unpack_aux(I915_READ(ch_data + i),
+                          recv + i, recv_bytes - i);
 
        return recv_bytes;
 }
@@ -1140,18 +1138,14 @@ static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
                        uint32_t dp_reg_value,
                        uint8_t dp_train_pat,
-                       uint8_t train_set[4],
-                       bool first)
+                       uint8_t train_set[4])
 {
        struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
        int ret;
 
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
-       if (first)
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
 
        intel_dp_aux_native_write_1(intel_dp,
                                    DP_TRAINING_PATTERN_SET,
@@ -1176,10 +1170,15 @@ intel_dp_link_train(struct intel_dp *intel_dp)
        uint8_t voltage;
        bool clock_recovery = false;
        bool channel_eq = false;
-       bool first = true;
        int tries;
        u32 reg;
        uint32_t DP = intel_dp->DP;
+       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
+
+       /* Enable output, wait for it to become active */
+       I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+       POSTING_READ(intel_dp->output_reg);
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
 
        /* Write the link configuration data */
        intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
@@ -1212,9 +1211,8 @@ intel_dp_link_train(struct intel_dp *intel_dp)
                        reg = DP | DP_LINK_TRAIN_PAT_1;
 
                if (!intel_dp_set_link_train(intel_dp, reg,
-                                            DP_TRAINING_PATTERN_1, train_set, first))
+                                            DP_TRAINING_PATTERN_1, train_set))
                        break;
-               first = false;
                /* Set training pattern 1 */
 
                udelay(100);
@@ -1268,8 +1266,7 @@ intel_dp_link_train(struct intel_dp *intel_dp)
 
                /* channel eq pattern */
                if (!intel_dp_set_link_train(intel_dp, reg,
-                                            DP_TRAINING_PATTERN_2, train_set,
-                                            false))
+                                            DP_TRAINING_PATTERN_2, train_set))
                        break;
 
                udelay(400);
@@ -1388,7 +1385,7 @@ ironlake_dp_detect(struct drm_connector *connector)
  * \return false if DP port is disconnected.
  */
 static enum drm_connector_status
-intel_dp_detect(struct drm_connector *connector)
+intel_dp_detect(struct drm_connector *connector, bool force)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
index 0e92aa07b38252a4ac3457e75dc2b5113d8d9ded..8828b3ac6414eabff93134e34a41ae5c38d1cd34 100644 (file)
@@ -176,6 +176,16 @@ struct intel_crtc {
 #define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 
+struct intel_unpin_work {
+       struct work_struct work;
+       struct drm_device *dev;
+       struct drm_gem_object *old_fb_obj;
+       struct drm_gem_object *pending_flip_obj;
+       struct drm_pending_vblank_event *event;
+       int pending;
+       bool enable_stall_check;
+};
+
 struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
                                     const char *name);
 void intel_i2c_destroy(struct i2c_adapter *adapter);
@@ -219,7 +229,6 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
                                                    struct drm_crtc *crtc);
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
-extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe);
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
 extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
index a399f4b2c1c526cdfd64aa2d476f6b97c3fd69d2..7c9ec1472d46ab3cbb08f6bffc8257af952a64b0 100644 (file)
@@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
  *
  * Unimplemented.
  */
-static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
+static enum drm_connector_status
+intel_dvo_detect(struct drm_connector *connector, bool force)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
        struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
index 7bdc96256bf55b6e87d102377b428a871792be91..b61966c126d3e3839d33be6c8df2c0170c5d1376 100644 (file)
@@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev,
        drm_fb_helper_fini(&ifbdev->helper);
 
        drm_framebuffer_cleanup(&ifb->base);
-       if (ifb->obj)
+       if (ifb->obj) {
                drm_gem_object_unreference(ifb->obj);
+               ifb->obj = NULL;
+       }
 
        return 0;
 }
index ccd4c97e652492f19d85abf532d56aafcab6968a..926934a482ec085c63256567e27f0309b51b24cf 100644 (file)
@@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
 }
 
 static enum drm_connector_status
-intel_hdmi_detect(struct drm_connector *connector)
+intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
index b819c10811470775b19826e407ba75fffd6a9b68..6ec39a86ed06d2bd6e716611f3ab4d384d950636 100644 (file)
@@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
  * connected and closed means disconnected.  We also send hotplug events as
  * needed, using lid status notification from the input layer.
  */
-static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
+static enum drm_connector_status
+intel_lvds_detect(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
        enum drm_connector_status status = connector_status_connected;
@@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
         * the LID nofication event.
         */
        if (connector)
-               connector->status = connector->funcs->detect(connector);
+               connector->status = connector->funcs->detect(connector,
+                                                            false);
+
        /* Don't force modeset on machines where it causes a GPU lockup */
        if (dmi_check_system(intel_no_modeset_on_lid))
                return NOTIFY_OK;
@@ -875,8 +878,6 @@ void intel_lvds_init(struct drm_device *dev)
 
        intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
        intel_encoder->crtc_mask = (1 << 1);
-       if (IS_I965G(dev))
-               intel_encoder->crtc_mask |= (1 << 0);
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
index 4f00390d7c616b1c87ffe145082e1913a04935d0..1d306a458be6463c8e1f6636d69ebf515d845889 100644 (file)
@@ -25,6 +25,8 @@
  *
  * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
  */
+
+#include <linux/seq_file.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
index 51e9c9e718c4c16453659ef873f7d30b88f18f9e..cb3508f78bc350735e16962f8283e598c53deca6 100644 (file)
@@ -220,9 +220,13 @@ static int init_render_ring(struct drm_device *dev,
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret = init_ring_common(dev, ring);
+       int mode;
+
        if (IS_I9XX(dev) && !IS_GEN3(dev)) {
-               I915_WRITE(MI_MODE,
-                               (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+               mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
+               if (IS_GEN6(dev))
+                       mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
+               I915_WRITE(MI_MODE, mode);
        }
        return ret;
 }
index 093e914e8a41a3d58b645dcf8475cb24312b3e1e..ee73e428a84a800dd8d70a1747457033f7e8da8e 100644 (file)
@@ -1061,8 +1061,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
                        return false;
 
-               if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode))
-                       return false;
+               (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
+                                                            mode,
+                                                            adjusted_mode);
        } else if (intel_sdvo->is_lvds) {
                drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0);
 
@@ -1070,8 +1071,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
                                                            intel_sdvo->sdvo_lvds_fixed_mode))
                        return false;
 
-               if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode))
-                       return false;
+               (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
+                                                            mode,
+                                                            adjusted_mode);
        }
 
        /* Make the CRTC code factor in the SDVO pixel multiplier.  The
@@ -1108,10 +1110,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
        in_out.in0 = intel_sdvo->attached_output;
        in_out.in1 = 0;
 
-       if (!intel_sdvo_set_value(intel_sdvo,
-                                 SDVO_CMD_SET_IN_OUT_MAP,
-                                 &in_out, sizeof(in_out)))
-               return;
+       intel_sdvo_set_value(intel_sdvo,
+                            SDVO_CMD_SET_IN_OUT_MAP,
+                            &in_out, sizeof(in_out));
 
        if (intel_sdvo->is_hdmi) {
                if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode))
@@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 
        /* We have tried to get input timing in mode_fixup, and filled into
           adjusted_mode */
-       if (intel_sdvo->is_tv || intel_sdvo->is_lvds) {
-               intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
                input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags;
-       } else
-               intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
        /* If it's a TV, we already set the output timing in mode_fixup.
         * Otherwise, the output timing is equal to the input timing.
@@ -1137,8 +1136,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
                                                  intel_sdvo->attached_output))
                        return;
 
-               if (!intel_sdvo_set_output_timing(intel_sdvo, &input_dtd))
-                       return;
+               (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd);
        }
 
        /* Set the input timing to the screen. Assume always input 0. */
@@ -1165,8 +1163,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
                intel_sdvo_set_input_timing(encoder, &input_dtd);
        }
 #else
-       if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
-               return;
+       (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
 #endif
 
        sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode);
@@ -1420,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev)
        if (!analog_connector)
                return false;
 
-       if (analog_connector->funcs->detect(analog_connector) ==
+       if (analog_connector->funcs->detect(analog_connector, false) ==
                        connector_status_disconnected)
                return false;
 
@@ -1489,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
        return status;
 }
 
-static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
+static enum drm_connector_status
+intel_sdvo_detect(struct drm_connector *connector, bool force)
 {
        uint16_t response;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -1932,6 +1930,41 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
        .destroy = intel_sdvo_enc_destroy,
 };
 
+static void
+intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
+{
+       uint16_t mask = 0;
+       unsigned int num_bits;
+
+       /* Make a mask of outputs less than or equal to our own priority in the
+        * list.
+        */
+       switch (sdvo->controlled_output) {
+       case SDVO_OUTPUT_LVDS1:
+               mask |= SDVO_OUTPUT_LVDS1;
+       case SDVO_OUTPUT_LVDS0:
+               mask |= SDVO_OUTPUT_LVDS0;
+       case SDVO_OUTPUT_TMDS1:
+               mask |= SDVO_OUTPUT_TMDS1;
+       case SDVO_OUTPUT_TMDS0:
+               mask |= SDVO_OUTPUT_TMDS0;
+       case SDVO_OUTPUT_RGB1:
+               mask |= SDVO_OUTPUT_RGB1;
+       case SDVO_OUTPUT_RGB0:
+               mask |= SDVO_OUTPUT_RGB0;
+               break;
+       }
+
+       /* Count bits to find what number we are in the priority list. */
+       mask &= sdvo->caps.output_flags;
+       num_bits = hweight16(mask);
+       /* If more than 3 outputs, default to DDC bus 3 for now. */
+       if (num_bits > 3)
+               num_bits = 3;
+
+       /* Corresponds to SDVO_CONTROL_BUS_DDCx */
+       sdvo->ddc_bus = 1 << num_bits;
+}
 
 /**
  * Choose the appropriate DDC bus for control bus switch command for this
@@ -1951,7 +1984,10 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
        else
                mapping = &(dev_priv->sdvo_mappings[1]);
 
-       sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
+       if (mapping->initialized)
+               sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
+       else
+               intel_sdvo_guess_ddc_bus(sdvo);
 }
 
 static bool
@@ -2134,8 +2170,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
         return true;
 
 err:
-       intel_sdvo_destroy_enhance_property(connector);
-       kfree(intel_sdvo_connector);
+       intel_sdvo_destroy(connector);
        return false;
 }
 
@@ -2207,8 +2242,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        return true;
 
 err:
-       intel_sdvo_destroy_enhance_property(connector);
-       kfree(intel_sdvo_connector);
+       intel_sdvo_destroy(connector);
        return false;
 }
 
@@ -2486,11 +2520,10 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
                uint16_t response;
        } enhancements;
 
-       if (!intel_sdvo_get_value(intel_sdvo,
-                                 SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
-                                 &enhancements, sizeof(enhancements)))
-               return false;
-
+       enhancements.response = 0;
+       intel_sdvo_get_value(intel_sdvo,
+                            SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
+                            &enhancements, sizeof(enhancements));
        if (enhancements.response == 0) {
                DRM_DEBUG_KMS("No enhancement is supported\n");
                return true;
index d2029efee982c3baff92538556ddae0b7a44ea9b..4a117e318a73a0a44c7ae4cc0be3447d11a403da 100644 (file)
@@ -1231,7 +1231,6 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
        struct drm_encoder *encoder = &intel_tv->base.enc;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
        unsigned long irqflags;
        u32 tv_ctl, save_tv_ctl;
        u32 tv_dac, save_tv_dac;
@@ -1268,11 +1267,15 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
                   DAC_C_0_7_V);
        I915_WRITE(TV_CTL, tv_ctl);
        I915_WRITE(TV_DAC, tv_dac);
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       POSTING_READ(TV_DAC);
+       msleep(20);
+
        tv_dac = I915_READ(TV_DAC);
        I915_WRITE(TV_DAC, save_tv_dac);
        I915_WRITE(TV_CTL, save_tv_ctl);
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       POSTING_READ(TV_CTL);
+       msleep(20);
+
        /*
         *  A B C
         *  0 1 1 Composite
@@ -1338,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
  * we have a pipe programmed in order to probe the TV.
  */
 static enum drm_connector_status
-intel_tv_detect(struct drm_connector *connector)
+intel_tv_detect(struct drm_connector *connector, bool force)
 {
        struct drm_display_mode mode;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -1350,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector)
 
        if (encoder->crtc && encoder->crtc->enabled) {
                type = intel_tv_detect_type(intel_tv);
-       } else {
+       } else if (force) {
                struct drm_crtc *crtc;
                int dpms_mode;
 
@@ -1361,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector)
                        intel_release_load_detect_pipe(&intel_tv->base, connector,
                                                       dpms_mode);
                } else
-                       type = -1;
-       }
-
-       intel_tv->type = type;
+                       return connector_status_unknown;
+       } else
+               return connector->status;
 
        if (type < 0)
                return connector_status_disconnected;
index 26d0d8ced80d4357421875b4c7344f53e21d96b4..ac64f0b0392edb32e57a3b0da85c4185ad4efa59 100644 (file)
@@ -75,6 +75,7 @@ static struct drm_driver driver = {
 #ifdef CONFIG_COMPAT
                .compat_ioctl = mga_compat_ioctl,
 #endif
+               .llseek = noop_llseek,
        },
        .pci_driver = {
                .name = DRIVER_NAME,
index fff82045c427eec5372c6ca3747f64bd16dcabd0..9ce2827f8c00d53a8b7a793f785024c846084d84 100644 (file)
@@ -1085,19 +1085,19 @@ file_priv)
 }
 
 struct drm_ioctl_desc mga_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 };
 
 int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
index 0b69a9628c95dee9585584672a1ec9f820aa600e..974b0f8ae0483cc462b1be9a81795413e7a7a0c1 100644 (file)
@@ -2166,7 +2166,7 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
        uint32_t val = 0;
 
        if (off < pci_resource_len(dev->pdev, 1)) {
-               uint32_t __iomem *p =
+               uint8_t __iomem *p =
                        io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
 
                val = ioread32(p + (off & ~PAGE_MASK));
@@ -2182,7 +2182,7 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
        uint32_t off, uint32_t val)
 {
        if (off < pci_resource_len(dev->pdev, 1)) {
-               uint32_t __iomem *p =
+               uint8_t __iomem *p =
                        io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
 
                iowrite32(val, p + (off & ~PAGE_MASK));
@@ -3869,27 +3869,10 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
        }
 #ifdef __powerpc__
        /* Powerbook specific quirks */
-       if ((dev->pci_device & 0xffff) == 0x0179 ||
-           (dev->pci_device & 0xffff) == 0x0189 ||
-           (dev->pci_device & 0xffff) == 0x0329) {
-               if (script == LVDS_RESET) {
-                       nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
-
-               } else if (script == LVDS_PANEL_ON) {
-                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
-                                 bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
-                                 | (1 << 31));
-                       bios_wr32(bios, NV_PCRTC_GPIO_EXT,
-                                 bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
-
-               } else if (script == LVDS_PANEL_OFF) {
-                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
-                                 bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
-                                 & ~(1 << 31));
-                       bios_wr32(bios, NV_PCRTC_GPIO_EXT,
-                                 bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
-               }
-       }
+       if (script == LVDS_RESET &&
+           (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 ||
+            dev->pci_device == 0x0329))
+               nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
 #endif
 
        return 0;
@@ -4381,11 +4364,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
         *
         * For the moment, a quirk will do :)
         */
-       if ((dev->pdev->device == 0x01d7) &&
-           (dev->pdev->subsystem_vendor == 0x1028) &&
-           (dev->pdev->subsystem_device == 0x01c2)) {
+       if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2))
                bios->fp.duallink_transition_clk = 80000;
-       }
 
        /* set dual_link flag for EDID case */
        if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
@@ -4587,7 +4567,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        return 1;
                }
 
-               NV_TRACE(dev, "0x%04X: parsing output script 0\n", script);
+               NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
                nouveau_bios_run_init_table(dev, script, dcbent);
        } else
        if (pxclk == -1) {
@@ -4597,7 +4577,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        return 1;
                }
 
-               NV_TRACE(dev, "0x%04X: parsing output script 1\n", script);
+               NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
                nouveau_bios_run_init_table(dev, script, dcbent);
        } else
        if (pxclk == -2) {
@@ -4610,7 +4590,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        return 1;
                }
 
-               NV_TRACE(dev, "0x%04X: parsing output script 2\n", script);
+               NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
                nouveau_bios_run_init_table(dev, script, dcbent);
        } else
        if (pxclk > 0) {
@@ -4622,7 +4602,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        return 1;
                }
 
-               NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script);
+               NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
                nouveau_bios_run_init_table(dev, script, dcbent);
        } else
        if (pxclk < 0) {
@@ -4634,7 +4614,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        return 1;
                }
 
-               NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script);
+               NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
                nouveau_bios_run_init_table(dev, script, dcbent);
        }
 
@@ -5357,19 +5337,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios,
        }
 
        tmdstableptr = ROM16(bios->data[bitentry->offset]);
-
-       if (tmdstableptr == 0x0) {
+       if (!tmdstableptr) {
                NV_ERROR(dev, "Pointer to TMDS table invalid\n");
                return -EINVAL;
        }
 
+       NV_INFO(dev, "TMDS table version %d.%d\n",
+               bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
+
        /* nv50+ has v2.0, but we don't parse it atm */
-       if (bios->data[tmdstableptr] != 0x11) {
-               NV_WARN(dev,
-                       "TMDS table revision %d.%d not currently supported\n",
-                       bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
+       if (bios->data[tmdstableptr] != 0x11)
                return -ENOSYS;
-       }
 
        /*
         * These two scripts are odd: they don't seem to get run even when
@@ -5809,6 +5787,20 @@ parse_dcb_gpio_table(struct nvbios *bios)
                        gpio->line = tvdac_gpio[1] >> 4;
                        gpio->invert = tvdac_gpio[0] & 2;
                }
+       } else {
+               /*
+                * No systematic way to store GPIO info on pre-v2.2
+                * DCBs, try to match the PCI device IDs.
+                */
+
+               /* Apple iMac G4 NV18 */
+               if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) {
+                       struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
+
+                       gpio->tag = DCB_GPIO_TVDAC0;
+                       gpio->line = 4;
+               }
+
        }
 
        if (!gpio_table_ptr)
@@ -5884,9 +5876,7 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
        struct drm_device *dev = bios->dev;
 
        /* Gigabyte NX85T */
-       if ((dev->pdev->device == 0x0421) &&
-           (dev->pdev->subsystem_vendor == 0x1458) &&
-           (dev->pdev->subsystem_device == 0x344c)) {
+       if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) {
                if (cte->type == DCB_CONNECTOR_HDMI_1)
                        cte->type = DCB_CONNECTOR_DVI_I;
        }
@@ -6139,7 +6129,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
                        entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
 
                break;
-       case 0xe:
+       case OUTPUT_EOL:
                /* weird g80 mobile type that "nv" treats as a terminator */
                dcb->entries--;
                return false;
@@ -6176,22 +6166,14 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
                entry->type = OUTPUT_TV;
                break;
        case 2:
-       case 3:
-               entry->type = OUTPUT_LVDS;
-               break;
        case 4:
-               switch ((conn & 0x000000f0) >> 4) {
-               case 0:
-                       entry->type = OUTPUT_TMDS;
-                       break;
-               case 1:
+               if (conn & 0x10)
                        entry->type = OUTPUT_LVDS;
-                       break;
-               default:
-                       NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
-                                (conn & 0x000000f0) >> 4);
-                       return false;
-               }
+               else
+                       entry->type = OUTPUT_TMDS;
+               break;
+       case 3:
+               entry->type = OUTPUT_LVDS;
                break;
        default:
                NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
@@ -6307,9 +6289,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
         * nasty problems until this is sorted (assuming it's not a
         * VBIOS bug).
         */
-       if ((dev->pdev->device == 0x040d) &&
-           (dev->pdev->subsystem_vendor == 0x1028) &&
-           (dev->pdev->subsystem_device == 0x019b)) {
+       if (nv_match_device(dev, 0x040d, 0x1028, 0x019b)) {
                if (*conn == 0x02026312 && *conf == 0x00000020)
                        return false;
        }
index fd14dfd3d780f6b45a280d1cf4c4aed6eb41ed20..c1de2f3fcb0ea7e78ec193d88c74683d5090eaba 100644 (file)
@@ -95,6 +95,7 @@ enum dcb_type {
        OUTPUT_TMDS = 2,
        OUTPUT_LVDS = 3,
        OUTPUT_DP = 6,
+       OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */
        OUTPUT_ANY = -1
 };
 
index 84f85183d041f38d9d848137abf24b236a32626f..f6f44779d82fb801ac738cc9e5f83e4179fd6de3 100644 (file)
 #include <linux/log2.h>
 #include <linux/slab.h>
 
+int
+nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan)
+{
+       struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
+       int ret;
+
+       if (!prev_fence || nouveau_fence_channel(prev_fence) == chan)
+               return 0;
+
+       spin_lock(&nvbo->bo.lock);
+       ret = ttm_bo_wait(&nvbo->bo, false, false, false);
+       spin_unlock(&nvbo->bo.lock);
+       return ret;
+}
+
 static void
 nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
 {
index 90fdcda332be360ab07cb862c9a6ad533724a55c..0480f064f2c14fd8c4bf41672fa039f9f2bc9029 100644 (file)
@@ -426,18 +426,18 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
  ***********************************/
 
 struct drm_ioctl_desc nouveau_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
index b1b22baf14284a6d2105a320f7602f3e81b00529..fc737037f751c3690dfb09239e3439df1fa4191c 100644 (file)
@@ -104,7 +104,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
        int i;
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               struct nouveau_i2c_chan *i2c;
+               struct nouveau_i2c_chan *i2c = NULL;
                struct nouveau_encoder *nv_encoder;
                struct drm_mode_object *obj;
                int id;
@@ -117,7 +117,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
                if (!obj)
                        continue;
                nv_encoder = nouveau_encoder(obj_to_encoder(obj));
-               i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+
+               if (nv_encoder->dcb->i2c_index < 0xf)
+                       i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
 
                if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
                        *pnv_encoder = nv_encoder;
@@ -166,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
 }
 
 static enum drm_connector_status
-nouveau_connector_detect(struct drm_connector *connector)
+nouveau_connector_detect(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
@@ -244,7 +246,7 @@ detect_analog:
 }
 
 static enum drm_connector_status
-nouveau_connector_detect_lvds(struct drm_connector *connector)
+nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -265,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector)
 
        /* Try retrieving EDID via DDC */
        if (!dev_priv->vbios.fp_no_ddc) {
-               status = nouveau_connector_detect(connector);
+               status = nouveau_connector_detect(connector, force);
                if (status == connector_status_connected)
                        goto out;
        }
@@ -556,8 +558,10 @@ nouveau_connector_get_modes(struct drm_connector *connector)
        if (nv_encoder->dcb->type == OUTPUT_LVDS &&
            (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
             dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
-               nv_connector->native_mode = drm_mode_create(dev);
-               nouveau_bios_fp_mode(dev, nv_connector->native_mode);
+               struct drm_display_mode mode;
+
+               nouveau_bios_fp_mode(dev, &mode);
+               nv_connector->native_mode = drm_mode_duplicate(dev, &mode);
        }
 
        /* Find the native mode if this is a digital panel, if we didn't
index 1de5eb53e0164be3cc81cf5a17f7969bc211e4ef..eb15345162a03af66a556ccd6f083907261abd90 100644 (file)
@@ -393,6 +393,7 @@ static struct drm_driver driver = {
 #if defined(CONFIG_COMPAT)
                .compat_ioctl = nouveau_compat_ioctl,
 #endif
+               .llseek = noop_llseek,
        },
        .pci_driver = {
                .name = DRIVER_NAME,
index e424bf74d706307c237c7c3976498dafea0fd29c..b1be617373b63891dc05b09f2dc75807cd8b8472 100644 (file)
@@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
 extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
 extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
 extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
+extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *);
 
 /* nouveau_fence.c */
 struct nouveau_fence;
@@ -1388,6 +1389,15 @@ nv_two_reg_pll(struct drm_device *dev)
        return false;
 }
 
+static inline bool
+nv_match_device(struct drm_device *dev, unsigned device,
+               unsigned sub_vendor, unsigned sub_device)
+{
+       return dev->pdev->device == device &&
+               dev->pdev->subsystem_vendor == sub_vendor &&
+               dev->pdev->subsystem_device == sub_device;
+}
+
 #define NV_SW                                                        0x0000506e
 #define NV_SW_DMA_SEMAPHORE                                          0x00000060
 #define NV_SW_SEMAPHORE_OFFSET                                       0x00000064
index 6b208ffafa8de1df0bdd5dd6ff6aede30f929341..87ac21ec23d290db82e90c6fe6257e4cffdb5955 100644 (file)
@@ -64,16 +64,17 @@ nouveau_fence_update(struct nouveau_channel *chan)
        struct nouveau_fence *fence;
        uint32_t sequence;
 
+       spin_lock(&chan->fence.lock);
+
        if (USE_REFCNT)
                sequence = nvchan_rd32(chan, 0x48);
        else
                sequence = atomic_read(&chan->fence.last_sequence_irq);
 
        if (chan->fence.sequence_ack == sequence)
-               return;
+               goto out;
        chan->fence.sequence_ack = sequence;
 
-       spin_lock(&chan->fence.lock);
        list_for_each_safe(entry, tmp, &chan->fence.pending) {
                fence = list_entry(entry, struct nouveau_fence, entry);
 
@@ -85,6 +86,7 @@ nouveau_fence_update(struct nouveau_channel *chan)
                if (sequence == chan->fence.sequence_ack)
                        break;
        }
+out:
        spin_unlock(&chan->fence.lock);
 }
 
index 0f417ac1b696b769a0982f762bfa696a50637de1..19620a6709f55c00e97efd5d2f816705788420f8 100644 (file)
@@ -167,11 +167,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
                goto out;
 
        ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+       /* drop reference from allocate - handle holds it now */
+       drm_gem_object_unreference_unlocked(nvbo->gem);
 out:
-       drm_gem_object_handle_unreference_unlocked(nvbo->gem);
-
-       if (ret)
-               drm_gem_object_unreference_unlocked(nvbo->gem);
        return ret;
 }
 
@@ -245,7 +243,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
                list_del(&nvbo->entry);
                nvbo->reserved_by = NULL;
                ttm_bo_unreserve(&nvbo->bo);
-               drm_gem_object_unreference(nvbo->gem);
+               drm_gem_object_unreference_unlocked(nvbo->gem);
        }
 }
 
@@ -300,7 +298,7 @@ retry:
                        validate_fini(op, NULL);
                        if (ret == -EAGAIN)
                                ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
-                       drm_gem_object_unreference(gem);
+                       drm_gem_object_unreference_unlocked(gem);
                        if (ret) {
                                NV_ERROR(dev, "fail reserve\n");
                                return ret;
@@ -337,7 +335,9 @@ retry:
                                return -EINVAL;
                        }
 
+                       mutex_unlock(&drm_global_mutex);
                        ret = ttm_bo_wait_cpu(&nvbo->bo, false);
+                       mutex_lock(&drm_global_mutex);
                        if (ret) {
                                NV_ERROR(dev, "fail wait_cpu\n");
                                return ret;
@@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
 
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
-               struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
 
-               if (prev_fence && nouveau_fence_channel(prev_fence) != chan) {
-                       spin_lock(&nvbo->bo.lock);
-                       ret = ttm_bo_wait(&nvbo->bo, false, false, false);
-                       spin_unlock(&nvbo->bo.lock);
-                       if (unlikely(ret)) {
-                               NV_ERROR(dev, "fail wait other chan\n");
-                               return ret;
-                       }
+               ret = nouveau_bo_sync_gpu(nvbo, chan);
+               if (unlikely(ret)) {
+                       NV_ERROR(dev, "fail pre-validate sync\n");
+                       return ret;
                }
 
                ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
@@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                        return ret;
                }
 
-               nvbo->channel = chan;
+               nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
                ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
                                      false, false, false);
                nvbo->channel = NULL;
@@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                        return ret;
                }
 
+               ret = nouveau_bo_sync_gpu(nvbo, chan);
+               if (unlikely(ret)) {
+                       NV_ERROR(dev, "fail post-validate sync\n");
+                       return ret;
+               }
+
                if (nvbo->bo.offset == b->presumed.offset &&
                    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
                      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
@@ -613,7 +614,20 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
                return PTR_ERR(bo);
        }
 
-       mutex_lock(&dev->struct_mutex);
+       /* Mark push buffers as being used on PFIFO, the validation code
+        * will then make sure that if the pushbuf bo moves, that they
+        * happen on the kernel channel, which will in turn cause a sync
+        * to happen before we try and submit the push buffer.
+        */
+       for (i = 0; i < req->nr_push; i++) {
+               if (push[i].bo_index >= req->nr_buffers) {
+                       NV_ERROR(dev, "push %d buffer not in list\n", i);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               bo[push[i].bo_index].read_domains |= (1 << 31);
+       }
 
        /* Validate buffer list */
        ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
@@ -647,7 +661,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
                                      push[i].length);
                }
        } else
-       if (dev_priv->card_type >= NV_20) {
+       if (dev_priv->chipset >= 0x25) {
                ret = RING_SPACE(chan, req->nr_push * 2);
                if (ret) {
                        NV_ERROR(dev, "cal_space: %d\n", ret);
@@ -713,7 +727,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 out:
        validate_fini(&op, fence);
        nouveau_fence_unref((void**)&fence);
-       mutex_unlock(&dev->struct_mutex);
        kfree(bo);
        kfree(push);
 
@@ -722,7 +735,7 @@ out_next:
                req->suffix0 = 0x00000000;
                req->suffix1 = 0x00000000;
        } else
-       if (dev_priv->card_type >= NV_20) {
+       if (dev_priv->chipset >= 0x25) {
                req->suffix0 = 0x00020000;
                req->suffix1 = 0x00000000;
        } else {
index 0bd407ca3d429117ac3cdf0e42f1ccf5b5e853d7..84614858728ba0f7ab959b54989cf9a512d89d6a 100644 (file)
@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
        if (entry->chan)
                return -EEXIST;
 
-       if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) {
+       if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
                NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
                return -EINVAL;
        }
index 491767fe4fcfd3b705c3bdb82b4ebeded1bfe9bb..6b9187d7f67de4383502973ef5cdfc9259ec6f1a 100644 (file)
@@ -214,6 +214,7 @@ int
 nouveau_sgdma_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct pci_dev *pdev = dev->pdev;
        struct nouveau_gpuobj *gpuobj = NULL;
        uint32_t aper_size, obj_size;
        int i, ret;
@@ -239,10 +240,19 @@ nouveau_sgdma_init(struct drm_device *dev)
 
        dev_priv->gart_info.sg_dummy_page =
                alloc_page(GFP_KERNEL|__GFP_DMA32);
+       if (!dev_priv->gart_info.sg_dummy_page) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return -ENOMEM;
+       }
+
        set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
        dev_priv->gart_info.sg_dummy_bus =
-               pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
+               pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0,
                             PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+       if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return -EFAULT;
+       }
 
        if (dev_priv->card_type < NV_50) {
                /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
index a5dcf7685800c4effb3d1c4938736b4c48c36eb0..0d3206a7046cb008814237250d5fa9fe2502ac2c 100644 (file)
@@ -444,6 +444,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct dcb_entry *dcbe = nv_encoder->dcb;
        int head = nouveau_crtc(encoder->crtc)->index;
+       struct drm_encoder *slave_encoder;
 
        if (dcbe->type == OUTPUT_TMDS)
                run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
@@ -462,9 +463,10 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
                NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
 
        /* Init external transmitters */
-       if (get_tmds_slave(encoder))
-               get_slave_funcs(get_tmds_slave(encoder))->mode_set(
-                       encoder, &nv_encoder->mode, &nv_encoder->mode);
+       slave_encoder = get_tmds_slave(encoder);
+       if (slave_encoder)
+               get_slave_funcs(slave_encoder)->mode_set(
+                       slave_encoder, &nv_encoder->mode, &nv_encoder->mode);
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
@@ -473,6 +475,27 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
+static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
+{
+#ifdef __powerpc__
+       struct drm_device *dev = encoder->dev;
+
+       /* BIOS scripts usually take care of the backlight, thanks
+        * Apple for your consistency.
+        */
+       if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 ||
+           dev->pci_device == 0x0329) {
+               if (mode == DRM_MODE_DPMS_ON) {
+                       nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31);
+                       nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 1);
+               } else {
+                       nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0);
+                       nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 0);
+               }
+       }
+#endif
+}
+
 static inline bool is_powersaving_dpms(int mode)
 {
        return (mode != DRM_MODE_DPMS_ON);
@@ -520,6 +543,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
                                         LVDS_PANEL_OFF, 0);
        }
 
+       nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
 
        if (mode == DRM_MODE_DPMS_ON)
@@ -543,6 +567,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
        NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n",
                     mode, nv_encoder->dcb->index);
 
+       nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
 }
 
index 44fefb0c7083caf5c4e77011675927dc3d60aec6..13cdc05b7c2d0f4e7785cbe428ce4ab86205bd67 100644 (file)
@@ -121,10 +121,14 @@ static bool
 get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
 {
        /* Zotac FX5200 */
-       if (dev->pdev->device == 0x0322 &&
-           dev->pdev->subsystem_vendor == 0x19da &&
-           (dev->pdev->subsystem_device == 0x1035 ||
-            dev->pdev->subsystem_device == 0x2035)) {
+       if (nv_match_device(dev, 0x0322, 0x19da, 0x1035) ||
+           nv_match_device(dev, 0x0322, 0x19da, 0x2035)) {
+               *pin_mask = 0xc;
+               return false;
+       }
+
+       /* MSI nForce2 IGP */
+       if (nv_match_device(dev, 0x01f0, 0x1462, 0x5710)) {
                *pin_mask = 0xc;
                return false;
        }
index 37c7b48ab24af8a37c3e8ac29656b989ec5935f5..91ef93cf1f352f89553b7dab4ab9fb4f219326ad 100644 (file)
@@ -139,6 +139,8 @@ nv50_instmem_init(struct drm_device *dev)
        chan->file_priv = (struct drm_file *)-2;
        dev_priv->fifos[0] = dev_priv->fifos[127] = chan;
 
+       INIT_LIST_HEAD(&chan->ramht_refs);
+
        /* Channel's PRAMIN object + heap */
        ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0,
                                                        NULL, &chan->ramin);
@@ -278,7 +280,7 @@ nv50_instmem_init(struct drm_device *dev)
        /*XXX: incorrect, but needed to make hash func "work" */
        dev_priv->ramht_offset = 0x10000;
        dev_priv->ramht_bits   = 9;
-       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
+       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits) * 8;
        return 0;
 }
 
index 3ab3cdc42173300490c7e667eced2f39b0d36690..6b451f864783e5c1ed3610c13c86adb5588a5783 100644 (file)
@@ -142,14 +142,16 @@ int
 nvc0_instmem_suspend(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       u32 *buf;
        int i;
 
        dev_priv->susres.ramin_copy = vmalloc(65536);
        if (!dev_priv->susres.ramin_copy)
                return -ENOMEM;
+       buf = dev_priv->susres.ramin_copy;
 
-       for (i = 0x700000; i < 0x710000; i += 4)
-               dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i);
+       for (i = 0; i < 65536; i += 4)
+               buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i);
        return 0;
 }
 
@@ -157,14 +159,15 @@ void
 nvc0_instmem_resume(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       u32 *buf = dev_priv->susres.ramin_copy;
        u64 chan;
        int i;
 
        chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
        nv_wr32(dev, 0x001700, chan >> 16);
 
-       for (i = 0x700000; i < 0x710000; i += 4)
-               nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]);
+       for (i = 0; i < 65536; i += 4)
+               nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]);
        vfree(dev_priv->susres.ramin_copy);
        dev_priv->susres.ramin_copy = NULL;
 
@@ -221,7 +224,7 @@ nvc0_instmem_init(struct drm_device *dev)
        /*XXX: incorrect, but needed to make hash func "work" */
        dev_priv->ramht_offset = 0x10000;
        dev_priv->ramht_bits   = 9;
-       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
+       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits) * 8;
        return 0;
 }
 
index 1e2971f13aa1f5775f518db92967c5c5a6c83ddf..d42c76c237142225adf95332a3e4ca2c2dee62ea 100644 (file)
@@ -71,6 +71,7 @@ static struct drm_driver driver = {
 #ifdef CONFIG_COMPAT
                .compat_ioctl = r128_compat_ioctl,
 #endif
+               .llseek = noop_llseek,
        },
        .pci_driver = {
                .name = DRIVER_NAME,
index 077af1f2f9b4faee1f3e840f8e4a52813cb05108..a9e33ce65918c98bed3c039dbc65fa8e02bac15e 100644 (file)
@@ -1639,30 +1639,29 @@ void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
                        r128_do_cleanup_pageflip(dev);
        }
 }
-
 void r128_driver_lastclose(struct drm_device *dev)
 {
        r128_do_cleanup_cce(dev);
 }
 
 struct drm_ioctl_desc r128_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH),
 };
 
 int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
index 1bc72c3190a9dcfe9b8f70f16087a231560d9b08..fe359a239df343437cce0b0c79d2692c559ffb9e 100644 (file)
@@ -4999,7 +4999,7 @@ typedef struct _SW_I2C_IO_DATA_PARAMETERS
 #define SW_I2C_CNTL_WRITE1BIT 6
 
 //==============================VESA definition Portion===============================
-#define VESA_OEM_PRODUCT_REV                               '01.00'
+#define VESA_OEM_PRODUCT_REV                               "01.00"
 #define VESA_MODE_ATTRIBUTE_MODE_SUPPORT            0xBB       //refer to VBE spec p.32, no TTY support
 #define VESA_MODE_WIN_ATTRIBUTE                                                     7
 #define VESA_WIN_SIZE                                                                                       64
index 12ad512bd3d33ad316655400212626585126c6de..cd0290f946cff51e8aa8c702dda5e650ec5f9af0 100644 (file)
@@ -332,6 +332,11 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
        args.usV_SyncWidth =
                cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
 
+       args.ucOverscanRight = radeon_crtc->h_border;
+       args.ucOverscanLeft = radeon_crtc->h_border;
+       args.ucOverscanBottom = radeon_crtc->v_border;
+       args.ucOverscanTop = radeon_crtc->v_border;
+
        if (mode->flags & DRM_MODE_FLAG_NVSYNC)
                misc |= ATOM_VSYNC_POLARITY;
        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
@@ -471,6 +476,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
        struct radeon_encoder *radeon_encoder = NULL;
        u32 adjusted_clock = mode->clock;
        int encoder_mode = 0;
+       u32 dp_clock = mode->clock;
+       int bpc = 8;
 
        /* reset the pll flags */
        pll->flags = 0;
@@ -513,6 +520,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if (encoder->crtc == crtc) {
                        radeon_encoder = to_radeon_encoder(encoder);
                        encoder_mode = atombios_get_encoder_mode(encoder);
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) {
+                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+                               if (connector) {
+                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+                                       struct radeon_connector_atom_dig *dig_connector =
+                                               radeon_connector->con_priv;
+
+                                       dp_clock = dig_connector->dp_clock;
+                               }
+                       }
+
                        if (ASIC_IS_AVIVO(rdev)) {
                                /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
                                if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
@@ -521,6 +539,21 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        pll->algo = PLL_ALGO_LEGACY;
                                        pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
                                }
+                               /* There is some evidence (often anecdotal) that RV515/RV620 LVDS
+                                * (on some boards at least) prefers the legacy algo.  I'm not
+                                * sure whether this should handled generically or on a
+                                * case-by-case quirk basis.  Both algos should work fine in the
+                                * majority of cases.
+                                */
+                               if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) &&
+                                   ((rdev->family == CHIP_RV515) ||
+                                    (rdev->family == CHIP_RV620))) {
+                                       /* allow the user to overrride just in case */
+                                       if (radeon_new_pll == 1)
+                                               pll->algo = PLL_ALGO_NEW;
+                                       else
+                                               pll->algo = PLL_ALGO_LEGACY;
+                               }
                        } else {
                                if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
                                        pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
@@ -555,6 +588,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
                                args.v1.ucTransmitterID = radeon_encoder->encoder_id;
                                args.v1.ucEncodeMode = encoder_mode;
+                               if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+                                       /* may want to enable SS on DP eventually */
+                                       /* args.v1.ucConfig |=
+                                          ADJUST_DISPLAY_CONFIG_SS_ENABLE;*/
+                               } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) {
+                                       args.v1.ucConfig |=
+                                               ADJUST_DISPLAY_CONFIG_SS_ENABLE;
+                               }
 
                                atom_execute_table(rdev->mode_info.atom_context,
                                                   index, (uint32_t *)&args);
@@ -568,10 +609,20 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
-                                       if (encoder_mode == ATOM_ENCODER_MODE_DP)
+                                       if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+                                               /* may want to enable SS on DP/eDP eventually */
+                                               /*args.v3.sInput.ucDispPllConfig |=
+                                                 DISPPLL_CONFIG_SS_ENABLE;*/
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_COHERENT_MODE;
-                                       else {
+                                               /* 16200 or 27000 */
+                                               args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
+                                       } else {
+                                               if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+                                                       /* deep color support */
+                                                       args.v3.sInput.usPixelClock =
+                                                               cpu_to_le16((mode->clock * bpc / 8) / 10);
+                                               }
                                                if (dig->coherent_mode)
                                                        args.v3.sInput.ucDispPllConfig |=
                                                                DISPPLL_CONFIG_COHERENT_MODE;
@@ -580,13 +631,19 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                                                DISPPLL_CONFIG_DUAL_LINK;
                                        }
                                } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                                       /* may want to enable SS on DP/eDP eventually */
-                                       /*args.v3.sInput.ucDispPllConfig |=
-                                               DISPPLL_CONFIG_SS_ENABLE;*/
-                                       if (encoder_mode == ATOM_ENCODER_MODE_DP)
+                                       if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+                                               /* may want to enable SS on DP/eDP eventually */
+                                               /*args.v3.sInput.ucDispPllConfig |=
+                                                 DISPPLL_CONFIG_SS_ENABLE;*/
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_COHERENT_MODE;
-                                       else {
+                                               /* 16200 or 27000 */
+                                               args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
+                                       } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) {
+                                               /* want to enable SS on LVDS eventually */
+                                               /*args.v3.sInput.ucDispPllConfig |=
+                                                 DISPPLL_CONFIG_SS_ENABLE;*/
+                                       } else {
                                                if (mode->clock > 165000)
                                                        args.v3.sInput.ucDispPllConfig |=
                                                                DISPPLL_CONFIG_DUAL_LINK;
@@ -1019,11 +1076,11 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 
        if (rdev->family >= CHIP_RV770) {
                if (radeon_crtc->crtc_id) {
-                       WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
-                       WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+                       WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
+                       WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
                } else {
-                       WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
-                       WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+                       WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
+                       WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
                }
        }
        WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
@@ -1160,8 +1217,18 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
+       struct drm_encoder *encoder;
+       bool is_tvcv = false;
 
-       /* TODO color tiling */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               /* find tv std */
+               if (encoder->crtc == crtc) {
+                       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+                       if (radeon_encoder->active_device &
+                           (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+                               is_tvcv = true;
+               }
+       }
 
        atombios_disable_ss(crtc);
        /* always set DCPLL */
@@ -1170,9 +1237,14 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
        atombios_crtc_set_pll(crtc, adjusted_mode);
        atombios_enable_ss(crtc);
 
-       if (ASIC_IS_AVIVO(rdev))
+       if (ASIC_IS_DCE4(rdev))
                atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
-       else {
+       else if (ASIC_IS_AVIVO(rdev)) {
+               if (is_tvcv)
+                       atombios_crtc_set_timing(crtc, adjusted_mode);
+               else
+                       atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
+       } else {
                atombios_crtc_set_timing(crtc, adjusted_mode);
                if (radeon_crtc->crtc_id == 0)
                        atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
index 36e0d4b545e60b674380746496525fed8b88ad39..4e7778d44b8d36fa4491c97de47aa5f4d400919f 100644 (file)
@@ -610,7 +610,7 @@ void dp_link_train(struct drm_encoder *encoder,
                enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
        else
                enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER;
-       if (dig_connector->linkb)
+       if (dig->linkb)
                enc_id |= ATOM_DP_CONFIG_LINK_B;
        else
                enc_id |= ATOM_DP_CONFIG_LINK_A;
index 957d5067ad9cc1495984f909d724fbf64c8d8856..2f93d46ae69ad58dfb90ea5db02021a402506ae5 100644 (file)
@@ -675,6 +675,43 @@ static int evergreen_cp_load_microcode(struct radeon_device *rdev)
        return 0;
 }
 
+static int evergreen_cp_start(struct radeon_device *rdev)
+{
+       int r;
+       uint32_t cp_me;
+
+       r = radeon_ring_lock(rdev, 7);
+       if (r) {
+               DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+               return r;
+       }
+       radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5));
+       radeon_ring_write(rdev, 0x1);
+       radeon_ring_write(rdev, 0x0);
+       radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1);
+       radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
+       radeon_ring_write(rdev, 0);
+       radeon_ring_write(rdev, 0);
+       radeon_ring_unlock_commit(rdev);
+
+       cp_me = 0xff;
+       WREG32(CP_ME_CNTL, cp_me);
+
+       r = radeon_ring_lock(rdev, 4);
+       if (r) {
+               DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+               return r;
+       }
+       /* init some VGT regs */
+       radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
+       radeon_ring_write(rdev, (VGT_VERTEX_REUSE_BLOCK_CNTL - PACKET3_SET_CONTEXT_REG_START) >> 2);
+       radeon_ring_write(rdev, 0xe);
+       radeon_ring_write(rdev, 0x10);
+       radeon_ring_unlock_commit(rdev);
+
+       return 0;
+}
+
 int evergreen_cp_resume(struct radeon_device *rdev)
 {
        u32 tmp;
@@ -719,7 +756,7 @@ int evergreen_cp_resume(struct radeon_device *rdev)
        rdev->cp.rptr = RREG32(CP_RB_RPTR);
        rdev->cp.wptr = RREG32(CP_RB_WPTR);
 
-       r600_cp_start(rdev);
+       evergreen_cp_start(rdev);
        rdev->cp.ready = true;
        r = radeon_ring_test(rdev);
        if (r) {
@@ -1100,7 +1137,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
 
                WREG32(RCU_IND_INDEX, 0x203);
                efuse_straps_3 = RREG32(RCU_IND_DATA);
-               efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28;
+               efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28);
 
                switch(efuse_box_bit_127_124) {
                case 0x0:
@@ -1123,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                                                                        EVERGREEN_MAX_BACKENDS_MASK));
                        break;
                }
-       } else
-               gb_backend_map =
-                       evergreen_get_tile_pipe_to_backend_map(rdev,
-                                                              rdev->config.evergreen.max_tile_pipes,
-                                                              rdev->config.evergreen.max_backends,
-                                                              ((EVERGREEN_MAX_BACKENDS_MASK <<
-                                                                rdev->config.evergreen.max_backends) &
-                                                               EVERGREEN_MAX_BACKENDS_MASK));
+       } else {
+               switch (rdev->family) {
+               case CHIP_CYPRESS:
+               case CHIP_HEMLOCK:
+                       gb_backend_map = 0x66442200;
+                       break;
+               case CHIP_JUNIPER:
+                       gb_backend_map = 0x00006420;
+                       break;
+               default:
+                       gb_backend_map =
+                               evergreen_get_tile_pipe_to_backend_map(rdev,
+                                                                      rdev->config.evergreen.max_tile_pipes,
+                                                                      rdev->config.evergreen.max_backends,
+                                                                      ((EVERGREEN_MAX_BACKENDS_MASK <<
+                                                                        rdev->config.evergreen.max_backends) &
+                                                                       EVERGREEN_MAX_BACKENDS_MASK));
+               }
+       }
 
        rdev->config.evergreen.tile_config = gb_addr_config;
        WREG32(GB_BACKEND_MAP, gb_backend_map);
@@ -1359,6 +1407,7 @@ int evergreen_mc_init(struct radeon_device *rdev)
        rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
        rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        r600_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
 
@@ -1472,7 +1521,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 {
        u32 tmp;
 
-       WREG32(CP_INT_CNTL, 0);
+       WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
        WREG32(GRBM_INT_CNTL, 0);
        WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
        WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
@@ -2054,11 +2103,6 @@ int evergreen_resume(struct radeon_device *rdev)
         */
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
-       /* Initialize clocks */
-       r = radeon_clocks_init(rdev);
-       if (r) {
-               return r;
-       }
 
        r = evergreen_startup(rdev);
        if (r) {
@@ -2164,9 +2208,6 @@ int evergreen_init(struct radeon_device *rdev)
        radeon_surface_init(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
-       r = radeon_clocks_init(rdev);
-       if (r)
-               return r;
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
@@ -2236,7 +2277,6 @@ void evergreen_fini(struct radeon_device *rdev)
        evergreen_pcie_gart_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
-       radeon_clocks_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
index e817a0bb5eb4a71550d0c9f6f8697cd80c31914e..e59422320bb6df9873fbf88f9e29d34fdc412110 100644 (file)
@@ -1030,6 +1030,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
                return r;
        }
        rdev->cp.ready = true;
+       rdev->mc.active_vram_size = rdev->mc.real_vram_size;
        return 0;
 }
 
@@ -1047,6 +1048,7 @@ void r100_cp_fini(struct radeon_device *rdev)
 void r100_cp_disable(struct radeon_device *rdev)
 {
        /* Disable ring */
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        rdev->cp.ready = false;
        WREG32(RADEON_CP_CSQ_MODE, 0);
        WREG32(RADEON_CP_CSQ_CNTL, 0);
@@ -2020,18 +2022,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l
                return false;
        }
        elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies);
-       if (elapsed >= 3000) {
-               /* very likely the improbable case where current
-                * rptr is equal to last recorded, a while ago, rptr
-                * this is more likely a false positive update tracking
-                * information which should force us to be recall at
-                * latter point
-                */
-               lockup->last_cp_rptr = cp->rptr;
-               lockup->last_jiffies = jiffies;
-               return false;
-       }
-       if (elapsed >= 1000) {
+       if (elapsed >= 10000) {
                dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed);
                return true;
        }
@@ -2306,6 +2297,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
        /* FIXME we don't use the second aperture yet when we could use it */
        if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
                rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
        if (rdev->flags & RADEON_IS_IGP) {
                uint32_t tom;
@@ -3308,13 +3300,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
        unsigned long size;
        unsigned prim_walk;
        unsigned nverts;
+       unsigned num_cb = track->num_cb;
 
-       for (i = 0; i < track->num_cb; i++) {
+       if (!track->zb_cb_clear && !track->color_channel_mask &&
+           !track->blend_read_enable)
+               num_cb = 0;
+
+       for (i = 0; i < num_cb; i++) {
                if (track->cb[i].robj == NULL) {
-                       if (!(track->zb_cb_clear || track->color_channel_mask ||
-                             track->blend_read_enable)) {
-                               continue;
-                       }
                        DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
                        return -EINVAL;
                }
index d0ebae9dde25ba400778b210dfc2e6a86179d682..7b65e4efe8af61e2df5404ea52c468fe8ee564db 100644 (file)
@@ -1248,6 +1248,7 @@ int r600_mc_init(struct radeon_device *rdev)
        rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
        rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        r600_vram_gtt_location(rdev, &rdev->mc);
 
        if (rdev->flags & RADEON_IS_IGP) {
@@ -1917,6 +1918,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
  */
 void r600_cp_stop(struct radeon_device *rdev)
 {
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 }
 
@@ -2119,10 +2121,7 @@ int r600_cp_start(struct radeon_device *rdev)
        }
        radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5));
        radeon_ring_write(rdev, 0x1);
-       if (rdev->family >= CHIP_CEDAR) {
-               radeon_ring_write(rdev, 0x0);
-               radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1);
-       } else if (rdev->family >= CHIP_RV770) {
+       if (rdev->family >= CHIP_RV770) {
                radeon_ring_write(rdev, 0x0);
                radeon_ring_write(rdev, rdev->config.rv770.max_hw_contexts - 1);
        } else {
@@ -2489,11 +2488,6 @@ int r600_resume(struct radeon_device *rdev)
         */
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
-       /* Initialize clocks */
-       r = radeon_clocks_init(rdev);
-       if (r) {
-               return r;
-       }
 
        r = r600_startup(rdev);
        if (r) {
@@ -2586,9 +2580,6 @@ int r600_init(struct radeon_device *rdev)
        radeon_surface_init(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
-       r = radeon_clocks_init(rdev);
-       if (r)
-               return r;
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
@@ -2663,7 +2654,6 @@ void r600_fini(struct radeon_device *rdev)
        radeon_agp_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
-       radeon_clocks_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
        kfree(rdev->bios);
@@ -2741,7 +2731,7 @@ int r600_ib_test(struct radeon_device *rdev)
        if (i < rdev->usec_timeout) {
                DRM_INFO("ib test succeeded in %u usecs\n", i);
        } else {
-               DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
+               DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n",
                          scratch, tmp);
                r = -EINVAL;
        }
@@ -2922,7 +2912,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
 {
        u32 tmp;
 
-       WREG32(CP_INT_CNTL, 0);
+       WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
        WREG32(GRBM_INT_CNTL, 0);
        WREG32(DxMODE_INT_MASK, 0);
        if (ASIC_IS_DCE3(rdev)) {
@@ -3540,8 +3530,9 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
        /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
         * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
         */
-       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
-               void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+           rdev->vram_scratch.ptr) {
+               void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
                u32 tmp;
 
                WREG32(HDP_DEBUG1, 0);
index d13622ae74e9799d75045cd282d2797071a23d21..3473c00781ffaaac06cab0c520231a5a66a21111 100644 (file)
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2009 Advanced Micro Devices, Inc.
+ * Copyright 2009 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
 #include "drmP.h"
 #include "drm.h"
 #include "radeon_drm.h"
@@ -507,6 +532,7 @@ int r600_blit_init(struct radeon_device *rdev)
        memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
        radeon_bo_kunmap(rdev->r600_blit.shader_obj);
        radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+       rdev->mc.active_vram_size = rdev->mc.real_vram_size;
        return 0;
 }
 
@@ -514,6 +540,7 @@ void r600_blit_fini(struct radeon_device *rdev)
 {
        int r;
 
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        if (rdev->r600_blit.shader_obj == NULL)
                return;
        /* If we can't reserve the bo, unref should be enough to destroy
index fdc3b378cbb0d78542987e111fc1693462dc2b1b..f437d36dd98c2f33d195f4fdaaae034c535be6e8 100644 (file)
@@ -1,3 +1,27 @@
+/*
+ * Copyright 2009 Advanced Micro Devices, Inc.
+ * Copyright 2009 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
 
 #ifndef R600_BLIT_SHADERS_H
 #define R600_BLIT_SHADERS_H
index d8864949e387a30d838e59cb5eb6d95a4549b1e3..250a3a918193e9821aa6f5836d463553cf6f903d 100644 (file)
@@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
        /* using get ib will give us the offset into the mipmap bo */
        word0 = radeon_get_ib_value(p, idx + 3) << 8;
        if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
-               dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
-                       w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
-               return -EINVAL;
+               /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
+                 w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/
        }
        return 0;
 }
index 3dfcfa3ca4250bf85e005dc5e6fd05f4c24fbea1..9ff38c99a6ea0e568f2567c0a7ad34b06e60e512 100644 (file)
@@ -344,6 +344,7 @@ struct radeon_mc {
         * about vram size near mc fb location */
        u64                     mc_vram_size;
        u64                     visible_vram_size;
+       u64                     active_vram_size;
        u64                     gtt_size;
        u64                     gtt_start;
        u64                     gtt_end;
@@ -1013,6 +1014,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *filp);
 
+/* VRAM scratch page for HDP bug */
+struct r700_vram_scratch {
+       struct radeon_bo                *robj;
+       volatile uint32_t               *ptr;
+};
 
 /*
  * Core structure, functions and helpers.
@@ -1079,6 +1085,7 @@ struct radeon_device {
        const struct firmware *pfp_fw;  /* r6/700 PFP firmware */
        const struct firmware *rlc_fw;  /* r6/700 RLC firmware */
        struct r600_blit r600_blit;
+       struct r700_vram_scratch vram_scratch;
        int msi_enabled; /* msi enabled */
        struct r600_ih ih; /* r6/700 interrupt ring */
        struct workqueue_struct *wq;
@@ -1333,8 +1340,6 @@ extern bool radeon_card_posted(struct radeon_device *rdev);
 extern void radeon_update_bandwidth_info(struct radeon_device *rdev);
 extern void radeon_update_display_priority(struct radeon_device *rdev);
 extern bool radeon_boot_test_post_card(struct radeon_device *rdev);
-extern int radeon_clocks_init(struct radeon_device *rdev);
-extern void radeon_clocks_fini(struct radeon_device *rdev);
 extern void radeon_scratch_init(struct radeon_device *rdev);
 extern void radeon_surface_init(struct radeon_device *rdev);
 extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
index f40dfb77f9b12cfa75c90c83ec608714f15ae423..bd2f33e5c91a695c2110af95397a6fa33cad0c10 100644 (file)
@@ -156,7 +156,13 @@ int radeon_agp_init(struct radeon_device *rdev)
        }
 
        mode.mode = info.mode;
-       agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode;
+       /* chips with the agp to pcie bridge don't have the AGP_STATUS register
+        * Just use the whatever mode the host sets up.
+        */
+       if (rdev->family <= CHIP_RV350)
+               agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode;
+       else
+               agp_status = mode.mode;
        is_v3 = !!(agp_status & RADEON_AGPv3_MODE);
 
        if (is_v3) {
index 646f96f97c77d8538919325be4bde664a7f3df8b..25e1dd1977917ad4151cdaf599add440ef14d625 100644 (file)
@@ -733,6 +733,7 @@ static struct radeon_asic evergreen_asic = {
        .set_engine_clock = &radeon_atom_set_engine_clock,
        .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
+       .get_pcie_lanes = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = NULL,
        .set_surface_reg = r600_set_surface_reg,
@@ -857,21 +858,3 @@ int radeon_asic_init(struct radeon_device *rdev)
        return 0;
 }
 
-/*
- * Wrapper around modesetting bits. Move to radeon_clocks.c?
- */
-int radeon_clocks_init(struct radeon_device *rdev)
-{
-       int r;
-
-       r = radeon_static_clocks_init(rdev->ddev);
-       if (r) {
-               return r;
-       }
-       DRM_INFO("Clocks initialized !\n");
-       return 0;
-}
-
-void radeon_clocks_fini(struct radeon_device *rdev)
-{
-}
index 6d30868744eeed8e1890a13532dd77a36161fa4b..8e43ddae70cc27d3c37d472561527432cc51dd53 100644 (file)
 
 /* from radeon_encoder.c */
 extern uint32_t
-radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
-                     uint8_t dac);
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+                       uint8_t dac);
 extern void radeon_link_encoder_connector(struct drm_device *dev);
 extern void
-radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id,
+radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
                        uint32_t supported_device);
 
 /* from radeon_connector.c */
@@ -46,14 +46,14 @@ radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t supported_device,
                          int connector_type,
                          struct radeon_i2c_bus_rec *i2c_bus,
-                         bool linkb, uint32_t igp_lane_info,
+                         uint32_t igp_lane_info,
                          uint16_t connector_object_id,
                          struct radeon_hpd *hpd,
                          struct radeon_router *router);
 
 /* from radeon_legacy_encoder.c */
 extern void
-radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
                          uint32_t supported_device);
 
 union atom_supported_devices {
@@ -85,6 +85,19 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
 
+                       /* some evergreen boards have bad data for this entry */
+                       if (ASIC_IS_DCE4(rdev)) {
+                               if ((i == 7) &&
+                                   (gpio->usClkMaskRegisterIndex == 0x1936) &&
+                                   (gpio->sucI2cId.ucAccess == 0)) {
+                                       gpio->sucI2cId.ucAccess = 0x97;
+                                       gpio->ucDataMaskShift = 8;
+                                       gpio->ucDataEnShift = 8;
+                                       gpio->ucDataY_Shift = 8;
+                                       gpio->ucDataA_Shift = 8;
+                               }
+                       }
+
                        if (gpio->sucI2cId.ucAccess == id) {
                                i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
                                i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
@@ -147,6 +160,20 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
                        i2c.valid = false;
+
+                       /* some evergreen boards have bad data for this entry */
+                       if (ASIC_IS_DCE4(rdev)) {
+                               if ((i == 7) &&
+                                   (gpio->usClkMaskRegisterIndex == 0x1936) &&
+                                   (gpio->sucI2cId.ucAccess == 0)) {
+                                       gpio->sucI2cId.ucAccess = 0x97;
+                                       gpio->ucDataMaskShift = 8;
+                                       gpio->ucDataEnShift = 8;
+                                       gpio->ucDataY_Shift = 8;
+                                       gpio->ucDataA_Shift = 8;
+                               }
+                       }
+
                        i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
                        i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
                        i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
@@ -226,6 +253,8 @@ static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device
        struct radeon_hpd hpd;
        u32 reg;
 
+       memset(&hpd, 0, sizeof(struct radeon_hpd));
+
        if (ASIC_IS_DCE4(rdev))
                reg = EVERGREEN_DC_GPIO_HPD_A;
        else
@@ -288,6 +317,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
                        *connector_type = DRM_MODE_CONNECTOR_DVID;
        }
 
+       /* MSI K9A2GM V2/V3 board has no HDMI or DVI */
+       if ((dev->pdev->device == 0x796e) &&
+           (dev->pdev->subsystem_vendor == 0x1462) &&
+           (dev->pdev->subsystem_device == 0x7302)) {
+               if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
+                   (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
+                       return false;
+       }
+
        /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
        if ((dev->pdev->device == 0x7941) &&
            (dev->pdev->subsystem_vendor == 0x147b) &&
@@ -477,7 +515,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        int i, j, k, path_size, device_support;
        int connector_type;
        u16 igp_lane_info, conn_id, connector_object_id;
-       bool linkb;
        struct radeon_i2c_bus_rec ddc_bus;
        struct radeon_router router;
        struct radeon_gpio_rec gpio;
@@ -510,7 +547,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                addr += path_size;
                path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
                path_size += le16_to_cpu(path->usSize);
-               linkb = false;
+
                if (device_support & le16_to_cpu(path->usDeviceTag)) {
                        uint8_t con_obj_id, con_obj_num, con_obj_type;
 
@@ -601,13 +638,10 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
 
                                if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
-                                       if (grph_obj_num == 2)
-                                               linkb = true;
-                                       else
-                                               linkb = false;
+                                       u16 encoder_obj = le16_to_cpu(path->usGraphicObjIds[j]);
 
                                        radeon_add_atom_encoder(dev,
-                                                               grph_obj_id,
+                                                               encoder_obj,
                                                                le16_to_cpu
                                                                (path->
                                                                 usDeviceTag));
@@ -744,7 +778,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                  le16_to_cpu(path->
                                                              usDeviceTag),
                                                  connector_type, &ddc_bus,
-                                                 linkb, igp_lane_info,
+                                                 igp_lane_info,
                                                  connector_object_id,
                                                  &hpd,
                                                  &router);
@@ -933,13 +967,13 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
                if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
                        radeon_add_atom_encoder(dev,
-                                               radeon_get_encoder_id(dev,
+                                               radeon_get_encoder_enum(dev,
                                                                      (1 << i),
                                                                      dac),
                                                (1 << i));
                else
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        (1 << i),
                                                                        dac),
                                                  (1 << i));
@@ -996,7 +1030,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
                                                  bios_connectors[i].
                                                  connector_type,
                                                  &bios_connectors[i].ddc_bus,
-                                                 false, 0,
+                                                 0,
                                                  connector_object_id,
                                                  &bios_connectors[i].hpd,
                                                  &router);
@@ -1183,7 +1217,7 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
                                return true;
                        break;
                case 2:
-                       if (igp_info->info_2.ucMemoryType & 0x0f)
+                       if (igp_info->info_2.ulBootUpSidePortClock)
                                return true;
                        break;
                default:
@@ -1305,6 +1339,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
        union lvds_info *lvds_info;
        uint8_t frev, crev;
        struct radeon_encoder_atom_dig *lvds = NULL;
+       int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
 
        if (atom_parse_data_header(mode_info->atom_context, index, NULL,
                                   &frev, &crev, &data_offset)) {
@@ -1368,6 +1403,12 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                }
 
                encoder->native_mode = lvds->native_mode;
+
+               if (encoder_enum == 2)
+                       lvds->linkb = true;
+               else
+                       lvds->linkb = false;
+
        }
        return lvds;
 }
@@ -1517,39 +1558,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
                switch (tv_info->ucTV_BootUpDefaultStandard) {
                case ATOM_TV_NTSC:
                        tv_std = TV_STD_NTSC;
-                       DRM_INFO("Default TV standard: NTSC\n");
+                       DRM_DEBUG_KMS("Default TV standard: NTSC\n");
                        break;
                case ATOM_TV_NTSCJ:
                        tv_std = TV_STD_NTSC_J;
-                       DRM_INFO("Default TV standard: NTSC-J\n");
+                       DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
                        break;
                case ATOM_TV_PAL:
                        tv_std = TV_STD_PAL;
-                       DRM_INFO("Default TV standard: PAL\n");
+                       DRM_DEBUG_KMS("Default TV standard: PAL\n");
                        break;
                case ATOM_TV_PALM:
                        tv_std = TV_STD_PAL_M;
-                       DRM_INFO("Default TV standard: PAL-M\n");
+                       DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
                        break;
                case ATOM_TV_PALN:
                        tv_std = TV_STD_PAL_N;
-                       DRM_INFO("Default TV standard: PAL-N\n");
+                       DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
                        break;
                case ATOM_TV_PALCN:
                        tv_std = TV_STD_PAL_CN;
-                       DRM_INFO("Default TV standard: PAL-CN\n");
+                       DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
                        break;
                case ATOM_TV_PAL60:
                        tv_std = TV_STD_PAL_60;
-                       DRM_INFO("Default TV standard: PAL-60\n");
+                       DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
                        break;
                case ATOM_TV_SECAM:
                        tv_std = TV_STD_SECAM;
-                       DRM_INFO("Default TV standard: SECAM\n");
+                       DRM_DEBUG_KMS("Default TV standard: SECAM\n");
                        break;
                default:
                        tv_std = TV_STD_NTSC;
-                       DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+                       DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
                        break;
                }
        }
index 14448a740ba632cf5f2fcbaf2d2d5804f3446b93..5249af8931e60549e01362102f9c8ca941ba0d24 100644 (file)
@@ -327,6 +327,14 @@ void radeon_get_clock_info(struct drm_device *dev)
        mpll->max_feedback_div = 0xff;
        mpll->best_vco = 0;
 
+       if (!rdev->clock.default_sclk)
+               rdev->clock.default_sclk = radeon_get_engine_clock(rdev);
+       if ((!rdev->clock.default_mclk) && rdev->asic->get_memory_clock)
+               rdev->clock.default_mclk = radeon_get_memory_clock(rdev);
+
+       rdev->pm.current_sclk = rdev->clock.default_sclk;
+       rdev->pm.current_mclk = rdev->clock.default_mclk;
+
 }
 
 /* 10 khz */
@@ -897,53 +905,3 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
        }
 }
 
-static void radeon_apply_clock_quirks(struct radeon_device *rdev)
-{
-       uint32_t tmp;
-
-       /* XXX make sure engine is idle */
-
-       if (rdev->family < CHIP_RS600) {
-               tmp = RREG32_PLL(RADEON_SCLK_CNTL);
-               if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev))
-                       tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP;
-               if ((rdev->family == CHIP_RV250)
-                   || (rdev->family == CHIP_RV280))
-                       tmp |=
-                           RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2;
-               if ((rdev->family == CHIP_RV350)
-                   || (rdev->family == CHIP_RV380))
-                       tmp |= R300_SCLK_FORCE_VAP;
-               if (rdev->family == CHIP_R420)
-                       tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX;
-               WREG32_PLL(RADEON_SCLK_CNTL, tmp);
-       } else if (rdev->family < CHIP_R600) {
-               tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL);
-               tmp |= AVIVO_CP_FORCEON;
-               WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp);
-
-               tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL);
-               tmp |= AVIVO_E2_FORCEON;
-               WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp);
-
-               tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL);
-               tmp |= AVIVO_IDCT_FORCEON;
-               WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp);
-       }
-}
-
-int radeon_static_clocks_init(struct drm_device *dev)
-{
-       struct radeon_device *rdev = dev->dev_private;
-
-       /* XXX make sure engine is idle */
-
-       if (radeon_dynclks != -1) {
-               if (radeon_dynclks) {
-                       if (rdev->asic->set_clock_gating)
-                               radeon_set_clock_gating(rdev, 1);
-               }
-       }
-       radeon_apply_clock_quirks(rdev);
-       return 0;
-}
index 885dcfac1838e89367487760aa717d54d7d7f978..7b7ea269549ccef95c1e6c343083071774e7e9de 100644 (file)
@@ -39,8 +39,8 @@
 
 /* from radeon_encoder.c */
 extern uint32_t
-radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
-                     uint8_t dac);
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+                       uint8_t dac);
 extern void radeon_link_encoder_connector(struct drm_device *dev);
 
 /* from radeon_connector.c */
@@ -55,7 +55,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 
 /* from radeon_legacy_encoder.c */
 extern void
-radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
                          uint32_t supported_device);
 
 /* old legacy ATI BIOS routines */
@@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev)
                        switch (RBIOS8(tv_info + 7) & 0xf) {
                        case 1:
                                tv_std = TV_STD_NTSC;
-                               DRM_INFO("Default TV standard: NTSC\n");
+                               DRM_DEBUG_KMS("Default TV standard: NTSC\n");
                                break;
                        case 2:
                                tv_std = TV_STD_PAL;
-                               DRM_INFO("Default TV standard: PAL\n");
+                               DRM_DEBUG_KMS("Default TV standard: PAL\n");
                                break;
                        case 3:
                                tv_std = TV_STD_PAL_M;
-                               DRM_INFO("Default TV standard: PAL-M\n");
+                               DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
                                break;
                        case 4:
                                tv_std = TV_STD_PAL_60;
-                               DRM_INFO("Default TV standard: PAL-60\n");
+                               DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
                                break;
                        case 5:
                                tv_std = TV_STD_NTSC_J;
-                               DRM_INFO("Default TV standard: NTSC-J\n");
+                               DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
                                break;
                        case 6:
                                tv_std = TV_STD_SCART_PAL;
-                               DRM_INFO("Default TV standard: SCART-PAL\n");
+                               DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n");
                                break;
                        default:
                                tv_std = TV_STD_NTSC;
-                               DRM_INFO
+                               DRM_DEBUG_KMS
                                    ("Unknown TV standard; defaulting to NTSC\n");
                                break;
                        }
 
                        switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
                        case 0:
-                               DRM_INFO("29.498928713 MHz TV ref clk\n");
+                               DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n");
                                break;
                        case 1:
-                               DRM_INFO("28.636360000 MHz TV ref clk\n");
+                               DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n");
                                break;
                        case 2:
-                               DRM_INFO("14.318180000 MHz TV ref clk\n");
+                               DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n");
                                break;
                        case 3:
-                               DRM_INFO("27.000000000 MHz TV ref clk\n");
+                               DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n");
                                break;
                        default:
                                break;
@@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
 
        if (tmds_info) {
                ver = RBIOS8(tmds_info);
-               DRM_INFO("DFP table revision: %d\n", ver);
+               DRM_DEBUG_KMS("DFP table revision: %d\n", ver);
                if (ver == 3) {
                        n = RBIOS8(tmds_info + 5) + 1;
                        if (n > 4)
@@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
                offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
                if (offset) {
                        ver = RBIOS8(offset);
-                       DRM_INFO("External TMDS Table revision: %d\n", ver);
+                       DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver);
                        tmds->slave_addr = RBIOS8(offset + 4 + 2);
                        tmds->slave_addr >>= 1; /* 7 bit addressing */
                        gpio = RBIOS8(offset + 4 + 3);
@@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        /* PowerMac8,1 ? */
                        /* imac g5 isight */
                        rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
+               } else if ((rdev->pdev->device == 0x4a48) &&
+                          (rdev->pdev->subsystem_vendor == 0x1002) &&
+                          (rdev->pdev->subsystem_device == 0x4a48)) {
+                       /* Mac X800 */
+                       rdev->mode_info.connector_table = CT_MAC_X800;
                } else
 #endif /* CONFIG_PPC_PMAC */
 #ifdef CONFIG_PPC64
@@ -1505,7 +1510,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                        hpd.hpd = RADEON_HPD_NONE;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_CRT1_SUPPORT,
                                                                        1),
                                                  ATOM_DEVICE_CRT1_SUPPORT);
@@ -1520,7 +1525,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0);
                        hpd.hpd = RADEON_HPD_NONE;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_LCD1_SUPPORT,
                                                                        0),
                                                  ATOM_DEVICE_LCD1_SUPPORT);
@@ -1535,7 +1540,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                        hpd.hpd = RADEON_HPD_NONE;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_CRT1_SUPPORT,
                                                                        1),
                                                  ATOM_DEVICE_CRT1_SUPPORT);
@@ -1550,12 +1555,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                        hpd.hpd = RADEON_HPD_1;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_DFP1_SUPPORT,
                                                                        0),
                                                  ATOM_DEVICE_DFP1_SUPPORT);
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_CRT2_SUPPORT,
                                                                        2),
                                                  ATOM_DEVICE_CRT2_SUPPORT);
@@ -1571,7 +1576,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                        hpd.hpd = RADEON_HPD_NONE;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_CRT1_SUPPORT,
                                                                        1),
                                                  ATOM_DEVICE_CRT1_SUPPORT);
@@ -1588,7 +1593,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        ddc_i2c.valid = false;
                        hpd.hpd = RADEON_HPD_NONE;
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_TV1_SUPPORT,
                                                                        2),
                                                  ATOM_DEVICE_TV1_SUPPORT);
@@ -1607,7 +1612,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_LCD1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
@@ -1619,7 +1624,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1631,7 +1636,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1648,7 +1653,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_LCD1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
@@ -1660,12 +1665,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_2; /* ??? */
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_DFP2_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_DFP2_SUPPORT);
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -1680,7 +1685,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1697,7 +1702,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_LCD1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
@@ -1709,12 +1714,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_1; /* ??? */
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_DFP1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_DFP1_SUPPORT);
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -1728,7 +1733,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1745,7 +1750,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_LCD1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
@@ -1757,7 +1762,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -1769,7 +1774,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1786,12 +1791,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
                hpd.hpd = RADEON_HPD_2; /* ??? */
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_DFP2_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_DFP2_SUPPORT);
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1806,7 +1811,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1823,12 +1828,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
                hpd.hpd = RADEON_HPD_1; /* ??? */
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_DFP1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_DFP1_SUPPORT);
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1842,7 +1847,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1859,7 +1864,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
                hpd.hpd = RADEON_HPD_1; /* ??? */
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_DFP1_SUPPORT,
                                                                0),
                                          ATOM_DEVICE_DFP1_SUPPORT);
@@ -1871,7 +1876,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1883,7 +1888,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1900,7 +1905,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -1912,7 +1917,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1924,7 +1929,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c.valid = false;
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_TV1_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_TV1_SUPPORT);
@@ -1941,7 +1946,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -1952,7 +1957,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
                hpd.hpd = RADEON_HPD_NONE;
                radeon_add_legacy_encoder(dev,
-                                         radeon_get_encoder_id(dev,
+                                         radeon_get_encoder_enum(dev,
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
@@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                            CONNECTOR_OBJECT_ID_VGA,
                                            &hpd);
                break;
+       case CT_MAC_X800:
+               DRM_INFO("Connector Table: %d (mac x800)\n",
+                        rdev->mode_info.connector_table);
+               /* DVI - primary dac, internal tmds */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
+               hpd.hpd = RADEON_HPD_1; /* ??? */
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                                 ATOM_DEVICE_DFP1_SUPPORT,
+                                                                 0),
+                                         ATOM_DEVICE_DFP1_SUPPORT);
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                                 ATOM_DEVICE_CRT1_SUPPORT,
+                                                                 1),
+                                         ATOM_DEVICE_CRT1_SUPPORT);
+               radeon_add_legacy_connector(dev, 0,
+                                           ATOM_DEVICE_DFP1_SUPPORT |
+                                           ATOM_DEVICE_CRT1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+                                           &hpd);
+               /* DVI - tv dac, dvo */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+               hpd.hpd = RADEON_HPD_2; /* ??? */
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                                 ATOM_DEVICE_DFP2_SUPPORT,
+                                                                 0),
+                                         ATOM_DEVICE_DFP2_SUPPORT);
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                                 ATOM_DEVICE_CRT2_SUPPORT,
+                                                                 2),
+                                         ATOM_DEVICE_CRT2_SUPPORT);
+               radeon_add_legacy_connector(dev, 1,
+                                           ATOM_DEVICE_DFP2_SUPPORT |
+                                           ATOM_DEVICE_CRT2_SUPPORT,
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
+                                           &hpd);
+               break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
                         rdev->mode_info.connector_table);
@@ -2109,7 +2156,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                else
                                        devices = ATOM_DEVICE_DFP1_SUPPORT;
                                radeon_add_legacy_encoder(dev,
-                                                         radeon_get_encoder_id
+                                                         radeon_get_encoder_enum
                                                          (dev, devices, 0),
                                                          devices);
                                radeon_add_legacy_connector(dev, i, devices,
@@ -2123,7 +2170,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                if (tmp & 0x1) {
                                        devices = ATOM_DEVICE_CRT2_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_CRT2_SUPPORT,
                                                                   2),
@@ -2131,7 +2178,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                } else {
                                        devices = ATOM_DEVICE_CRT1_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_CRT1_SUPPORT,
                                                                   1),
@@ -2151,7 +2198,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                if (tmp & 0x1) {
                                        devices |= ATOM_DEVICE_CRT2_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_CRT2_SUPPORT,
                                                                   2),
@@ -2159,7 +2206,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                } else {
                                        devices |= ATOM_DEVICE_CRT1_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_CRT1_SUPPORT,
                                                                   1),
@@ -2168,7 +2215,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                if ((tmp >> 4) & 0x1) {
                                        devices |= ATOM_DEVICE_DFP2_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_DFP2_SUPPORT,
                                                                   0),
@@ -2177,7 +2224,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                } else {
                                        devices |= ATOM_DEVICE_DFP1_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_DFP1_SUPPORT,
                                                                   0),
@@ -2202,7 +2249,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                        connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
                                }
                                radeon_add_legacy_encoder(dev,
-                                                         radeon_get_encoder_id
+                                                         radeon_get_encoder_enum
                                                          (dev, devices, 0),
                                                          devices);
                                radeon_add_legacy_connector(dev, i, devices,
@@ -2215,7 +2262,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                        case CONNECTOR_CTV_LEGACY:
                        case CONNECTOR_STV_LEGACY:
                                radeon_add_legacy_encoder(dev,
-                                                         radeon_get_encoder_id
+                                                         radeon_get_encoder_enum
                                                          (dev,
                                                           ATOM_DEVICE_TV1_SUPPORT,
                                                           2),
@@ -2242,12 +2289,12 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                        DRM_DEBUG_KMS("Found DFP table, assuming DVI connector\n");
 
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_CRT1_SUPPORT,
                                                                        1),
                                                  ATOM_DEVICE_CRT1_SUPPORT);
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_DFP1_SUPPORT,
                                                                        0),
                                                  ATOM_DEVICE_DFP1_SUPPORT);
@@ -2268,7 +2315,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                        DRM_DEBUG_KMS("Found CRT table, assuming VGA connector\n");
                        if (crt_info) {
                                radeon_add_legacy_encoder(dev,
-                                                         radeon_get_encoder_id(dev,
+                                                         radeon_get_encoder_enum(dev,
                                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                                1),
                                                          ATOM_DEVICE_CRT1_SUPPORT);
@@ -2297,7 +2344,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                     COMBIOS_LCD_DDC_INFO_TABLE);
 
                        radeon_add_legacy_encoder(dev,
-                                                 radeon_get_encoder_id(dev,
+                                                 radeon_get_encoder_enum(dev,
                                                                        ATOM_DEVICE_LCD1_SUPPORT,
                                                                        0),
                                                  ATOM_DEVICE_LCD1_SUPPORT);
@@ -2351,7 +2398,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                        hpd.hpd = RADEON_HPD_NONE;
                                        ddc_i2c.valid = false;
                                        radeon_add_legacy_encoder(dev,
-                                                                 radeon_get_encoder_id
+                                                                 radeon_get_encoder_enum
                                                                  (dev,
                                                                   ATOM_DEVICE_TV1_SUPPORT,
                                                                   2),
index 47c4b276d30c5fc4c0cd1fdbb9b7cdd5aa7bd634..ecc1a8fafbfd3eb3c12c0c4d45b4b091a1bee03b 100644 (file)
@@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
+static enum drm_connector_status
+radeon_lvds_detect(struct drm_connector *connector, bool force)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = radeon_best_single_encoder(connector);
@@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector)
+static enum drm_connector_status
+radeon_vga_detect(struct drm_connector *connector, bool force)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder;
@@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
+static enum drm_connector_status
+radeon_tv_detect(struct drm_connector *connector, bool force)
 {
        struct drm_encoder *encoder;
        struct drm_encoder_helper_funcs *encoder_funcs;
@@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
  * we have to check if this analog encoder is shared with anyone else (TV)
  * if its shared we have to set the other connector to disconnected.
  */
-static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
+static enum drm_connector_status
+radeon_dvi_detect(struct drm_connector *connector, bool force)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = NULL;
@@ -972,32 +976,35 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector)
+static enum drm_connector_status
+radeon_dp_detect(struct drm_connector *connector, bool force)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        enum drm_connector_status ret = connector_status_disconnected;
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
-       u8 sink_type;
 
        if (radeon_connector->edid) {
                kfree(radeon_connector->edid);
                radeon_connector->edid = NULL;
        }
 
-       sink_type = radeon_dp_getsinktype(radeon_connector);
-       if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-           (sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-               if (radeon_dp_getdpcd(radeon_connector)) {
-                       radeon_dig_connector->dp_sink_type = sink_type;
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               /* eDP is always DP */
+               radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
+               if (radeon_dp_getdpcd(radeon_connector))
                        ret = connector_status_connected;
-               }
        } else {
-               if (radeon_ddc_probe(radeon_connector)) {
-                       radeon_dig_connector->dp_sink_type = sink_type;
-                       ret = connector_status_connected;
+               radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
+               if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+                       if (radeon_dp_getdpcd(radeon_connector))
+                               ret = connector_status_connected;
+               } else {
+                       if (radeon_ddc_probe(radeon_connector))
+                               ret = connector_status_connected;
                }
        }
 
+       radeon_connector_update_scratch_regs(connector, ret);
        return ret;
 }
 
@@ -1037,7 +1044,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t supported_device,
                          int connector_type,
                          struct radeon_i2c_bus_rec *i2c_bus,
-                         bool linkb,
                          uint32_t igp_lane_info,
                          uint16_t connector_object_id,
                          struct radeon_hpd *hpd,
@@ -1050,10 +1056,16 @@ radeon_add_atom_connector(struct drm_device *dev,
        uint32_t subpixel_order = SubPixelNone;
        bool shared_ddc = false;
 
-       /* fixme - tv/cv/din */
        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
                return;
 
+       /* if the user selected tv=0 don't try and add the connector */
+       if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
+            (connector_type == DRM_MODE_CONNECTOR_Composite) ||
+            (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
+           (radeon_tv == 0))
+               return;
+
        /* see if we already added it */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                radeon_connector = to_radeon_connector(connector);
@@ -1128,7 +1140,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
@@ -1158,7 +1169,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
@@ -1182,7 +1192,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
@@ -1211,25 +1220,22 @@ radeon_add_atom_connector(struct drm_device *dev,
        case DRM_MODE_CONNECTOR_SVIDEO:
        case DRM_MODE_CONNECTOR_Composite:
        case DRM_MODE_CONNECTOR_9PinDIN:
-               if (radeon_tv == 1) {
-                       drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
-                       drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
-                       radeon_connector->dac_load_detect = true;
-                       drm_connector_attach_property(&radeon_connector->base,
-                                                     rdev->mode_info.load_detect_property,
-                                                     1);
-                       drm_connector_attach_property(&radeon_connector->base,
-                                                     rdev->mode_info.tv_std_property,
-                                                     radeon_atombios_get_tv_info(rdev));
-                       /* no HPD on analog connectors */
-                       radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-               }
+               drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
+               drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+               radeon_connector->dac_load_detect = true;
+               drm_connector_attach_property(&radeon_connector->base,
+                                             rdev->mode_info.load_detect_property,
+                                             1);
+               drm_connector_attach_property(&radeon_connector->base,
+                                             rdev->mode_info.tv_std_property,
+                                             radeon_atombios_get_tv_info(rdev));
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
@@ -1275,10 +1281,16 @@ radeon_add_legacy_connector(struct drm_device *dev,
        struct radeon_connector *radeon_connector;
        uint32_t subpixel_order = SubPixelNone;
 
-       /* fixme - tv/cv/din */
        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
                return;
 
+       /* if the user selected tv=0 don't try and add the connector */
+       if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
+            (connector_type == DRM_MODE_CONNECTOR_Composite) ||
+            (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
+           (radeon_tv == 0))
+               return;
+
        /* see if we already added it */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                radeon_connector = to_radeon_connector(connector);
@@ -1350,26 +1362,24 @@ radeon_add_legacy_connector(struct drm_device *dev,
        case DRM_MODE_CONNECTOR_SVIDEO:
        case DRM_MODE_CONNECTOR_Composite:
        case DRM_MODE_CONNECTOR_9PinDIN:
-               if (radeon_tv == 1) {
-                       drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
-                       drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
-                       radeon_connector->dac_load_detect = true;
-                       /* RS400,RC410,RS480 chipset seems to report a lot
-                        * of false positive on load detect, we haven't yet
-                        * found a way to make load detect reliable on those
-                        * chipset, thus just disable it for TV.
-                        */
-                       if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480)
-                               radeon_connector->dac_load_detect = false;
-                       drm_connector_attach_property(&radeon_connector->base,
-                                                     rdev->mode_info.load_detect_property,
-                                                     radeon_connector->dac_load_detect);
-                       drm_connector_attach_property(&radeon_connector->base,
-                                                     rdev->mode_info.tv_std_property,
-                                                     radeon_combios_get_tv_info(rdev));
-                       /* no HPD on analog connectors */
-                       radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-               }
+               drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
+               drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+               radeon_connector->dac_load_detect = true;
+               /* RS400,RC410,RS480 chipset seems to report a lot
+                * of false positive on load detect, we haven't yet
+                * found a way to make load detect reliable on those
+                * chipset, thus just disable it for TV.
+                */
+               if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480)
+                       radeon_connector->dac_load_detect = false;
+               drm_connector_attach_property(&radeon_connector->base,
+                                             rdev->mode_info.load_detect_property,
+                                             radeon_connector->dac_load_detect);
+               drm_connector_attach_property(&radeon_connector->base,
+                                             rdev->mode_info.tv_std_property,
+                                             radeon_combios_get_tv_info(rdev));
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
index 5731fc9b1ae3ae9274188a5bf8cdae7aa78f3b33..3eef567b0421ae71826abd77ac3bc035a5ec1c33 100644 (file)
@@ -203,6 +203,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
        int xorigin = 0, yorigin = 0;
+       int w = radeon_crtc->cursor_width;
 
        if (x < 0)
                xorigin = -x + 1;
@@ -213,22 +214,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
        if (yorigin >= CURSOR_HEIGHT)
                yorigin = CURSOR_HEIGHT - 1;
 
-       radeon_lock_cursor(crtc, true);
-       if (ASIC_IS_DCE4(rdev)) {
-               /* cursors are offset into the total surface */
-               x += crtc->x;
-               y += crtc->y;
-               DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
-
-               /* XXX: check if evergreen has the same issues as avivo chips */
-               WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
-                      ((xorigin ? 0 : x) << 16) |
-                      (yorigin ? 0 : y));
-               WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
-               WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
-                      ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
-       } else if (ASIC_IS_AVIVO(rdev)) {
-               int w = radeon_crtc->cursor_width;
+       if (ASIC_IS_AVIVO(rdev)) {
                int i = 0;
                struct drm_crtc *crtc_p;
 
@@ -260,7 +246,17 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                        if (w <= 0)
                                w = 1;
                }
+       }
 
+       radeon_lock_cursor(crtc, true);
+       if (ASIC_IS_DCE4(rdev)) {
+               WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
+                      ((xorigin ? 0 : x) << 16) |
+                      (yorigin ? 0 : y));
+               WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+               WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
+                      ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
+       } else if (ASIC_IS_AVIVO(rdev)) {
                WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
                             ((xorigin ? 0 : x) << 16) |
                             (yorigin ? 0 : y));
index 4f7a170d15663a3f3030f2e02e517718e6998968..256d204a6d24226a93f68b5d4d097fc4b52739c7 100644 (file)
@@ -199,7 +199,7 @@ 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 (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) {
+       if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) {
                dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
                mc->real_vram_size = mc->aper_size;
                mc->mc_vram_size = mc->aper_size;
@@ -293,30 +293,20 @@ bool radeon_card_posted(struct radeon_device *rdev)
 void radeon_update_bandwidth_info(struct radeon_device *rdev)
 {
        fixed20_12 a;
-       u32 sclk, mclk;
+       u32 sclk = rdev->pm.current_sclk;
+       u32 mclk = rdev->pm.current_mclk;
 
-       if (rdev->flags & RADEON_IS_IGP) {
-               sclk = radeon_get_engine_clock(rdev);
-               mclk = rdev->clock.default_mclk;
-
-               a.full = dfixed_const(100);
-               rdev->pm.sclk.full = dfixed_const(sclk);
-               rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a);
-               rdev->pm.mclk.full = dfixed_const(mclk);
-               rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a);
+       /* sclk/mclk in Mhz */
+       a.full = dfixed_const(100);
+       rdev->pm.sclk.full = dfixed_const(sclk);
+       rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a);
+       rdev->pm.mclk.full = dfixed_const(mclk);
+       rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a);
 
+       if (rdev->flags & RADEON_IS_IGP) {
                a.full = dfixed_const(16);
                /* core_bandwidth = sclk(Mhz) * 16 */
                rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a);
-       } else {
-               sclk = radeon_get_engine_clock(rdev);
-               mclk = radeon_get_memory_clock(rdev);
-
-               a.full = dfixed_const(100);
-               rdev->pm.sclk.full = dfixed_const(sclk);
-               rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a);
-               rdev->pm.mclk.full = dfixed_const(mclk);
-               rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a);
        }
 }
 
index 5764f4d3b4f1a0804caf56f39e6a75c6c9afaf57..b92d2f2fcbed6a8bd472ce9f4b936aa82f309278 100644 (file)
@@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev)
                                        DRM_INFO("    DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
                                if (devices & ATOM_DEVICE_DFP5_SUPPORT)
                                        DRM_INFO("    DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
+                               if (devices & ATOM_DEVICE_DFP6_SUPPORT)
+                                       DRM_INFO("    DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]);
                                if (devices & ATOM_DEVICE_TV1_SUPPORT)
                                        DRM_INFO("    TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
                                if (devices & ATOM_DEVICE_CV_SUPPORT)
@@ -841,8 +843,9 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
 
-       if (radeon_fb->obj)
+       if (radeon_fb->obj) {
                drm_gem_object_unreference_unlocked(radeon_fb->obj);
+       }
        drm_framebuffer_cleanup(fb);
        kfree(radeon_fb);
 }
@@ -1094,6 +1097,18 @@ void radeon_modeset_fini(struct radeon_device *rdev)
        radeon_i2c_fini(rdev);
 }
 
+static bool is_hdtv_mode(struct drm_display_mode *mode)
+{
+       /* try and guess if this is a tv or a monitor */
+       if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */
+           (mode->vdisplay == 576) || /* 576p */
+           (mode->vdisplay == 720) || /* 720p */
+           (mode->vdisplay == 1080)) /* 1080p */
+               return true;
+       else
+               return false;
+}
+
 bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
@@ -1128,20 +1143,22 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                                radeon_crtc->rmx_type = radeon_encoder->rmx_type;
                        else
                                radeon_crtc->rmx_type = RMX_OFF;
-                       src_v = crtc->mode.vdisplay;
-                       dst_v = radeon_crtc->native_mode.vdisplay;
-                       src_h = crtc->mode.hdisplay;
-                       dst_h = radeon_crtc->native_mode.vdisplay;
                        /* copy native mode */
                        memcpy(&radeon_crtc->native_mode,
                               &radeon_encoder->native_mode,
                                sizeof(struct drm_display_mode));
+                       src_v = crtc->mode.vdisplay;
+                       dst_v = radeon_crtc->native_mode.vdisplay;
+                       src_h = crtc->mode.hdisplay;
+                       dst_h = radeon_crtc->native_mode.hdisplay;
 
                        /* fix up for overscan on hdmi */
                        if (ASIC_IS_AVIVO(rdev) &&
+                           (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
                            ((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
                             ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
-                             drm_detect_hdmi_monitor(radeon_connector->edid)))) {
+                             drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                             is_hdtv_mode(mode)))) {
                                radeon_crtc->h_border = (mode->hdisplay >> 5) + 16;
                                radeon_crtc->v_border = (mode->vdisplay >> 5) + 16;
                                radeon_crtc->rmx_type = RMX_FULL;
index 795403b0e2cda8ac392e8faac9cded15746fc500..29c1237c2e7b8357d7b72d07cf76a99ed9375869 100644 (file)
@@ -219,6 +219,7 @@ static struct drm_driver driver_old = {
 #ifdef CONFIG_COMPAT
                 .compat_ioctl = radeon_compat_ioctl,
 #endif
+                .llseek = noop_llseek,
        },
 
        .pci_driver = {
index 263c8098d7dd279447ebba20e408c25f791f0b7d..2c293e8304d657d047144708bff75c6474d560f0 100644 (file)
@@ -81,7 +81,7 @@ void radeon_setup_encoder_clones(struct drm_device *dev)
 }
 
 uint32_t
-radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
 {
        struct radeon_device *rdev = dev->dev_private;
        uint32_t ret = 0;
@@ -97,59 +97,59 @@ radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t
                        if ((rdev->family == CHIP_RS300) ||
                            (rdev->family == CHIP_RS400) ||
                            (rdev->family == CHIP_RS480))
-                               ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
+                               ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
                        else if (ASIC_IS_AVIVO(rdev))
-                               ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+                               ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
                        else
-                               ret = ENCODER_OBJECT_ID_INTERNAL_DAC1;
+                               ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
                        break;
                case 2: /* dac b */
                        if (ASIC_IS_AVIVO(rdev))
-                               ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+                               ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
                        else {
                                /*if (rdev->family == CHIP_R200)
-                                 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+                                 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
                                  else*/
-                               ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
+                               ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
                        }
                        break;
                case 3: /* external dac */
                        if (ASIC_IS_AVIVO(rdev))
-                               ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
+                               ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
                        else
-                               ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+                               ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
                        break;
                }
                break;
        case ATOM_DEVICE_LCD1_SUPPORT:
                if (ASIC_IS_AVIVO(rdev))
-                       ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+                       ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
                else
-                       ret = ENCODER_OBJECT_ID_INTERNAL_LVDS;
+                       ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
                break;
        case ATOM_DEVICE_DFP1_SUPPORT:
                if ((rdev->family == CHIP_RS300) ||
                    (rdev->family == CHIP_RS400) ||
                    (rdev->family == CHIP_RS480))
-                       ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+                       ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
                else if (ASIC_IS_AVIVO(rdev))
-                       ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+                       ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
                else
-                       ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+                       ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
                break;
        case ATOM_DEVICE_LCD2_SUPPORT:
        case ATOM_DEVICE_DFP2_SUPPORT:
                if ((rdev->family == CHIP_RS600) ||
                    (rdev->family == CHIP_RS690) ||
                    (rdev->family == CHIP_RS740))
-                       ret = ENCODER_OBJECT_ID_INTERNAL_DDI;
+                       ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
                else if (ASIC_IS_AVIVO(rdev))
-                       ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
+                       ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
                else
-                       ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+                       ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
                break;
        case ATOM_DEVICE_DFP3_SUPPORT:
-               ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+               ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
                break;
        }
 
@@ -228,32 +228,6 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
        return NULL;
 }
 
-static struct radeon_connector_atom_dig *
-radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct drm_connector *connector;
-       struct radeon_connector *radeon_connector;
-       struct radeon_connector_atom_dig *dig_connector;
-
-       if (!rdev->is_atom_bios)
-               return NULL;
-
-       connector = radeon_get_connector_for_encoder(encoder);
-       if (!connector)
-               return NULL;
-
-       radeon_connector = to_radeon_connector(connector);
-
-       if (!radeon_connector->con_priv)
-               return NULL;
-
-       dig_connector = radeon_connector->con_priv;
-
-       return dig_connector;
-}
-
 void radeon_panel_mode_fixup(struct drm_encoder *encoder,
                             struct drm_display_mode *adjusted_mode)
 {
@@ -512,14 +486,12 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       struct radeon_connector_atom_dig *dig_connector =
-               radeon_get_atom_connector_priv_from_encoder(encoder);
        union lvds_encoder_control args;
        int index = 0;
        int hdmi_detected = 0;
        uint8_t frev, crev;
 
-       if (!dig || !dig_connector)
+       if (!dig)
                return;
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
@@ -562,7 +534,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                                if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
                                        args.v1.ucMisc |= (1 << 1);
                        } else {
-                               if (dig_connector->linkb)
+                               if (dig->linkb)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
                                if (radeon_encoder->pixel_clock > 165000)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
@@ -601,7 +573,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                                                args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
                                }
                        } else {
-                               if (dig_connector->linkb)
+                               if (dig->linkb)
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
                                if (radeon_encoder->pixel_clock > 165000)
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
@@ -623,6 +595,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 {
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector;
        struct radeon_connector_atom_dig *dig_connector;
@@ -636,9 +610,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        switch (connector->connector_type) {
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-               if (drm_detect_hdmi_monitor(radeon_connector->edid))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else if (radeon_connector->use_digital)
+               if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else if (radeon_connector->use_digital)
                        return ATOM_ENCODER_MODE_DVI;
                else
                        return ATOM_ENCODER_MODE_CRT;
@@ -646,9 +624,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
-               if (drm_detect_hdmi_monitor(radeon_connector->edid))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else
+               if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else
                        return ATOM_ENCODER_MODE_DVI;
                break;
        case DRM_MODE_CONNECTOR_LVDS:
@@ -660,9 +642,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
                    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
                        return ATOM_ENCODER_MODE_DP;
-               else if (drm_detect_hdmi_monitor(radeon_connector->edid))
-                       return ATOM_ENCODER_MODE_HDMI;
-               else
+               else if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else
                        return ATOM_ENCODER_MODE_DVI;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
@@ -729,13 +715,24 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       struct radeon_connector_atom_dig *dig_connector =
-               radeon_get_atom_connector_priv_from_encoder(encoder);
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        union dig_encoder_control args;
        int index = 0;
        uint8_t frev, crev;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
 
-       if (!dig || !dig_connector)
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+       }
+
+       /* no dig encoder assigned */
+       if (dig->dig_encoder == -1)
                return;
 
        memset(&args, 0, sizeof(args));
@@ -757,9 +754,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
        args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
 
        if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-               if (dig_connector->dp_clock == 270000)
+               if (dp_clock == 270000)
                        args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-               args.v1.ucLaneNum = dig_connector->dp_lane_count;
+               args.v1.ucLaneNum = dp_lane_count;
        } else if (radeon_encoder->pixel_clock > 165000)
                args.v1.ucLaneNum = 8;
        else
@@ -781,7 +778,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
                        args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
                        break;
                }
-               if (dig_connector->linkb)
+               if (dig->linkb)
                        args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
                else
                        args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
@@ -804,38 +801,47 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       struct radeon_connector_atom_dig *dig_connector =
-               radeon_get_atom_connector_priv_from_encoder(encoder);
-       struct drm_connector *connector;
-       struct radeon_connector *radeon_connector;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        union dig_transmitter_control args;
        int index = 0;
        uint8_t frev, crev;
        bool is_dp = false;
        int pll_id = 0;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+       int connector_object_id = 0;
+       int igp_lane_info = 0;
 
-       if (!dig || !dig_connector)
-               return;
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
 
-       connector = radeon_get_connector_for_encoder(encoder);
-       radeon_connector = to_radeon_connector(connector);
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+               connector_object_id =
+                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+               igp_lane_info = dig_connector->igp_lane_info;
+       }
+
+       /* no dig encoder assigned */
+       if (dig->dig_encoder == -1)
+               return;
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
                is_dp = true;
 
        memset(&args, 0, sizeof(args));
 
-       if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev))
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
                index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-       else {
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-                       index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
-                       break;
-               }
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
+               break;
        }
 
        if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
@@ -843,14 +849,14 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
 
        args.v1.ucAction = action;
        if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-               args.v1.usInitInfo = radeon_connector->connector_object_id;
+               args.v1.usInitInfo = connector_object_id;
        } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
                args.v1.asMode.ucLaneSel = lane_num;
                args.v1.asMode.ucLaneSet = lane_set;
        } else {
                if (is_dp)
                        args.v1.usPixelClock =
-                               cpu_to_le16(dig_connector->dp_clock / 10);
+                               cpu_to_le16(dp_clock / 10);
                else if (radeon_encoder->pixel_clock > 165000)
                        args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                else
@@ -858,13 +864,13 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        }
        if (ASIC_IS_DCE4(rdev)) {
                if (is_dp)
-                       args.v3.ucLaneNum = dig_connector->dp_lane_count;
+                       args.v3.ucLaneNum = dp_lane_count;
                else if (radeon_encoder->pixel_clock > 165000)
                        args.v3.ucLaneNum = 8;
                else
                        args.v3.ucLaneNum = 4;
 
-               if (dig_connector->linkb) {
+               if (dig->linkb) {
                        args.v3.acConfig.ucLinkSel = 1;
                        args.v3.acConfig.ucEncoderSel = 1;
                }
@@ -904,7 +910,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                }
        } else if (ASIC_IS_DCE32(rdev)) {
                args.v2.acConfig.ucEncoderSel = dig->dig_encoder;
-               if (dig_connector->linkb)
+               if (dig->linkb)
                        args.v2.acConfig.ucLinkSel = 1;
 
                switch (radeon_encoder->encoder_id) {
@@ -938,23 +944,23 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                if ((rdev->flags & RADEON_IS_IGP) &&
                    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
                        if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
-                               if (dig_connector->igp_lane_info & 0x1)
+                               if (igp_lane_info & 0x1)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-                               else if (dig_connector->igp_lane_info & 0x2)
+                               else if (igp_lane_info & 0x2)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
-                               else if (dig_connector->igp_lane_info & 0x4)
+                               else if (igp_lane_info & 0x4)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
-                               else if (dig_connector->igp_lane_info & 0x8)
+                               else if (igp_lane_info & 0x8)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
                        } else {
-                               if (dig_connector->igp_lane_info & 0x3)
+                               if (igp_lane_info & 0x3)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
-                               else if (dig_connector->igp_lane_info & 0xc)
+                               else if (igp_lane_info & 0xc)
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
                        }
                }
 
-               if (dig_connector->linkb)
+               if (dig->linkb)
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
                else
                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
@@ -1072,8 +1078,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        if (is_dig) {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
-                       if (!ASIC_IS_DCE4(rdev))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
@@ -1085,8 +1090,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
-                       if (!ASIC_IS_DCE4(rdev))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                if (ASIC_IS_DCE4(rdev))
                                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
@@ -1290,24 +1294,22 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
        uint32_t dig_enc_in_use = 0;
 
        if (ASIC_IS_DCE4(rdev)) {
-               struct radeon_connector_atom_dig *dig_connector =
-                       radeon_get_atom_connector_priv_from_encoder(encoder);
-
+               dig = radeon_encoder->enc_priv;
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       if (dig_connector->linkb)
+                       if (dig->linkb)
                                return 1;
                        else
                                return 0;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-                       if (dig_connector->linkb)
+                       if (dig->linkb)
                                return 3;
                        else
                                return 2;
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                       if (dig_connector->linkb)
+                       if (dig->linkb)
                                return 5;
                        else
                                return 4;
@@ -1641,6 +1643,7 @@ radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
 struct radeon_encoder_atom_dig *
 radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
 {
+       int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
        struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
 
        if (!dig)
@@ -1650,11 +1653,16 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
        dig->coherent_mode = true;
        dig->dig_encoder = -1;
 
+       if (encoder_enum == 2)
+               dig->linkb = true;
+       else
+               dig->linkb = false;
+
        return dig;
 }
 
 void
-radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
+radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *encoder;
@@ -1663,7 +1671,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
        /* see if we already added it */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                radeon_encoder = to_radeon_encoder(encoder);
-               if (radeon_encoder->encoder_id == encoder_id) {
+               if (radeon_encoder->encoder_enum == encoder_enum) {
                        radeon_encoder->devices |= supported_device;
                        return;
                }
@@ -1691,7 +1699,8 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
 
        radeon_encoder->enc_priv = NULL;
 
-       radeon_encoder->encoder_id = encoder_id;
+       radeon_encoder->encoder_enum = encoder_enum;
+       radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
        radeon_encoder->devices = supported_device;
        radeon_encoder->rmx_type = RMX_OFF;
        radeon_encoder->underscan_type = UNDERSCAN_OFF;
index dbf86962bdd16a5741c3de1369c4ebe7d6c36d29..40b0c087b5921384d46bf7f745cf93f2b391015b 100644 (file)
@@ -94,6 +94,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
        ret = radeon_bo_reserve(rbo, false);
        if (likely(ret == 0)) {
                radeon_bo_kunmap(rbo);
+               radeon_bo_unpin(rbo);
                radeon_bo_unreserve(rbo);
        }
        drm_gem_object_unreference_unlocked(gobj);
@@ -118,7 +119,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
        aligned_size = ALIGN(size, PAGE_SIZE);
        ret = radeon_gem_object_create(rdev, aligned_size, 0,
                                       RADEON_GEM_DOMAIN_VRAM,
-                                      false, ttm_bo_type_kernel,
+                                      false, true,
                                       &gobj);
        if (ret) {
                printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
@@ -325,8 +326,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
 {
        struct fb_info *info;
        struct radeon_framebuffer *rfb = &rfbdev->rfb;
-       struct radeon_bo *rbo;
-       int r;
 
        if (rfbdev->helper.fbdev) {
                info = rfbdev->helper.fbdev;
@@ -338,14 +337,8 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
        }
 
        if (rfb->obj) {
-               rbo = rfb->obj->driver_private;
-               r = radeon_bo_reserve(rbo, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rbo);
-                       radeon_bo_unpin(rbo);
-                       radeon_bo_unreserve(rbo);
-               }
-               drm_gem_object_unreference_unlocked(rfb->obj);
+               radeonfb_destroy_pinned_object(rfb->obj);
+               rfb->obj = NULL;
        }
        drm_fb_helper_fini(&rfbdev->helper);
        drm_framebuffer_cleanup(&rfb->base);
index c578f265b24cefc6dce21734783b01c1aed1ce27..d1e595d9172396b8104d19c7a1d0a87d3b14b772 100644 (file)
@@ -201,11 +201,11 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
                return r;
        }
        r = drm_gem_handle_create(filp, gobj, &handle);
+       /* drop reference from allocate - handle holds it now */
+       drm_gem_object_unreference_unlocked(gobj);
        if (r) {
-               drm_gem_object_unreference_unlocked(gobj);
                return r;
        }
-       drm_gem_object_handle_unreference_unlocked(gobj);
        args->handle = handle;
        return 0;
 }
index bfd2ce5f53728dd322767ec186cda77993215f24..6a13ee38a5b9fc71201a0a9a38dd93b3ab5957eb 100644 (file)
@@ -99,6 +99,13 @@ static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
                }
        }
 
+       /* switch the pads to ddc mode */
+       if (ASIC_IS_DCE3(rdev) && rec->hw_capable) {
+               temp = RREG32(rec->mask_clk_reg);
+               temp &= ~(1 << 16);
+               WREG32(rec->mask_clk_reg, temp);
+       }
+
        /* clear the output pin values */
        temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask;
        WREG32(rec->a_clk_reg, temp);
@@ -206,7 +213,7 @@ static void post_xfer(struct i2c_adapter *i2c_adap)
 
 static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
 {
-       u32 sclk = radeon_get_engine_clock(rdev);
+       u32 sclk = rdev->pm.current_sclk;
        u32 prescale = 0;
        u32 nm;
        u8 n, m, loop;
index 059bfa4098d7a5990034cf00c0d3bd84b8b09270..a108c7ed14f5941a4954839a583bc2f48f7cf44e 100644 (file)
@@ -121,11 +121,12 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
         * chips.  Disable MSI on them for now.
         */
        if ((rdev->family >= CHIP_RV380) &&
-           (!(rdev->flags & RADEON_IS_IGP))) {
+           (!(rdev->flags & RADEON_IS_IGP)) &&
+           (!(rdev->flags & RADEON_IS_AGP))) {
                int ret = pci_enable_msi(rdev->pdev);
                if (!ret) {
                        rdev->msi_enabled = 1;
-                       DRM_INFO("radeon: using MSI.\n");
+                       dev_info(rdev->dev, "radeon: using MSI.\n");
                }
        }
        rdev->irq.installed = true;
index b1c8ace5f0802c908ce653022bbe2921470c8e90..8fbbe1c6ebbda854f7bf9dc9f76ae1c4eefdafc5 100644 (file)
@@ -161,6 +161,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
                        return -EINVAL;
                }
+               break;
        case RADEON_INFO_WANT_HYPERZ:
                /* The "value" here is both an input and output parameter.
                 * If the input value is 1, filp requests hyper-z access.
@@ -202,6 +203,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
  */
 int radeon_driver_firstopen_kms(struct drm_device *dev)
 {
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (rdev->powered_down)
+               return -EINVAL;
        return 0;
 }
 
@@ -323,45 +328,45 @@ KMS_INVALID_IOCTL(radeon_surface_free_kms)
 
 
 struct drm_ioctl_desc radeon_ioctls_kms[] = {
-       DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
        /* KMS */
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
 };
 int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
index 989df519a1e453b618e2599f0eeced23e637dc91..305049afde15235e558dc22f3992543508f362e6 100644 (file)
@@ -272,7 +272,7 @@ static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div,
        if (!ref_div)
                return 1;
 
-       vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div;
+       vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div;
 
        /*
         * This is horribly crude: the VCO frequency range is divided into
index b8149cbc0c70ca3511f748d13e05cb85c16073e9..0b8397000f4c68ae98e80df717a652cb2ddf6253 100644 (file)
@@ -1345,7 +1345,7 @@ static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct ra
 }
 
 void
-radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *encoder;
@@ -1354,7 +1354,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
        /* see if we already added it */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                radeon_encoder = to_radeon_encoder(encoder);
-               if (radeon_encoder->encoder_id == encoder_id) {
+               if (radeon_encoder->encoder_enum == encoder_enum) {
                        radeon_encoder->devices |= supported_device;
                        return;
                }
@@ -1374,7 +1374,8 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
 
        radeon_encoder->enc_priv = NULL;
 
-       radeon_encoder->encoder_id = encoder_id;
+       radeon_encoder->encoder_enum = encoder_enum;
+       radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
        radeon_encoder->devices = supported_device;
        radeon_encoder->rmx_type = RMX_OFF;
 
index 5bbc086b9267bb16e6d324de5af25977cdf76dae..17a6602b5885786fecd6dd3231940a7b5d3c4261 100644 (file)
@@ -204,7 +204,7 @@ struct radeon_i2c_chan {
 
 /* mostly for macs, but really any system without connector tables */
 enum radeon_connector_table {
-       CT_NONE,
+       CT_NONE = 0,
        CT_GENERIC,
        CT_IBOOK,
        CT_POWERBOOK_EXTERNAL,
@@ -215,6 +215,7 @@ enum radeon_connector_table {
        CT_IMAC_G5_ISIGHT,
        CT_EMAC,
        CT_RN50_POWER,
+       CT_MAC_X800,
 };
 
 enum radeon_dvo_chip {
@@ -342,6 +343,7 @@ struct radeon_atom_ss {
 };
 
 struct radeon_encoder_atom_dig {
+       bool linkb;
        /* atom dig */
        bool coherent_mode;
        int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB */
@@ -360,6 +362,7 @@ struct radeon_encoder_atom_dac {
 
 struct radeon_encoder {
        struct drm_encoder base;
+       uint32_t encoder_enum;
        uint32_t encoder_id;
        uint32_t devices;
        uint32_t active_device;
@@ -378,7 +381,6 @@ struct radeon_encoder {
 
 struct radeon_connector_atom_dig {
        uint32_t igp_lane_info;
-       bool linkb;
        /* displayport */
        struct radeon_i2c_chan *dp_i2c_bus;
        u8 dpcd[8];
@@ -599,7 +601,6 @@ extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct d
 void radeon_enc_destroy(struct drm_encoder *encoder);
 void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
 void radeon_combios_asic_init(struct drm_device *dev);
-extern int radeon_static_clocks_init(struct drm_device *dev);
 bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                                        struct drm_display_mode *mode,
                                        struct drm_display_mode *adjusted_mode);
index 0afd1e62347dcfb9670d20e13a818d8d7a99b59c..b3b5306bb578bf88547e4078fe48f59d9e0ea720 100644 (file)
@@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        u32 c = 0;
 
        rbo->placement.fpfn = 0;
-       rbo->placement.lpfn = 0;
+       rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT;
        rbo->placement.placement = rbo->placements;
        rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM)
index 353998dc2c03b12992cd244ff116d01e45db2b96..3481bc7f6f582b08a0c2a9ff079fa9787defb6cd 100644 (file)
@@ -124,11 +124,8 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
        int r;
 
        r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-       if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS)
-                       dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
+       if (unlikely(r != 0))
                return r;
-       }
        spin_lock(&bo->tbo.lock);
        if (mem_type)
                *mem_type = bo->tbo.mem.mem_type;
index 58038f5cab38d4b0c31ac7c2abfbad9a18c533b2..f87efec76236966ac790ff0709f5cf2ae3c57563 100644 (file)
@@ -226,6 +226,11 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
 {
        int i;
 
+       /* no need to take locks, etc. if nothing's going to change */
+       if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
+           (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
+               return;
+
        mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->vram_mutex);
        mutex_lock(&rdev->cp.mutex);
@@ -632,8 +637,6 @@ void radeon_pm_fini(struct radeon_device *rdev)
        }
 
        radeon_hwmon_fini(rdev);
-       if (rdev->pm.i2c_bus)
-               radeon_i2c_destroy(rdev->pm.i2c_bus);
 }
 
 void radeon_pm_compute_clocks(struct radeon_device *rdev)
index b3ba44c0a81801a9f528edf833be726a05a55c40..4ae5a3d1074e19c9a203f7433cfc12e1c7724042 100644 (file)
@@ -3228,34 +3228,34 @@ void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
 }
 
 struct drm_ioctl_desc radeon_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
+       DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
 };
 
 int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
index cc05b230d7effbbae88524da0d698dace6228ccf..51d5f7b5ab21b40a6e34d2fd286f28da91e4f0b0 100644 (file)
@@ -693,6 +693,7 @@ void rs600_mc_init(struct radeon_device *rdev)
        rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
        rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
        base = RREG32_MC(R_000004_MC_FB_LOCATION);
        base = G_000004_MC_FB_START(base) << 16;
index 3e3f75718be3e83ab156465dc80a11f604b58a64..4dc2a87ea68018f0292cc0724d6ef4868c00e8ac 100644 (file)
@@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
        base = G_000100_MC_FB_START(base) << 16;
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
index f1c796810117fdb9dfb0b66aa5a89eee5e1da1e9..9490da700749487c00fe9c57671ec89727653136 100644 (file)
@@ -267,6 +267,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
  */
 void r700_cp_stop(struct radeon_device *rdev)
 {
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 }
 
@@ -905,6 +906,54 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
 }
 
+static int rv770_vram_scratch_init(struct radeon_device *rdev)
+{
+       int r;
+       u64 gpu_addr;
+
+       if (rdev->vram_scratch.robj == NULL) {
+               r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
+                                       true, RADEON_GEM_DOMAIN_VRAM,
+                                       &rdev->vram_scratch.robj);
+               if (r) {
+                       return r;
+               }
+       }
+
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (unlikely(r != 0))
+               return r;
+       r = radeon_bo_pin(rdev->vram_scratch.robj,
+                         RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+               return r;
+       }
+       r = radeon_bo_kmap(rdev->vram_scratch.robj,
+                               (void **)&rdev->vram_scratch.ptr);
+       if (r)
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+       radeon_bo_unreserve(rdev->vram_scratch.robj);
+
+       return r;
+}
+
+static void rv770_vram_scratch_fini(struct radeon_device *rdev)
+{
+       int r;
+
+       if (rdev->vram_scratch.robj == NULL) {
+               return;
+       }
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (likely(r == 0)) {
+               radeon_bo_kunmap(rdev->vram_scratch.robj);
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+       }
+       radeon_bo_unref(&rdev->vram_scratch.robj);
+}
+
 int rv770_mc_init(struct radeon_device *rdev)
 {
        u32 tmp;
@@ -944,6 +993,7 @@ int rv770_mc_init(struct radeon_device *rdev)
        rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
        rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        r600_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
 
@@ -970,6 +1020,9 @@ static int rv770_startup(struct radeon_device *rdev)
                if (r)
                        return r;
        }
+       r = rv770_vram_scratch_init(rdev);
+       if (r)
+               return r;
        rv770_gpu_init(rdev);
        r = r600_blit_init(rdev);
        if (r) {
@@ -1023,11 +1076,6 @@ int rv770_resume(struct radeon_device *rdev)
         */
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
-       /* Initialize clocks */
-       r = radeon_clocks_init(rdev);
-       if (r) {
-               return r;
-       }
 
        r = rv770_startup(rdev);
        if (r) {
@@ -1118,9 +1166,6 @@ int rv770_init(struct radeon_device *rdev)
        radeon_surface_init(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
-       r = radeon_clocks_init(rdev);
-       if (r)
-               return r;
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
@@ -1195,9 +1240,9 @@ void rv770_fini(struct radeon_device *rdev)
        r600_irq_fini(rdev);
        radeon_irq_kms_fini(rdev);
        rv770_pcie_gart_fini(rdev);
+       rv770_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
-       radeon_clocks_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
index 976dc8d25280c749798f1c1f124219190c10ca84..bf5f83ea14fe19819874311b66618957859286f2 100644 (file)
@@ -1082,10 +1082,10 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 }
 
 struct drm_ioctl_desc savage_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH),
 };
 
 int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
index 021de44c15ab75245fde74c95701c6c8a72aadaf..2a2830f5a8409b802a000b663faa1580d9a20815 100644 (file)
@@ -54,6 +54,7 @@ static struct drm_driver driver = {
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
+                .llseek = noop_llseek,
        },
 
        .pci_driver = {
index 776bf9e9ea1adfec718e6b5a4c7906eedaf72348..4bb10ef6676a711b795346006f2e97ebdce51e42 100644 (file)
@@ -83,6 +83,7 @@ static struct drm_driver driver = {
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
+                .llseek = noop_llseek,
        },
        .pci_driver = {
                 .name = DRIVER_NAME,
index 07d0f2979cac1158f4db86a90e28bf4184d2b1fa..7fe2b63412ce96aa2c0829127c25261a7bb7aa6d 100644 (file)
@@ -320,12 +320,12 @@ void sis_reclaim_buffers_locked(struct drm_device *dev,
 }
 
 struct drm_ioctl_desc sis_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
 };
 
 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
index ec5a43e65722ec3a3b2a7a63a4e97fd531730a34..640567ef713dbe97e9f22c710a7d951cc73c46b5 100644 (file)
@@ -52,6 +52,7 @@ static struct drm_driver driver = {
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
+                .llseek = noop_llseek,
        },
        .pci_driver = {
                 .name = DRIVER_NAME,
index cb4cf7ef4d1eee9bc726c4d4ee34f8962526b316..db809e034cc48b6d8c246cba1ede0660113e30de 100644 (file)
@@ -441,6 +441,43 @@ out_err:
        return ret;
 }
 
+/**
+ * Call bo::reserved and with the lru lock held.
+ * Will release GPU memory type usage on destruction.
+ * This is the place to put in driver specific hooks.
+ * Will release the bo::reserved lock and the
+ * lru lock on exit.
+ */
+
+static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
+{
+       struct ttm_bo_global *glob = bo->glob;
+
+       if (bo->ttm) {
+
+               /**
+                * Release the lru_lock, since we don't want to have
+                * an atomic requirement on ttm_tt[unbind|destroy].
+                */
+
+               spin_unlock(&glob->lru_lock);
+               ttm_tt_unbind(bo->ttm);
+               ttm_tt_destroy(bo->ttm);
+               bo->ttm = NULL;
+               spin_lock(&glob->lru_lock);
+       }
+
+       if (bo->mem.mm_node) {
+               drm_mm_put_block(bo->mem.mm_node);
+               bo->mem.mm_node = NULL;
+       }
+
+       atomic_set(&bo->reserved, 0);
+       wake_up_all(&bo->event_queue);
+       spin_unlock(&glob->lru_lock);
+}
+
+
 /**
  * If bo idle, remove from delayed- and lru lists, and unref.
  * If not idle, and already on delayed list, do nothing.
@@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
        int ret;
 
        spin_lock(&bo->lock);
+retry:
        (void) ttm_bo_wait(bo, false, false, !remove_all);
 
        if (!bo->sync_obj) {
@@ -464,31 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
                spin_unlock(&bo->lock);
 
                spin_lock(&glob->lru_lock);
-               put_count = ttm_bo_del_from_lru(bo);
+               ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
+
+               /**
+                * Someone else has the object reserved. Bail and retry.
+                */
 
-               ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
-               BUG_ON(ret);
-               if (bo->ttm)
-                       ttm_tt_unbind(bo->ttm);
+               if (unlikely(ret == -EBUSY)) {
+                       spin_unlock(&glob->lru_lock);
+                       spin_lock(&bo->lock);
+                       goto requeue;
+               }
+
+               /**
+                * We can re-check for sync object without taking
+                * the bo::lock since setting the sync object requires
+                * also bo::reserved. A busy object at this point may
+                * be caused by another thread starting an accelerated
+                * eviction.
+                */
+
+               if (unlikely(bo->sync_obj)) {
+                       atomic_set(&bo->reserved, 0);
+                       wake_up_all(&bo->event_queue);
+                       spin_unlock(&glob->lru_lock);
+                       spin_lock(&bo->lock);
+                       if (remove_all)
+                               goto retry;
+                       else
+                               goto requeue;
+               }
+
+               put_count = ttm_bo_del_from_lru(bo);
 
                if (!list_empty(&bo->ddestroy)) {
                        list_del_init(&bo->ddestroy);
                        ++put_count;
                }
-               if (bo->mem.mm_node) {
-                       drm_mm_put_block(bo->mem.mm_node);
-                       bo->mem.mm_node = NULL;
-               }
-               spin_unlock(&glob->lru_lock);
 
-               atomic_set(&bo->reserved, 0);
+               ttm_bo_cleanup_memtype_use(bo);
 
                while (put_count--)
                        kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
                return 0;
        }
-
+requeue:
        spin_lock(&glob->lru_lock);
        if (list_empty(&bo->ddestroy)) {
                void *sync_obj = bo->sync_obj;
index 7cffb3e0423249ec4f78f7c7cbdc72b6df921e50..3451a82adba76c31672ee96f086146f5da1ab12b 100644 (file)
@@ -351,6 +351,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        INIT_LIST_HEAD(&fbo->lru);
        INIT_LIST_HEAD(&fbo->swap);
        fbo->vm_node = NULL;
+       atomic_set(&fbo->cpu_writers, 0);
 
        fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
        kref_init(&fbo->list_kref);
index ca904799f018a6e3ae23c80933bd1e007aec8f7f..b1e02fffd3ccdebf256d38bb55bed9a37ea1c8d7 100644 (file)
@@ -69,7 +69,7 @@ struct ttm_page_pool {
        spinlock_t              lock;
        bool                    fill_lock;
        struct list_head        list;
-       int                     gfp_flags;
+       gfp_t                   gfp_flags;
        unsigned                npages;
        char                    *name;
        unsigned long           nfrees;
@@ -475,7 +475,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
  * This function is reentrant if caller updates count depending on number of
  * pages returned in pages array.
  */
-static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
+static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
                int ttm_flags, enum ttm_caching_state cstate, unsigned count)
 {
        struct page **caching_array;
@@ -666,7 +666,7 @@ int ttm_get_pages(struct list_head *pages, int flags,
 {
        struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
        struct page *p = NULL;
-       int gfp_flags = GFP_USER;
+       gfp_t gfp_flags = GFP_USER;
        int r;
 
        /* set zero flag for page allocation if required */
@@ -818,7 +818,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
        return 0;
 }
 
-void ttm_page_alloc_fini()
+void ttm_page_alloc_fini(void)
 {
        int i;
 
index 68dda74a50ae54c8273eb0e076d7ff151f9f7231..cc0ffa9abd00da2ff0504679bad6f32b04f0d561 100644 (file)
@@ -722,20 +722,20 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
 }
 
 struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
+       DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
 };
 
 int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
index 7a1b210401e080908a394368f4797c63dd745d65..b8984a5ae5218b375764fe2845d6c8cb5febc548 100644 (file)
@@ -62,6 +62,7 @@ static struct drm_driver driver = {
                .mmap = drm_mmap,
                .poll = drm_poll,
                .fasync = drm_fasync,
+               .llseek = noop_llseek,
                },
        .pci_driver = {
                .name = DRIVER_NAME,
index 9dd395b90216b17c54598c9309502785a2684220..2ef93df9e8ae39f8c9e267a500ee5157f2fda420 100644 (file)
  */
 
 #define VMW_IOCTL_DEF(ioctl, func, flags) \
-       [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+  [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_##ioctl, flags, func, DRM_IOCTL_##ioctl}
 
 /**
  * Ioctl definitions.
  */
 
 static struct drm_ioctl_desc vmw_ioctls[] = {
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl,
+       VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
+       VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
+       VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS,
+       VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
                      vmw_kms_cursor_bypass_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
 
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl,
+       VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
+       VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
+       VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
 
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
+       VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
+       VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
+       VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
+       VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl,
+       VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl,
+       VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
+       VMW_IOCTL_DEF(VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
                      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+       VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
                      DRM_AUTH | DRM_UNLOCKED),
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
+       VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
                      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
 };
 
@@ -148,13 +148,16 @@ static struct pci_device_id vmw_pci_id_list[] = {
        {0, 0, 0}
 };
 
-static char *vmw_devname = "vmwgfx";
+static int enable_fbdev;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
                              void *ptr);
 
+MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
+module_param_named(enable_fbdev, enable_fbdev, int, 0600);
+
 static void vmw_print_capabilities(uint32_t capabilities)
 {
        DRM_INFO("Capabilities:\n");
@@ -192,8 +195,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
 {
        int ret;
 
-       vmw_kms_save_vga(dev_priv);
-
        ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Unable to initialize FIFO.\n");
@@ -206,9 +207,35 @@ static int vmw_request_device(struct vmw_private *dev_priv)
 static void vmw_release_device(struct vmw_private *dev_priv)
 {
        vmw_fifo_release(dev_priv, &dev_priv->fifo);
-       vmw_kms_restore_vga(dev_priv);
 }
 
+int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+{
+       int ret = 0;
+
+       mutex_lock(&dev_priv->release_mutex);
+       if (unlikely(dev_priv->num_3d_resources++ == 0)) {
+               ret = vmw_request_device(dev_priv);
+               if (unlikely(ret != 0))
+                       --dev_priv->num_3d_resources;
+       }
+       mutex_unlock(&dev_priv->release_mutex);
+       return ret;
+}
+
+
+void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+{
+       int32_t n3d;
+
+       mutex_lock(&dev_priv->release_mutex);
+       if (unlikely(--dev_priv->num_3d_resources == 0))
+               vmw_release_device(dev_priv);
+       n3d = (int32_t) dev_priv->num_3d_resources;
+       mutex_unlock(&dev_priv->release_mutex);
+
+       BUG_ON(n3d < 0);
+}
 
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
@@ -228,6 +255,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->last_read_sequence = (uint32_t) -100;
        mutex_init(&dev_priv->hw_mutex);
        mutex_init(&dev_priv->cmdbuf_mutex);
+       mutex_init(&dev_priv->release_mutex);
        rwlock_init(&dev_priv->resource_lock);
        idr_init(&dev_priv->context_idr);
        idr_init(&dev_priv->surface_idr);
@@ -244,6 +272,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
        dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
+       dev_priv->enable_fb = enable_fbdev;
+
        mutex_lock(&dev_priv->hw_mutex);
 
        vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -343,17 +373,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
        dev->dev_private = dev_priv;
 
-       if (!dev->devname)
-               dev->devname = vmw_devname;
-
-       if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
-               ret = drm_irq_install(dev);
-               if (unlikely(ret != 0)) {
-                       DRM_ERROR("Failed installing irq: %d\n", ret);
-                       goto out_no_irq;
-               }
-       }
-
        ret = pci_request_regions(dev->pdev, "vmwgfx probe");
        dev_priv->stealth = (ret != 0);
        if (dev_priv->stealth) {
@@ -369,26 +388,52 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                        goto out_no_device;
                }
        }
-       ret = vmw_request_device(dev_priv);
+       ret = vmw_kms_init(dev_priv);
        if (unlikely(ret != 0))
-               goto out_no_device;
-       vmw_kms_init(dev_priv);
+               goto out_no_kms;
        vmw_overlay_init(dev_priv);
-       vmw_fb_init(dev_priv);
+       if (dev_priv->enable_fb) {
+               ret = vmw_3d_resource_inc(dev_priv);
+               if (unlikely(ret != 0))
+                       goto out_no_fifo;
+               vmw_kms_save_vga(dev_priv);
+               vmw_fb_init(dev_priv);
+               DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
+                        "Detected device 3D availability.\n" :
+                        "Detected no device 3D availability.\n");
+       } else {
+               DRM_INFO("Delayed 3D detection since we're not "
+                        "running the device in SVGA mode yet.\n");
+       }
+
+       if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+               ret = drm_irq_install(dev);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Failed installing irq: %d\n", ret);
+                       goto out_no_irq;
+               }
+       }
 
        dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
        register_pm_notifier(&dev_priv->pm_nb);
 
-       DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
-
        return 0;
 
-out_no_device:
-       if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-               drm_irq_uninstall(dev_priv->dev);
-       if (dev->devname == vmw_devname)
-               dev->devname = NULL;
 out_no_irq:
+       if (dev_priv->enable_fb) {
+               vmw_fb_close(dev_priv);
+               vmw_kms_restore_vga(dev_priv);
+               vmw_3d_resource_dec(dev_priv);
+       }
+out_no_fifo:
+       vmw_overlay_close(dev_priv);
+       vmw_kms_close(dev_priv);
+out_no_kms:
+       if (dev_priv->stealth)
+               pci_release_region(dev->pdev, 2);
+       else
+               pci_release_regions(dev->pdev);
+out_no_device:
        ttm_object_device_release(&dev_priv->tdev);
 out_err4:
        iounmap(dev_priv->mmio_virt);
@@ -415,19 +460,20 @@ static int vmw_driver_unload(struct drm_device *dev)
 
        unregister_pm_notifier(&dev_priv->pm_nb);
 
-       vmw_fb_close(dev_priv);
+       if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+               drm_irq_uninstall(dev_priv->dev);
+       if (dev_priv->enable_fb) {
+               vmw_fb_close(dev_priv);
+               vmw_kms_restore_vga(dev_priv);
+               vmw_3d_resource_dec(dev_priv);
+       }
        vmw_kms_close(dev_priv);
        vmw_overlay_close(dev_priv);
-       vmw_release_device(dev_priv);
        if (dev_priv->stealth)
                pci_release_region(dev->pdev, 2);
        else
                pci_release_regions(dev->pdev);
 
-       if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-               drm_irq_uninstall(dev_priv->dev);
-       if (dev->devname == vmw_devname)
-               dev->devname = NULL;
        ttm_object_device_release(&dev_priv->tdev);
        iounmap(dev_priv->mmio_virt);
        drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
@@ -500,7 +546,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
                struct drm_ioctl_desc *ioctl =
                    &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
-               if (unlikely(ioctl->cmd != cmd)) {
+               if (unlikely(ioctl->cmd_drv != cmd)) {
                        DRM_ERROR("Invalid command format, ioctl %d\n",
                                  nr - DRM_COMMAND_BASE);
                        return -EINVAL;
@@ -589,6 +635,16 @@ static int vmw_master_set(struct drm_device *dev,
        struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret = 0;
 
+       if (!dev_priv->enable_fb) {
+               ret = vmw_3d_resource_inc(dev_priv);
+               if (unlikely(ret != 0))
+                       return ret;
+               vmw_kms_save_vga(dev_priv);
+               mutex_lock(&dev_priv->hw_mutex);
+               vmw_write(dev_priv, SVGA_REG_TRACES, 0);
+               mutex_unlock(&dev_priv->hw_mutex);
+       }
+
        if (active) {
                BUG_ON(active != &dev_priv->fbdev_master);
                ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -617,7 +673,13 @@ static int vmw_master_set(struct drm_device *dev,
        return 0;
 
 out_no_active_lock:
-       vmw_release_device(dev_priv);
+       if (!dev_priv->enable_fb) {
+               mutex_lock(&dev_priv->hw_mutex);
+               vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+               mutex_unlock(&dev_priv->hw_mutex);
+               vmw_kms_restore_vga(dev_priv);
+               vmw_3d_resource_dec(dev_priv);
+       }
        return ret;
 }
 
@@ -645,11 +707,23 @@ static void vmw_master_drop(struct drm_device *dev,
 
        ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
 
+       if (!dev_priv->enable_fb) {
+               ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+               if (unlikely(ret != 0))
+                       DRM_ERROR("Unable to clean VRAM on master drop.\n");
+               mutex_lock(&dev_priv->hw_mutex);
+               vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+               mutex_unlock(&dev_priv->hw_mutex);
+               vmw_kms_restore_vga(dev_priv);
+               vmw_3d_resource_dec(dev_priv);
+       }
+
        dev_priv->active_master = &dev_priv->fbdev_master;
        ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
        ttm_vt_unlock(&dev_priv->fbdev_master.lock);
 
-       vmw_fb_on(dev_priv);
+       if (dev_priv->enable_fb)
+               vmw_fb_on(dev_priv);
 }
 
 
@@ -722,6 +796,7 @@ static struct drm_driver driver = {
        .irq_postinstall = vmw_irq_postinstall,
        .irq_uninstall = vmw_irq_uninstall,
        .irq_handler = vmw_irq_handler,
+       .get_vblank_counter = vmw_get_vblank_counter,
        .reclaim_buffers_locked = NULL,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
@@ -745,6 +820,7 @@ static struct drm_driver driver = {
 #if defined(CONFIG_COMPAT)
                 .compat_ioctl = drm_compat_ioctl,
 #endif
+                .llseek = noop_llseek,
                 },
        .pci_driver = {
                       .name = VMWGFX_DRIVER_NAME,
index 429f917b60bf4b30ecdfd0946f9f1f0978bd5c58..58de6393f611dd79fbbebeab81102dcf0f4abfcb 100644 (file)
@@ -277,6 +277,7 @@ struct vmw_private {
 
        bool stealth;
        bool is_opened;
+       bool enable_fb;
 
        /**
         * Master management.
@@ -285,6 +286,9 @@ struct vmw_private {
        struct vmw_master *active_master;
        struct vmw_master fbdev_master;
        struct notifier_block pm_nb;
+
+       struct mutex release_mutex;
+       uint32_t num_3d_resources;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
        return val;
 }
 
+int vmw_3d_resource_inc(struct vmw_private *dev_priv);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+
 /**
  * GMR utilities - vmwgfx_gmr.c
  */
@@ -511,6 +518,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
                        unsigned bbp, unsigned depth);
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
 
 /**
  * Overlay control - vmwgfx_overlay.c
index 870967a97c15d52eb3f380323e6038d32ed6e76f..409e172f4abfe94502be96502e251b5d6b2e54c9 100644 (file)
@@ -615,6 +615,11 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
        if (unlikely(ret != 0))
                goto err_unlock;
 
+       if (bo->mem.mem_type == TTM_PL_VRAM &&
+           bo->mem.mm_node->start < bo->num_pages)
+               (void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+                                      false, false);
+
        ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
 
        /* Could probably bug on */
index e6a1eb7ea95498f00e65d123adeae79160af8fa8..0fe31766e4cf5f11e6025e5a85f96baa5936408f 100644 (file)
@@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
        mutex_lock(&dev_priv->hw_mutex);
        dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
        dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+       dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
        vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
 
        min = 4;
@@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
                  dev_priv->config_done_state);
        vmw_write(dev_priv, SVGA_REG_ENABLE,
                  dev_priv->enable_state);
+       vmw_write(dev_priv, SVGA_REG_TRACES,
+                 dev_priv->traces_state);
 
        mutex_unlock(&dev_priv->hw_mutex);
        vmw_fence_queue_takedown(&fifo->fence_queue);
index 64d7f47df8683ef49cfbb3c83eb449026949af03..e882ba099f0c33dab30f12f7b9328b3b628ac712 100644 (file)
@@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
                save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
                save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+               if (i == 0 && vmw_priv->num_displays == 1 &&
+                   save->width == 0 && save->height == 0) {
+
+                       /*
+                        * It should be fairly safe to assume that these
+                        * values are uninitialized.
+                        */
+
+                       save->width = vmw_priv->vga_width - save->pos_x;
+                       save->height = vmw_priv->vga_height - save->pos_y;
+               }
        }
+
        return 0;
 }
 
@@ -984,3 +996,8 @@ out_unlock:
        ttm_read_unlock(&vmaster->lock);
        return ret;
 }
+
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       return 0;
+}
index 2ff5cf78235f35379cf409b3ec659774124a0757..11cb39e3accbfa9581801095ab0398952d2313f1 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "vmwgfx_kms.h"
 
+#define VMWGFX_LDU_NUM_DU 8
+
 #define vmw_crtc_to_ldu(x) \
        container_of(x, struct vmw_legacy_display_unit, base.crtc)
 #define vmw_encoder_to_ldu(x) \
@@ -335,7 +337,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
 }
 
 static enum drm_connector_status
-       vmw_ldu_connector_detect(struct drm_connector *connector)
+       vmw_ldu_connector_detect(struct drm_connector *connector,
+                                bool force)
 {
        if (vmw_connector_to_ldu(connector)->pref_active)
                return connector_status_connected;
@@ -516,7 +519,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 
        drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
                           DRM_MODE_CONNECTOR_LVDS);
-       connector->status = vmw_ldu_connector_detect(connector);
+       connector->status = vmw_ldu_connector_detect(connector, true);
 
        drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
                         DRM_MODE_ENCODER_LVDS);
@@ -535,6 +538,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+       int i;
+       int ret;
+
        if (dev_priv->ldu_priv) {
                DRM_INFO("ldu system already on\n");
                return -EINVAL;
@@ -552,23 +559,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 
        drm_mode_create_dirty_info_property(dev_priv->dev);
 
-       vmw_ldu_init(dev_priv, 0);
-       /* for old hardware without multimon only enable one display */
        if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_ldu_init(dev_priv, 1);
-               vmw_ldu_init(dev_priv, 2);
-               vmw_ldu_init(dev_priv, 3);
-               vmw_ldu_init(dev_priv, 4);
-               vmw_ldu_init(dev_priv, 5);
-               vmw_ldu_init(dev_priv, 6);
-               vmw_ldu_init(dev_priv, 7);
+               for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+                       vmw_ldu_init(dev_priv, i);
+               ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
+       } else {
+               /* for old hardware without multimon only enable one display */
+               vmw_ldu_init(dev_priv, 0);
+               ret = drm_vblank_init(dev, 1);
        }
 
-       return 0;
+       return ret;
 }
 
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+
+       drm_vblank_cleanup(dev);
        if (!dev_priv->ldu_priv)
                return -ENOSYS;
 
@@ -610,7 +618,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
                        ldu->pref_height = 600;
                        ldu->pref_active = false;
                }
-               con->status = vmw_ldu_connector_detect(con);
+               con->status = vmw_ldu_connector_detect(con, true);
        }
 
        mutex_unlock(&dev->mode_config.mutex);
index 5f2d5df01e5c370acbc1be99772701626419daf5..c8c40e9979dbd21442a5d87cf6ac4cdcad08cfad 100644 (file)
@@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
        cmd->body.cid = cpu_to_le32(res->id);
 
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       vmw_3d_resource_dec(dev_priv);
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
        cmd->body.cid = cpu_to_le32(res->id);
 
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       (void) vmw_3d_resource_inc(dev_priv);
        vmw_resource_activate(res, vmw_hw_context_destroy);
        return 0;
 }
@@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
        cmd->body.sid = cpu_to_le32(res->id);
 
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       vmw_3d_resource_dec(dev_priv);
 }
 
 void vmw_surface_res_free(struct vmw_resource *res)
@@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
        }
 
        vmw_fifo_commit(dev_priv, submit_size);
+       (void) vmw_3d_resource_inc(dev_priv);
        vmw_resource_activate(res, vmw_hw_surface_destroy);
        return 0;
 }
index b87569e96b163c04fb35790ef8c457999480e3f3..c380c65da41798faf91b9e730f585be97a7b49d6 100644 (file)
@@ -598,7 +598,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
        pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
 }
 
-void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
+static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
 {
        struct vga_device *vgadev;
        unsigned long flags;
@@ -1211,6 +1211,7 @@ static const struct file_operations vga_arb_device_fops = {
        .poll = vga_arb_fpoll,
        .open = vga_arb_open,
        .release = vga_arb_release,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice vga_arb_device = {
index 4267a6fdc277a183cc840342fb5508cadda90815..5925bdcd417dbbf74d878b52fedcbc24a4d4de31 100644 (file)
@@ -237,6 +237,8 @@ static const struct hid_device_id cando_devices[] = {
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+               USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, cando_devices);
index 0c52899be9643d85af5c7ac6be8c87bc67d6e6ce..a0dea3d1296e65ebc9b84e24ec1aeacd69aa59d7 100644 (file)
@@ -1285,10 +1285,14 @@ static const struct hid_device_id hid_blacklist[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
@@ -1578,7 +1582,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
        { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)},
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)},
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)},
        { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
index 850d02a7a92539056d85b0b18eba88f8cb73cb38..61a3e572224aa4b578002e5699a37dfc26a7d243 100644 (file)
@@ -1051,6 +1051,7 @@ static const struct file_operations hid_debug_events_fops = {
        .read           = hid_debug_events_read,
        .poll           = hid_debug_events_poll,
        .release        = hid_debug_events_release,
+       .llseek         = noop_llseek,
 };
 
 
index 85c6d13c9ffa9369fca613eda828133b2b69a3e2..c5ae5f1545bd0a18d516edab6f04b3c18d0fca71 100644 (file)
 
 #define USB_VENDOR_ID_ASUS             0x0486
 #define USB_DEVICE_ID_ASUS_T91MT       0x0185
+#define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO   0x0186
 
 #define USB_VENDOR_ID_ASUSTEK          0x0b05
 #define USB_DEVICE_ID_ASUSTEK_LCM      0x1726
 
 #define USB_VENDOR_ID_BTC              0x046e
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE        0x5578
+#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2      0x5577
 
 #define USB_VENDOR_ID_CANDO            0x2087
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH        0x0a01
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
 #define USB_VENDOR_ID_CH               0x068e
 #define USB_DEVICE_ID_CH_PRO_PEDALS    0x00f2
 
 #define USB_VENDOR_ID_CHICONY          0x04f2
 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD     0x0418
+#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH      0xb19d
 
 #define USB_VENDOR_ID_CIDC             0x1677
 
 
 #define USB_VENDOR_ID_TURBOX           0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
+#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART        0x7100
 
 #define USB_VENDOR_ID_TWINHAN          0x6253
 #define USB_DEVICE_ID_TWINHAN_IR_REMOTE        0x0100
 #define USB_VENDOR_ID_UCLOGIC          0x5543
 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209    0x0042
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U   0x0003
+#define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5      0x6001
 
 #define USB_VENDOR_ID_VERNIER          0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
index e91437c189061cf7c862a74b3b6054f369528af7..ac5421d568f151cd6937f33244740d9f9759fedb 100644 (file)
@@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev)
 
 static const struct hid_device_id mosart_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, mosart_devices);
index f6e80c7ca61e53c0f9655778306ffc3e82a28b9f..5a6879e235ac5264482fe94d3c8976231dbc6c36 100644 (file)
@@ -384,6 +384,7 @@ static const struct file_operations roccat_ops = {
        .poll = roccat_poll,
        .open = roccat_open,
        .release = roccat_release,
+       .llseek = noop_llseek,
 };
 
 static int __init roccat_init(void)
index 5771f851f85693a46bd581085e25e09775fbcae5..956ed9ac19d4dee7fc3b259b1453662ec0bd8146 100644 (file)
@@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 static const struct hid_device_id ts_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
        { }
 };
index 47d70c523d93474a658bbaa5aa5b1cfb327f194b..925992f549f09abdefd1ba6ab8f280529910920f 100644 (file)
@@ -109,6 +109,12 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
        int ret = 0;
 
        mutex_lock(&minors_lock);
+
+       if (!hidraw_table[minor]) {
+               ret = -ENODEV;
+               goto out;
+       }
+
        dev = hidraw_table[minor]->hid;
 
        if (!dev->hid_output_raw_report) {
@@ -244,6 +250,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 
        mutex_lock(&minors_lock);
        dev = hidraw_table[minor];
+       if (!dev) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        switch (cmd) {
                case HIDIOCGRDESCSIZE:
@@ -317,6 +327,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 
                ret = -ENOTTY;
        }
+out:
        mutex_unlock(&minors_lock);
        return ret;
 }
@@ -329,6 +340,7 @@ static const struct file_operations hidraw_ops = {
        .open =         hidraw_open,
        .release =      hidraw_release,
        .unlocked_ioctl = hidraw_ioctl,
+       .llseek =       noop_llseek,
 };
 
 void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
index b729c02866798c00ae4d2c77eadba097a79d7f73..599041a7f670a9f105e00da3272d79642aefb78c 100644 (file)
@@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
                }
        } else {
                int skipped_report_id = 0;
+               int report_id = buf[0];
                if (buf[0] == 0x0) {
                        /* Don't send the Report ID */
                        buf++;
@@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
                ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        HID_REQ_SET_REPORT,
                        USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                       ((report_type + 1) << 8) | *buf,
+                       ((report_type + 1) << 8) | report_id,
                        interface->desc.bInterfaceNumber, buf, count,
                        USB_CTRL_SET_TIMEOUT);
                /* count also the report id, if this was a numbered report. */
@@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = {
        { }
 };
 
+struct usb_interface *usbhid_find_interface(int minor)
+{
+       return usb_find_interface(&hid_driver, minor);
+}
+
 static struct hid_driver hid_usb_driver = {
        .name = "generic-usb",
        .id_table = hid_usb_table,
index 2643d31476213cd41f5d1b39042e83d5a70a63a4..f0260c699adb45ac9d5b11f119c1491a95e04504 100644 (file)
@@ -33,8 +33,10 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+       { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -69,6 +71,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
@@ -77,6 +80,8 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
 
+       { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
+
        { 0, 0 }
 };
 
index 0a29c51114aaf0d36c64f6c8c25195db5e2f3747..dfcb27613ec54005033f5fe4309550bfb2539998 100644 (file)
@@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
        struct hiddev *hiddev;
        int res;
 
-       intf = usb_find_interface(&hiddev_driver, iminor(inode));
+       intf = usbhid_find_interface(iminor(inode));
        if (!intf)
                return -ENODEV;
        hid = usb_get_intfdata(intf);
@@ -847,6 +847,7 @@ static const struct file_operations hiddev_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = hiddev_compat_ioctl,
 #endif
+       .llseek         = noop_llseek,
 };
 
 static char *hiddev_devnode(struct device *dev, mode_t *mode)
index 693fd3e720df41c8ded8ccf15f9575648de77c96..89d2e847dcc671b65f15484b3df34f6c4a6c288d 100644 (file)
@@ -42,6 +42,7 @@ void usbhid_submit_report
 (struct hid_device *hid, struct hid_report *report, unsigned char dir);
 int usbhid_get_power(struct hid_device *hid);
 void usbhid_put_power(struct hid_device *hid);
+struct usb_interface *usbhid_find_interface(int minor);
 
 /* iofl flags */
 #define HID_CTRL_RUNNING       1
index 4d4d09bdec0a7a7cb043725b2fb94dc1fff23dc7..97499d00615aacbddcf5963bcfa08b5f4733a1bb 100644 (file)
@@ -409,7 +409,7 @@ config SENSORS_CORETEMP
 
 config SENSORS_PKGTEMP
        tristate "Intel processor package temperature sensor"
-       depends on X86 && PCI && EXPERIMENTAL
+       depends on X86 && EXPERIMENTAL
        help
          If you say yes here you get support for the package level temperature
          sensor inside your CPU. Check documentation/driver for details.
index 15c1a9616af33ba13ae8a79823cb7d30729c42fe..0683e6be662cfe28e803cac2b6ddd6501f06ef29 100644 (file)
@@ -79,7 +79,7 @@ struct adm1031_data {
        int chip_type;
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
-       unsigned int update_rate;       /* In milliseconds */
+       unsigned int update_interval;   /* In milliseconds */
        /* The chan_select_table contains the possible configurations for
         * auto fan control.
         */
@@ -743,23 +743,23 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
 static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
 
-/* Update Rate */
-static const unsigned int update_rates[] = {
+/* Update Interval */
+static const unsigned int update_intervals[] = {
        16000, 8000, 4000, 2000, 1000, 500, 250, 125,
 };
 
-static ssize_t show_update_rate(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+static ssize_t show_update_interval(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
 
-       return sprintf(buf, "%u\n", data->update_rate);
+       return sprintf(buf, "%u\n", data->update_interval);
 }
 
-static ssize_t set_update_rate(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t count)
+static ssize_t set_update_interval(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
@@ -771,12 +771,15 @@ static ssize_t set_update_rate(struct device *dev,
        if (err)
                return err;
 
-       /* find the nearest update rate from the table */
-       for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) {
-               if (val >= update_rates[i])
+       /*
+        * Find the nearest update interval from the table.
+        * Use it to determine the matching update rate.
+        */
+       for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
+               if (val >= update_intervals[i])
                        break;
        }
-       /* if not found, we point to the last entry (lowest update rate) */
+       /* if not found, we point to the last entry (lowest update interval) */
 
        /* set the new update rate while preserving other settings */
        reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
@@ -785,14 +788,14 @@ static ssize_t set_update_rate(struct device *dev,
        adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
 
        mutex_lock(&data->update_lock);
-       data->update_rate = update_rates[i];
+       data->update_interval = update_intervals[i];
        mutex_unlock(&data->update_lock);
 
        return count;
 }
 
-static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate,
-                  set_update_rate);
+static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
+                  set_update_interval);
 
 static struct attribute *adm1031_attributes[] = {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
@@ -830,7 +833,7 @@ static struct attribute *adm1031_attributes[] = {
 
        &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
 
-       &dev_attr_update_rate.attr,
+       &dev_attr_update_interval.attr,
        &dev_attr_alarms.attr,
 
        NULL
@@ -981,7 +984,8 @@ static void adm1031_init_client(struct i2c_client *client)
        mask = ADM1031_UPDATE_RATE_MASK;
        read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
        i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
-       data->update_rate = update_rates[i];
+       /* Save it as update interval */
+       data->update_interval = update_intervals[i];
 }
 
 static struct adm1031_data *adm1031_update_device(struct device *dev)
@@ -993,7 +997,8 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
 
        mutex_lock(&data->update_lock);
 
-       next_update = data->last_updated + msecs_to_jiffies(data->update_rate);
+       next_update = data->last_updated
+         + msecs_to_jiffies(data->update_interval);
        if (time_after(jiffies, next_update) || !data->valid) {
 
                dev_dbg(&client->dev, "Starting adm1031 update\n");
index b300a2048af153f9aa09cbd546a06fcadb3a4588..52319340e182da8f189eae518d80bd3674d26425 100644 (file)
@@ -160,30 +160,12 @@ static const struct attribute_group ads7871_group = {
 
 static int __devinit ads7871_probe(struct spi_device *spi)
 {
-       int status, ret, err = 0;
+       int ret, err;
        uint8_t val;
        struct ads7871_data *pdata;
 
        dev_dbg(&spi->dev, "probe\n");
 
-       pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL);
-       if (!pdata) {
-               err = -ENOMEM;
-               goto exit;
-       }
-
-       status = sysfs_create_group(&spi->dev.kobj, &ads7871_group);
-       if (status < 0)
-               goto error_free;
-
-       pdata->hwmon_dev = hwmon_device_register(&spi->dev);
-       if (IS_ERR(pdata->hwmon_dev)) {
-               err = PTR_ERR(pdata->hwmon_dev);
-               goto error_remove;
-       }
-
-       spi_set_drvdata(spi, pdata);
-
        /* Configure the SPI bus */
        spi->mode = (SPI_MODE_0);
        spi->bits_per_word = 8;
@@ -201,6 +183,24 @@ static int __devinit ads7871_probe(struct spi_device *spi)
        we need to make sure we really have a chip*/
        if (val != ret) {
                err = -ENODEV;
+               goto exit;
+       }
+
+       pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL);
+       if (!pdata) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       err = sysfs_create_group(&spi->dev.kobj, &ads7871_group);
+       if (err < 0)
+               goto error_free;
+
+       spi_set_drvdata(spi, pdata);
+
+       pdata->hwmon_dev = hwmon_device_register(&spi->dev);
+       if (IS_ERR(pdata->hwmon_dev)) {
+               err = PTR_ERR(pdata->hwmon_dev);
                goto error_remove;
        }
 
index 653db1bda9348ebaa62d8f17f93c46a4b8cdadda..23b8555215d2fa61e52e2e08f85935fdd0ca2860 100644 (file)
@@ -762,6 +762,7 @@ static const struct file_operations atk_debugfs_ggrp_fops = {
        .read           = atk_debugfs_ggrp_read,
        .open           = atk_debugfs_ggrp_open,
        .release        = atk_debugfs_ggrp_release,
+       .llseek         = no_llseek,
 };
 
 static void atk_debugfs_init(struct atk_data *data)
index c070c9714cbe2fa84646b41626655b4c51a7157e..a23b17a78ace8f42cb114b30f593b9019a24a982 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/smp.h>
 
 #define DRVNAME        "coretemp"
 
@@ -423,9 +424,18 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
        int err;
        struct platform_device *pdev;
        struct pdev_entry *pdev_entry;
-#ifdef CONFIG_SMP
        struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
+
+       /*
+        * CPUID.06H.EAX[0] indicates whether the CPU has thermal
+        * sensors. We check this bit only, all the early CPUs
+        * without thermal sensors will be filtered out.
+        */
+       if (!cpu_has(c, X86_FEATURE_DTS)) {
+               printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
+                      " has no thermal sensor.\n", c->x86_model);
+               return 0;
+       }
 
        mutex_lock(&pdev_list_mutex);
 
@@ -482,14 +492,22 @@ exit:
 
 static void coretemp_device_remove(unsigned int cpu)
 {
-       struct pdev_entry *p, *n;
+       struct pdev_entry *p;
+       unsigned int i;
+
        mutex_lock(&pdev_list_mutex);
-       list_for_each_entry_safe(p, n, &pdev_list, list) {
-               if (p->cpu == cpu) {
-                       platform_device_unregister(p->pdev);
-                       list_del(&p->list);
-                       kfree(p);
-               }
+       list_for_each_entry(p, &pdev_list, list) {
+               if (p->cpu != cpu)
+                       continue;
+
+               platform_device_unregister(p->pdev);
+               list_del(&p->list);
+               mutex_unlock(&pdev_list_mutex);
+               kfree(p);
+               for_each_cpu(i, cpu_sibling_mask(cpu))
+                       if (i != cpu && !coretemp_device_add(i))
+                               break;
+               return;
        }
        mutex_unlock(&pdev_list_mutex);
 }
@@ -518,7 +536,6 @@ static struct notifier_block coretemp_cpu_notifier __refdata = {
 static int __init coretemp_init(void)
 {
        int i, err = -ENODEV;
-       struct pdev_entry *p, *n;
 
        /* quick check if we run Intel */
        if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
@@ -528,30 +545,21 @@ static int __init coretemp_init(void)
        if (err)
                goto exit;
 
-       for_each_online_cpu(i) {
-               struct cpuinfo_x86 *c = &cpu_data(i);
-               /*
-                * CPUID.06H.EAX[0] indicates whether the CPU has thermal
-                * sensors. We check this bit only, all the early CPUs
-                * without thermal sensors will be filtered out.
-                */
-               if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01))
-                       coretemp_device_add(i);
-               else {
-                       printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
-                               " has no thermal sensor.\n", c->x86_model);
-               }
-       }
+       for_each_online_cpu(i)
+               coretemp_device_add(i);
+
+#ifndef CONFIG_HOTPLUG_CPU
        if (list_empty(&pdev_list)) {
                err = -ENODEV;
                goto exit_driver_unreg;
        }
+#endif
 
        register_hotcpu_notifier(&coretemp_cpu_notifier);
        return 0;
 
-exit_driver_unreg:
 #ifndef CONFIG_HOTPLUG_CPU
+exit_driver_unreg:
        platform_driver_unregister(&coretemp_driver);
 #endif
 exit:
index 5b58b20dead1fa92b79af5c05036d45de8bf88ca..8dee3f38fdfb27e1c80a9fb36add60e414aeb805 100644 (file)
@@ -308,7 +308,6 @@ static int emc1403_probe(struct i2c_client *client,
        res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);
        if (res) {
                dev_warn(&client->dev, "create group failed\n");
-               hwmon_device_unregister(data->hwmon_dev);
                goto thermal_error1;
        }
        data->hwmon_dev = hwmon_device_register(&client->dev);
index 537841ef44b99d179318f7510dbf28dddedb0ed8..75afb3b0e0763c184a1b22cdc163ef32d10d2969 100644 (file)
@@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev;
 /* Super-I/O Function prototypes */
 static inline int superio_inb(int base, int reg);
 static inline int superio_inw(int base, int reg);
-static inline void superio_enter(int base);
+static inline int superio_enter(int base);
 static inline void superio_select(int base, int ld);
 static inline void superio_exit(int base);
 
@@ -861,11 +861,20 @@ static int superio_inw(int base, int reg)
        return val;
 }
 
-static inline void superio_enter(int base)
+static inline int superio_enter(int base)
 {
+       /* Don't step on other drivers' I/O space by accident */
+       if (!request_muxed_region(base, 2, DRVNAME)) {
+               printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
+                               base);
+               return -EBUSY;
+       }
+
        /* according to the datasheet the key must be send twice! */
        outb(SIO_UNLOCK_KEY, base);
        outb(SIO_UNLOCK_KEY, base);
+
+       return 0;
 }
 
 static inline void superio_select(int base, int ld)
@@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld)
 static inline void superio_exit(int base)
 {
        outb(SIO_LOCK_KEY, base);
+       release_region(base, 2);
 }
 
 static inline int fan_from_reg(u16 reg)
@@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev)
 static int __init f71882fg_find(int sioaddr, unsigned short *address,
        struct f71882fg_sio_data *sio_data)
 {
-       int err = -ENODEV;
        u16 devid;
-
-       /* Don't step on other drivers' I/O space by accident */
-       if (!request_region(sioaddr, 2, DRVNAME)) {
-               printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
-                               (int)sioaddr);
-               return -EBUSY;
-       }
-
-       superio_enter(sioaddr);
+       int err = superio_enter(sioaddr);
+       if (err)
+               return err;
 
        devid = superio_inw(sioaddr, SIO_REG_MANID);
        if (devid != SIO_FINTEK_ID) {
                pr_debug(DRVNAME ": Not a Fintek device\n");
+               err = -ENODEV;
                goto exit;
        }
 
@@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
        default:
                printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
                       (unsigned int)devid);
+               err = -ENODEV;
                goto exit;
        }
 
@@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
 
        if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
                printk(KERN_WARNING DRVNAME ": Device not activated\n");
+               err = -ENODEV;
                goto exit;
        }
 
        *address = superio_inw(sioaddr, SIO_REG_ADDR);
        if (*address == 0) {
                printk(KERN_WARNING DRVNAME ": Base address not set\n");
+               err = -ENODEV;
                goto exit;
        }
        *address &= ~(REGION_LENGTH - 1);       /* Ignore 3 LSB */
@@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
                (int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
        superio_exit(sioaddr);
-       release_region(sioaddr, 2);
        return err;
 }
 
index 0f58ecc5334d941cb4114a3681e2e5a44893280e..9638d58f99fdb0e56f15832f824dc6096d99d3ea 100644 (file)
@@ -79,7 +79,7 @@ enum chips { f75373, f75375 };
 #define F75375_REG_PWM2_DROP_DUTY      0x6C
 
 #define FAN_CTRL_LINEAR(nr)            (4 + nr)
-#define FAN_CTRL_MODE(nr)              (5 + ((nr) * 2))
+#define FAN_CTRL_MODE(nr)              (4 + ((nr) * 2))
 
 /*
  * Data structures and manipulation thereof
@@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
                return -EINVAL;
 
        fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
-       fanmode = ~(3 << FAN_CTRL_MODE(nr));
+       fanmode &= ~(3 << FAN_CTRL_MODE(nr));
 
        switch (val) {
        case 0: /* Full speed */
@@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
 
        mutex_lock(&data->update_lock);
        conf = f75375_read8(client, F75375_REG_CONFIG1);
-       conf = ~(1 << FAN_CTRL_LINEAR(nr));
+       conf &= ~(1 << FAN_CTRL_LINEAR(nr));
 
        if (val == 0)
                conf |= (1 << FAN_CTRL_LINEAR(nr)) ;
index b7ca2a9676cf8b62aab21fa7a04d205457828c6e..d4d4ca65d3716f61c21008ff1d390e54aa256e86 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/smp_lock.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -50,6 +49,7 @@
 #include <linux/kref.h>
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
@@ -858,7 +858,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar
        int i, ret = 0;
        struct fschmd_data *data = filp->private_data;
 
-       lock_kernel();
+       mutex_lock(&watchdog_mutex);
        switch (cmd) {
        case WDIOC_GETSUPPORT:
                ident.firmware_version = data->revision;
@@ -915,7 +915,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar
        default:
                ret = -ENOTTY;
        }
-       unlock_kernel();
+       mutex_unlock(&watchdog_mutex);
        return ret;
 }
 
index 7580f55e67e3cf1560437b428d9fb1e5b8e411d0..36e95753223059ab0e1b5ed8490fe7364b39673e 100644 (file)
@@ -221,6 +221,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
        AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
        AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
+       AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+       AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
index b9bb3e0ca53083bd152332be698c58dbd0ff66bd..39ead2a4d3c50bfa34acb37651739920c22c76ee 100644 (file)
@@ -143,6 +143,37 @@ static const struct pci_device_id k8temp_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, k8temp_ids);
 
+static int __devinit is_rev_g_desktop(u8 model)
+{
+       u32 brandidx;
+
+       if (model < 0x69)
+               return 0;
+
+       if (model == 0xc1 || model == 0x6c || model == 0x7c)
+               return 0;
+
+       /*
+        * Differentiate between AM2 and ASB1.
+        * See "Constructing the processor Name String" in "Revision
+        * Guide for AMD NPT Family 0Fh Processors" (33610).
+        */
+       brandidx = cpuid_ebx(0x80000001);
+       brandidx = (brandidx >> 9) & 0x1f;
+
+       /* Single core */
+       if ((model == 0x6f || model == 0x7f) &&
+           (brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc))
+               return 0;
+
+       /* Dual core */
+       if (model == 0x6b &&
+           (brandidx == 0xb || brandidx == 0xc))
+               return 0;
+
+       return 1;
+}
+
 static int __devinit k8temp_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *id)
 {
@@ -179,9 +210,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
                                 "wrong - check erratum #141\n");
                }
 
-               if ((model >= 0x69) &&
-                   !(model == 0xc1 || model == 0x6c || model == 0x7c ||
-                     model == 0x6b || model == 0x6f || model == 0x7f)) {
+               if (is_rev_g_desktop(model)) {
                        /*
                         * RevG desktop CPUs (i.e. no socket S1G1 or
                         * ASB1 parts) need additional offset,
index 6138f036b159956dbc4eec8282636db794485527..fc591ae53107da8481a2ab5e02f53117ac6e2471 100644 (file)
@@ -277,7 +277,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
        wake_up_interruptible(&lis3_dev.misc_wait);
        kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
 out:
-       if (lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
+       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
            lis3_dev.idev->input->users)
                return IRQ_WAKE_THREAD;
        return IRQ_HANDLED;
@@ -718,7 +718,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
         * io-apic is not configurable (and generates a warning) but I keep it
         * in case of support for other hardware.
         */
-       if (dev->whoami == WAI_8B)
+       if (dev->pdata && dev->whoami == WAI_8B)
                thread_fn = lis302dl_interrupt_thread1_8b;
        else
                thread_fn = NULL;
index dc1f5402c1d7ddcdaf4396fe177a689550b9ac2b..8e5933b72d1956c2a931ea7176b1c589e3066968 100644 (file)
@@ -121,7 +121,7 @@ static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 {
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
-       if (!lis3->pdata->wakeup_flags)
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
                lis3lv02d_poweroff(lis3);
        return 0;
 }
@@ -130,7 +130,7 @@ static int lis3lv02d_i2c_resume(struct i2c_client *client)
 {
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
-       if (!lis3->pdata->wakeup_flags)
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
                lis3lv02d_poweron(lis3);
        return 0;
 }
index 82b16808a274c1e0045692fcfc32dcfdb641ec31..b9be5e3a22b3825bc640d9c038c8c724e888c5b4 100644 (file)
@@ -92,7 +92,7 @@ static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg)
 {
        struct lis3lv02d *lis3 = spi_get_drvdata(spi);
 
-       if (!lis3->pdata->wakeup_flags)
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
                lis3lv02d_poweroff(&lis3_dev);
 
        return 0;
@@ -102,7 +102,7 @@ static int lis3lv02d_spi_resume(struct spi_device *spi)
 {
        struct lis3lv02d *lis3 = spi_get_drvdata(spi);
 
-       if (!lis3->pdata->wakeup_flags)
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
                lis3lv02d_poweron(lis3);
 
        return 0;
index 94741d42112da02ca902b2e87beacbe96aab3cd3..464340f25496402dd15a69e2d59281544e267c37 100644 (file)
@@ -91,7 +91,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev);
 struct lm95241_data {
        struct device *hwmon_dev;
        struct mutex update_lock;
-       unsigned long last_updated, rate; /* in jiffies */
+       unsigned long last_updated, interval; /* in jiffies */
        char valid; /* zero until following fields are valid */
        /* registers values */
        u8 local_h, local_l; /* local */
@@ -114,23 +114,23 @@ show_temp(local);
 show_temp(remote1);
 show_temp(remote2);
 
-static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
+static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
        struct lm95241_data *data = lm95241_update_device(dev);
 
-       snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ);
+       snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ);
        return strlen(buf);
 }
 
-static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
+static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm95241_data *data = i2c_get_clientdata(client);
 
-       strict_strtol(buf, 10, &data->rate);
-       data->rate = data->rate * HZ / 1000;
+       strict_strtol(buf, 10, &data->interval);
+       data->interval = data->interval * HZ / 1000;
 
        return count;
 }
@@ -286,7 +286,8 @@ static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1);
 static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2);
 static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1);
 static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2);
-static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate);
+static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
+                  set_interval);
 
 static struct attribute *lm95241_attributes[] = {
        &dev_attr_temp1_input.attr,
@@ -298,7 +299,7 @@ static struct attribute *lm95241_attributes[] = {
        &dev_attr_temp3_min.attr,
        &dev_attr_temp2_max.attr,
        &dev_attr_temp3_max.attr,
-       &dev_attr_rate.attr,
+       &dev_attr_update_interval.attr,
        NULL
 };
 
@@ -376,7 +377,7 @@ static void lm95241_init_client(struct i2c_client *client)
 {
        struct lm95241_data *data = i2c_get_clientdata(client);
 
-       data->rate = HZ;    /* 1 sec default */
+       data->interval = HZ;    /* 1 sec default */
        data->valid = 0;
        data->config = CFG_CR0076;
        data->model = 0;
@@ -410,7 +411,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev)
 
        mutex_lock(&data->update_lock);
 
-       if (time_after(jiffies, data->last_updated + data->rate) ||
+       if (time_after(jiffies, data->last_updated + data->interval) ||
            !data->valid) {
                dev_dbg(&client->dev, "Updating lm95241 data.\n");
                data->local_h =
index 74157fcda6edf4bc569469db4ae1de9efa5b882d..f11903936c8b3a51c3f8dddcb20318185952fa79 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
-#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -224,7 +223,7 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev)
 
        err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
        if (err)
-               goto exit_free;
+               goto exit_dev;
 
        data->hwmon_dev = hwmon_device_register(&pdev->dev);
        if (IS_ERR(data->hwmon_dev)) {
@@ -238,6 +237,8 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev)
 
 exit_class:
        sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
+exit_dev:
+       device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
 exit_free:
        kfree(data);
 exit:
@@ -250,6 +251,7 @@ static int __devexit pkgtemp_remove(struct platform_device *pdev)
 
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
+       device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
        platform_set_drvdata(pdev, NULL);
        kfree(data);
        return 0;
@@ -281,9 +283,10 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu)
        int err;
        struct platform_device *pdev;
        struct pdev_entry *pdev_entry;
-#ifdef CONFIG_SMP
        struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
+
+       if (!cpu_has(c, X86_FEATURE_PTS))
+               return 0;
 
        mutex_lock(&pdev_list_mutex);
 
@@ -339,17 +342,18 @@ exit:
 #ifdef CONFIG_HOTPLUG_CPU
 static void pkgtemp_device_remove(unsigned int cpu)
 {
-       struct pdev_entry *p, *n;
+       struct pdev_entry *p;
        unsigned int i;
        int err;
 
        mutex_lock(&pdev_list_mutex);
-       list_for_each_entry_safe(p, n, &pdev_list, list) {
+       list_for_each_entry(p, &pdev_list, list) {
                if (p->cpu != cpu)
                        continue;
 
                platform_device_unregister(p->pdev);
                list_del(&p->list);
+               mutex_unlock(&pdev_list_mutex);
                kfree(p);
                for_each_cpu(i, cpu_core_mask(cpu)) {
                        if (i != cpu) {
@@ -358,7 +362,7 @@ static void pkgtemp_device_remove(unsigned int cpu)
                                        break;
                        }
                }
-               break;
+               return;
        }
        mutex_unlock(&pdev_list_mutex);
 }
@@ -399,11 +403,6 @@ static int __init pkgtemp_init(void)
                goto exit;
 
        for_each_online_cpu(i) {
-               struct cpuinfo_x86 *c = &cpu_data(i);
-
-               if (!cpu_has(c, X86_FEATURE_PTS))
-                       continue;
-
                err = pkgtemp_device_add(i);
                if (err)
                        goto exit_devices_unreg;
index e96e69dd36fb4b4faba43ffad13b53815d06bc65..072c58008a633b713e1f68fd3a522572a41842d1 100644 (file)
@@ -127,6 +127,7 @@ superio_enter(int ioreg)
 static inline void
 superio_exit(int ioreg)
 {
+       outb(0xaa, ioreg);
        outb(0x02, ioreg);
        outb(0x02, ioreg + 1);
 }
index 697202e278917db50ca07c84aa92feb503e1e109..8e540ada47d27aaf8f78c6ee5b0c513407d80d1a 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
-#include <linux/smp_lock.h>
 #include <linux/hwmon-vid.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
@@ -52,6 +51,7 @@
 #define WATCHDOG_TIMEOUT 2     /* 2 minute default timeout */
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
                                                I2C_CLIENT_END };
 
@@ -1333,7 +1333,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd,
        int val, ret = 0;
        struct w83793_data *data = filp->private_data;
 
-       lock_kernel();
+       mutex_lock(&watchdog_mutex);
        switch (cmd) {
        case WDIOC_GETSUPPORT:
                if (!nowayout)
@@ -1387,7 +1387,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd,
        default:
                ret = -ENOTTY;
        }
-       unlock_kernel();
+       mutex_unlock(&watchdog_mutex);
        return ret;
 }
 
index f7bd2613ceccbc69e4d04b69432fdc40638b2555..f2de3be35df36265cdfca5d899097b161ef10171 100644 (file)
@@ -677,6 +677,11 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev,
        dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
                cpm->adap.name);
 
+       /*
+        * register OF I2C devices
+        */
+       of_i2c_register_devices(&cpm->adap);
+
        return 0;
 out_shut:
        cpm_i2c_shutdown(cpm);
index 2222c87876b97bc711b6d739fd4a82deef7db330..5795c8398c7c3a25af82319a0ce1d46741def8b2 100644 (file)
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        INIT_COMPLETION(dev->cmd_complete);
        dev->cmd_err = 0;
 
-       /* Take I2C out of reset, configure it as master and set the
-        * start bit */
-       flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+       /* Take I2C out of reset and configure it as master */
+       flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
 
        /* if the slave address is ten bit address, enable XA bit */
        if (msg->flags & I2C_M_TEN)
                flag |= DAVINCI_I2C_MDR_XA;
        if (!(msg->flags & I2C_M_RD))
                flag |= DAVINCI_I2C_MDR_TRX;
-       if (stop)
-               flag |= DAVINCI_I2C_MDR_STP;
-       if (msg->len == 0) {
+       if (msg->len == 0)
                flag |= DAVINCI_I2C_MDR_RM;
-               flag &= ~DAVINCI_I2C_MDR_STP;
-       }
 
        /* Enable receive or transmit interrupts */
        w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -357,7 +352,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 
        dev->terminate = 0;
 
-       /* write the data into mode register */
+       /*
+        * Write mode register first as needed for correct behaviour
+        * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+        * occuring before we have loaded DXR
+        */
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
        /*
@@ -365,12 +364,19 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
         * because transmit-data-ready interrupt can come before
         * NACK-interrupt during sending of previous message and
         * ICDXR may have wrong data
+        * It also saves us one interrupt, slightly faster
         */
        if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
                davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
                dev->buf_len--;
        }
 
+       /* Set STT to begin transmit now DXR is loaded */
+       flag |= DAVINCI_I2C_MDR_STT;
+       if (stop && msg->len != 0)
+               flag |= DAVINCI_I2C_MDR_STP;
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
        r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
                                                      dev->adapter.timeout);
        if (r == 0) {
index 43ca32fddde2b77309c92533f9c2c50e44719879..89eedf45d30ed877e6abbc76c66507372c4a3f83 100644 (file)
@@ -761,6 +761,9 @@ static int __devinit iic_probe(struct platform_device *ofdev,
        dev_info(&ofdev->dev, "using %s mode\n",
                 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
 
+       /* Now register all the child nodes */
+       of_i2c_register_devices(adap);
+
        return 0;
 
 error_cleanup:
index d1ff9408dc1f2d68cdbe305c6777ba259eed64e4..4c2a62b75b5cf188dd896dff100c80bfe253aded 100644 (file)
@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 
 static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
 {
-       int result;
-
-       result = wait_event_interruptible_timeout(i2c_imx->queue,
-               i2c_imx->i2csr & I2SR_IIF, HZ / 10);
+       wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
 
-       if (unlikely(result < 0)) {
-               dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__);
-               return result;
-       } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
+       if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
                dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
                return -ETIMEDOUT;
        }
@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
                i2c_imx->i2csr = temp;
                temp &= ~I2SR_IIF;
                writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
-               wake_up_interruptible(&i2c_imx->queue);
+               wake_up(&i2c_imx->queue);
                return IRQ_HANDLED;
        }
 
index a1c419a716af8d24f4a84a680cc93123b6c8bff9..b74e6dc6886c71ed5ebe3e02f219a68f8f0a2df8 100644 (file)
@@ -632,6 +632,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op,
                dev_err(i2c->dev, "failed to add adapter\n");
                goto fail_add;
        }
+       of_i2c_register_devices(&i2c->adap);
 
        return result;
 
index 0e9f85d0a835718dac97ecd52ff270f327d84136..56dbe54e88118a3fb7b112da16e11ccd5bdbc9fb 100644 (file)
@@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
                return result;
        } else if (result == 0) {
                dev_dbg(i2c->dev, "%s: timeout\n", __func__);
-               result = -ETIMEDOUT;
+               return -ETIMEDOUT;
        }
 
        return 0;
index 7674efb553786e4e2a639c5a5b263362564b626b..b33c78586bfccf815d9322df1d561b7bec5797b5 100644 (file)
@@ -680,6 +680,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        if (r == 0)
                r = num;
+
+       omap_i2c_wait_for_bb(dev);
 out:
        omap_i2c_idle(dev);
        return r;
index 4174101660c91430782620ce0df8895c1d3c734a..837b8c1aa02a494ef92899c46ccaf67cb709f9c1 100644 (file)
@@ -88,7 +88,7 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)
        reg_write(smbus, REG_SMSTA, status);
 }
 
-static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
+static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
 {
        int timeout = 10;
        unsigned int status;
index bbd77603a4173b8f29aa1353ef1e47376c594196..29933f87d8fa8fdc31ffdd38c4ff905fddd7774d 100644 (file)
@@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg)
 
 static int pca_isa_waitforcompletion(void *pd)
 {
-       long ret = ~0;
        unsigned long timeout;
+       long ret;
 
        if (irq > -1) {
                ret = wait_event_timeout(pca_wait,
@@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd)
        } else {
                /* Do polling */
                timeout = jiffies + pca_isa_ops.timeout;
-               while (((pca_isa_readbyte(pd, I2C_PCA_CON)
-                               & I2C_PCA_CON_SI) == 0)
-                               && (ret = time_before(jiffies, timeout)))
+               do {
+                       ret = time_before(jiffies, timeout);
+                       if (pca_isa_readbyte(pd, I2C_PCA_CON)
+                                       & I2C_PCA_CON_SI)
+                               break;
                        udelay(100);
+               } while (ret);
        }
+
        return ret > 0;
 }
 
index ef5c78487eb779c36fd5b98f3fd8d0727c34494e..5f6d7f89e2252d1a4806a3be9e6368c212ceed48 100644 (file)
@@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
 static int i2c_pca_pf_waitforcompletion(void *pd)
 {
        struct i2c_pca_pf_data *i2c = pd;
-       long ret = ~0;
        unsigned long timeout;
+       long ret;
 
        if (i2c->irq) {
                ret = wait_event_timeout(i2c->wait,
@@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd)
        } else {
                /* Do polling */
                timeout = jiffies + i2c->adap.timeout;
-               while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
-                               & I2C_PCA_CON_SI) == 0)
-                               && (ret = time_before(jiffies, timeout)))
+               do {
+                       ret = time_before(jiffies, timeout);
+                       if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
+                                       & I2C_PCA_CON_SI)
+                               break;
                        udelay(100);
+               } while (ret);
        }
 
        return ret > 0;
index 72902e0bbfa79a48caaf2193420d4b8712af1e18..bf831bf8158741a9f857eb541afc1f3a48d38e52 100644 (file)
@@ -662,8 +662,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
                unsigned long sda_delay;
 
                if (pdata->sda_delay) {
-                       sda_delay = (freq / 1000) * pdata->sda_delay;
-                       sda_delay /= 1000000;
+                       sda_delay = clkin * pdata->sda_delay;
+                       sda_delay = DIV_ROUND_UP(sda_delay, 1000000);
                        sda_delay = DIV_ROUND_UP(sda_delay, 5);
                        if (sda_delay > 3)
                                sda_delay = 3;
index 6649176de940572a317b2744bd1d4e393c4bbd04..bea4c5021d26cb5b4c92e9b58cabeda2b882023c 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/idr.h>
 #include <linux/mutex.h>
-#include <linux/of_i2c.h>
 #include <linux/of_device.h>
 #include <linux/completion.h>
 #include <linux/hardirq.h>
@@ -197,11 +196,12 @@ static int i2c_device_pm_suspend(struct device *dev)
 {
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (pm_runtime_suspended(dev))
-               return 0;
-
-       if (pm)
-               return pm->suspend ? pm->suspend(dev) : 0;
+       if (pm) {
+               if (pm_runtime_suspended(dev))
+                       return 0;
+               else
+                       return pm->suspend ? pm->suspend(dev) : 0;
+       }
 
        return i2c_legacy_suspend(dev, PMSG_SUSPEND);
 }
@@ -216,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev)
        else
                ret = i2c_legacy_resume(dev);
 
-       if (!ret) {
-               pm_runtime_disable(dev);
-               pm_runtime_set_active(dev);
-               pm_runtime_enable(dev);
-       }
-
        return ret;
 }
 
@@ -229,11 +223,12 @@ static int i2c_device_pm_freeze(struct device *dev)
 {
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (pm_runtime_suspended(dev))
-               return 0;
-
-       if (pm)
-               return pm->freeze ? pm->freeze(dev) : 0;
+       if (pm) {
+               if (pm_runtime_suspended(dev))
+                       return 0;
+               else
+                       return pm->freeze ? pm->freeze(dev) : 0;
+       }
 
        return i2c_legacy_suspend(dev, PMSG_FREEZE);
 }
@@ -242,11 +237,12 @@ static int i2c_device_pm_thaw(struct device *dev)
 {
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (pm_runtime_suspended(dev))
-               return 0;
-
-       if (pm)
-               return pm->thaw ? pm->thaw(dev) : 0;
+       if (pm) {
+               if (pm_runtime_suspended(dev))
+                       return 0;
+               else
+                       return pm->thaw ? pm->thaw(dev) : 0;
+       }
 
        return i2c_legacy_resume(dev);
 }
@@ -255,11 +251,12 @@ static int i2c_device_pm_poweroff(struct device *dev)
 {
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (pm_runtime_suspended(dev))
-               return 0;
-
-       if (pm)
-               return pm->poweroff ? pm->poweroff(dev) : 0;
+       if (pm) {
+               if (pm_runtime_suspended(dev))
+                       return 0;
+               else
+                       return pm->poweroff ? pm->poweroff(dev) : 0;
+       }
 
        return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
 }
@@ -876,9 +873,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);
 
-       /* Register devices from the device tree */
-       of_i2c_register_devices(adap);
-
        /* Notify drivers */
        mutex_lock(&core_lock);
        bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
index 31fc76960a8fd29e4e640f8b1636bca3b91d9730..0c73fe39a236bb6d6e05f37814c646098a57b715 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -52,6 +51,7 @@
 
 #include "ide-cd.h"
 
+static DEFINE_MUTEX(ide_cd_mutex);
 static DEFINE_MUTEX(idecd_ref_mutex);
 
 static void ide_cd_release(struct device *);
@@ -1602,7 +1602,7 @@ static int idecd_open(struct block_device *bdev, fmode_t mode)
        struct cdrom_info *info;
        int rc = -ENXIO;
 
-       lock_kernel();
+       mutex_lock(&ide_cd_mutex);
        info = ide_cd_get(bdev->bd_disk);
        if (!info)
                goto out;
@@ -1611,7 +1611,7 @@ static int idecd_open(struct block_device *bdev, fmode_t mode)
        if (rc < 0)
                ide_cd_put(info);
 out:
-       unlock_kernel();
+       mutex_unlock(&ide_cd_mutex);
        return rc;
 }
 
@@ -1619,11 +1619,11 @@ static int idecd_release(struct gendisk *disk, fmode_t mode)
 {
        struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
 
-       lock_kernel();
+       mutex_lock(&ide_cd_mutex);
        cdrom_release(&info->devinfo, mode);
 
        ide_cd_put(info);
-       unlock_kernel();
+       mutex_unlock(&ide_cd_mutex);
 
        return 0;
 }
@@ -1694,9 +1694,9 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ide_cd_mutex);
        ret = idecd_locked_ioctl(bdev, mode, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ide_cd_mutex);
 
        return ret;
 }
index 2a4cb9c18f01706ce7a3c6b17126882321185612..404843e8611b158d3feb1efc5a4c281d3fde660b 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -72,17 +71,6 @@ static int ide_config(struct pcmcia_device *);
 
 static void ide_detach(struct pcmcia_device *p_dev);
 
-
-
-
-/*======================================================================
-
-    ide_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int ide_probe(struct pcmcia_device *link)
 {
     ide_info_t *info;
@@ -97,23 +85,12 @@ static int ide_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+           CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
     return ide_config(link);
 } /* ide_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void ide_detach(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
@@ -187,79 +164,31 @@ out_release:
     return NULL;
 }
 
-/*======================================================================
-
-    ide_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ide device available to the system.
-
-======================================================================*/
-
-struct pcmcia_config_check {
-       unsigned long ctl_base;
-       int skip_vcc;
-       int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-                                  cistpl_cftable_entry_t *cfg,
-                                  cistpl_cftable_entry_t *dflt,
-                                  unsigned int vcc,
-                                  void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-       struct pcmcia_config_check *stk = priv_data;
-
-       /* Check for matching Vcc, unless we're desperate */
-       if (!stk->skip_vcc) {
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               }
-       }
+       int *is_kme = priv_data;
 
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-               pdev->conf.ConfigIndex = cfg->index;
-               pdev->resource[0]->start = io->win[0].base;
-               if (!(io->flags & CISTPL_IO_16BIT)) {
-                       pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-                       pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-               }
-               if (io->nwin == 2) {
-                       pdev->resource[0]->end = 8;
-                       pdev->resource[1]->start = io->win[1].base;
-                       pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-                       if (pcmcia_request_io(pdev) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->resource[1]->start;
-               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-                       pdev->resource[0]->end = io->win[0].len;
-                       pdev->resource[1]->end = 0;
-                       if (pcmcia_request_io(pdev) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->resource[0]->start + 0x0e;
-               } else
+       if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+               pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+               pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+       }
+       pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       if (pdev->resource[1]->end) {
+               pdev->resource[0]->end = 8;
+               pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+       } else {
+               if (pdev->resource[0]->end < 16)
                        return -ENODEV;
-               /* If we've got this far, we're done */
-               return 0;
        }
-       return -ENODEV;
+
+       return pcmcia_request_io(pdev);
 }
 
 static int ide_config(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    struct pcmcia_config_check *stk = NULL;
     int ret = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
     struct ide_host *host;
@@ -270,23 +199,21 @@ static int ide_config(struct pcmcia_device *link)
              ((link->card_id == PRODID_KME_KXLC005_A) ||
               (link->card_id == PRODID_KME_KXLC005_B)));
 
-    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-    if (!stk)
-           goto err_mem;
-    stk->is_kme = is_kme;
-    stk->skip_vcc = io_base = ctl_base = 0;
-
-    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
-           stk->skip_vcc = 1;
-           if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+    if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
+           link->config_flags &= ~CONF_AUTO_CHECK_VCC;
+           if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
                    goto failed; /* No suitable config found */
     }
     io_base = link->resource[0]->start;
-    ctl_base = stk->ctl_base;
+    if (link->resource[1]->end)
+           ctl_base = link->resource[1]->start;
+    else
+           ctl_base = link->resource[0]->start + 0x0e;
 
     if (!link->irq)
            goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -311,29 +238,15 @@ static int ide_config(struct pcmcia_device *link)
     info->host = host;
     dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
            'a' + host->ports[0]->index * 2,
-           link->conf.Vpp / 10, link->conf.Vpp % 10);
+           link->vpp / 10, link->vpp % 10);
 
-    kfree(stk);
     return 0;
 
-err_mem:
-    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
-    goto failed;
-
 failed:
-    kfree(stk);
     ide_release(link);
     return -ENODEV;
 } /* ide_config */
 
-/*======================================================================
-
-    After a card is removed, ide_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
@@ -359,15 +272,6 @@ static void ide_release(struct pcmcia_device *link)
 } /* ide_release */
 
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the ide drivers from
-    talking to the ports.
-
-======================================================================*/
-
 static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_FUNC_ID(4),
        PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
@@ -440,9 +344,7 @@ MODULE_DEVICE_TABLE(pcmcia, ide_ids);
 
 static struct pcmcia_driver ide_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "ide-cs",
-       },
+       .name           = "ide-cs",
        .probe          = ide_probe,
        .remove         = ide_detach,
        .id_table       = ide_ids,
index ec94c66918f6c6cc2ee06e9e2e3fba4357606008..da36f729ff3273b99e8700670047299ad3cfeab3 100644 (file)
@@ -1,10 +1,11 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "ide-disk.h"
 
+static DEFINE_MUTEX(ide_disk_ioctl_mutex);
 static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
 { HDIO_GET_ADDRESS,    HDIO_SET_ADDRESS,   &ide_devset_address   },
 { HDIO_GET_MULTCOUNT,  HDIO_SET_MULTCOUNT, &ide_devset_multcount },
@@ -19,13 +20,13 @@ int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode,
 {
        int err;
 
-       lock_kernel();
+       mutex_lock(&ide_disk_ioctl_mutex);
        err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
        if (err != -EOPNOTSUPP)
                goto out;
 
        err = generic_ide_ioctl(drive, bdev, cmd, arg);
 out:
-       unlock_kernel();
+       mutex_unlock(&ide_disk_ioctl_mutex);
        return err;
 }
index fd3d05ab3417544b9b2a02a445ab55002af285ff..d267b7affad63fab887a10585e647cec6eb98020 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/cdrom.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/unaligned.h>
 
@@ -32,6 +32,7 @@
  * On exit we set nformats to the number of records we've actually initialized.
  */
 
+static DEFINE_MUTEX(ide_floppy_ioctl_mutex);
 static int ide_floppy_get_format_capacities(ide_drive_t *drive,
                                            struct ide_atapi_pc *pc,
                                            int __user *arg)
@@ -276,7 +277,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
        void __user *argp = (void __user *)arg;
        int err;
 
-       lock_kernel();
+       mutex_lock(&ide_floppy_ioctl_mutex);
        if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
                err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
                goto out;
@@ -298,6 +299,6 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
                err = generic_ide_ioctl(drive, bdev, cmd, arg);
 
 out:
-       unlock_kernel();
+       mutex_unlock(&ide_floppy_ioctl_mutex);
        return err;
 }
index 70aeeb18833e92e14c444c9cacb9d174307125bb..35c4b43585e3418ebb7ad1b74c94550d5fbcfb86 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -23,6 +22,7 @@
 #define IDE_GD_VERSION "1.18"
 
 /* module parameters */
+static DEFINE_MUTEX(ide_gd_mutex);
 static unsigned long debug_mask;
 module_param(debug_mask, ulong, 0644);
 
@@ -242,9 +242,9 @@ static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&ide_gd_mutex);
        ret = ide_gd_open(bdev, mode);
-       unlock_kernel();
+       mutex_unlock(&ide_gd_mutex);
 
        return ret;
 }
@@ -257,7 +257,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode)
 
        ide_debug_log(IDE_DBG_FUNC, "enter");
 
-       lock_kernel();
+       mutex_lock(&ide_gd_mutex);
        if (idkp->openers == 1)
                drive->disk_ops->flush(drive);
 
@@ -269,7 +269,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode)
        idkp->openers--;
 
        ide_disk_put(idkp);
-       unlock_kernel();
+       mutex_unlock(&ide_gd_mutex);
 
        return 0;
 }
index 4c3d1bfec0c5b450fbbe68014e1c15fe9e29c454..068cef0a987aa672566d986eb7353670d533fdd6 100644 (file)
@@ -1444,14 +1444,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        ide_acpi_port_init_devices(hwif);
        }
 
-       ide_host_for_each_port(i, hwif, host) {
-               if (hwif == NULL)
-                       continue;
-
-               if (hwif->present)
-                       hwif_register_devices(hwif);
-       }
-
        ide_host_for_each_port(i, hwif, host) {
                if (hwif == NULL)
                        continue;
@@ -1459,8 +1451,10 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                ide_sysfs_register_port(hwif);
                ide_proc_register_port(hwif);
 
-               if (hwif->present)
+               if (hwif->present) {
                        ide_proc_port_register_devices(hwif);
+                       hwif_register_devices(hwif);
+               }
        }
 
        return j ? 0 : -1;
index 6d622cb5ac8160c57c372bc0c0d30f5ee912d6e0..7ecb1ade8874b86c293a5d1a4a2a59ffc7efc860 100644 (file)
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
@@ -220,6 +218,7 @@ typedef struct ide_tape_obj {
        char write_prot;
 } idetape_tape_t;
 
+static DEFINE_MUTEX(ide_tape_mutex);
 static DEFINE_MUTEX(idetape_ref_mutex);
 
 static DEFINE_MUTEX(idetape_chrdev_mutex);
@@ -1426,9 +1425,9 @@ static long idetape_chrdev_ioctl(struct file *file,
                                unsigned int cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&ide_tape_mutex);
        ret = do_idetape_chrdev_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ide_tape_mutex);
        return ret;
 }
 
@@ -1903,15 +1902,16 @@ static const struct file_operations idetape_fops = {
        .unlocked_ioctl = idetape_chrdev_ioctl,
        .open           = idetape_chrdev_open,
        .release        = idetape_chrdev_release,
+       .llseek         = noop_llseek,
 };
 
 static int idetape_open(struct block_device *bdev, fmode_t mode)
 {
        struct ide_tape_obj *tape;
 
-       lock_kernel();
+       mutex_lock(&ide_tape_mutex);
        tape = ide_tape_get(bdev->bd_disk, false, 0);
-       unlock_kernel();
+       mutex_unlock(&ide_tape_mutex);
 
        if (!tape)
                return -ENXIO;
@@ -1923,9 +1923,9 @@ static int idetape_release(struct gendisk *disk, fmode_t mode)
 {
        struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
 
-       lock_kernel();
+       mutex_lock(&ide_tape_mutex);
        ide_tape_put(tape);
-       unlock_kernel();
+       mutex_unlock(&ide_tape_mutex);
 
        return 0;
 }
@@ -1937,11 +1937,11 @@ static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
        ide_drive_t *drive = tape->drive;
        int err;
 
-       lock_kernel();
+       mutex_lock(&ide_tape_mutex);
        err = generic_ide_ioctl(drive, bdev, cmd, arg);
        if (err == -EINVAL)
                err = idetape_blkdev_ioctl(drive, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ide_tape_mutex);
 
        return err;
 }
index 15341fc1c68b0600e769141562bf08897c1718fe..c976285d313eea4a6b5e2916c73a56350eeb3074 100644 (file)
@@ -536,6 +536,7 @@ static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
 static const struct file_operations idle_fops = {
        .open   = stats_open_generic,
        .read   = stats_read_ul,
+       .llseek = default_llseek,
 };
 
 struct debugfs_file_info {
old mode 100755 (executable)
new mode 100644 (file)
index a10152b..cb3ccf3
 #include <linux/hrtimer.h>     /* ktime_get_real() */
 #include <trace/events/power.h>
 #include <linux/sched.h>
+#include <asm/mwait.h>
 
 #define INTEL_IDLE_VERSION "0.4"
 #define PREFIX "intel_idle: "
 
-#define MWAIT_SUBSTATE_MASK    (0xf)
-#define MWAIT_CSTATE_MASK      (0xf)
-#define MWAIT_SUBSTATE_SIZE    (4)
-#define MWAIT_MAX_NUM_CSTATES  8
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK     (0x2)
-
 static struct cpuidle_driver intel_idle_driver = {
        .name = "intel_idle",
        .owner = THIS_MODULE,
@@ -83,7 +76,7 @@ static unsigned int mwait_substates;
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
 static unsigned int lapic_timer_reliable_states;
 
-static struct cpuidle_device *intel_idle_cpuidle_devices;
+static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
 
 static struct cpuidle_state *cpuidle_state_table;
@@ -108,7 +101,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .name = "NHM-C3",
                .desc = "MWAIT 0x10",
                .driver_data = (void *) 0x10,
-               .flags = CPUIDLE_FLAG_TIME_VALID,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 20,
                .power_usage = 500,
                .target_residency = 80,
@@ -117,7 +110,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .name = "NHM-C6",
                .desc = "MWAIT 0x20",
                .driver_data = (void *) 0x20,
-               .flags = CPUIDLE_FLAG_TIME_VALID,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 200,
                .power_usage = 350,
                .target_residency = 800,
@@ -149,7 +142,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .name = "ATM-C4",
                .desc = "MWAIT 0x30",
                .driver_data = (void *) 0x30,
-               .flags = CPUIDLE_FLAG_TIME_VALID,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 100,
                .power_usage = 250,
                .target_residency = 400,
@@ -157,13 +150,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C5 */ },
        { /* MWAIT C6 */
                .name = "ATM-C6",
-               .desc = "MWAIT 0x40",
-               .driver_data = (void *) 0x40,
-               .flags = CPUIDLE_FLAG_TIME_VALID,
-               .exit_latency = 200,
+               .desc = "MWAIT 0x52",
+               .driver_data = (void *) 0x52,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 140,
                .power_usage = 150,
-               .target_residency = 800,
-               .enter = NULL },        /* disabled */
+               .target_residency = 560,
+               .enter = &intel_idle },
 };
 
 /**
@@ -185,6 +178,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
 
        local_irq_disable();
 
+       /*
+        * If the state flag indicates that the TLB will be flushed or if this
+        * is the deepest c-state supported, do a voluntary leave mm to avoid
+        * costly and mostly unnecessary wakeups for flushing the user TLB's
+        * associated with the active mm.
+        */
+       if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
+           (&dev->states[dev->state_count - 1] == state))
+               leave_mm(cpu);
+
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
index d0dc1db80b295adc31ad88eb38bb82a3106f6175..50815022cff1dccc4a285d70a9b58d5760315175 100644 (file)
@@ -1106,7 +1106,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
                if (recv->block_irq_interval * 4 > iso->buf_packets)
                        recv->block_irq_interval = iso->buf_packets / 4;
                if (recv->block_irq_interval < 1)
-               recv->block_irq_interval = 1;
+                       recv->block_irq_interval = 1;
 
                /* choose a buffer stride */
                /* must be a power of 2, and <= PAGE_SIZE */
index 8f0caf7d4482079ef45aa9ea3b8a66d6a37500d4..78fbe9ffe7f024f3f4e1ca486bcbeb5976087e27 100644 (file)
@@ -53,7 +53,7 @@
 #define T3_MAX_PBL_SIZE 256
 #define T3_MAX_RQ_SIZE 1024
 #define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1)
-#define T3_MAX_CQ_DEPTH 262144
+#define T3_MAX_CQ_DEPTH 65536
 #define T3_MAX_NUM_STAG (1<<15)
 #define T3_MAX_MR_SIZE 0x100000000ULL
 #define T3_PAGESIZE_MASK 0xffff000  /* 4KB-128MB */
index d88077a219944ec49e2f594de780d0f216f9201f..13c88871dc3b90f564a52b4651aa371a4cd15633 100644 (file)
@@ -463,7 +463,8 @@ static int send_connect(struct iwch_ep *ep)
            V_MSS_IDX(mtu_idx) |
            V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
        opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-       opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+       opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+              V_CONG_CONTROL_FLAVOR(cong_flavor);
        skb->priority = CPL_PRIORITY_SETUP;
        set_arp_failure_handler(skb, act_open_req_arp_failure);
 
@@ -1280,7 +1281,8 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
            V_MSS_IDX(mtu_idx) |
            V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
        opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-       opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+       opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+              V_CONG_CONTROL_FLAVOR(cong_flavor);
 
        rpl = cplhdr(skb);
        rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
index d4ce8b63e19eba275cc2e11235dc751ed438e1f1..daef61d5e5bb58afaf224da91a9789869a1224ce 100644 (file)
@@ -65,7 +65,8 @@ static const struct file_operations diag_file_ops = {
        .write = ipath_diag_write,
        .read = ipath_diag_read,
        .open = ipath_diag_open,
-       .release = ipath_diag_release
+       .release = ipath_diag_release,
+       .llseek = default_llseek,
 };
 
 static ssize_t ipath_diagpkt_write(struct file *fp,
@@ -75,6 +76,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
 static const struct file_operations diagpkt_file_ops = {
        .owner = THIS_MODULE,
        .write = ipath_diagpkt_write,
+       .llseek = noop_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
index 65eb8929db22c69da11950ef0ee5e80913a9cc52..6078992da3f04d6de686838c46ccfd61f6f43922 100644 (file)
@@ -63,7 +63,8 @@ static const struct file_operations ipath_file_ops = {
        .open = ipath_open,
        .release = ipath_close,
        .poll = ipath_poll,
-       .mmap = ipath_mmap
+       .mmap = ipath_mmap,
+       .llseek = noop_llseek,
 };
 
 /*
index 2fca70836daea5d4f24f16ecc65d32f1a4249099..d13e72685dcfa17388c274a62df80f88f68b558f 100644 (file)
@@ -103,6 +103,7 @@ static ssize_t atomic_stats_read(struct file *file, char __user *buf,
 
 static const struct file_operations atomic_stats_ops = {
        .read = atomic_stats_read,
+       .llseek = default_llseek,
 };
 
 static ssize_t atomic_counters_read(struct file *file, char __user *buf,
@@ -120,6 +121,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
 
 static const struct file_operations atomic_counters_ops = {
        .read = atomic_counters_read,
+       .llseek = default_llseek,
 };
 
 static ssize_t flash_read(struct file *file, char __user *buf,
@@ -224,6 +226,7 @@ bail:
 static const struct file_operations flash_ops = {
        .read = flash_read,
        .write = flash_write,
+       .llseek = default_llseek,
 };
 
 static int create_device_files(struct super_block *sb,
index 443cea55daac5973469cf43fabe2a388abeadb55..61e0efd4ccfb5d9d4d6f6bdc50f765d365c07d0e 100644 (file)
@@ -502,7 +502,9 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
 static void nes_retrans_expired(struct nes_cm_node *cm_node)
 {
        struct iw_cm_id *cm_id = cm_node->cm_id;
-       switch (cm_node->state) {
+       enum nes_cm_node_state state = cm_node->state;
+       cm_node->state = NES_CM_STATE_CLOSED;
+       switch (state) {
        case NES_CM_STATE_SYN_RCVD:
        case NES_CM_STATE_CLOSING:
                rem_ref_cm_node(cm_node->cm_core, cm_node);
@@ -511,7 +513,6 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)
        case NES_CM_STATE_FIN_WAIT1:
                if (cm_node->cm_id)
                        cm_id->rem_ref(cm_id);
-               cm_node->state = NES_CM_STATE_CLOSED;
                send_reset(cm_node, NULL);
                break;
        default:
@@ -1439,9 +1440,6 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
                break;
        case NES_CM_STATE_MPAREQ_RCVD:
                passive_state = atomic_add_return(1, &cm_node->passive_state);
-               if (passive_state ==  NES_SEND_RESET_EVENT)
-                       create_event(cm_node, NES_CM_EVENT_RESET);
-               cm_node->state = NES_CM_STATE_CLOSED;
                dev_kfree_skb_any(skb);
                break;
        case NES_CM_STATE_ESTABLISHED:
@@ -1456,6 +1454,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
        case NES_CM_STATE_CLOSED:
                drop_packet(skb);
                break;
+       case NES_CM_STATE_FIN_WAIT2:
        case NES_CM_STATE_FIN_WAIT1:
        case NES_CM_STATE_LAST_ACK:
                cm_node->cm_id->rem_ref(cm_node->cm_id);
@@ -2777,6 +2776,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                return -EINVAL;
        }
 
+       passive_state = atomic_add_return(1, &cm_node->passive_state);
+       if (passive_state == NES_SEND_RESET_EVENT) {
+               rem_ref_cm_node(cm_node->cm_core, cm_node);
+               return -ECONNRESET;
+       }
+
        /* associate the node with the QP */
        nesqp->cm_node = (void *)cm_node;
        cm_node->nesqp = nesqp;
@@ -2979,9 +2984,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
                        "ret=%d\n", __func__, __LINE__, ret);
 
-       passive_state = atomic_add_return(1, &cm_node->passive_state);
-       if (passive_state == NES_SEND_RESET_EVENT)
-               create_event(cm_node, NES_CM_EVENT_RESET);
        return 0;
 }
 
index f8233c851c694862d76861e515b93183b8d387a5..1980a461c49904e93102e02e655e5b033c5f92be 100644 (file)
@@ -3468,6 +3468,19 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                return; /* Ignore it, wait for close complete */
 
                        if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
+                               if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
+                                       (nesqp->ibqp_state == IB_QPS_RTS) &&
+                                       ((nesadapter->eeprom_version >> 16) != NES_A0)) {
+                                       spin_lock_irqsave(&nesqp->lock, flags);
+                                       nesqp->hw_iwarp_state = iwarp_state;
+                                       nesqp->hw_tcp_state = tcp_state;
+                                       nesqp->last_aeq = async_event_id;
+                                       next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
+                                       nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+                                       spin_unlock_irqrestore(&nesqp->lock, flags);
+                                       nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
+                                       nes_cm_disconn(nesqp);
+                               }
                                nesqp->cm_id->add_ref(nesqp->cm_id);
                                schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
                                                NES_TIMER_TYPE_CLOSE, 1, 0);
@@ -3477,7 +3490,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                                nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
                                                async_event_id, nesqp->last_aeq, tcp_state);
                        }
-
                        break;
                case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
                        if (nesqp->term_flags) {
index aa9183db32b104aaaa7bfad081c3c969699cec72..1204c3432b6322f23518c42d550746f19d9e4ce6 100644 (file)
@@ -45,6 +45,7 @@
 #define NES_PHY_TYPE_KR               9
 
 #define NES_MULTICAST_PF_MAX 8
+#define NES_A0 3
 
 enum pci_regs {
        NES_INT_STAT = 0x0000,
index 6dfdd49cdbcf36ef5cd68aee3caf46dbdaeb77f0..10560c796fd6c0ffc591601c610579d3e1b6e8ca 100644 (file)
@@ -1446,14 +1446,14 @@ static int nes_netdev_set_pauseparam(struct net_device *netdev,
                                NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
                u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
                nes_write_indexed(nesdev,
-                               NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
+                               NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp);
                nesdev->disable_tx_flow_control = 0;
        } else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) {
                u32temp = nes_read_indexed(nesdev,
                                NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
                u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
                nes_write_indexed(nesdev,
-                               NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
+                               NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp);
                nesdev->disable_tx_flow_control = 1;
        }
        if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) {
index 05dcf0d9a7d31a253267010e51d4a3e20fb02edc..204c4dd9dce0608eecfcfa74822e837d9e895916 100644 (file)
@@ -136,7 +136,8 @@ static const struct file_operations diag_file_ops = {
        .write = qib_diag_write,
        .read = qib_diag_read,
        .open = qib_diag_open,
-       .release = qib_diag_release
+       .release = qib_diag_release,
+       .llseek = default_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
@@ -149,6 +150,7 @@ static ssize_t qib_diagpkt_write(struct file *fp, const char __user *data,
 static const struct file_operations diagpkt_file_ops = {
        .owner = THIS_MODULE,
        .write = qib_diagpkt_write,
+       .llseek = noop_llseek,
 };
 
 int qib_diag_add(struct qib_devdata *dd)
index 6b11645edf35532506edc38076148b3ccb85c6df..aa2be214270fcfc12a9d33d20f3c4054d8b8dc02 100644 (file)
@@ -63,7 +63,8 @@ static const struct file_operations qib_file_ops = {
        .open = qib_open,
        .release = qib_close,
        .poll = qib_poll,
-       .mmap = qib_mmapf
+       .mmap = qib_mmapf,
+       .llseek = noop_llseek,
 };
 
 /*
index 9f989c0ba9d302fd7d643d4a5389e012d44559a5..a0e6613e8be6151d3fdc00efc3005ad8c6f22ebd 100644 (file)
@@ -367,6 +367,7 @@ bail:
 static const struct file_operations flash_ops = {
        .read = flash_read,
        .write = flash_write,
+       .llseek = default_llseek,
 };
 
 static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd)
index c908c5f83645c901f87823e2a587ba65d9b5ee97..535fea4fe67f026bbe6475c5cd70c8a18d0bc4dd 100644 (file)
@@ -28,7 +28,7 @@ struct evdev {
        int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
-       struct evdev_client *grab;
+       struct evdev_client __rcu *grab;
        struct list_head client_list;
        spinlock_t client_lock; /* protects client_list */
        struct mutex mutex;
@@ -669,6 +669,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
+                       if (!dev->absinfo)
+                               return -EINVAL;
+
                        t = _IOC_NR(cmd) & ABS_MAX;
                        abs = dev->absinfo[t];
 
@@ -680,10 +683,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                }
        }
 
-       if (_IOC_DIR(cmd) == _IOC_READ) {
+       if (_IOC_DIR(cmd) == _IOC_WRITE) {
 
                if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
+                       if (!dev->absinfo)
+                               return -EINVAL;
+
                        t = _IOC_NR(cmd) & ABS_MAX;
 
                        if (copy_from_user(&abs, p, min_t(size_t,
@@ -761,7 +767,8 @@ static const struct file_operations evdev_fops = {
        .compat_ioctl   = evdev_ioctl_compat,
 #endif
        .fasync         = evdev_fasync,
-       .flush          = evdev_flush
+       .flush          = evdev_flush,
+       .llseek         = no_llseek,
 };
 
 static int evdev_install_chrdev(struct evdev *evdev)
index a9b025f4147a0692845d2407b6efbd9220f9837e..7919c25372257e0baa922903565f55fd94effb29 100644 (file)
@@ -1599,11 +1599,14 @@ EXPORT_SYMBOL(input_free_device);
  * @dev: input device supporting MT events and finger tracking
  * @num_slots: number of slots used by the device
  *
- * This function allocates all necessary memory for MT slot handling
- * in the input device, and adds ABS_MT_SLOT to the device capabilities.
+ * This function allocates all necessary memory for MT slot handling in the
+ * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
+ * are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1.
  */
 int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
 {
+       int i;
+
        if (!num_slots)
                return 0;
 
@@ -1614,6 +1617,10 @@ int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
        dev->mtsize = num_slots;
        input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
 
+       /* Mark slots as 'unused' */
+       for (i = 0; i < num_slots; i++)
+               dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1;
+
        return 0;
 }
 EXPORT_SYMBOL(input_mt_create_slots);
@@ -2040,6 +2047,7 @@ out:
 static const struct file_operations input_fops = {
        .owner = THIS_MODULE,
        .open = input_open_file,
+       .llseek = noop_llseek,
 };
 
 static int __init input_init(void)
index d85bd8a7967d2ee26aff8e5313c67a0cd7290532..9d424cebfd2c7d6e31e3cd433342e94f6fc7625c 100644 (file)
@@ -483,6 +483,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
 
        memcpy(joydev->abspam, abspam, len);
 
+       for (i = 0; i < joydev->nabs; i++)
+               joydev->absmap[joydev->abspam[i]] = i;
+
  out:
        kfree(abspam);
        return retval;
@@ -736,6 +739,7 @@ static const struct file_operations joydev_fops = {
        .compat_ioctl   = joydev_compat_ioctl,
 #endif
        .fasync         = joydev_fasync,
+       .llseek         = no_llseek,
 };
 
 static int joydev_install_chrdev(struct joydev *joydev)
index 9cc488d2149019626101d3c5f76d0b2bdab0fe57..aa037fec2f86122500cbd5d14cfca0c59e614804 100644 (file)
@@ -338,7 +338,7 @@ config KEYBOARD_OPENCORES
 
 config KEYBOARD_PXA27x
        tristate "PXA27x/PXA3xx keypad support"
-       depends on PXA27x || PXA3xx
+       depends on PXA27x || PXA3xx || ARCH_MMP
        help
          Enable support for PXA27x/PXA3xx keypad controller.
 
index dcc86b97a1535c6a3ba098543d691ee249d56cf5..19fa94af207a6fa37fbadc7a3d39a65ea2010482 100644 (file)
@@ -232,13 +232,13 @@ static void hil_dev_handle_ptr_events(struct hil_dev *ptr)
                if (absdev) {
                        val = lo + (hi << 8);
 #ifdef TABLET_AUTOADJUST
-                       if (val < input_abs_min(dev, ABS_X + i))
+                       if (val < input_abs_get_min(dev, ABS_X + i))
                                input_abs_set_min(dev, ABS_X + i, val);
-                       if (val > input_abs_max(dev, ABS_X + i))
+                       if (val > input_abs_get_max(dev, ABS_X + i))
                                input_abs_set_max(dev, ABS_X + i, val);
 #endif
                        if (i % 3)
-                               val = input_abs_max(dev, ABS_X + i) - val;
+                               val = input_abs_get_max(dev, ABS_X + i) - val;
                        input_report_abs(dev, ABS_X + i, val);
                } else {
                        val = (int) (((int8_t) lo) | ((int8_t) hi << 8));
@@ -388,11 +388,11 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr)
 
 #ifdef TABLET_AUTOADJUST
                for (i = 0; i < ABS_MAX; i++) {
-                       int diff = input_abs_max(input_dev, ABS_X + i) / 10;
+                       int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
                        input_abs_set_min(input_dev, ABS_X + i,
-                               input_abs_min(input_dev, ABS_X + i) + diff)
+                               input_abs_get_min(input_dev, ABS_X + i) + diff);
                        input_abs_set_max(input_dev, ABS_X + i,
-                               input_abs_max(input_dev, ABS_X + i) - diff)
+                               input_abs_get_max(input_dev, ABS_X + i) - diff);
                }
 #endif
 
index 0e53b3bc39afe4d7925d4aec0cea66174dfc1e5e..4b0ec35259a17f70357df965ae4f9b698bf4e01a 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 /*
  * Keypad Controller registers
  */
@@ -330,11 +330,21 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
        keypad->direct_key_state = new_state;
 }
 
+static void clear_wakeup_event(struct pxa27x_keypad *keypad)
+{
+       struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
+
+       if (pdata->clear_wakeup_event)
+               (pdata->clear_wakeup_event)();
+}
+
 static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
 {
        struct pxa27x_keypad *keypad = dev_id;
        unsigned long kpc = keypad_readl(KPC);
 
+       clear_wakeup_event(keypad);
+
        if (kpc & KPC_DI)
                pxa27x_keypad_scan_direct(keypad);
 
@@ -567,8 +577,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
        clk_put(keypad->clk);
 
        input_unregister_device(keypad->input_dev);
-       input_free_device(keypad->input_dev);
-
        iounmap(keypad->mmio_base);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index c19066479057ff3567d7168c38922e0fd0b84da3..0b4f54265f62d31031598aaeadd3240c50af7d1b 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/rtc.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/semaphore.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
@@ -52,6 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 #define RTC_VERSION "1.10d"
 
+static DEFINE_MUTEX(hp_sdc_rtc_mutex);
 static unsigned long epoch = 2000;
 
 static struct semaphore i8042tregs;
@@ -104,7 +105,7 @@ static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
        t.endidx =              91;
        t.seq =                 tseq;
        t.act.semaphore =       &tsem;
-       init_MUTEX_LOCKED(&tsem);
+       sema_init(&tsem, 0);
        
        if (hp_sdc_enqueue_transaction(&t)) return -1;
        
@@ -665,9 +666,9 @@ static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&hp_sdc_rtc_mutex);
        ret = hp_sdc_rtc_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&hp_sdc_rtc_mutex);
 
        return ret;
 }
@@ -698,7 +699,7 @@ static int __init hp_sdc_rtc_init(void)
                return -ENODEV;
 #endif
 
-       init_MUTEX(&i8042tregs);
+       sema_init(&i8042tregs, 1);
 
        if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
                return ret;
index bb53fd33cd1cb64e5d3c108b84eea4e1f11ccff4..b9410784e6a1f1503fb57a720c9f91b1fcec2fce 100644 (file)
@@ -404,6 +404,13 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
                retval = uinput_validate_absbits(dev);
                if (retval < 0)
                        goto exit;
+               if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+                       int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+                       input_mt_create_slots(dev, nslot);
+                       input_set_events_per_packet(dev, 6 * nslot);
+               } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+                       input_set_events_per_packet(dev, 60);
+               }
        }
 
        udev->state = UIST_SETUP_COMPLETE;
@@ -804,6 +811,7 @@ static const struct file_operations uinput_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = uinput_compat_ioctl,
 #endif
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice uinput_misc = {
@@ -811,6 +819,8 @@ static struct miscdevice uinput_misc = {
        .minor          = UINPUT_MINOR,
        .name           = UINPUT_NAME,
 };
+MODULE_ALIAS_MISCDEV(UINPUT_MINOR);
+MODULE_ALIAS("devname:" UINPUT_NAME);
 
 static int __init uinput_init(void)
 {
index ea67c49146a3a03280ee8719c362c41d8033c743..b952317639116f2f18a7bc1f41ff5887c17f2a49 100644 (file)
@@ -337,10 +337,14 @@ static void report_finger_data(struct input_dev *input,
                               const struct bcm5974_config *cfg,
                               const struct tp_finger *f)
 {
-       input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major));
-       input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor));
-       input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major));
-       input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor));
+       input_report_abs(input, ABS_MT_TOUCH_MAJOR,
+                        raw2int(f->force_major) << 1);
+       input_report_abs(input, ABS_MT_TOUCH_MINOR,
+                        raw2int(f->force_minor) << 1);
+       input_report_abs(input, ABS_MT_WIDTH_MAJOR,
+                        raw2int(f->size_major) << 1);
+       input_report_abs(input, ABS_MT_WIDTH_MINOR,
+                        raw2int(f->size_minor) << 1);
        input_report_abs(input, ABS_MT_ORIENTATION,
                         MAX_FINGER_ORIENTATION - raw2int(f->orientation));
        input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
index 83c24cca234a5849545adeda916b0e4a136769fb..31ec7265aac63806060a665278afc70d6e18946f 100644 (file)
@@ -138,8 +138,8 @@ static void mousedev_touchpad_event(struct input_dev *dev,
 
                fx(0) = value;
                if (mousedev->touch && mousedev->pkt_count >= 2) {
-                       size = input_abs_get_min(dev, ABS_X) -
-                                       input_abs_get_max(dev, ABS_X);
+                       size = input_abs_get_max(dev, ABS_X) -
+                                       input_abs_get_min(dev, ABS_X);
                        if (size == 0)
                                size = 256 * 2;
 
@@ -155,8 +155,8 @@ static void mousedev_touchpad_event(struct input_dev *dev,
                fy(0) = value;
                if (mousedev->touch && mousedev->pkt_count >= 2) {
                        /* use X size for ABS_Y to keep the same scale */
-                       size = input_abs_get_min(dev, ABS_X) -
-                                       input_abs_get_max(dev, ABS_X);
+                       size = input_abs_get_max(dev, ABS_X) -
+                                       input_abs_get_min(dev, ABS_X);
                        if (size == 0)
                                size = 256 * 2;
 
@@ -792,6 +792,7 @@ static const struct file_operations mousedev_fops = {
        .open =         mousedev_open,
        .release =      mousedev_release,
        .fasync =       mousedev_fasync,
+       .llseek = noop_llseek,
 };
 
 static int mousedev_install_chrdev(struct mousedev *mousedev)
index c92f4edfee7beef3a326e0af4e43275093fba8dc..e5624d8f1709e6c576547c6e78ba66e766d39743 100644 (file)
@@ -915,15 +915,15 @@ int hil_mlc_register(hil_mlc *mlc)
        mlc->ostarted = 0;
 
        rwlock_init(&mlc->lock);
-       init_MUTEX(&mlc->osem);
+       sema_init(&mlc->osem, 1);
 
-       init_MUTEX(&mlc->isem);
+       sema_init(&mlc->isem, 1);
        mlc->icount = -1;
        mlc->imatch = 0;
 
        mlc->opercnt = 0;
 
-       init_MUTEX_LOCKED(&(mlc->csem));
+       sema_init(&(mlc->csem), 0);
 
        hil_mlc_clear_di_scratch(mlc);
        hil_mlc_clear_di_map(mlc, 0);
index bcc2d30ec245ef8349e81745958e0cf8112dfcbf..8c0b51c31424ce2e0c9b15a2a9eb467424e9b3ec 100644 (file)
@@ -905,7 +905,7 @@ static int __init hp_sdc_init(void)
        ts_sync[1]      = 0x0f;
        ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
        t_sync.act.semaphore = &s_sync;
-       init_MUTEX_LOCKED(&s_sync);
+       sema_init(&s_sync, 0);
        hp_sdc_enqueue_transaction(&t_sync);
        down(&s_sync); /* Wait for t_sync to complete */
 
@@ -1039,7 +1039,7 @@ static int __init hp_sdc_register(void)
                return hp_sdc.dev_err;
        }
 
-       init_MUTEX_LOCKED(&tq_init_sem);
+       sema_init(&tq_init_sem, 0);
 
        tq_init.actidx          = 0;
        tq_init.idx             = 1;
index 46e4ba0b92463184d5e398345e50ca68809628b2..f585131604806f531f91c48ebb867919339fd80f 100644 (file)
@@ -1485,8 +1485,8 @@ static int __init i8042_init(void)
 
 static void __exit i8042_exit(void)
 {
-       platform_driver_unregister(&i8042_driver);
        platform_device_unregister(i8042_platform_device);
+       platform_driver_unregister(&i8042_driver);
        i8042_platform_exit();
 
        panic_blink = NULL;
index 998664854440005cd62d0fdcbab339dd55e968f3..cd82bb12591593be230f06fbf89aa2a52f6b73b2 100644 (file)
@@ -243,6 +243,7 @@ static const struct file_operations serio_raw_fops = {
        .write =        serio_raw_write,
        .poll =         serio_raw_poll,
        .fasync =       serio_raw_fasync,
+       .llseek = noop_llseek,
 };
 
 
index 42ba3691d908bc1fc8c370da5ada4287ceb21115..b35876ee6908c7328f29e2505fd29a94a61b2d61 100644 (file)
@@ -103,27 +103,26 @@ static void wacom_sys_irq(struct urb *urb)
 static int wacom_open(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
+       int retval = 0;
 
-       mutex_lock(&wacom->lock);
-
-       wacom->irq->dev = wacom->usbdev;
-
-       if (usb_autopm_get_interface(wacom->intf) < 0) {
-               mutex_unlock(&wacom->lock);
+       if (usb_autopm_get_interface(wacom->intf) < 0)
                return -EIO;
-       }
+
+       mutex_lock(&wacom->lock);
 
        if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
-               usb_autopm_put_interface(wacom->intf);
-               mutex_unlock(&wacom->lock);
-               return -EIO;
+               retval = -EIO;
+               goto out;
        }
 
        wacom->open = true;
        wacom->intf->needs_remote_wakeup = 1;
 
+out:
        mutex_unlock(&wacom->lock);
-       return 0;
+       if (retval)
+               usb_autopm_put_interface(wacom->intf);
+       return retval;
 }
 
 static void wacom_close(struct input_dev *dev)
@@ -135,6 +134,8 @@ static void wacom_close(struct input_dev *dev)
        wacom->open = false;
        wacom->intf->needs_remote_wakeup = 0;
        mutex_unlock(&wacom->lock);
+
+       usb_autopm_put_interface(wacom->intf);
 }
 
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
index 40d77ba8fdc138ff98b0320b877358a5302d7a28..47fd7a041c52e1898a8727c5386569fb3caed45c 100644 (file)
@@ -243,10 +243,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                        if (features->type == WACOM_G4 ||
                                        features->type == WACOM_MO) {
                                input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
-                               rw = (signed)(data[7] & 0x04) - (data[7] & 0x03);
+                               rw = (data[7] & 0x04) - (data[7] & 0x03);
                        } else {
                                input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
-                               rw = -(signed)data[6];
+                               rw = -(signed char)data[6];
                        }
                        input_report_rel(input, REL_WHEEL, rw);
                }
@@ -442,8 +442,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
        /* general pen packet */
        if ((data[1] & 0xb8) == 0xa0) {
                t = (data[6] << 2) | ((data[7] >> 6) & 3);
-               if (features->type >= INTUOS4S && features->type <= INTUOS4L)
+               if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
+                   features->type == WACOM_21UX2) {
                        t = (t << 1) | (data[1] & 1);
+               }
                input_report_abs(input, ABS_PRESSURE, t);
                input_report_abs(input, ABS_TILT_X,
                                ((data[7] << 1) & 0x7e) | (data[8] >> 7));
index d4c50512a1ffc038795acb06248e1b245f63f3a5..88c9423500d838a1748c74b283d9b612a754d7fd 100644 (file)
@@ -141,9 +141,9 @@ typedef struct irq_data_isa {
        __u8            rcvhdr[8];
 } irq_data_isa;
 
-typedef union irq_data {
+typedef union act2000_irq_data {
        irq_data_isa isa;
-} irq_data;
+} act2000_irq_data;
 
 /*
  * Per card driver data
@@ -176,7 +176,7 @@ typedef struct act2000_card {
        char   *status_buf_read;
        char   *status_buf_write;
        char   *status_buf_end;
-       irq_data idat;                  /* Data used for IRQ handler        */
+       act2000_irq_data idat;          /* Data used for IRQ handler        */
        isdn_if interface;              /* Interface to upper layer         */
        char regname[35];               /* Name used for request_region     */
 } act2000_card;
index 5dbcbe3a54a610d81d61b6e0b4d227af7751636d..b99b906ea9b1bfef709bec43e61237a74b177949 100644 (file)
@@ -36,12 +36,13 @@ config ISDN_DRV_AVMB1_T1ISA
 
 config ISDN_DRV_AVMB1_B1PCMCIA
        tristate "AVM B1/M1/M2 PCMCIA support"
+       depends on PCMCIA
        help
          Enable support for the PCMCIA version of the AVM B1 card.
 
 config ISDN_DRV_AVMB1_AVM_CS
        tristate "AVM B1/M1/M2 PCMCIA cs module"
-       depends on ISDN_DRV_AVMB1_B1PCMCIA && PCMCIA
+       depends on ISDN_DRV_AVMB1_B1PCMCIA
        help
          Enable the PCMCIA client driver for the AVM B1/M1/M2
          PCMCIA cards.
index 09b1795516f4e95c4e49f0ce6e1e91c9eefa5bd1..91f06a3ef00223a4403230579fa71f9cc404c7c1 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -39,87 +38,32 @@ MODULE_LICENSE("GPL");
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the skeleton event
-   handler.
-*/
-
 static int avmcs_config(struct pcmcia_device *link);
 static void avmcs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void avmcs_detach(struct pcmcia_device *p_dev);
 
-/*======================================================================
-
-    avmcs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-    
-======================================================================*/
-
 static int avmcs_probe(struct pcmcia_device *p_dev)
 {
-
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avmcs_config(p_dev);
 } /* avmcs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
 
 static void avmcs_detach(struct pcmcia_device *link)
 {
        avmcs_release(link);
 } /* avmcs_detach */
 
-/*======================================================================
-
-    avmcs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-    
-======================================================================*/
-
-static int avmcs_configcheck(struct pcmcia_device *p_dev,
-                            cistpl_cftable_entry_t *cf,
-                            cistpl_cftable_entry_t *dflt,
-                            unsigned int vcc,
-                            void *priv_data)
+static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cf->io.nwin <= 0)
-               return -ENODEV;
+       p_dev->resource[0]->end = 16;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
-       p_dev->resource[0]->start = cf->io.win[0].base;
-       p_dev->resource[0]->end = cf->io.win[0].len;
        return pcmcia_request_io(p_dev);
 }
 
@@ -150,7 +94,7 @@ static int avmcs_config(struct pcmcia_device *link)
        /*
          * configure the PCMCIA socket
          */
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0) {
            pcmcia_disable_device(link);
            break;
@@ -197,13 +141,6 @@ static int avmcs_config(struct pcmcia_device *link)
 
 } /* avmcs_config */
 
-/*======================================================================
-
-    After a card is removed, avmcs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
 
 static void avmcs_release(struct pcmcia_device *link)
 {
@@ -222,9 +159,7 @@ MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
 
 static struct pcmcia_driver avmcs_driver = {
        .owner  = THIS_MODULE,
-       .drv    = {
-               .name   = "avm_cs",
-       },
+       .name           = "avm_cs",
        .probe = avmcs_probe,
        .remove = avmcs_detach,
        .id_table = avmcs_ids,
index 94263c22b8746965109cc6b1654a8a30df2355fd..ac4dd7857cbd3e50edb12b3eb715614a0e17643c 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include "hisax_cfg.h"
@@ -40,67 +39,22 @@ module_param(isdnprot, int, 0);
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the skeleton event
-   handler.
-*/
-
 static int avma1cs_config(struct pcmcia_device *link) __devinit ;
 static void avma1cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ;
 
-
-/*======================================================================
-
-    avma1cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-    
-======================================================================*/
-
 static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 {
     dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    p_dev->resource[1]->end = 16;
-    p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avma1cs_config(p_dev);
 } /* avma1cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit avma1cs_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
@@ -108,26 +62,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
        kfree(link->priv);
 } /* avma1cs_detach */
 
-/*======================================================================
-
-    avma1cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-    
-======================================================================*/
-
-static int avma1cs_configcheck(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cf,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cf->io.nwin <= 0)
-               return -ENODEV;
-
-       p_dev->resource[0]->start = cf->io.win[0].base;
-       p_dev->resource[0]->end = cf->io.win[0].len;
+       p_dev->resource[0]->end = 16;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
        p_dev->io_lines = 5;
+
        return pcmcia_request_io(p_dev);
 }
 
@@ -161,7 +102,7 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
        /*
         * configure the PCMCIA socket
         */
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0) {
            pcmcia_disable_device(link);
            break;
@@ -175,9 +116,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
        return -ENODEV;
     }
 
-    printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
-               (unsigned int) link->resource[0]->start, link->irq);
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = isdnprot;
@@ -196,14 +134,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
     return 0;
 } /* avma1cs_config */
 
-/*======================================================================
-
-    After a card is removed, avma1cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void avma1cs_release(struct pcmcia_device *link)
 {
        unsigned long minor = (unsigned long) link->priv;
@@ -216,7 +146,6 @@ static void avma1cs_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 } /* avma1cs_release */
 
-
 static struct pcmcia_device_id avma1cs_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
        PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
@@ -226,19 +155,15 @@ MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
 
 static struct pcmcia_driver avma1cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "avma1_cs",
-       },
+       .name           = "avma1_cs",
        .probe          = avma1cs_probe,
        .remove         = __devexit_p(avma1cs_detach),
        .id_table       = avma1cs_ids,
 };
 
-/*====================================================================*/
-
 static int __init init_avma1_cs(void)
 {
-       return(pcmcia_register_driver(&avma1cs_driver));
+       return pcmcia_register_driver(&avma1cs_driver);
 }
 
 static void __exit exit_avma1_cs(void)
index 6f9afcd5ca4e9301a07c8ec5a4c0473e255363c3..b133378d4dc9b1707c749102c345c3c2f7b2d7d4 100644 (file)
@@ -801,6 +801,16 @@ static void closecard(int cardnr)
        ll_unload(csta);
 }
 
+static irqreturn_t card_irq(int intno, void *dev_id)
+{
+       struct IsdnCardState *cs = dev_id;
+       irqreturn_t ret = cs->irq_func(intno, cs);
+
+       if (ret == IRQ_HANDLED)
+               cs->irq_cnt++;
+       return ret;
+}
+
 static int init_card(struct IsdnCardState *cs)
 {
        int     irq_cnt, cnt = 3, ret;
@@ -809,10 +819,10 @@ static int init_card(struct IsdnCardState *cs)
                ret = cs->cardmsg(cs, CARD_INIT, NULL);
                return(ret);
        }
-       irq_cnt = kstat_irqs(cs->irq);
+       irq_cnt = cs->irq_cnt = 0;
        printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
               cs->irq, irq_cnt);
-       if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+       if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) {
                printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
                       cs->irq);
                return 1;
@@ -822,8 +832,8 @@ static int init_card(struct IsdnCardState *cs)
                /* Timeout 10ms */
                msleep(10);
                printk(KERN_INFO "%s: IRQ %d count %d\n",
-                      CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
-               if (kstat_irqs(cs->irq) == irq_cnt) {
+                      CardType[cs->typ], cs->irq, cs->irq_cnt);
+               if (cs->irq_cnt == irq_cnt) {
                        printk(KERN_WARNING
                               "%s: IRQ(%d) getting no interrupts during init %d\n",
                               CardType[cs->typ], cs->irq, 4 - cnt);
index b3c08aaf41c410e57c91aaa82fefddc4af6212a8..496d477af0f82fe428798c208e858d407e93d9a8 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,26 +63,8 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the elsa_cs event
-   handler.
-*/
-
 static int elsa_cs_config(struct pcmcia_device *link) __devinit ;
 static void elsa_cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit;
 
 typedef struct local_info_t {
@@ -92,18 +73,6 @@ typedef struct local_info_t {
     int                        cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    elsa_cs_attach() creates an "instance" of the driver, allocatingx
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int __devinit elsa_cs_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -119,31 +88,9 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
 
     local->cardnr = -1;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit elsa_cs_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
@@ -156,27 +103,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
        kfree(info);
 } /* elsa_cs_detach */
 
-/*======================================================================
-
-    elsa_cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
-static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cf,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
        int j;
 
        p_dev->io_lines = 3;
+       p_dev->resource[0]->end = 8;
+       p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+       if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
                printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-               p_dev->resource[0]->start = cf->io.win[0].base;
                if (!pcmcia_request_io(p_dev))
                        return 0;
        } else {
@@ -199,6 +136,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
     dev = link->priv;
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
     if (i != 0)
        goto failed;
@@ -206,21 +145,10 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
     if (!link->irq)
        goto failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
        goto failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x: ",
-           link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-       printk(", irq %d", link->irq);
-    if (link->resource[0])
-       printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-       printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -240,14 +168,6 @@ failed:
     return -ENODEV;
 } /* elsa_cs_config */
 
-/*======================================================================
-
-    After a card is removed, elsa_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void elsa_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -291,9 +211,7 @@ MODULE_DEVICE_TABLE(pcmcia, elsa_ids);
 
 static struct pcmcia_driver elsa_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "elsa_cs",
-       },
+       .name           = "elsa_cs",
        .probe          = elsa_cs_probe,
        .remove         = __devexit_p(elsa_cs_detach),
        .id_table       = elsa_ids,
index 832a87855ffb5900fa22ded56b5586ed907ed886..32ab3924aa7341f5f390623faee36d9a308abc67 100644 (file)
@@ -959,6 +959,7 @@ struct IsdnCardState {
        u_long          event;
        struct work_struct tqueue;
        struct timer_list dbusytimer;
+       unsigned int    irq_cnt;
 #ifdef ERROR_STATISTIC
        int             err_crc;
        int             err_tx;
index a024192b672a3113c0e6663fc1778c5abe4ac6f2..360204bc2777d6f2b941f478ab0a11d2881f07fb 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,26 +63,9 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the sedlbauer
-   event handler. 
-*/
-
 static int sedlbauer_config(struct pcmcia_device *link) __devinit ;
 static void sedlbauer_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
 
 typedef struct local_info_t {
@@ -92,18 +74,6 @@ typedef struct local_info_t {
     int                        cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    sedlbauer_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-    
-======================================================================*/
-
 static int __devinit sedlbauer_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -118,35 +88,9 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
     local->p_dev = link;
     link->priv = local;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-
-    /* from old sedl_cs 
-    */
-    /* The io structure describes IO port mapping */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
-    link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit sedlbauer_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
@@ -158,70 +102,15 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
        kfree(link->priv);
 } /* sedlbauer_detach */
 
-/*======================================================================
-
-    sedlbauer_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-    
-======================================================================*/
-static int sedlbauer_config_check(struct pcmcia_device *p_dev,
-                                 cistpl_cftable_entry_t *cfg,
-                                 cistpl_cftable_entry_t *dflt,
-                                 unsigned int vcc,
-                                 void *priv_data)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-                       return -ENODEV;
-       } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-                       return -ENODEV;
-       }
-
-       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                                       pcmcia_io_cfg_data_width(io->flags);
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               p_dev->io_lines = 3;
-               if (pcmcia_request_io(p_dev) != 0)
-                       return -ENODEV;
-       }
-
-       return 0;
+       p_dev->io_lines = 3;
+       return pcmcia_request_io(p_dev);
 }
 
-
-
 static int __devinit sedlbauer_config(struct pcmcia_device *link)
 {
     int ret;
@@ -229,44 +118,17 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
 
-    /*
-      In this loop, we scan the CIS for configuration table entries,
-      each of which describes a valid card configuration, including
-      voltage, IO window, memory window, and interrupt settings.
-
-      We make no assumptions about the card to be configured: we use
-      just the information available in the CIS.  In an ideal world,
-      this would work for any PCMCIA card, but it requires a complete
-      and accurate CIS.  In practice, a driver usually "knows" most of
-      these things without consulting the CIS, and most client drivers
-      will only use the CIS to fill in implementation-defined details.
-    */
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+           CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
     ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL);
     if (ret)
            goto failed;
 
-    /*
-       This actually configures the PCMCIA socket -- setting up
-       the I/O windows and the interrupt mapping, and putting the
-       card and host interface into "Memory and IO" mode.
-    */
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x:",
-          link->conf.ConfigIndex);
-    if (link->conf.Vpp)
-       printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-       printk(", irq %d", link->irq);
-    if (link->resource[0])
-       printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-       printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -290,14 +152,6 @@ failed:
 
 } /* sedlbauer_config */
 
-/*======================================================================
-
-    After a card is removed, sedlbauer_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void sedlbauer_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -346,9 +200,7 @@ MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
 
 static struct pcmcia_driver sedlbauer_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "sedlbauer_cs",
-       },
+       .name           = "sedlbauer_cs",
        .probe          = sedlbauer_probe,
        .remove         = __devexit_p(sedlbauer_detach),
        .id_table       = sedlbauer_ids,
index 7296102ca255d89ef34bee0a1736d695629214d2..282a4467ef19571c803f296aee3b82b2e5883c20 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -45,26 +44,8 @@ MODULE_LICENSE("GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the teles_cs event
-   handler.
-*/
-
 static int teles_cs_config(struct pcmcia_device *link) __devinit ;
 static void teles_cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
 
 typedef struct local_info_t {
@@ -73,18 +54,6 @@ typedef struct local_info_t {
     int                        cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    teles_attach() creates an "instance" of the driver, allocatingx
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int __devinit teles_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -99,31 +68,11 @@ static int __devinit teles_probe(struct pcmcia_device *link)
     local->p_dev = link;
     link->priv = local;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-    link->resource[0]->end = 96;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return teles_cs_config(link);
 } /* teles_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit teles_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
@@ -136,27 +85,17 @@ static void __devexit teles_detach(struct pcmcia_device *link)
        kfree(info);
 } /* teles_detach */
 
-/*======================================================================
-
-    teles_cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
-static int teles_cs_configcheck(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cf,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
        int j;
 
        p_dev->io_lines = 5;
+       p_dev->resource[0]->end = 96;
+       p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+       if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
                printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-               p_dev->resource[0]->start = cf->io.win[0].base;
                if (!pcmcia_request_io(p_dev))
                        return 0;
        } else {
@@ -186,21 +125,10 @@ static int __devinit teles_cs_config(struct pcmcia_device *link)
     if (!link->irq)
         goto cs_failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
       goto cs_failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x:",
-           link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-           printk(", irq %d", link->irq);
-    if (link->resource[0])
-       printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-       printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -222,14 +150,6 @@ cs_failed:
     return -ENODEV;
 } /* teles_cs_config */
 
-/*======================================================================
-
-    After a card is removed, teles_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void teles_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -273,9 +193,7 @@ MODULE_DEVICE_TABLE(pcmcia, teles_ids);
 
 static struct pcmcia_driver teles_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "teles_cs",
-       },
+       .name           = "teles_cs",
        .probe          = teles_probe,
        .remove         = __devexit_p(teles_detach),
        .id_table       = teles_ids,
index de43c8c70ad082451bbce7e7545a234c0043b836..859c81e9483bd760cf48d401457d06c07efadfd4 100644 (file)
@@ -267,6 +267,7 @@ static const struct file_operations mISDN_fops = {
        .unlocked_ioctl = mISDN_ioctl,
        .open           = mISDN_open,
        .release        = mISDN_close,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice mISDNtimer = {
index 485be8b1e1b33bef2bd7e3af8fab2066d3687ec3..f0225bc0f2670ce2f0fde9b5d276f26151c6a046 100644 (file)
@@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst)
                        }
                        else if(callid>=0x0000 && callid<=0x7FFF)
                        {
+                               int len;
+
                                pr_debug("%s: Got Incoming Call\n",
                                                sc_adapter[card]->devicename);
-                               strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
-                               strcpy(setup.eazmsn,
-                                       sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
+                               len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
+                                               sizeof(setup.phone));
+                               if (len >= sizeof(setup.phone))
+                                       continue;
+                               len = strlcpy(setup.eazmsn,
+                                               sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+                                               sizeof(setup.eazmsn));
+                               if (len >= sizeof(setup.eazmsn))
+                                       continue;
                                setup.si1 = 7;
                                setup.si2 = 0;
                                setup.plan = 0;
@@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst)
                 * Handle a GetMyNumber Rsp
                 */
                if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
-                       strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
+                       strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+                               rcvmsg.msg_data.byte_array,
+                               sizeof(rcvmsg.msg_data.byte_array));
                        continue;
                }
                        
index e4112622e5a25e7eb90b615bcc93475bcfd054a7..cc2a88d5192fbb359f3027082c0843ad34055d97 100644 (file)
@@ -304,13 +304,22 @@ config LEDS_MC13783
 
 config LEDS_NS2
        tristate "LED support for Network Space v2 GPIO LEDs"
-       depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2
+       depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2
        default y
        help
          This option enable support for the dual-GPIO LED found on the
          Network Space v2 board (and parents). This include Internet Space v2,
          Network Space (Max) v2 and d2 Network v2 boards.
 
+config LEDS_NETXBIG
+       tristate "LED support for Big Network series LEDs"
+       depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
+       default y
+       help
+         This option enable support for LEDs found on the LaCie 2Big
+         and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
+         controlled through a GPIO extension bus.
+
 config LEDS_TRIGGERS
        bool "LED Trigger support"
        help
index 7d6b95831f8eb5da86fad02ab6eedf680c437e3c..9c96db40ef6d7d3a12f776ab4d764371a71026a5 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_LEDS_ADP5520)            += leds-adp5520.o
 obj-$(CONFIG_LEDS_DELL_NETBOOKS)       += dell-led.o
 obj-$(CONFIG_LEDS_MC13783)             += leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)                 += leds-ns2.o
+obj-$(CONFIG_LEDS_NETXBIG)             += leds-netxbig.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
new file mode 100644 (file)
index 0000000..f2e51c1
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.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.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <mach/leds-netxbig.h>
+
+/*
+ * GPIO extension bus.
+ */
+
+static DEFINE_SPINLOCK(gpio_ext_lock);
+
+static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr)
+{
+       int pin;
+
+       for (pin = 0; pin < gpio_ext->num_addr; pin++)
+               gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
+}
+
+static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data)
+{
+       int pin;
+
+       for (pin = 0; pin < gpio_ext->num_data; pin++)
+               gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1);
+}
+
+static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext)
+{
+       /* Enable select is done on the raising edge. */
+       gpio_set_value(gpio_ext->enable, 0);
+       gpio_set_value(gpio_ext->enable, 1);
+}
+
+static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
+                              int addr, int value)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&gpio_ext_lock, flags);
+       gpio_ext_set_addr(gpio_ext, addr);
+       gpio_ext_set_data(gpio_ext, value);
+       gpio_ext_enable_select(gpio_ext);
+       spin_unlock_irqrestore(&gpio_ext_lock, flags);
+}
+
+static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+{
+       int err;
+       int i;
+
+       if (unlikely(!gpio_ext))
+               return -EINVAL;
+
+       /* Configure address GPIOs. */
+       for (i = 0; i < gpio_ext->num_addr; i++) {
+               err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
+               if (err)
+                       goto err_free_addr;
+               err = gpio_direction_output(gpio_ext->addr[i], 0);
+               if (err) {
+                       gpio_free(gpio_ext->addr[i]);
+                       goto err_free_addr;
+               }
+       }
+       /* Configure data GPIOs. */
+       for (i = 0; i < gpio_ext->num_data; i++) {
+               err = gpio_request(gpio_ext->data[i], "GPIO extension data");
+               if (err)
+                       goto err_free_data;
+               err = gpio_direction_output(gpio_ext->data[i], 0);
+               if (err) {
+                       gpio_free(gpio_ext->data[i]);
+                       goto err_free_data;
+               }
+       }
+       /* Configure "enable select" GPIO. */
+       err = gpio_request(gpio_ext->enable, "GPIO extension enable");
+       if (err)
+               goto err_free_data;
+       err = gpio_direction_output(gpio_ext->enable, 0);
+       if (err) {
+               gpio_free(gpio_ext->enable);
+               goto err_free_data;
+       }
+
+       return 0;
+
+err_free_data:
+       for (i = i - 1; i >= 0; i--)
+               gpio_free(gpio_ext->data[i]);
+       i = gpio_ext->num_addr;
+err_free_addr:
+       for (i = i - 1; i >= 0; i--)
+               gpio_free(gpio_ext->addr[i]);
+
+       return err;
+}
+
+static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext)
+{
+       int i;
+
+       gpio_free(gpio_ext->enable);
+       for (i = gpio_ext->num_addr - 1; i >= 0; i--)
+               gpio_free(gpio_ext->addr[i]);
+       for (i = gpio_ext->num_data - 1; i >= 0; i--)
+               gpio_free(gpio_ext->data[i]);
+}
+
+/*
+ * Class LED driver.
+ */
+
+struct netxbig_led_data {
+       struct netxbig_gpio_ext *gpio_ext;
+       struct led_classdev     cdev;
+       int                     mode_addr;
+       int                     *mode_val;
+       int                     bright_addr;
+       int                     bright_max;
+       struct                  netxbig_led_timer *timer;
+       int                     num_timer;
+       enum netxbig_led_mode   mode;
+       int                     sata;
+       spinlock_t              lock;
+};
+
+static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode,
+                                     unsigned long delay_on,
+                                     unsigned long delay_off,
+                                     struct netxbig_led_timer *timer,
+                                     int num_timer)
+{
+       int i;
+
+       for (i = 0; i < num_timer; i++) {
+               if (timer[i].delay_on == delay_on &&
+                   timer[i].delay_off == delay_off) {
+                       *mode = timer[i].mode;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int netxbig_led_blink_set(struct led_classdev *led_cdev,
+                                unsigned long *delay_on,
+                                unsigned long *delay_off)
+{
+       struct netxbig_led_data *led_dat =
+               container_of(led_cdev, struct netxbig_led_data, cdev);
+       enum netxbig_led_mode mode;
+       int mode_val;
+       int ret;
+
+       /* Look for a LED mode with the requested timer frequency. */
+       ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off,
+                                        led_dat->timer, led_dat->num_timer);
+       if (ret < 0)
+               return ret;
+
+       mode_val = led_dat->mode_val[mode];
+       if (mode_val == NETXBIG_LED_INVALID_MODE)
+               return -EINVAL;
+
+       spin_lock_irq(&led_dat->lock);
+
+       gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+       led_dat->mode = mode;
+
+       spin_unlock_irq(&led_dat->lock);
+
+       return 0;
+}
+
+static void netxbig_led_set(struct led_classdev *led_cdev,
+                           enum led_brightness value)
+{
+       struct netxbig_led_data *led_dat =
+               container_of(led_cdev, struct netxbig_led_data, cdev);
+       enum netxbig_led_mode mode;
+       int mode_val, bright_val;
+       int set_brightness = 1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&led_dat->lock, flags);
+
+       if (value == LED_OFF) {
+               mode = NETXBIG_LED_OFF;
+               set_brightness = 0;
+       } else {
+               if (led_dat->sata)
+                       mode = NETXBIG_LED_SATA;
+               else if (led_dat->mode == NETXBIG_LED_OFF)
+                       mode = NETXBIG_LED_ON;
+               else /* Keep 'timer' mode. */
+                       mode = led_dat->mode;
+       }
+       mode_val = led_dat->mode_val[mode];
+
+       gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+       led_dat->mode = mode;
+       /*
+        * Note that the brightness register is shared between all the
+        * SATA LEDs. So, change the brightness setting for a single
+        * SATA LED will affect all the others.
+        */
+       if (set_brightness) {
+               bright_val = DIV_ROUND_UP(value * led_dat->bright_max,
+                                         LED_FULL);
+               gpio_ext_set_value(led_dat->gpio_ext,
+                                  led_dat->bright_addr, bright_val);
+       }
+
+       spin_unlock_irqrestore(&led_dat->lock, flags);
+}
+
+static ssize_t netxbig_led_sata_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buff, size_t count)
+{
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct netxbig_led_data *led_dat =
+               container_of(led_cdev, struct netxbig_led_data, cdev);
+       unsigned long enable;
+       enum netxbig_led_mode mode;
+       int mode_val;
+       int ret;
+
+       ret = strict_strtoul(buff, 10, &enable);
+       if (ret < 0)
+               return ret;
+
+       enable = !!enable;
+
+       spin_lock_irq(&led_dat->lock);
+
+       if (led_dat->sata == enable) {
+               ret = count;
+               goto exit_unlock;
+       }
+
+       if (led_dat->mode != NETXBIG_LED_ON &&
+           led_dat->mode != NETXBIG_LED_SATA)
+               mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */
+       else if (enable)
+               mode = NETXBIG_LED_SATA;
+       else
+               mode = NETXBIG_LED_ON;
+
+       mode_val = led_dat->mode_val[mode];
+       if (mode_val == NETXBIG_LED_INVALID_MODE) {
+               ret = -EINVAL;
+               goto exit_unlock;
+       }
+
+       gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+       led_dat->mode = mode;
+       led_dat->sata = enable;
+
+       ret = count;
+
+exit_unlock:
+       spin_unlock_irq(&led_dat->lock);
+
+       return ret;
+}
+
+static ssize_t netxbig_led_sata_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct netxbig_led_data *led_dat =
+               container_of(led_cdev, struct netxbig_led_data, cdev);
+
+       return sprintf(buf, "%d\n", led_dat->sata);
+}
+
+static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
+
+static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat)
+{
+       if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
+               device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
+       led_classdev_unregister(&led_dat->cdev);
+}
+
+static int __devinit
+create_netxbig_led(struct platform_device *pdev,
+                  struct netxbig_led_data *led_dat,
+                  const struct netxbig_led *template)
+{
+       struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+       int ret;
+
+       spin_lock_init(&led_dat->lock);
+       led_dat->gpio_ext = pdata->gpio_ext;
+       led_dat->cdev.name = template->name;
+       led_dat->cdev.default_trigger = template->default_trigger;
+       led_dat->cdev.blink_set = netxbig_led_blink_set;
+       led_dat->cdev.brightness_set = netxbig_led_set;
+       /*
+        * Because the GPIO extension bus don't allow to read registers
+        * value, there is no way to probe the LED initial state.
+        * So, the initial sysfs LED value for the "brightness" and "sata"
+        * attributes are inconsistent.
+        *
+        * Note that the initial LED state can't be reconfigured.
+        * The reason is that the LED behaviour must stay uniform during
+        * the whole boot process (bootloader+linux).
+        */
+       led_dat->sata = 0;
+       led_dat->cdev.brightness = LED_OFF;
+       led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+       led_dat->mode_addr = template->mode_addr;
+       led_dat->mode_val = template->mode_val;
+       led_dat->bright_addr = template->bright_addr;
+       led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1;
+       led_dat->timer = pdata->timer;
+       led_dat->num_timer = pdata->num_timer;
+
+       ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * If available, expose the SATA activity blink capability through
+        * a "sata" sysfs attribute.
+        */
+       if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
+               ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
+               if (ret)
+                       led_classdev_unregister(&led_dat->cdev);
+       }
+
+       return ret;
+}
+
+static int __devinit netxbig_led_probe(struct platform_device *pdev)
+{
+       struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+       struct netxbig_led_data *leds_data;
+       int i;
+       int ret;
+
+       if (!pdata)
+               return -EINVAL;
+
+       leds_data = kzalloc(sizeof(struct netxbig_led_data) * pdata->num_leds,
+                           GFP_KERNEL);
+       if (!leds_data)
+               return -ENOMEM;
+
+       ret = gpio_ext_init(pdata->gpio_ext);
+       if (ret < 0)
+               goto err_free_data;
+
+       for (i = 0; i < pdata->num_leds; i++) {
+               ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]);
+               if (ret < 0)
+                       goto err_free_leds;
+       }
+
+       platform_set_drvdata(pdev, leds_data);
+
+       return 0;
+
+err_free_leds:
+       for (i = i - 1; i >= 0; i--)
+               delete_netxbig_led(&leds_data[i]);
+
+       gpio_ext_free(pdata->gpio_ext);
+err_free_data:
+       kfree(leds_data);
+
+       return ret;
+}
+
+static int __devexit netxbig_led_remove(struct platform_device *pdev)
+{
+       struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+       struct netxbig_led_data *leds_data;
+       int i;
+
+       leds_data = platform_get_drvdata(pdev);
+
+       for (i = 0; i < pdata->num_leds; i++)
+               delete_netxbig_led(&leds_data[i]);
+
+       gpio_ext_free(pdata->gpio_ext);
+       kfree(leds_data);
+
+       return 0;
+}
+
+static struct platform_driver netxbig_led_driver = {
+       .probe          = netxbig_led_probe,
+       .remove         = __devexit_p(netxbig_led_remove),
+       .driver         = {
+               .name   = "leds-netxbig",
+               .owner  = THIS_MODULE,
+       },
+};
+MODULE_ALIAS("platform:leds-netxbig");
+
+static int __init netxbig_led_init(void)
+{
+       return platform_driver_register(&netxbig_led_driver);
+}
+
+static void __exit netxbig_led_exit(void)
+{
+       platform_driver_unregister(&netxbig_led_driver);
+}
+
+module_init(netxbig_led_init);
+module_exit(netxbig_led_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
+MODULE_LICENSE("GPL");
index 74dce4ba0262560977ae88d69fbb2fbe7db62009..f77d48d0b3e484bea2d48fd76568f4aa42cce445 100644 (file)
@@ -81,7 +81,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat,
        int cmd_level;
        int slow_level;
 
-       read_lock(&led_dat->rw_lock);
+       read_lock_irq(&led_dat->rw_lock);
 
        cmd_level = gpio_get_value(led_dat->cmd);
        slow_level = gpio_get_value(led_dat->slow);
@@ -95,7 +95,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat,
                }
        }
 
-       read_unlock(&led_dat->rw_lock);
+       read_unlock_irq(&led_dat->rw_lock);
 
        return ret;
 }
@@ -104,8 +104,9 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat,
                             enum ns2_led_modes mode)
 {
        int i;
+       unsigned long flags;
 
-       write_lock(&led_dat->rw_lock);
+       write_lock_irqsave(&led_dat->rw_lock, flags);
 
        for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
                if (mode == ns2_led_modval[i].mode) {
@@ -116,7 +117,7 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat,
                }
        }
 
-       write_unlock(&led_dat->rw_lock);
+       write_unlock_irqrestore(&led_dat->rw_lock, flags);
 }
 
 static void ns2_led_set(struct led_classdev *led_cdev,
@@ -140,10 +141,12 @@ static ssize_t ns2_led_sata_store(struct device *dev,
                                  struct device_attribute *attr,
                                  const char *buff, size_t count)
 {
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct ns2_led_data *led_dat =
+               container_of(led_cdev, struct ns2_led_data, cdev);
        int ret;
        unsigned long enable;
        enum ns2_led_modes mode;
-       struct ns2_led_data *led_dat = dev_get_drvdata(dev);
 
        ret = strict_strtoul(buff, 10, &enable);
        if (ret < 0)
@@ -171,7 +174,9 @@ static ssize_t ns2_led_sata_store(struct device *dev,
 static ssize_t ns2_led_sata_show(struct device *dev,
                                 struct device_attribute *attr, char *buf)
 {
-       struct ns2_led_data *led_dat = dev_get_drvdata(dev);
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct ns2_led_data *led_dat =
+               container_of(led_cdev, struct ns2_led_data, cdev);
 
        return sprintf(buf, "%d\n", led_dat->sata);
 }
@@ -233,7 +238,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        if (ret < 0)
                goto err_free_slow;
 
-       dev_set_drvdata(led_dat->cdev.dev, led_dat);
        ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
        if (ret < 0)
                goto err_free_cdev;
index 85b714df8eae8d8ef372f74bedeb4497eab1f8d7..3c781cdddda97f52f10b7daa72d5bd41e1436fc4 100644 (file)
@@ -514,6 +514,7 @@ static const struct file_operations lguest_fops = {
        .release = close,
        .write   = write,
        .read    = read,
+       .llseek  = default_llseek,
 };
 
 /*
index 1c4ee6e77937f596378f88587787052106cd3c58..75049e765191eb6a75ec44b1670304785cba3a9e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
@@ -55,6 +54,7 @@ extern struct adb_driver adb_iop_driver;
 extern struct adb_driver via_pmu_driver;
 extern struct adb_driver macio_adb_driver;
 
+static DEFINE_MUTEX(adb_mutex);
 static struct adb_driver *adb_driver_list[] = {
 #ifdef CONFIG_ADB_MACII
        &via_macii_driver,
@@ -83,7 +83,7 @@ static struct adb_driver *adb_controller;
 BLOCKING_NOTIFIER_HEAD(adb_client_list);
 static int adb_got_sleep;
 static int adb_inited;
-static DECLARE_MUTEX(adb_probe_mutex);
+static DEFINE_SEMAPHORE(adb_probe_mutex);
 static int sleepy_trackpad;
 static int autopoll_devs;
 int __adb_probe_sync;
@@ -647,7 +647,7 @@ static int adb_open(struct inode *inode, struct file *file)
        struct adbdev_state *state;
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&adb_mutex);
        if (iminor(inode) > 0 || adb_controller == NULL) {
                ret = -ENXIO;
                goto out;
@@ -665,7 +665,7 @@ static int adb_open(struct inode *inode, struct file *file)
        state->inuse = 1;
 
 out:
-       unlock_kernel();
+       mutex_unlock(&adb_mutex);
        return ret;
 }
 
@@ -674,7 +674,7 @@ static int adb_release(struct inode *inode, struct file *file)
        struct adbdev_state *state = file->private_data;
        unsigned long flags;
 
-       lock_kernel();
+       mutex_lock(&adb_mutex);
        if (state) {
                file->private_data = NULL;
                spin_lock_irqsave(&state->lock, flags);
@@ -687,7 +687,7 @@ static int adb_release(struct inode *inode, struct file *file)
                        spin_unlock_irqrestore(&state->lock, flags);
                }
        }
-       unlock_kernel();
+       mutex_unlock(&adb_mutex);
        return 0;
 }
 
index a3d25da2f275f0fa3023f1338073ecdc717bede8..1a57e88a38f7554ef3c09199090ce52575d041ef 100644 (file)
@@ -137,6 +137,7 @@ const struct file_operations anslcd_fops = {
        .write          = anslcd_write,
        .unlocked_ioctl = anslcd_ioctl,
        .open           = anslcd_open,
+       .llseek         = default_llseek,
 };
 
 static struct miscdevice anslcd_dev = {
index e58c3d33e035e4cba5e5213417e08d9a6be91c2f..290cb325a94c8b48becedab2ffe9e363aa4dd7fa 100644 (file)
@@ -19,7 +19,6 @@
  *    the userland interface
  */
 
-#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -97,6 +96,7 @@ struct smu_device {
  * I don't think there will ever be more than one SMU, so
  * for now, just hard code that
  */
+static DEFINE_MUTEX(smu_mutex);
 static struct smu_device       *smu;
 static DEFINE_MUTEX(smu_part_access);
 static int smu_irq_inited;
@@ -1095,12 +1095,12 @@ static int smu_open(struct inode *inode, struct file *file)
        pp->mode = smu_file_commands;
        init_waitqueue_head(&pp->wait);
 
-       lock_kernel();
+       mutex_lock(&smu_mutex);
        spin_lock_irqsave(&smu_clist_lock, flags);
        list_add(&pp->list, &smu_clist);
        spin_unlock_irqrestore(&smu_clist_lock, flags);
        file->private_data = pp;
-       unlock_kernel();
+       mutex_unlock(&smu_mutex);
 
        return 0;
 }
index d242976bcfe71455b966d3a8cdfa69a7f40dbdbc..19c371809d7776f19aa2adaff75fae9b3bd7904c 100644 (file)
@@ -92,8 +92,10 @@ static int __init via_pmu_led_init(void)
        if (dt == NULL)
                return -ENODEV;
        model = of_get_property(dt, "model", NULL);
-       if (model == NULL)
+       if (model == NULL) {
+               of_node_put(dt);
                return -ENODEV;
+       }
        if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
            strncmp(model, "iBook", strlen("iBook")) != 0 &&
            strcmp(model, "PowerMac7,2") != 0 &&
index 35bc2737412fddaa3323e99ea34a3dd3de762355..cd29c8248386c124070ec2a8287bb30c31d68374 100644 (file)
@@ -18,7 +18,7 @@
  *
  */
 #include <stdarg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -45,6 +45,7 @@
 #include <linux/syscalls.h>
 #include <linux/suspend.h>
 #include <linux/cpu.h>
+#include <linux/compat.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -72,6 +73,7 @@
 /* How many iterations between battery polls */
 #define BATTERY_POLLING_COUNT  2
 
+static DEFINE_MUTEX(pmu_info_proc_mutex);
 static volatile unsigned char __iomem *via;
 
 /* VIA registers - spaced 0x200 bytes apart */
@@ -2077,7 +2079,7 @@ pmu_open(struct inode *inode, struct file *file)
        pp->rb_get = pp->rb_put = 0;
        spin_lock_init(&pp->lock);
        init_waitqueue_head(&pp->wait);
-       lock_kernel();
+       mutex_lock(&pmu_info_proc_mutex);
        spin_lock_irqsave(&all_pvt_lock, flags);
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
        pp->backlight_locker = 0;
@@ -2085,7 +2087,7 @@ pmu_open(struct inode *inode, struct file *file)
        list_add(&pp->list, &all_pmu_pvt);
        spin_unlock_irqrestore(&all_pvt_lock, flags);
        file->private_data = pp;
-       unlock_kernel();
+       mutex_unlock(&pmu_info_proc_mutex);
        return 0;
 }
 
@@ -2342,20 +2344,62 @@ static long pmu_unlocked_ioctl(struct file *filp,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&pmu_info_proc_mutex);
        ret = pmu_ioctl(filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&pmu_info_proc_mutex);
 
        return ret;
 }
 
+#ifdef CONFIG_COMPAT
+#define PMU_IOC_GET_BACKLIGHT32        _IOR('B', 1, compat_size_t)
+#define PMU_IOC_SET_BACKLIGHT32        _IOW('B', 2, compat_size_t)
+#define PMU_IOC_GET_MODEL32    _IOR('B', 3, compat_size_t)
+#define PMU_IOC_HAS_ADB32      _IOR('B', 4, compat_size_t)
+#define PMU_IOC_CAN_SLEEP32    _IOR('B', 5, compat_size_t)
+#define PMU_IOC_GRAB_BACKLIGHT32 _IOR('B', 6, compat_size_t)
+
+static long compat_pmu_ioctl (struct file *filp, u_int cmd, u_long arg)
+{
+       switch (cmd) {
+       case PMU_IOC_SLEEP:
+               break;
+       case PMU_IOC_GET_BACKLIGHT32:
+               cmd = PMU_IOC_GET_BACKLIGHT;
+               break;
+       case PMU_IOC_SET_BACKLIGHT32:
+               cmd = PMU_IOC_SET_BACKLIGHT;
+               break;
+       case PMU_IOC_GET_MODEL32:
+               cmd = PMU_IOC_GET_MODEL;
+               break;
+       case PMU_IOC_HAS_ADB32:
+               cmd = PMU_IOC_HAS_ADB;
+               break;
+       case PMU_IOC_CAN_SLEEP32:
+               cmd = PMU_IOC_CAN_SLEEP;
+               break;
+       case PMU_IOC_GRAB_BACKLIGHT32:
+               cmd = PMU_IOC_GRAB_BACKLIGHT;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return pmu_unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
 static const struct file_operations pmu_device_fops = {
        .read           = pmu_read,
        .write          = pmu_write,
        .poll           = pmu_fpoll,
        .unlocked_ioctl = pmu_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = compat_pmu_ioctl,
+#endif
        .open           = pmu_open,
        .release        = pmu_release,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice pmu_device = {
diff --git a/drivers/md/.gitignore b/drivers/md/.gitignore
deleted file mode 100644 (file)
index a7afec6..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-mktables
-raid6altivec*.c
-raid6int*.c
-raid6tables.c
index 1ba1e122e948931bf16a504ebe662e16e1404a8f..e4fb58db5454d4bfc5cc5257bb74435907b3b3f2 100644 (file)
@@ -1000,10 +1000,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
                                page = bitmap->sb_page;
                                offset = sizeof(bitmap_super_t);
                                if (!file)
-                                       read_sb_page(bitmap->mddev,
-                                                    bitmap->mddev->bitmap_info.offset,
-                                                    page,
-                                                    index, count);
+                                       page = read_sb_page(
+                                               bitmap->mddev,
+                                               bitmap->mddev->bitmap_info.offset,
+                                               page,
+                                               index, count);
                        } else if (file) {
                                page = read_page(file, index, bitmap, count);
                                offset = 0;
@@ -1542,8 +1543,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
                   atomic_read(&bitmap->mddev->recovery_active) == 0);
 
        bitmap->mddev->curr_resync_completed = bitmap->mddev->curr_resync;
-       if (bitmap->mddev->persistent)
-               set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
+       set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
        sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1);
        s = 0;
        while (s < sector && s < bitmap->mddev->resync_max_sectors) {
index 3e39193e5036e709665e08345ba242d83662c606..4b54618b4159368eed4e3febee680b2ff94724df 100644 (file)
@@ -1596,6 +1596,7 @@ static const struct file_operations _ctl_fops = {
        .unlocked_ioctl  = dm_ctl_ioctl,
        .compat_ioctl = dm_compat_ctl_ioctl,
        .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice _dm_misc = {
index ac384b2a6a3396238e9f0810cbeee52d08cd7fa7..7967eca5a2d5fdaf3a009dde0eee189437103dc9 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/blkpg.h>
 #include <linux/bio.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/mempool.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
@@ -33,6 +32,7 @@
 #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
 #define DM_COOKIE_LENGTH 24
 
+static DEFINE_MUTEX(dm_mutex);
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
@@ -344,7 +344,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
 {
        struct mapped_device *md;
 
-       lock_kernel();
+       mutex_lock(&dm_mutex);
        spin_lock(&_minor_lock);
 
        md = bdev->bd_disk->private_data;
@@ -362,7 +362,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
 
 out:
        spin_unlock(&_minor_lock);
-       unlock_kernel();
+       mutex_unlock(&dm_mutex);
 
        return md ? 0 : -ENXIO;
 }
@@ -371,10 +371,10 @@ static int dm_blk_close(struct gendisk *disk, fmode_t mode)
 {
        struct mapped_device *md = disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&dm_mutex);
        atomic_dec(&md->open_count);
        dm_put(md);
-       unlock_kernel();
+       mutex_unlock(&dm_mutex);
 
        return 0;
 }
index c148b630215484f9689bf9257d6acf286685c37a..dbf822df942a70e7fb701d80936800dca40c2cbf 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/blkdev.h>
 #include <linux/sysctl.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/poll.h>
 #include <linux/ctype.h>
@@ -57,6 +57,7 @@
 #define DEBUG 0
 #define dprintk(x...) ((void)(DEBUG && printk(x)))
 
+static DEFINE_MUTEX(md_mutex);
 
 #ifndef MODULE
 static void autostart_arrays(int part);
@@ -1643,7 +1644,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
                if (rdev->sb_size & bmask)
                        rdev->sb_size = (rdev->sb_size | bmask) + 1;
-       }
+       } else
+               max_dev = le32_to_cpu(sb->max_dev);
+
        for (i=0; i<max_dev;i++)
                sb->dev_roles[i] = cpu_to_le16(0xfffe);
        
@@ -2167,9 +2170,9 @@ repeat:
                                rdev->recovery_offset = mddev->curr_resync_completed;
 
        }       
-       if (mddev->external || !mddev->persistent) {
-               clear_bit(MD_CHANGE_DEVS, &mddev->flags);
+       if (!mddev->persistent) {
                clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
+               clear_bit(MD_CHANGE_DEVS, &mddev->flags);
                wake_up(&mddev->sb_wait);
                return;
        }
@@ -2178,7 +2181,6 @@ repeat:
 
        mddev->utime = get_seconds();
 
-       set_bit(MD_CHANGE_PENDING, &mddev->flags);
        if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags))
                force_change = 1;
        if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags))
@@ -3371,7 +3373,7 @@ array_state_show(mddev_t *mddev, char *page)
                case 0:
                        if (mddev->in_sync)
                                st = clean;
-                       else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
+                       else if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
                                st = write_pending;
                        else if (mddev->safemode)
                                st = active_idle;
@@ -3452,9 +3454,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                                        mddev->in_sync = 1;
                                        if (mddev->safemode == 1)
                                                mddev->safemode = 0;
-                                       if (mddev->persistent)
-                                               set_bit(MD_CHANGE_CLEAN,
-                                                       &mddev->flags);
+                                       set_bit(MD_CHANGE_CLEAN, &mddev->flags);
                                }
                                err = 0;
                        } else
@@ -3466,8 +3466,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
        case active:
                if (mddev->pers) {
                        restart_array(mddev);
-                       if (mddev->external)
-                               clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       clear_bit(MD_CHANGE_PENDING, &mddev->flags);
                        wake_up(&mddev->sb_wait);
                        err = 0;
                } else {
@@ -5953,7 +5952,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
        mddev_t *mddev = mddev_find(bdev->bd_dev);
        int err;
 
-       lock_kernel();
+       mutex_lock(&md_mutex);
        if (mddev->gendisk != bdev->bd_disk) {
                /* we are racing with mddev_put which is discarding this
                 * bd_disk.
@@ -5962,7 +5961,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
                /* Wait until bdev->bd_disk is definitely gone */
                flush_scheduled_work();
                /* Then retry the open from the top */
-               unlock_kernel();
+               mutex_unlock(&md_mutex);
                return -ERESTARTSYS;
        }
        BUG_ON(mddev != bdev->bd_disk->private_data);
@@ -5976,7 +5975,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
 
        check_disk_size_change(mddev->gendisk, bdev);
  out:
-       unlock_kernel();
+       mutex_unlock(&md_mutex);
        return err;
 }
 
@@ -5985,10 +5984,10 @@ static int md_release(struct gendisk *disk, fmode_t mode)
        mddev_t *mddev = disk->private_data;
 
        BUG_ON(!mddev);
-       lock_kernel();
+       mutex_lock(&md_mutex);
        atomic_dec(&mddev->openers);
        mddev_put(mddev);
-       unlock_kernel();
+       mutex_unlock(&md_mutex);
 
        return 0;
 }
@@ -6572,6 +6571,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
                if (mddev->in_sync) {
                        mddev->in_sync = 0;
                        set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       set_bit(MD_CHANGE_PENDING, &mddev->flags);
                        md_wakeup_thread(mddev->thread);
                        did_change = 1;
                }
@@ -6580,7 +6580,6 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
        if (did_change)
                sysfs_notify_dirent_safe(mddev->sysfs_state);
        wait_event(mddev->sb_wait,
-                  !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
                   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
 }
 
@@ -6616,6 +6615,7 @@ int md_allow_write(mddev_t *mddev)
        if (mddev->in_sync) {
                mddev->in_sync = 0;
                set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+               set_bit(MD_CHANGE_PENDING, &mddev->flags);
                if (mddev->safemode_delay &&
                    mddev->safemode == 0)
                        mddev->safemode = 1;
@@ -6625,7 +6625,7 @@ int md_allow_write(mddev_t *mddev)
        } else
                spin_unlock_irq(&mddev->write_lock);
 
-       if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
+       if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
                return -EAGAIN;
        else
                return 0;
@@ -6823,8 +6823,7 @@ void md_do_sync(mddev_t *mddev)
                                   atomic_read(&mddev->recovery_active) == 0);
                        mddev->curr_resync_completed =
                                mddev->curr_resync;
-                       if (mddev->persistent)
-                               set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       set_bit(MD_CHANGE_CLEAN, &mddev->flags);
                        sysfs_notify(&mddev->kobj, NULL, "sync_completed");
                }
 
@@ -7073,7 +7072,7 @@ void md_check_recovery(mddev_t *mddev)
        if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
                return;
        if ( ! (
-               (mddev->flags && !mddev->external) ||
+               (mddev->flags & ~ (1<<MD_CHANGE_PENDING)) ||
                test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
                test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
                (mddev->external == 0 && mddev->safemode == 1) ||
@@ -7103,8 +7102,7 @@ void md_check_recovery(mddev_t *mddev)
                            mddev->recovery_cp == MaxSector) {
                                mddev->in_sync = 1;
                                did_change = 1;
-                               if (mddev->persistent)
-                                       set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                               set_bit(MD_CHANGE_CLEAN, &mddev->flags);
                        }
                        if (mddev->safemode == 1)
                                mddev->safemode = 0;
index a953fe2808ae7ef17b1046b6cff6bc6276c1b8c1..3931299788dcefe14385980c584321289cedc8db 100644 (file)
@@ -140,7 +140,7 @@ struct mddev_s
        unsigned long                   flags;
 #define MD_CHANGE_DEVS 0       /* Some device status has changed */
 #define MD_CHANGE_CLEAN 1      /* transition to or from 'clean' */
-#define MD_CHANGE_PENDING 2    /* superblock update in progress */
+#define MD_CHANGE_PENDING 2    /* switch from 'clean' to 'active' in progress */
 
        int                             suspended;
        atomic_t                        active_io;
index ad83a4dcadc3ed7cafa914d2e4dcb7ef1a939fdf..0b830bbe1d8b6323bac02106c2ccc4d806e1e390 100644 (file)
@@ -1839,7 +1839,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 
                /* take from bio_init */
                bio->bi_next = NULL;
+               bio->bi_flags &= ~(BIO_POOL_MASK-1);
                bio->bi_flags |= 1 << BIO_UPTODATE;
+               bio->bi_comp_cpu = -1;
                bio->bi_rw = READ;
                bio->bi_vcnt = 0;
                bio->bi_idx = 0;
@@ -1912,7 +1914,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
                                break;
                        BUG_ON(sync_blocks < (PAGE_SIZE>>9));
-                       if (len > (sync_blocks<<9))
+                       if ((len >> 9) > sync_blocks)
                                len = sync_blocks<<9;
                }
 
index c185422ef28c8c31f1c67d0718773614a4e0fc73..faed5a332c718f0720bd87b44dbb8f09f0d5b5fb 100644 (file)
@@ -151,7 +151,8 @@ static const struct file_operations vfd_fops = {
        .owner          = THIS_MODULE,
        .open           = &display_open,
        .write          = &vfd_write,
-       .release        = &display_close
+       .release        = &display_close,
+       .llseek         = noop_llseek,
 };
 
 /* lcd character device file operations */
@@ -159,7 +160,8 @@ static const struct file_operations lcd_fops = {
        .owner          = THIS_MODULE,
        .open           = &display_open,
        .write          = &lcd_write,
-       .release        = &display_close
+       .release        = &display_close,
+       .llseek         = noop_llseek,
 };
 
 enum {
index 7e82a9df726b51ab6d90f00fc1b1fa22998c8862..7961d59f5cace91b18fc6a67fef4caea09f08265 100644 (file)
@@ -319,7 +319,7 @@ static void ir_timer_keyup(unsigned long cookie)
         * a keyup event might follow immediately after the keydown.
         */
        spin_lock_irqsave(&ir->keylock, flags);
-       if (time_is_after_eq_jiffies(ir->keyup_jiffies))
+       if (time_is_before_eq_jiffies(ir->keyup_jiffies))
                ir_keyup(ir);
        spin_unlock_irqrestore(&ir->keylock, flags);
 }
@@ -510,6 +510,13 @@ int __ir_input_register(struct input_dev *input_dev,
                   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
                        " in raw mode" : "");
 
+       /*
+        * Default delay of 250ms is too short for some protocols, expecially
+        * since the timeout is currently set to 250ms. Increase it to 500ms,
+        * to avoid wrong repetition of the keycodes.
+        */
+       input_dev->rep[REP_DELAY] = 500;
+
        return 0;
 
 out_event:
index 77b5946413c0203739d9bdcecb129e218f194356..1983cd3f39945cbbdae6ef3a6b8b6f3618ad1b47 100644 (file)
@@ -235,6 +235,7 @@ static struct file_operations lirc_fops = {
        .poll           = lirc_dev_fop_poll,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
+       .llseek         = no_llseek,
 };
 
 static int ir_lirc_register(struct input_dev *input_dev)
@@ -267,7 +268,7 @@ static int ir_lirc_register(struct input_dev *input_dev)
                        features |= LIRC_CAN_SET_SEND_CARRIER;
 
                if (ir_dev->props->s_tx_duty_cycle)
-                       features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
+                       features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
        }
 
        if (ir_dev->props->s_rx_carrier_range)
index 43094e7eccfa92ba6213115ecdab06d88b1387ec..8e0e1b1f8c87ef9f83f05ab6a564e30ddd78aa4c 100644 (file)
@@ -279,9 +279,11 @@ int ir_raw_event_register(struct input_dev *input_dev)
                        "rc%u",  (unsigned int)ir->devno);
 
        if (IS_ERR(ir->raw->thread)) {
+               int ret = PTR_ERR(ir->raw->thread);
+
                kfree(ir->raw);
                ir->raw = NULL;
-               return PTR_ERR(ir->raw->thread);
+               return ret;
        }
 
        mutex_lock(&ir_raw_handler_lock);
index 96dafc425c8e61495cd662bf7f4c11182d674e79..46d42467f9b43010739895f165ed7bfe93793137 100644 (file)
@@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d,
        char *tmp = buf;
        int i;
 
-       if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+       if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
                enabled = ir_dev->rc_tab.ir_type;
                allowed = ir_dev->props->allowed_protos;
-       } else {
+       } else if (ir_dev->raw) {
                enabled = ir_dev->raw->enabled_protocols;
                allowed = ir_raw_get_allowed_protocols();
-       }
+       } else
+               return sprintf(tmp, "[builtin]\n");
 
        IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
                   (long long)allowed,
@@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d,
        int rc, i, count = 0;
        unsigned long flags;
 
-       if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+       if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
                type = ir_dev->rc_tab.ir_type;
-       else
+       else if (ir_dev->raw)
                type = ir_dev->raw->enabled_protocols;
+       else {
+               IR_dprintk(1, "Protocol switching not supported\n");
+               return -EINVAL;
+       }
 
        while ((tmp = strsep((char **) &data, " \n")) != NULL) {
                if (!*tmp)
@@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d,
                }
        }
 
-       if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+       if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
                spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
                ir_dev->rc_tab.ir_type = type;
                spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
index 64264f7f838f29a0be7861f872f8e852bf376669..39557ad401b63fce5a892e5245fe7d6f42b83ee1 100644 (file)
@@ -19,6 +19,7 @@ static struct ir_scancode rc6_mce[] = {
 
        { 0x800f0416, KEY_PLAY },
        { 0x800f0418, KEY_PAUSE },
+       { 0x800f046e, KEY_PLAYPAUSE },
        { 0x800f0419, KEY_STOP },
        { 0x800f0417, KEY_RECORD },
 
@@ -37,6 +38,8 @@ static struct ir_scancode rc6_mce[] = {
        { 0x800f0411, KEY_VOLUMEDOWN },
        { 0x800f0412, KEY_CHANNELUP },
        { 0x800f0413, KEY_CHANNELDOWN },
+       { 0x800f043a, KEY_BRIGHTNESSUP },
+       { 0x800f0480, KEY_BRIGHTNESSDOWN },
 
        { 0x800f0401, KEY_NUMERIC_1 },
        { 0x800f0402, KEY_NUMERIC_2 },
index 899891bec352a3f20fd00975e8cadfacce4da9c7..0acf6396e068212d14bb36d240f62304d9087565 100644 (file)
@@ -163,6 +163,7 @@ static struct file_operations fops = {
        .unlocked_ioctl = lirc_dev_fop_ioctl,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
+       .llseek         = noop_llseek,
 };
 
 static int lirc_cdev_add(struct irctl *ir)
@@ -460,6 +461,8 @@ error:
 
        mutex_unlock(&lirc_dev_lock);
 
+       nonseekable_open(inode, file);
+
        return retval;
 }
 EXPORT_SYMBOL(lirc_dev_fop_open);
index ac6bb2c01a4810446451d2651df53936b57d104c..bc620e10ef77e46149f57bdf278cc8bf79d150b3 100644 (file)
@@ -120,6 +120,10 @@ static struct usb_device_id mceusb_dev_table[] = {
        { USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
        /* Philips eHome Infrared Transceiver */
        { USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+       /* Philips/Spinel plus IR transceiver for ASUS */
+       { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
+       /* Philips/Spinel plus IR transceiver for ASUS */
+       { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
        /* Realtek MCE IR Receiver */
        { USB_DEVICE(VENDOR_REALTEK, 0x0161) },
        /* SMK/Toshiba G83C0004D410 */
index a28541b2b1a219e5a2804f20201191f1ff98c953..bad2cedb8d96886cec38af4b0003c476fbdd11f9 100644 (file)
@@ -19,6 +19,7 @@ comment "Multimedia core support"
 
 config VIDEO_DEV
        tristate "Video For Linux"
+       depends on BKL # used in many drivers for ioctl handling, need to kill
        ---help---
          V4L core support for video capture and overlay devices, webcams and
          AM/FM radio cards.
index cf87051628458efd1035b172d22c40f3b3e00c8a..48e48e8af55a0584535804240d0ba7e1f26d1562 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
@@ -52,6 +52,7 @@
 } while(0)
 
 
+static DEFINE_MUTEX(dst_ca_mutex);
 static unsigned int verbose = 5;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
@@ -564,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
        void __user *arg = (void __user *)ioctl_arg;
        int result = 0;
 
-       lock_kernel();
+       mutex_lock(&dst_ca_mutex);
        dvbdev = file->private_data;
        state = (struct dst_state *)dvbdev->priv;
        p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
@@ -652,7 +653,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
        kfree (p_ca_slot_info);
        kfree (p_ca_caps);
 
-       unlock_kernel();
+       mutex_unlock(&dst_ca_mutex);
        return result;
 }
 
@@ -694,7 +695,8 @@ static const struct file_operations dst_ca_fops = {
        .open = dst_ca_open,
        .release = dst_ca_release,
        .read = dst_ca_read,
-       .write = dst_ca_write
+       .write = dst_ca_write,
+       .llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
index 0042306ea11b8539eeba3a8f41f73fd970e6e5f7..ad1f61d301e1eb9add35fe71930618fba12142b8 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
@@ -1088,13 +1087,7 @@ static int dvb_demux_do_ioctl(struct file *file,
 static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg)
 {
-       int ret;
-
-       lock_kernel();
-       ret = dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
-       unlock_kernel();
-
-       return ret;
+       return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
 }
 
 static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
@@ -1150,6 +1143,7 @@ static const struct file_operations dvb_demux_fops = {
        .open = dvb_demux_open,
        .release = dvb_demux_release,
        .poll = dvb_demux_poll,
+       .llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_demux = {
@@ -1186,13 +1180,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
 static long dvb_dvr_ioctl(struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       int ret;
-
-       lock_kernel();
-       ret = dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
-       unlock_kernel();
-
-       return ret;
+       return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
 }
 
 static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
@@ -1225,6 +1213,7 @@ static const struct file_operations dvb_dvr_fops = {
        .open = dvb_dvr_open,
        .release = dvb_dvr_release,
        .poll = dvb_dvr_poll,
+       .llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_dvr = {
index cb97e6b8543295971d30f8b21c233791a725f26e..4d0646da6087b05e02c87767232417c2b1f94d93 100644 (file)
@@ -1259,13 +1259,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
 static long dvb_ca_en50221_io_ioctl(struct file *file,
                                    unsigned int cmd, unsigned long arg)
 {
-       int ret;
-
-       lock_kernel();
-       ret = dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
-       unlock_kernel();
-
-       return ret;
+       return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
 }
 
 
@@ -1628,6 +1622,7 @@ static const struct file_operations dvb_ca_fops = {
        .open = dvb_ca_en50221_io_open,
        .release = dvb_ca_en50221_io_release,
        .poll = dvb_ca_en50221_io_poll,
+       .llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
index 4d45b7d6b3fb248f267f4754601120c591e8bcb3..970c9b8882d4445eecbc42961255d45c31486341 100644 (file)
@@ -2034,7 +2034,8 @@ static const struct file_operations dvb_frontend_fops = {
        .unlocked_ioctl = dvb_generic_ioctl,
        .poll           = dvb_frontend_poll,
        .open           = dvb_frontend_open,
-       .release        = dvb_frontend_release
+       .release        = dvb_frontend_release,
+       .llseek         = noop_llseek,
 };
 
 int dvb_register_frontend(struct dvb_adapter* dvb,
index 6c3a8a06ccab03ed30fcf4481958a1d532f7fbcf..4df42aaae7f708801663dfc3eea018ee7ed9cfc8 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dvb/net.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
@@ -1445,13 +1444,7 @@ static int dvb_net_do_ioctl(struct file *file,
 static long dvb_net_ioctl(struct file *file,
              unsigned int cmd, unsigned long arg)
 {
-       int ret;
-
-       lock_kernel();
-       ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
-       unlock_kernel();
-
-       return ret;
+       return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
 }
 
 static int dvb_net_close(struct inode *inode, struct file *file)
@@ -1475,6 +1468,7 @@ static const struct file_operations dvb_net_fops = {
        .unlocked_ioctl = dvb_net_ioctl,
        .open = dvb_generic_open,
        .release = dvb_net_close,
+       .llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_net = {
index b915c39d782f1edc994472d8788aaedc0b722b8c..f73287775953599c80062c978d73604b82dc07e0 100644 (file)
@@ -32,9 +32,9 @@
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include "dvbdev.h"
 
+static DEFINE_MUTEX(dvbdev_mutex);
 static int dvbdev_debug;
 
 module_param(dvbdev_debug, int, 0644);
@@ -68,7 +68,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
 {
        struct dvb_device *dvbdev;
 
-       lock_kernel();
+       mutex_lock(&dvbdev_mutex);
        down_read(&minor_rwsem);
        dvbdev = dvb_minors[iminor(inode)];
 
@@ -91,12 +91,12 @@ static int dvb_device_open(struct inode *inode, struct file *file)
                }
                fops_put(old_fops);
                up_read(&minor_rwsem);
-               unlock_kernel();
+               mutex_unlock(&dvbdev_mutex);
                return err;
        }
 fail:
        up_read(&minor_rwsem);
-       unlock_kernel();
+       mutex_unlock(&dvbdev_mutex);
        return -ENODEV;
 }
 
@@ -105,6 +105,7 @@ static const struct file_operations dvb_device_fops =
 {
        .owner =        THIS_MODULE,
        .open =         dvb_device_open,
+       .llseek =       noop_llseek,
 };
 
 static struct cdev dvb_device_cdev;
@@ -158,7 +159,6 @@ long dvb_generic_ioctl(struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        struct dvb_device *dvbdev = file->private_data;
-       int ret;
 
        if (!dvbdev)
                return -ENODEV;
@@ -166,11 +166,7 @@ long dvb_generic_ioctl(struct file *file,
        if (!dvbdev->kernel_ioctl)
                return -EINVAL;
 
-       lock_kernel();
-       ret = dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
-       unlock_kernel();
-
-       return ret;
+       return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
 }
 EXPORT_SYMBOL(dvb_generic_ioctl);
 
@@ -421,8 +417,10 @@ int dvb_usercopy(struct file *file,
        }
 
        /* call driver */
+       mutex_lock(&dvbdev_mutex);
        if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
                err = -EINVAL;
+       mutex_unlock(&dvbdev_mutex);
 
        if (err < 0)
                goto out;
index fe818348b8a36450357f2b19571b000afdcd873f..48397f103d326264b261506539bc1c4cee9a343d 100644 (file)
@@ -673,9 +673,6 @@ static int dib0700_probe(struct usb_interface *intf,
                        else
                                dev->props.rc.core.bulk_mode = false;
 
-                       /* Need a higher delay, to avoid wrong repeat */
-                       dev->rc_input_dev->rep[REP_DELAY] = 500;
-
                        dib0700_rc_setup(dev);
 
                        return 0;
index f634d2e784b2ce24a005b0593372b505b903e1c3..e06acd1fecb61b9f3bf2676f0a16375f9101e907 100644 (file)
@@ -940,6 +940,58 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
        return adap->fe == NULL ? -ENODEV : 0;
 }
 
+/* STK7770P */
+static struct dib7000p_config dib7770p_dib7000p_config = {
+       .output_mpeg2_in_188_bytes = 1,
+
+       .agc_config_count = 1,
+       .agc = &dib7070_agc_config,
+       .bw  = &dib7070_bw_config_12_mhz,
+       .tuner_is_baseband = 1,
+       .spur_protect = 1,
+
+       .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+       .hostbus_diversity = 1,
+       .enable_current_mirror = 1,
+       .disable_sample_and_hold = 0,
+};
+
+static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+       if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
+           p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+               dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+       else
+               dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+
+       msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+       if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+                                    &dib7770p_dib7000p_config) != 0) {
+               err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+                   __func__);
+               return -ENODEV;
+       }
+
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+               &dib7770p_dib7000p_config);
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
 /* DIB807x generic */
 static struct dibx000_agc_config dib807x_agc_config[2] = {
        {
@@ -1781,7 +1833,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
 /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) },
        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XPVR) },
        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XP) },
-       { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
+       { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) },
        { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
 /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) },
        { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV282E) },
@@ -2406,7 +2458,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                .pid_filter_count = 32,
                                .pid_filter       = stk70x0p_pid_filter,
                                .pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-                               .frontend_attach  = stk7070p_frontend_attach,
+                               .frontend_attach  = stk7770p_frontend_attach,
                                .tuner_attach     = dib7770p_tuner_attach,
 
                                DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
index 6b22ec64ab0cc69d7124bc16421309d3e9c070cd..f896337b453518e603419beedd5093a9a5f1fb16 100644 (file)
@@ -483,9 +483,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
                }
        }
        kfree(p);
-       if (fw) {
-               release_firmware(fw);
-       }
+       release_firmware(fw);
        return ret;
 }
 
index d3c2cf60de7613ff7ba44a93c811d7273d5cff07..8ffb565f0704112cb10c63edc6cafb0aed6a3cd0 100644 (file)
@@ -220,6 +220,7 @@ static const struct file_operations fdtv_ca_fops = {
        .open           = dvb_generic_open,
        .release        = dvb_generic_release,
        .poll           = fdtv_ca_io_poll,
+       .llseek         = noop_llseek,
 };
 
 static struct dvb_device fdtv_ca = {
index 2e28b973dfd3cbb1743ac48d3fb931c9d2600063..3aed0d43392152688bbe4176ebc8ee68712ab724 100644 (file)
@@ -260,6 +260,9 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad
 
 //     dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
 
+       reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
+       reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
+
        dib7000p_write_word(state, 908, reg_908);
        dib7000p_write_word(state, 909, reg_909);
 }
@@ -778,7 +781,10 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                default:
                case GUARD_INTERVAL_1_32: value *= 1; break;
        }
-       state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
+       if (state->cfg.diversity_delay == 0)
+               state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo
+       else
+               state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo
 
        /* deactive the possibility of diversity reception if extended interleaver */
        state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
index 805dd13a97ee347d3b06e517e266d2bb1de9e4d3..da17345bf5bdd66002ea64080e2c4456bfde1ca3 100644 (file)
@@ -33,6 +33,11 @@ struct dib7000p_config {
        int (*agc_control) (struct dvb_frontend *, u8 before);
 
        u8 output_mode;
+       u8 disable_sample_and_hold : 1;
+
+       u8 enable_current_mirror : 1;
+       u8 diversity_delay;
+
 };
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
index decdeda840d01158f070a2dcf8778c1c749d41a8..fd0830ed10d81cccb53b574336daa0942353b96c 100644 (file)
@@ -1,6 +1,6 @@
 config MANTIS_CORE
        tristate "Mantis/Hopper PCI bridge based devices"
-       depends on PCI && I2C && INPUT
+       depends on PCI && I2C && INPUT && IR_CORE
 
        help
          Support for PCI cards based on the Mantis and Hopper PCi bridge.
index d93468cd3a85e1a5a3d8eee586c7ec29b69d3051..ff3b0fa901b39f00e23250e20dda2502fbb42e04 100644 (file)
@@ -1098,33 +1098,26 @@ EXPORT_SYMBOL_GPL(smscore_onresponse);
  *
  * @return pointer to descriptor on success, NULL on error.
  */
-struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+
+struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
 {
        struct smscore_buffer_t *cb = NULL;
        unsigned long flags;
 
-       DEFINE_WAIT(wait);
-
        spin_lock_irqsave(&coredev->bufferslock, flags);
-
-       /* This function must return a valid buffer, since the buffer list is
-        * finite, we check that there is an available buffer, if not, we wait
-        * until such buffer become available.
-        */
-
-       prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
-       if (list_empty(&coredev->buffers)) {
-               spin_unlock_irqrestore(&coredev->bufferslock, flags);
-               schedule();
-               spin_lock_irqsave(&coredev->bufferslock, flags);
+       if (!list_empty(&coredev->buffers)) {
+               cb = (struct smscore_buffer_t *) coredev->buffers.next;
+               list_del(&cb->entry);
        }
+       spin_unlock_irqrestore(&coredev->bufferslock, flags);
+       return cb;
+}
 
-       finish_wait(&coredev->buffer_mng_waitq, &wait);
-
-       cb = (struct smscore_buffer_t *) coredev->buffers.next;
-       list_del(&cb->entry);
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+       struct smscore_buffer_t *cb = NULL;
 
-       spin_unlock_irqrestore(&coredev->bufferslock, flags);
+       wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
 
        return cb;
 }
index a6be529eec5ca72e3dd8f965e334b956b4911557..893fbc57c72f59a6b3e1c8e2d58fff86031bed5c 100644 (file)
@@ -730,6 +730,7 @@ static const struct file_operations dvb_osd_fops = {
        .unlocked_ioctl = dvb_generic_ioctl,
        .open           = dvb_generic_open,
        .release        = dvb_generic_release,
+       .llseek         = noop_llseek,
 };
 
 static struct dvb_device dvbdev_osd = {
index 13efba942dac42579eafb43870ee3fc5d85082c9..6ef3996565adb3455b3cd4d141d9f2d25106ce01 100644 (file)
@@ -1521,6 +1521,7 @@ static const struct file_operations dvb_video_fops = {
        .open           = dvb_video_open,
        .release        = dvb_video_release,
        .poll           = dvb_video_poll,
+       .llseek         = noop_llseek,
 };
 
 static struct dvb_device dvbdev_video = {
@@ -1539,6 +1540,7 @@ static const struct file_operations dvb_audio_fops = {
        .open           = dvb_audio_open,
        .release        = dvb_audio_release,
        .poll           = dvb_audio_poll,
+       .llseek         = noop_llseek,
 };
 
 static struct dvb_device dvbdev_audio = {
index 4eba35a018e3de051db314ea573e9400ff2fd816..43f61f2eca986a7542c6f5d827fc4a0fdf815df1 100644 (file)
@@ -353,6 +353,7 @@ static const struct file_operations dvb_ca_fops = {
        .open           = dvb_ca_open,
        .release        = dvb_generic_release,
        .poll           = dvb_ca_poll,
+       .llseek         = default_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
index b070e88d8c6b3b7e14ae83dad807f2d33b259b1f..908f272fe26cc0b1c6ad8c4517c8342b1a94a44a 100644 (file)
@@ -312,6 +312,7 @@ static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer
 static const struct file_operations av7110_ir_proc_fops = {
        .owner          = THIS_MODULE,
        .write          = av7110_ir_proc_write,
+       .llseek         = noop_llseek,
 };
 
 /* interrupt handler */
index 67a4ec8768a6145ecfd6fb1d44095bfb51f29fdc..4ce541a5eb47558f5b26dc9bd14523e937c5cfaf 100644 (file)
@@ -395,7 +395,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
        radio->registers[POWERCFG] = POWERCFG_ENABLE;
        if (si470x_set_register(radio, POWERCFG) < 0) {
                retval = -EIO;
-               goto err_all;
+               goto err_video;
        }
        msleep(110);
 
index 755dd0ce65ff724f2fd479f502e314e0cabf236e..6f2b57384488b3bb8124eed072217ef8ecf3194b 100644 (file)
@@ -11,4 +11,5 @@ EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
 
index 6bdc0ef18119716dadc5facc2347f22fda5c6192..f2a4900014bc5c1dace49615b123cb86184ba814 100644 (file)
@@ -32,6 +32,7 @@
 #include <media/v4l2-chip-ident.h>
 
 #include <media/cx25840.h>
+#include "dvb-usb-ids.h"
 #include "xc5000.h"
 
 #include "cx231xx.h"
@@ -175,6 +176,8 @@ struct usb_device_id cx231xx_id_table[] = {
         .driver_info = CX231XX_BOARD_CNXT_RDE_250},
        {USB_DEVICE(0x0572, 0x58A1),
         .driver_info = CX231XX_BOARD_CNXT_RDU_250},
+       {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff),
+        .driver_info = CX231XX_BOARD_UNKNOWN},
        {},
 };
 
@@ -226,14 +229,16 @@ void cx231xx_pre_card_setup(struct cx231xx *dev)
                     dev->board.name, dev->model);
 
        /* set the direction for GPIO pins */
-       cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
-       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
-       cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
+       if (dev->board.tuner_gpio) {
+               cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
+               cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
+               cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
 
-       /* request some modules if any required */
+               /* request some modules if any required */
 
-       /* reset the Tuner */
-       cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+               /* reset the Tuner */
+               cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+       }
 
        /* set the mode to Analog mode initially */
        cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
index 86ca8c2359dd8bb409cadd434dc951a17ff170a9..f5a3e74c3c7cc0e6e52ebec222b28604e7cf53ef 100644 (file)
@@ -1996,7 +1996,7 @@ static int cx25840_probe(struct i2c_client *client,
 
                state->volume = v4l2_ctrl_new_std(&state->hdl,
                        &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
-                       0, 65335, 65535 / 100, default_volume);
+                       0, 65535, 65535 / 100, default_volume);
                state->mute = v4l2_ctrl_new_std(&state->hdl,
                        &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
                        0, 1, 1, 0);
index 99dbae1175919befc55ae7e2e00a3a524f666053..0fa85cbefbb12ffbe1e5729581ce6544dbadcfce 100644 (file)
@@ -17,7 +17,7 @@ config VIDEO_CX88
 
 config VIDEO_CX88_ALSA
        tristate "Conexant 2388x DMA audio support"
-       depends on VIDEO_CX88 && SND && EXPERIMENTAL
+       depends on VIDEO_CX88 && SND
        select SND_PCM
        ---help---
          This is a video4linux driver for direct (DMA) audio on
index 5b176bd7afdbffea7eb94f52bcb50d07b6c74170..f3e25e91366d2b171a72f6ac20d50d4c4233f39b 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
@@ -621,7 +620,6 @@ static int dabusb_open (struct inode *inode, struct file *file)
        if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
                return -EIO;
 
-       lock_kernel();
        s = &dabusb[devnum - DABUSB_MINOR];
 
        dbg("dabusb_open");
@@ -630,21 +628,17 @@ static int dabusb_open (struct inode *inode, struct file *file)
        while (!s->usbdev || s->opened) {
                mutex_unlock(&s->mutex);
 
-               if (file->f_flags & O_NONBLOCK) {
+               if (file->f_flags & O_NONBLOCK)
                        return -EBUSY;
-               }
                msleep_interruptible(500);
 
-               if (signal_pending (current)) {
-                       unlock_kernel();
+               if (signal_pending (current))
                        return -EAGAIN;
-               }
                mutex_lock(&s->mutex);
        }
        if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
                mutex_unlock(&s->mutex);
                dev_err(&s->usbdev->dev, "set_interface failed\n");
-               unlock_kernel();
                return -EINVAL;
        }
        s->opened = 1;
@@ -654,7 +648,6 @@ static int dabusb_open (struct inode *inode, struct file *file)
        file->private_data = s;
 
        r = nonseekable_open(inode, file);
-       unlock_kernel();
        return r;
 }
 
@@ -689,17 +682,13 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
 
        dbg("dabusb_ioctl");
 
-       lock_kernel();
-       if (s->remove_pending) {
-               unlock_kernel();
+       if (s->remove_pending)
                return -EIO;
-       }
 
        mutex_lock(&s->mutex);
 
        if (!s->usbdev) {
                mutex_unlock(&s->mutex);
-               unlock_kernel();
                return -EIO;
        }
 
@@ -735,7 +724,6 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
                break;
        }
        mutex_unlock(&s->mutex);
-       unlock_kernel();
        return ret;
 }
 
index b9846106913eb4871f429924092dd27563f0f115..78abc1c1f9d52766704af26c0ec3769cd08f9198 100644 (file)
@@ -223,6 +223,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
                usb_rcvintpipe(dev, ep->bEndpointAddress),
                buffer, buffer_len,
                int_irq, (void *)gspca_dev, interval);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
        gspca_dev->int_urb = urb;
        ret = usb_submit_urb(urb, GFP_KERNEL);
        if (ret < 0) {
index 83a718f0f3f9841b8412c34967f41476040398e0..9052d5702556539fbf77dbd8cf1da66e5d87bdc4 100644 (file)
@@ -2357,8 +2357,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                            (data[33] << 10);
                avg_lum >>= 9;
                atomic_set(&sd->avg_lum, avg_lum);
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               data, len);
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
                return;
        }
        if (gspca_dev->last_packet_type == LAST_PACKET) {
index be03a712731c3b61a249d607927fb852f0517881..f0316d02f09f6df1297a6f3e5e6ed4e0c1b8ff1f 100644 (file)
@@ -466,6 +466,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
                        struct fb_vblank vblank;
                        u32 trace;
 
+                       memset(&vblank, 0, sizeof(struct fb_vblank));
+
                        vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
                                        FB_VBLANK_HAVE_VSYNC;
                        trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
index 4525335f9bd416388484cbc5872ea0db3c3af768..a7210d981388e8c4724f524e3fd5c77bbd672dca 100644 (file)
@@ -239,7 +239,7 @@ static int device_process(struct m2mtest_ctx *ctx,
                return -EFAULT;
        }
 
-       if (in_buf->vb.size < out_buf->vb.size) {
+       if (in_buf->vb.size > out_buf->vb.size) {
                v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
                return -EINVAL;
        }
@@ -1014,6 +1014,7 @@ static int m2mtest_remove(struct platform_device *pdev)
        v4l2_m2m_release(dev->m2m_dev);
        del_timer_sync(&dev->timer);
        video_unregister_device(dev->vfd);
+       video_device_release(dev->vfd);
        v4l2_device_unregister(&dev->v4l2_dev);
        kfree(dev);
 
index 758a4db27d65651481eec16b970f755a9036f622..c71af4e0e517f61631b1cc936021104dbcd30f92 100644 (file)
@@ -447,6 +447,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
                __func__, rect.left, rect.top, rect.width, rect.height);
 
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        ret = mt9m111_make_rect(client, &rect);
        if (!ret)
                mt9m111->rect = rect;
@@ -466,12 +469,14 @@ static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 
 static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        a->bounds.left                  = MT9M111_MIN_DARK_COLS;
        a->bounds.top                   = MT9M111_MIN_DARK_ROWS;
        a->bounds.width                 = MT9M111_MAX_WIDTH;
        a->bounds.height                = MT9M111_MAX_HEIGHT;
        a->defrect                      = a->bounds;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
        a->pixelaspect.denominator      = 1;
 
@@ -487,6 +492,7 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
        mf->width       = mt9m111->rect.width;
        mf->height      = mt9m111->rect.height;
        mf->code        = mt9m111->fmt->code;
+       mf->colorspace  = mt9m111->fmt->colorspace;
        mf->field       = V4L2_FIELD_NONE;
 
        return 0;
index e7cd23cd63941ecb3380243f623960cf91c8ea31..b48473c7896b4b31d6d816ac544be70e6a1ac3c7 100644 (file)
@@ -402,9 +402,6 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
                if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
                        return -EINVAL;
                break;
-       case 0:
-               /* No format change, only geometry */
-               break;
        default:
                return -EINVAL;
        }
index 66ff174151b5f3d909022fbc096f8c432e6f65f4..b6ea67221d1d5fc64594348f49715539c19f9840 100644 (file)
@@ -378,6 +378,9 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
 
        spin_lock_irqsave(&pcdev->lock, flags);
 
+       if (*fb_active == NULL)
+               goto out;
+
        vb = &(*fb_active)->vb;
        dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
@@ -402,6 +405,7 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
 
        *fb_active = buf;
 
+out:
        spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
index 1b992b847198a486bc0eb62342d3d1b020c99919..55ea914c7fcd3e0a21a17671ef68294831b4a567 100644 (file)
@@ -513,7 +513,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
                        if (ret >= 0) {
                                ret = pvr2_ctrl_range_check(cptr,*valptr);
                        }
-                       if (maskptr) *maskptr = ~0;
+                       *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bool) {
                        ret = parse_token(ptr,len,valptr,boolNames,
                                          ARRAY_SIZE(boolNames));
@@ -522,7 +522,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
                        } else if (ret == 0) {
                                *valptr = (*valptr & 1) ? !0 : 0;
                        }
-                       if (maskptr) *maskptr = 1;
+                       *maskptr = 1;
                } else if (cptr->info->type == pvr2_ctl_enum) {
                        ret = parse_token(
                                ptr,len,valptr,
@@ -531,7 +531,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
                        if (ret >= 0) {
                                ret = pvr2_ctrl_range_check(cptr,*valptr);
                        }
-                       if (maskptr) *maskptr = ~0;
+                       *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bitmask) {
                        ret = parse_tlist(
                                ptr,len,maskptr,valptr,
index b151c7be8a506b18ae1ff544de0ba604f7e05e8f..6961c55baf9b1140609dd470b4abc3e05eed86c3 100644 (file)
@@ -393,6 +393,37 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx)
        dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
 }
 
+static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
+{
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+
+       f->dma_offset.y_h = f->offs_h;
+       if (!variant->pix_hoff)
+               f->dma_offset.y_h *= (f->fmt->depth >> 3);
+
+       f->dma_offset.y_v = f->offs_v;
+
+       f->dma_offset.cb_h = f->offs_h;
+       f->dma_offset.cb_v = f->offs_v;
+
+       f->dma_offset.cr_h = f->offs_h;
+       f->dma_offset.cr_v = f->offs_v;
+
+       if (!variant->pix_hoff) {
+               if (f->fmt->planes_cnt == 3) {
+                       f->dma_offset.cb_h >>= 1;
+                       f->dma_offset.cr_h >>= 1;
+               }
+               if (f->fmt->color == S5P_FIMC_YCBCR420) {
+                       f->dma_offset.cb_v >>= 1;
+                       f->dma_offset.cr_v >>= 1;
+               }
+       }
+
+       dbg("in_offset: color= %d, y_h= %d, y_v= %d",
+           f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
+}
+
 /**
  * fimc_prepare_config - check dimensions, operation and color mode
  *                      and pre-calculate offset and the scaling coefficients.
@@ -406,7 +437,6 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
 {
        struct fimc_frame *s_frame, *d_frame;
        struct fimc_vid_buffer *buf = NULL;
-       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
        int ret = 0;
 
        s_frame = &ctx->s_frame;
@@ -419,61 +449,16 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
                        swap(d_frame->width, d_frame->height);
                }
 
-               /* Prepare the output offset ratios for scaler. */
-               d_frame->dma_offset.y_h = d_frame->offs_h;
-               if (!variant->pix_hoff)
-                       d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3);
-
-               d_frame->dma_offset.y_v = d_frame->offs_v;
-
-               d_frame->dma_offset.cb_h = d_frame->offs_h;
-               d_frame->dma_offset.cb_v = d_frame->offs_v;
-
-               d_frame->dma_offset.cr_h = d_frame->offs_h;
-               d_frame->dma_offset.cr_v = d_frame->offs_v;
+               /* Prepare the DMA offset ratios for scaler. */
+               fimc_prepare_dma_offset(ctx, &ctx->s_frame);
+               fimc_prepare_dma_offset(ctx, &ctx->d_frame);
 
-               if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) {
-                       d_frame->dma_offset.cb_h >>= 1;
-                       d_frame->dma_offset.cb_v >>= 1;
-                       d_frame->dma_offset.cr_h >>= 1;
-                       d_frame->dma_offset.cr_v >>= 1;
-               }
-
-               dbg("out offset: color= %d, y_h= %d, y_v= %d",
-                       d_frame->fmt->color,
-                       d_frame->dma_offset.y_h, d_frame->dma_offset.y_v);
-
-               /* Prepare the input offset ratios for scaler. */
-               s_frame->dma_offset.y_h = s_frame->offs_h;
-               if (!variant->pix_hoff)
-                       s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3);
-               s_frame->dma_offset.y_v = s_frame->offs_v;
-
-               s_frame->dma_offset.cb_h = s_frame->offs_h;
-               s_frame->dma_offset.cb_v = s_frame->offs_v;
-
-               s_frame->dma_offset.cr_h = s_frame->offs_h;
-               s_frame->dma_offset.cr_v = s_frame->offs_v;
-
-               if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) {
-                       s_frame->dma_offset.cb_h >>= 1;
-                       s_frame->dma_offset.cb_v >>= 1;
-                       s_frame->dma_offset.cr_h >>= 1;
-                       s_frame->dma_offset.cr_v >>= 1;
-               }
-
-               dbg("in offset: color= %d, y_h= %d, y_v= %d",
-                       s_frame->fmt->color, s_frame->dma_offset.y_h,
-                       s_frame->dma_offset.y_v);
-
-               fimc_set_yuv_order(ctx);
-
-               /* Check against the scaler ratio. */
                if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
                    s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
                        err("out of scaler range");
                        return -EINVAL;
                }
+               fimc_set_yuv_order(ctx);
        }
 
        /* Input DMA mode is not allowed when the scaler is disabled. */
@@ -822,7 +807,8 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
        } else {
                v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
                         "Wrong buffer/video queue type (%d)\n", f->type);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto s_fmt_out;
        }
 
        pix = &f->fmt.pix;
@@ -1414,8 +1400,10 @@ static int fimc_probe(struct platform_device *pdev)
        }
 
        fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
-       if (!fimc->work_queue)
+       if (!fimc->work_queue) {
+               ret = -ENOMEM;
                goto err_irq;
+       }
 
        ret = fimc_register_m2m_device(fimc);
        if (ret)
@@ -1492,6 +1480,7 @@ static struct samsung_fimc_variant fimc2_variant_s5p = {
 };
 
 static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
+       .pix_hoff       = 1,
        .has_inp_rot    = 1,
        .has_out_rot    = 1,
        .min_inp_pixsize = 16,
@@ -1506,6 +1495,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
 };
 
 static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+       .pix_hoff        = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 32,
 
index ec697fcd406ede6b23c9691ceb5d0fe1fc0134a4..bb8d83d8ddafbd79dd892e971e6d8152f5483a37 100644 (file)
@@ -4323,13 +4323,13 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
                /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV Columbus TVFM",
+               /* Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV Columbus TV/FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_ALPS_TSBE5_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0xc2 >> 1,
+               .radio_addr     = 0xc0 >> 1,
                .tda9887_conf   = TDA9887_PRESENT,
                .gpiomask       = 0x000A8004,
                .inputs         = {{
index 5713f3a4b76c952bf9b1db333bb547caf3e40376..ddd25d32723dc0436f2477a641afaa0d75d9f2d3 100644 (file)
@@ -136,10 +136,11 @@ ret:
 int saa7164_buffer_dealloc(struct saa7164_tsport *port,
        struct saa7164_buffer *buf)
 {
-       struct saa7164_dev *dev = port->dev;
+       struct saa7164_dev *dev;
 
-       if ((buf == 0) || (port == 0))
+       if (!buf || !port)
                return SAA_ERR_BAD_PARAMETER;
+       dev = port->dev;
 
        dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf);
 
index 8bdd940f32e689c5b51a94ec8975014567d9f00c..2ac85d8984f025cb0ec9933f87bf00e91bf656dd 100644 (file)
@@ -486,6 +486,12 @@ static int uvc_parse_format(struct uvc_device *dev,
                            max(frame->dwFrameInterval[0],
                                frame->dwDefaultFrameInterval));
 
+               if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
+                       frame->bFrameIntervalType = 1;
+                       frame->dwFrameInterval[0] =
+                               frame->dwDefaultFrameInterval;
+               }
+
                uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
                        frame->wWidth, frame->wHeight,
                        10000000/frame->dwDefaultFrameInterval,
@@ -2026,6 +2032,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0 },
+       /* Chicony CNF7129 (Asus EEE 100HE) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x04f2,
+         .idProduct            = 0xb071,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_RESTRICT_FRAME_RATE },
        /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2091,6 +2106,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX
                                | UVC_QUIRK_PROBE_DEF },
+       /* IMC Networks (Medion Akoya) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x13d3,
+         .idProduct            = 0x5103,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
        /* Syntek (HP Spartan) */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
index bdacf3beabf54fcbe1f9f901692a0134e6b48ed1..892e0e51916c31853d9e8fa681ecce27e75edc53 100644 (file)
@@ -182,6 +182,7 @@ struct uvc_xu_control {
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
 #define UVC_QUIRK_FIX_BANDWIDTH                0x00000080
 #define UVC_QUIRK_PROBE_DEF            0x00000100
+#define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED                0x00000001
index 073f01390cdd0a00de7e34dc7cd30360b72912c4..86294ed35c9b643cc7bab7411904476d0f7467a7 100644 (file)
@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
 struct video_code32 {
        char            loadwhat[16];   /* name or tag of file being passed */
        compat_int_t    datasize;
-       unsigned char   *data;
+       compat_uptr_t   data;
 };
 
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
-               copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
-               get_user(kp->datasize, &up->datasize) ||
-               copy_from_user(kp->data, up->data, up->datasize))
-                       return -EFAULT;
-       return 0;
+       struct video_code __user *up;
+
+       up = compat_alloc_user_space(sizeof(*up));
+
+       /*
+        * NOTE! We don't actually care if these fail. If the
+        * user address is invalid, the native ioctl will do
+        * the error handling for us
+        */
+       (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
+       (void) put_user(kp->datasize, &up->datasize);
+       (void) put_user(compat_ptr(kp->data), &up->data);
+       return up;
 }
 
 #define VIDIOCGTUNER32         _IOWR('v', 4, struct video_tuner32)
@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct video_tuner vt;
                struct video_buffer vb;
                struct video_window vw;
-               struct video_code vc;
+               struct video_code32 vc;
                struct video_audio va;
 #endif
                struct v4l2_format v2f;
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                break;
 
        case VIDIOCSMICROCODE:
-               err = get_microcode32(&karg.vc, up);
-               compatible_arg = 0;
+               /* Copy the 32-bit "video_code32" to kernel space */
+               if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
+                       return -EFAULT;
+               /* Convert the 32-bit version to a 64-bit version in user space */
+               up = get_microcode32(&karg.vc);
                break;
 
        case VIDIOCSFREQ:
index 372b87efcd0538ec6c91c1bb45749177294f7442..6ff9e4bac3ea14fd6248bf07e1dfc6109fe43d27 100644 (file)
@@ -393,8 +393,10 @@ void videobuf_dma_contig_free(struct videobuf_queue *q,
        }
 
        /* read() method */
-       dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
-       mem->vaddr = NULL;
+       if (mem->vaddr) {
+               dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
+               mem->vaddr = NULL;
+       }
 }
 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
 
index 06f9a9c2a39add9256a58850d0cf5c4b0c52bf5b..2ad0bc252b0eaed1612ddaac477d21f6d7033b0c 100644 (file)
@@ -94,7 +94,7 @@ err:
  * must free the memory.
  */
 static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
-                                               int nr_pages, int offset)
+                                       int nr_pages, int offset, size_t size)
 {
        struct scatterlist *sglist;
        int i;
@@ -110,12 +110,14 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
                /* DMA to highmem pages might not work */
                goto highmem;
        sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
+       size -= PAGE_SIZE - offset;
        for (i = 1; i < nr_pages; i++) {
                if (NULL == pages[i])
                        goto nopage;
                if (PageHighMem(pages[i]))
                        goto highmem;
-               sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0);
+               sg_set_page(&sglist[i], pages[i], min(PAGE_SIZE, size), 0);
+               size -= min(PAGE_SIZE, size);
        }
        return sglist;
 
@@ -170,7 +172,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 
        first = (data          & PAGE_MASK) >> PAGE_SHIFT;
        last  = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
-       dma->offset   = data & ~PAGE_MASK;
+       dma->offset = data & ~PAGE_MASK;
+       dma->size = size;
        dma->nr_pages = last-first+1;
        dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL);
        if (NULL == dma->pages)
@@ -252,7 +255,7 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
 
        if (dma->pages) {
                dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
-                                                  dma->offset);
+                                                  dma->offset, dma->size);
        }
        if (dma->vaddr) {
                dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr,
index d3f1a087ecedf8545d4e765716a79c94406f6458..02362eccc58866e1757f63c3776ec7993de4c3d4 100644 (file)
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/memstick.h>
 
 #define DRIVER_NAME "mspro_block"
 
+static DEFINE_MUTEX(mspro_block_mutex);
 static int major;
 module_param(major, int, 0644);
 
@@ -180,7 +181,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
        struct mspro_block_data *msb = disk->private_data;
        int rc = -ENXIO;
 
-       lock_kernel();
+       mutex_lock(&mspro_block_mutex);
        mutex_lock(&mspro_block_disk_lock);
 
        if (msb && msb->card) {
@@ -192,7 +193,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
        }
 
        mutex_unlock(&mspro_block_disk_lock);
-       unlock_kernel();
+       mutex_unlock(&mspro_block_mutex);
 
        return rc;
 }
@@ -225,9 +226,9 @@ static int mspro_block_disk_release(struct gendisk *disk)
 static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
 {
        int ret;
-       lock_kernel();
+       mutex_lock(&mspro_block_mutex);
        ret = mspro_block_disk_release(disk);
-       unlock_kernel();
+       mutex_unlock(&mspro_block_mutex);
        return ret;
 }
 
index d8ddfdf8be14927c3e7a412355077b86ace48262..a3856ed90aef7ce7c6953f2303581b03bddb3e3c 100644 (file)
@@ -54,7 +54,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>       /* for mdelay */
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <asm/io.h>
@@ -83,6 +83,7 @@ MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+static DEFINE_MUTEX(mpctl_mutex);
 static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
 static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
 
@@ -601,12 +602,12 @@ mptctl_fasync(int fd, struct file *filep, int mode)
        MPT_ADAPTER     *ioc;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&mpctl_mutex);
        list_for_each_entry(ioc, &ioc_list, list)
                ioc->aen_event_read_flag=0;
 
        ret = fasync_helper(fd, filep, mode, &async_queue);
-       unlock_kernel();
+       mutex_unlock(&mpctl_mutex);
        return ret;
 }
 
@@ -698,9 +699,9 @@ static long
 mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&mpctl_mutex);
        ret = __mptctl_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&mpctl_mutex);
        return ret;
 }
 
@@ -2926,7 +2927,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
 static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&mpctl_mutex);
        switch (cmd) {
        case MPTIOCINFO:
        case MPTIOCINFO1:
@@ -2951,7 +2952,7 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a
                ret = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&mpctl_mutex);
        return ret;
 }
 
index f0f1e667000f30b8769587d9036a36b4b4c3b715..f87a9d405a5e2f9de35cd5a917f43922adf135ec 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2o.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <linux/mempool.h>
 
@@ -69,6 +69,7 @@
 #define OSM_VERSION    "1.325"
 #define OSM_DESCRIPTION        "I2O Block Device OSM"
 
+static DEFINE_MUTEX(i2o_block_mutex);
 static struct i2o_driver i2o_block_driver;
 
 /* global Block OSM request mempool */
@@ -578,7 +579,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode)
        if (!dev->i2o_dev)
                return -ENODEV;
 
-       lock_kernel();
+       mutex_lock(&i2o_block_mutex);
        if (dev->power > 0x1f)
                i2o_block_device_power(dev, 0x02);
 
@@ -587,7 +588,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode)
        i2o_block_device_lock(dev->i2o_dev, -1);
 
        osm_debug("Ready.\n");
-       unlock_kernel();
+       mutex_unlock(&i2o_block_mutex);
 
        return 0;
 };
@@ -618,7 +619,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
        if (!dev->i2o_dev)
                return 0;
 
-       lock_kernel();
+       mutex_lock(&i2o_block_mutex);
        i2o_block_device_flush(dev->i2o_dev);
 
        i2o_block_device_unlock(dev->i2o_dev, -1);
@@ -629,7 +630,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
                operation = 0x24;
 
        i2o_block_device_power(dev, operation);
-       unlock_kernel();
+       mutex_unlock(&i2o_block_mutex);
 
        return 0;
 }
@@ -664,7 +665,7 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       lock_kernel();
+       mutex_lock(&i2o_block_mutex);
        switch (cmd) {
        case BLKI2OGRSTRAT:
                ret = put_user(dev->rcache, (int __user *)arg);
@@ -688,7 +689,7 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
                ret = 0;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&i2o_block_mutex);
 
        return ret;
 };
index 068ba0785bb4e1eaa3db77fcc0fd84bd7cbd6f67..7d3cc575c36167a436b43052b11942b3e0f80ac7 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
 
@@ -41,6 +41,7 @@
 
 #define SG_TABLESIZE           30
 
+static DEFINE_MUTEX(i2o_cfg_mutex);
 static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
 
 static spinlock_t i2o_config_lock;
@@ -741,7 +742,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
                                 unsigned long arg)
 {
        int ret;
-       lock_kernel();
+       mutex_lock(&i2o_cfg_mutex);
        switch (cmd) {
        case I2OGETIOPS:
                ret = i2o_cfg_ioctl(file, cmd, arg);
@@ -753,7 +754,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
                ret = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&i2o_cfg_mutex);
        return ret;
 }
 
@@ -981,7 +982,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&i2o_cfg_mutex);
        switch (cmd) {
        case I2OGETIOPS:
                ret = i2o_cfg_getiops(arg);
@@ -1037,7 +1038,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                osm_debug("unknown ioctl called!\n");
                ret = -EINVAL;
        }
-       unlock_kernel();
+       mutex_unlock(&i2o_cfg_mutex);
        return ret;
 }
 
@@ -1051,7 +1052,7 @@ static int cfg_open(struct inode *inode, struct file *file)
        if (!tmp)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&i2o_cfg_mutex);
        file->private_data = (void *)(i2o_cfg_info_id++);
        tmp->fp = file;
        tmp->fasync = NULL;
@@ -1065,7 +1066,7 @@ static int cfg_open(struct inode *inode, struct file *file)
        spin_lock_irqsave(&i2o_config_lock, flags);
        open_files = tmp;
        spin_unlock_irqrestore(&i2o_config_lock, flags);
-       unlock_kernel();
+       mutex_unlock(&i2o_cfg_mutex);
 
        return 0;
 }
@@ -1076,14 +1077,14 @@ static int cfg_fasync(int fd, struct file *fp, int on)
        struct i2o_cfg_info *p;
        int ret = -EBADF;
 
-       lock_kernel();
+       mutex_lock(&i2o_cfg_mutex);
        for (p = open_files; p; p = p->next)
                if (p->q_id == id)
                        break;
 
        if (p)
                ret = fasync_helper(fd, fp, on, &p->fasync);
-       unlock_kernel();
+       mutex_unlock(&i2o_cfg_mutex);
        return ret;
 }
 
@@ -1093,7 +1094,7 @@ static int cfg_release(struct inode *inode, struct file *file)
        struct i2o_cfg_info *p, **q;
        unsigned long flags;
 
-       lock_kernel();
+       mutex_lock(&i2o_cfg_mutex);
        spin_lock_irqsave(&i2o_config_lock, flags);
        for (q = &open_files; (p = *q) != NULL; q = &p->next) {
                if (p->q_id == id) {
@@ -1103,7 +1104,7 @@ static int cfg_release(struct inode *inode, struct file *file)
                }
        }
        spin_unlock_irqrestore(&i2o_config_lock, flags);
-       unlock_kernel();
+       mutex_unlock(&i2o_cfg_mutex);
 
        return 0;
 }
index 66379b413906a3ed5147370040ed7ccffd0b5068..b048ecc56db9ca75ad79f1ebf63c75181344fc43 100644 (file)
@@ -583,6 +583,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
 static const struct file_operations ab3100_get_set_reg_fops = {
        .open = ab3100_get_set_reg_open_file,
        .write = ab3100_get_set_reg,
+       .llseek = noop_llseek,
 };
 
 static struct dentry *ab3100_dir;
index e1c8b62b086d506ef46d8a52ccb6d5c4d73e0a18..01b6d584442cdcf686c8c4f643193b9c51360e4a 100644 (file)
@@ -83,6 +83,11 @@ static int __devinit ab8500_spi_probe(struct spi_device *spi)
        struct ab8500 *ab8500;
        int ret;
 
+       spi->bits_per_word = 24;
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
        ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
        if (!ab8500)
                return -ENOMEM;
index 04028a9ee082735278557b606840619ade7e29a9..428377a5a6f56fe94ca033730a49102f19164dd2 100644 (file)
@@ -429,24 +429,25 @@ static void max8925_irq_sync_unlock(unsigned int irq)
        irq_tsc = cache_tsc;
        for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
                irq_data = &max8925_irqs[i];
+               /* 1 -- disable, 0 -- enable */
                switch (irq_data->mask_reg) {
                case MAX8925_CHG_IRQ1_MASK:
-                       irq_chg[0] &= irq_data->enable;
+                       irq_chg[0] &= ~irq_data->enable;
                        break;
                case MAX8925_CHG_IRQ2_MASK:
-                       irq_chg[1] &= irq_data->enable;
+                       irq_chg[1] &= ~irq_data->enable;
                        break;
                case MAX8925_ON_OFF_IRQ1_MASK:
-                       irq_on[0] &= irq_data->enable;
+                       irq_on[0] &= ~irq_data->enable;
                        break;
                case MAX8925_ON_OFF_IRQ2_MASK:
-                       irq_on[1] &= irq_data->enable;
+                       irq_on[1] &= ~irq_data->enable;
                        break;
                case MAX8925_RTC_IRQ_MASK:
-                       irq_rtc &= irq_data->enable;
+                       irq_rtc &= ~irq_data->enable;
                        break;
                case MAX8925_TSC_IRQ_MASK:
-                       irq_tsc &= irq_data->enable;
+                       irq_tsc &= ~irq_data->enable;
                        break;
                default:
                        dev_err(chip->dev, "wrong IRQ\n");
index 097f24d8bceb9ec2ad0d1440430c302d7f0a4a35..b9fda7018cef9a4b07cdeec3c71c3e29c5f63775 100644 (file)
@@ -78,7 +78,7 @@ struct sih {
        u8      irq_lines;              /* number of supported irq lines */
 
        /* SIR ignored -- set interrupt, for testing only */
-       struct irq_data {
+       struct sih_irq_data {
                u8      isr_offset;
                u8      imr_offset;
        } mask[2];
@@ -810,7 +810,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        twl4030_irq_chip = dummy_irq_chip;
        twl4030_irq_chip.name = "twl4030";
 
-       twl4030_sih_irq_chip.ack = dummy_irq_chip.ack;
+       twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
 
        for (i = irq_base; i < irq_end; i++) {
                set_irq_chip_and_handler(i, &twl4030_irq_chip,
index 7dabe4dbd3732e1d75c396b9b1e01bdeafafa57c..294183b6260b1facff3d26764eb3cea8c6d4b011 100644 (file)
@@ -394,8 +394,13 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type)
 
        irq = irq - wm831x->irq_base;
 
-       if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11)
-               return -EINVAL;
+       if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
+               /* Ignore internal-only IRQs */
+               if (irq >= 0 && irq < WM831X_NUM_IRQS)
+                       return 0;
+               else
+                       return -EINVAL;
+       }
 
        switch (type) {
        case IRQ_TYPE_EDGE_BOTH:
index 0b591b658243a7675ac66d24b97e7ea1ceaa9781..b74331260744db8829a2a8712a0d08bf5d42f949 100644 (file)
@@ -368,7 +368,7 @@ config VMWARE_BALLOON
          If unsure, say N.
 
          To compile this driver as a module, choose M here: the
-         module will be called vmware_balloon.
+         module will be called vmw_balloon.
 
 config ARM_CHARLCD
        bool "ARM Ltd. Character LCD Driver"
index 255a80dc9d73267a115da07c5729e04aa1c8a8ee..42eab95cde2af49e8ae737036695a1093caa01d9 100644 (file)
@@ -33,5 +33,5 @@ obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)          += hmc6352.o
 obj-y                          += eeprom/
 obj-y                          += cb710/
-obj-$(CONFIG_VMWARE_BALLOON)   += vmware_balloon.o
+obj-$(CONFIG_VMWARE_BALLOON)   += vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)      += arm-charlcd.o
index 714c6b487313a4ad7b360687591b75a6cddedc55..d5f3a3fd231931508948a9b0227aae2a3648a96f 100644 (file)
@@ -190,7 +190,6 @@ static int __devexit bh1780_remove(struct i2c_client *client)
 
        ddata = i2c_get_clientdata(client);
        sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
-       i2c_set_clientdata(client, NULL);
        kfree(ddata);
 
        return 0;
index 557a8c2a73367e579e8db86fbc3487702aae16a4..69c1f2fca1415a9f18fb71fc47cf4a7a9197e944 100644 (file)
@@ -640,6 +640,7 @@ static const struct file_operations ilo_fops = {
        .poll           = ilo_poll,
        .open           = ilo_open,
        .release        = ilo_close,
+       .llseek         = noop_llseek,
 };
 
 static irqreturn_t ilo_isr(int irq, void *data)
index 8844a3f45381e8bd34c2a13901f77810fe87aa95..af2497ae5fe32be990aabdb6732c44eaaf0591fb 100644 (file)
@@ -584,6 +584,7 @@ static const struct file_operations command_fops = {
        .release =      command_file_close,
        .read =         command_file_read,
        .write =        command_file_write,
+       .llseek =       generic_file_llseek,
 };
 
 static const struct file_operations event_fops = {
@@ -591,6 +592,7 @@ static const struct file_operations event_fops = {
        .release =      event_file_close,
        .read =         event_file_read,
        .write =        event_file_write,
+       .llseek =       generic_file_llseek,
 };
 
 static const struct file_operations r_heartbeat_fops = {
@@ -598,6 +600,7 @@ static const struct file_operations r_heartbeat_fops = {
        .release =      r_heartbeat_file_close,
        .read =         r_heartbeat_file_read,
        .write =        r_heartbeat_file_write,
+       .llseek =       generic_file_llseek,
 };
 
 static const struct file_operations remote_settings_fops = {
@@ -605,6 +608,7 @@ static const struct file_operations remote_settings_fops = {
        .release =      remote_settings_file_close,
        .read =         remote_settings_file_read,
        .write =        remote_settings_file_write,
+       .llseek =       generic_file_llseek,
 };
 
 
index e9eda471f6e0fd9ee4e2781e8d9176761a752591..62fbaec482075ec53cb27d1db4eade9fc01a6142 100644 (file)
@@ -71,6 +71,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file,                 \
        static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
                .read = iwmct_dbgfs_##name##_read,                      \
                .open = iwmct_dbgfs_open_file_generic,                  \
+               .llseek = generic_file_llseek,                          \
        };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                   \
@@ -78,6 +79,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file,                 \
        static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
                .write = iwmct_dbgfs_##name##_write,                    \
                .open = iwmct_dbgfs_open_file_generic,                  \
+               .llseek = generic_file_llseek,                          \
        };
 
 #define DEBUGFS_READ_WRITE_FILE_OPS(name)                              \
@@ -87,6 +89,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file,                 \
                .write = iwmct_dbgfs_##name##_write,                    \
                .read = iwmct_dbgfs_##name##_read,                      \
                .open = iwmct_dbgfs_open_file_generic,                  \
+               .llseek = generic_file_llseek,                          \
        };
 
 
index ef34de7a802606309fbaf02b8396456763fd4b62..343b5d8ea6971fc07ddbb443b91ddfee6439e31c 100644 (file)
@@ -575,30 +575,39 @@ struct crash_entry {
 
 static const struct crash_entry crash_entries[] = {
        {"DIRECT", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = direct_entry} },
        {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = int_hardware_entry} },
        {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = int_hw_irq_en} },
        {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = int_tasklet_entry} },
        {"FS_DEVRW", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = fs_devrw_entry} },
        {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = mem_swapout_entry} },
        {"TIMERADD", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = timeradd_entry} },
        {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = scsi_dispatch_cmd_entry} },
        {"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
+                       .llseek = generic_file_llseek,
                        .open = lkdtm_debugfs_open,
                        .write = ide_core_cp_entry} },
 };
index 75ee0d3f6f457707d79cbf5f5d021469710eb06d..4197a3cb26ba42d674ef7d0935207adee0d70be1 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/phantom.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -38,6 +38,7 @@
 #define PHB_RUNNING            1
 #define PHB_NOT_OH             2
 
+static DEFINE_MUTEX(phantom_mutex);
 static struct class *phantom_class;
 static int phantom_major;
 
@@ -215,17 +216,17 @@ static int phantom_open(struct inode *inode, struct file *file)
        struct phantom_device *dev = container_of(inode->i_cdev,
                        struct phantom_device, cdev);
 
-       lock_kernel();
+       mutex_lock(&phantom_mutex);
        nonseekable_open(inode, file);
 
        if (mutex_lock_interruptible(&dev->open_lock)) {
-               unlock_kernel();
+               mutex_unlock(&phantom_mutex);
                return -ERESTARTSYS;
        }
 
        if (dev->opened) {
                mutex_unlock(&dev->open_lock);
-               unlock_kernel();
+               mutex_unlock(&phantom_mutex);
                return -EINVAL;
        }
 
@@ -236,7 +237,7 @@ static int phantom_open(struct inode *inode, struct file *file)
        atomic_set(&dev->counter, 0);
        dev->opened++;
        mutex_unlock(&dev->open_lock);
-       unlock_kernel();
+       mutex_unlock(&phantom_mutex);
        return 0;
 }
 
@@ -279,6 +280,7 @@ static const struct file_operations phantom_file_ops = {
        .unlocked_ioctl = phantom_ioctl,
        .compat_ioctl = phantom_compat_ioctl,
        .poll = phantom_poll,
+       .llseek = no_llseek,
 };
 
 static irqreturn_t phantom_isr(int irq, void *data)
index cb3b4d228475905fbdc25bc00605188e2afc53c4..28852dfa310dbfe60122ce6fce90597164a05d2a 100644 (file)
@@ -587,6 +587,7 @@ static const struct file_operations gru_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = gru_file_unlocked_ioctl,
        .mmap           = gru_file_mmap,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice gru_miscdev = {
index d545f79f6000ebe8b5219c56a19c7bd0acbfc343..00073b7c036859ca199eb46caaed8476de82c23d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 
@@ -51,6 +50,7 @@ MODULE_ALIAS("mmc:block");
 #define MMC_SHIFT      3
 #define MMC_NUM_MINORS (256 >> MMC_SHIFT)
 
+static DEFINE_MUTEX(block_mutex);
 static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);
 
 /*
@@ -108,7 +108,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
        struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
        int ret = -ENXIO;
 
-       lock_kernel();
+       mutex_lock(&block_mutex);
        if (md) {
                if (md->usage == 2)
                        check_disk_change(bdev);
@@ -119,7 +119,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
                        ret = -EROFS;
                }
        }
-       unlock_kernel();
+       mutex_unlock(&block_mutex);
 
        return ret;
 }
@@ -128,9 +128,9 @@ static int mmc_blk_release(struct gendisk *disk, fmode_t mode)
 {
        struct mmc_blk_data *md = disk->private_data;
 
-       lock_kernel();
+       mutex_lock(&block_mutex);
        mmc_blk_put(md);
-       unlock_kernel();
+       mutex_unlock(&block_mutex);
        return 0;
 }
 
index 5db49b124ffa158793e0cfb3d1db72321679d440..09eee6df0653c84fc5c08023f8913a6afbb884a7 100644 (file)
@@ -1631,6 +1631,19 @@ int mmc_suspend_host(struct mmc_host *host)
        if (host->bus_ops && !host->bus_dead) {
                if (host->bus_ops->suspend)
                        err = host->bus_ops->suspend(host);
+               if (err == -ENOSYS || !host->bus_ops->resume) {
+                       /*
+                        * We simply "remove" the card in this case.
+                        * It will be redetected on resume.
+                        */
+                       if (host->bus_ops->remove)
+                               host->bus_ops->remove(host);
+                       mmc_claim_host(host);
+                       mmc_detach_bus(host);
+                       mmc_release_host(host);
+                       host->pm_flags = 0;
+                       err = 0;
+               }
        }
        mmc_bus_put(host);
 
index 53cb380c0987d9d5e460828c801e2f25790c1f40..46bc6d7551a3e7ea7b6398a9bc44d74f5fac8c6f 100644 (file)
@@ -245,6 +245,7 @@ static const struct file_operations mmc_dbg_ext_csd_fops = {
        .open           = mmc_ext_csd_open,
        .read           = mmc_ext_csd_read,
        .release        = mmc_ext_csd_release,
+       .llseek         = default_llseek,
 };
 
 void mmc_add_card_debugfs(struct mmc_card *card)
index bd2755e8d9a3d327f7ae54bedd0e7820f85ea5fe..f332c52968b75d7528ee8c5f21eaf561a76d373d 100644 (file)
@@ -362,9 +362,8 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
                goto err;
        }
 
-       err = mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid);
-
-       if (!err) {
+       if (ocr & R4_MEMORY_PRESENT
+           && mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid) == 0) {
                card->type = MMC_TYPE_SD_COMBO;
 
                if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
index 5f3a599ead07bbdfae11f7abc0198285e743db81..87226cd202a5086f7d90699f0a43d6d4e99725a1 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/clk.h>
 #include <linux/atmel_pdc.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 
 #include <linux/mmc/host.h>
 
index 9a68ff4353a2e83878fce5429afe9351140daf57..5a950b16d9e629dc3d08041bda547b165cadee76 100644 (file)
@@ -148,11 +148,12 @@ static int imxmci_start_clock(struct imxmci_host *host)
 
                while (delay--) {
                        reg = readw(host->base + MMC_REG_STATUS);
-                       if (reg & STATUS_CARD_BUS_CLK_RUN)
+                       if (reg & STATUS_CARD_BUS_CLK_RUN) {
                                /* Check twice before cut */
                                reg = readw(host->base + MMC_REG_STATUS);
                                if (reg & STATUS_CARD_BUS_CLK_RUN)
                                        return 0;
+                       }
 
                        if (test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
                                return 0;
index 840b301b567142b4e264924a14feb91c5cb54003..f2e02d7d9f3d45555356a54aecb5e5ec3228472d 100644 (file)
@@ -41,23 +41,35 @@ static unsigned int fmax = 515633;
  * @clkreg: default value for MCICLOCK register
  * @clkreg_enable: enable value for MMCICLOCK register
  * @datalength_bits: number of bits in the MMCIDATALENGTH register
+ * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
+ *           is asserted (likewise for RX)
+ * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
+ *               is asserted (likewise for RX)
  */
 struct variant_data {
        unsigned int            clkreg;
        unsigned int            clkreg_enable;
        unsigned int            datalength_bits;
+       unsigned int            fifosize;
+       unsigned int            fifohalfsize;
 };
 
 static struct variant_data variant_arm = {
+       .fifosize               = 16 * 4,
+       .fifohalfsize           = 8 * 4,
        .datalength_bits        = 16,
 };
 
 static struct variant_data variant_u300 = {
+       .fifosize               = 16 * 4,
+       .fifohalfsize           = 8 * 4,
        .clkreg_enable          = 1 << 13, /* HWFCEN */
        .datalength_bits        = 16,
 };
 
 static struct variant_data variant_ux500 = {
+       .fifosize               = 30 * 4,
+       .fifohalfsize           = 8 * 4,
        .clkreg                 = MCI_CLK_ENABLE,
        .clkreg_enable          = 1 << 14, /* HWFCEN */
        .datalength_bits        = 24,
@@ -138,6 +150,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
 
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 {
+       struct variant_data *variant = host->variant;
        unsigned int datactrl, timeout, irqmask;
        unsigned long long clks;
        void __iomem *base;
@@ -173,7 +186,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
                 * If we have less than a FIFOSIZE of bytes to transfer,
                 * trigger a PIO interrupt as soon as any data is available.
                 */
-               if (host->size < MCI_FIFOSIZE)
+               if (host->size < variant->fifosize)
                        irqmask |= MCI_RXDATAAVLBLMASK;
        } else {
                /*
@@ -332,13 +345,15 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
 
 static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
 {
+       struct variant_data *variant = host->variant;
        void __iomem *base = host->base;
        char *ptr = buffer;
 
        do {
                unsigned int count, maxcnt;
 
-               maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
+               maxcnt = status & MCI_TXFIFOEMPTY ?
+                        variant->fifosize : variant->fifohalfsize;
                count = min(remain, maxcnt);
 
                writesl(base + MMCIFIFO, ptr, count >> 2);
@@ -362,6 +377,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 {
        struct mmci_host *host = dev_id;
        struct sg_mapping_iter *sg_miter = &host->sg_miter;
+       struct variant_data *variant = host->variant;
        void __iomem *base = host->base;
        unsigned long flags;
        u32 status;
@@ -420,7 +436,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
         * If we're nearing the end of the read, switch to
         * "any data available" mode.
         */
-       if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
+       if (status & MCI_RXACTIVE && host->size < variant->fifosize)
                writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
 
        /*
@@ -564,18 +580,23 @@ static int mmci_get_ro(struct mmc_host *mmc)
        if (host->gpio_wp == -ENOSYS)
                return -ENOSYS;
 
-       return gpio_get_value(host->gpio_wp);
+       return gpio_get_value_cansleep(host->gpio_wp);
 }
 
 static int mmci_get_cd(struct mmc_host *mmc)
 {
        struct mmci_host *host = mmc_priv(mmc);
+       struct mmci_platform_data *plat = host->plat;
        unsigned int status;
 
-       if (host->gpio_cd == -ENOSYS)
-               status = host->plat->status(mmc_dev(host->mmc));
-       else
-               status = !gpio_get_value(host->gpio_cd);
+       if (host->gpio_cd == -ENOSYS) {
+               if (!plat->status)
+                       return 1; /* Assume always present */
+
+               status = plat->status(mmc_dev(host->mmc));
+       } else
+               status = !!gpio_get_value_cansleep(host->gpio_cd)
+                       ^ plat->cd_invert;
 
        /*
         * Use positive logic throughout - status is zero for no card,
@@ -584,6 +605,15 @@ static int mmci_get_cd(struct mmc_host *mmc)
        return status;
 }
 
+static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
+{
+       struct mmci_host *host = dev_id;
+
+       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+
+       return IRQ_HANDLED;
+}
+
 static const struct mmc_host_ops mmci_ops = {
        .request        = mmci_request,
        .set_ios        = mmci_set_ios,
@@ -620,6 +650,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 
        host->gpio_wp = -ENOSYS;
        host->gpio_cd = -ENOSYS;
+       host->gpio_cd_irq = -1;
 
        host->hw_designer = amba_manf(dev);
        host->hw_revision = amba_rev(dev);
@@ -699,7 +730,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
        if (host->vcc == NULL)
                mmc->ocr_avail = plat->ocr_mask;
        mmc->caps = plat->capabilities;
-       mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        /*
         * We can do SGIO
@@ -744,6 +774,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
                        host->gpio_cd = plat->gpio_cd;
                else if (ret != -ENOSYS)
                        goto err_gpio_cd;
+
+               ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
+                                             mmci_cd_irq, 0,
+                                             DRIVER_NAME " (cd)", host);
+               if (ret >= 0)
+                       host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
        }
        if (gpio_is_valid(plat->gpio_wp)) {
                ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
@@ -755,6 +791,10 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
                        goto err_gpio_wp;
        }
 
+       if ((host->plat->status || host->gpio_cd != -ENOSYS)
+           && host->gpio_cd_irq < 0)
+               mmc->caps |= MMC_CAP_NEEDS_POLL;
+
        ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
        if (ret)
                goto unmap;
@@ -781,6 +821,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
        if (host->gpio_wp != -ENOSYS)
                gpio_free(host->gpio_wp);
  err_gpio_wp:
+       if (host->gpio_cd_irq >= 0)
+               free_irq(host->gpio_cd_irq, host);
        if (host->gpio_cd != -ENOSYS)
                gpio_free(host->gpio_cd);
  err_gpio_cd:
@@ -819,6 +861,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
 
                if (host->gpio_wp != -ENOSYS)
                        gpio_free(host->gpio_wp);
+               if (host->gpio_cd_irq >= 0)
+                       free_irq(host->gpio_cd_irq, host);
                if (host->gpio_cd != -ENOSYS)
                        gpio_free(host->gpio_cd);
 
index 68970cfb81e1396ca9f5a3f817e4c7ede777d6ea..4ae887fc01892e3a844b064ce6dd72c3a8773aa9 100644 (file)
 #define MCI_DPSM_MODE          (1 << 2)
 #define MCI_DPSM_DMAENABLE     (1 << 3)
 #define MCI_DPSM_BLOCKSIZE     (1 << 4)
-#define MCI_DPSM_RWSTART       (1 << 8)
-#define MCI_DPSM_RWSTOP                (1 << 9)
-#define MCI_DPSM_RWMOD         (1 << 10)
-#define MCI_DPSM_SDIOEN                (1 << 11)
+/* Control register extensions in the ST Micro U300 and Ux500 versions */
+#define MCI_ST_DPSM_RWSTART    (1 << 8)
+#define MCI_ST_DPSM_RWSTOP     (1 << 9)
+#define MCI_ST_DPSM_RWMOD      (1 << 10)
+#define MCI_ST_DPSM_SDIOEN     (1 << 11)
+/* Control register extensions in the ST Micro Ux500 versions */
+#define MCI_ST_DPSM_DMAREQCTL  (1 << 12)
+#define MCI_ST_DPSM_DBOOTMODEEN        (1 << 13)
+#define MCI_ST_DPSM_BUSYMODE   (1 << 14)
+#define MCI_ST_DPSM_DDRMODE    (1 << 15)
 
 #define MMCIDATACNT            0x030
 #define MMCISTATUS             0x034
        MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|       \
        MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
 
-/*
- * The size of the FIFO in bytes.
- */
-#define MCI_FIFOSIZE   (16*4)
-       
-#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
-
 #define NR_SG          16
 
 struct clk;
@@ -154,6 +153,7 @@ struct mmci_host {
        struct clk              *clk;
        int                     gpio_cd;
        int                     gpio_wp;
+       int                     gpio_cd_irq;
 
        unsigned int            data_xfered;
 
index 4a8776f8afdd690048c69de91e755d35d2c884a5..4526d2791f2990229acbe9ef0f5c88286819807f 100644 (file)
@@ -2305,7 +2305,6 @@ static int omap_hsmmc_suspend(struct device *dev)
        int ret = 0;
        struct platform_device *pdev = to_platform_device(dev);
        struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
-       pm_message_t state = PMSG_SUSPEND; /* unused by MMC core */
 
        if (host && host->suspended)
                return 0;
@@ -2324,8 +2323,8 @@ static int omap_hsmmc_suspend(struct device *dev)
                        }
                }
                cancel_work_sync(&host->mmc_carddetect_work);
-               mmc_host_enable(host->mmc);
                ret = mmc_suspend_host(host->mmc);
+               mmc_host_enable(host->mmc);
                if (ret == 0) {
                        omap_hsmmc_disable_irq(host);
                        OMAP_HSMMC_WRITE(host->base, HCTL,
index 2e16e0a90a5e1a5d8d3d7487727baa39d701b8fb..976330de379ecc78cbe91f19c4bd9495d4722dae 100644 (file)
@@ -1600,7 +1600,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev)
        host->pio_active        = XFER_NONE;
 
 #ifdef CONFIG_MMC_S3C_PIODMA
-       host->dodma             = host->pdata->dma;
+       host->dodma             = host->pdata->use_dma;
 #endif
 
        host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 71ad4163b95e12b45aab7d41379c8022995d8ac4..aacb862ecc8a979f8022b8e0dd3428ed26c15baa 100644 (file)
@@ -241,8 +241,10 @@ static struct sdhci_ops sdhci_s3c_ops = {
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
 {
        struct sdhci_host *host = platform_get_drvdata(dev);
+       unsigned long flags;
+
        if (host) {
-               spin_lock(&host->lock);
+               spin_lock_irqsave(&host->lock, flags);
                if (state) {
                        dev_dbg(&dev->dev, "card inserted.\n");
                        host->flags &= ~SDHCI_DEVICE_DEAD;
@@ -253,7 +255,7 @@ static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
                        host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
                }
                tasklet_schedule(&host->card_tasklet);
-               spin_unlock(&host->lock);
+               spin_unlock_irqrestore(&host->lock, flags);
        }
 }
 
@@ -481,8 +483,10 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        sdhci_remove_host(host, 1);
 
        for (ptr = 0; ptr < 3; ptr++) {
-               clk_disable(sc->clk_bus[ptr]);
-               clk_put(sc->clk_bus[ptr]);
+               if (sc->clk_bus[ptr]) {
+                       clk_disable(sc->clk_bus[ptr]);
+                       clk_put(sc->clk_bus[ptr]);
+               }
        }
        clk_disable(sc->clk_io);
        clk_put(sc->clk_io);
index 7aa65bb2af4a29cc03231589de9083e48589b66f..f472c2714eb88a4289598ed9e454e7aefceaac45 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/scatterlist.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <linux/io.h>
@@ -536,9 +535,7 @@ static int sdricoh_pcmcia_resume(struct pcmcia_device *link)
 #endif
 
 static struct pcmcia_driver sdricoh_driver = {
-       .drv = {
-               .name = DRIVER_NAME,
-               },
+       .name = DRIVER_NAME,
        .probe = sdricoh_pcmcia_probe,
        .remove = sdricoh_pcmcia_detach,
        .id_table = pcmcia_ids,
index ee7d0a5a51c496cb92b04e7b9bc8172f8a233875..69d98e3bf6abaa3c784d1d70f171387b3142eb64 100644 (file)
@@ -164,6 +164,7 @@ tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
 static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 {
        struct mmc_data *data = host->data;
+       void *sg_virt;
        unsigned short *buf;
        unsigned int count;
        unsigned long flags;
@@ -173,8 +174,8 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
                return;
        }
 
-       buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) +
-             host->sg_off);
+       sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags);
+       buf = (unsigned short *)(sg_virt + host->sg_off);
 
        count = host->sg_ptr->length - host->sg_off;
        if (count > data->blksz)
@@ -191,7 +192,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 
        host->sg_off += count;
 
-       tmio_mmc_kunmap_atomic(host, &flags);
+       tmio_mmc_kunmap_atomic(sg_virt, &flags);
 
        if (host->sg_off == host->sg_ptr->length)
                tmio_mmc_next_sg(host);
index 64f7d5dfc106ac7b39e37842c5eca9a898dbbb06..0fedc78e3ea5c4613767d7d31e534143b4bf1780 100644 (file)
 
 #define ack_mmc_irqs(host, i) \
        do { \
-               u32 mask;\
-               mask  = sd_ctrl_read32((host), CTL_STATUS); \
-               mask &= ~((i) & TMIO_MASK_IRQ); \
-               sd_ctrl_write32((host), CTL_STATUS, mask); \
+               sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
        } while (0)
 
 
@@ -177,19 +174,17 @@ static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host)
        return --host->sg_len;
 }
 
-static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host,
+static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
        unsigned long *flags)
 {
-       struct scatterlist *sg = host->sg_ptr;
-
        local_irq_save(*flags);
        return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
 }
 
-static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host,
+static inline void tmio_mmc_kunmap_atomic(void *virt,
        unsigned long *flags)
 {
-       kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ);
+       kunmap_atomic(virt, KM_BIO_SRC_IRQ);
        local_irq_restore(*flags);
 }
 
index e9ca5ba7d9d2cfa1fe1671205f0a9db584d00e49..57a1acfe22c4a2df13903e42918b14ac47f875a4 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -101,7 +100,7 @@ MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)")
 static caddr_t remap_window(struct map_info *map, unsigned long to)
 {
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
-       window_handle_t win = (window_handle_t)map->map_priv_2;
+       struct resource *win = (struct resource *) map->map_priv_2;
        unsigned int offset;
        int ret;
 
@@ -316,30 +315,19 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
 {
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
        struct pcmcia_device *link = dev->p_dev;
-       modconf_t mod;
-       int ret;
-
-       mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
-       mod.Vcc = 0;
-       mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 
        DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
-       ret = pcmcia_modify_configuration(link, &mod);
+       pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
 }
 
 
-/* After a card is removed, pcmciamtd_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
-
 static void pcmciamtd_release(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
 
        DEBUG(3, "link = 0x%p", link);
 
-       if (link->win) {
+       if (link->resource[2]->end) {
                if(dev->win_base) {
                        iounmap(dev->win_base);
                        dev->win_base = NULL;
@@ -482,18 +470,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
 }
 
 
-/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * MTD device available to the system.
- */
-
 static int pcmciamtd_config(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
        struct mtd_info *mtd = NULL;
-       win_req_t req;
        int ret;
-       int i;
+       int i, j = 0;
        static char *probes[] = { "jedec_probe", "cfi_probe" };
        int new_name = 0;
 
@@ -520,28 +502,34 @@ static int pcmciamtd_config(struct pcmcia_device *link)
         * smaller windows until we succeed
         */
 
-       req.Attributes =  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-       req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
-       req.Base = 0;
-       req.AccessSpeed = mem_speed;
-       link->win = (window_handle_t)link;
-       req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
+       link->resource[2]->flags |=  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+       link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
+                                       WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
+       link->resource[2]->start = 0;
+       link->resource[2]->end = (force_size) ? force_size << 20 :
+                                       MAX_PCMCIA_ADDR;
        dev->win_size = 0;
 
        do {
                int ret;
-               DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
-                     req.Size >> 10, req.AccessSpeed);
-               ret = pcmcia_request_window(link, &req, &link->win);
+               DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+                       (unsigned long) resource_size(link->resource[2]) >> 10,
+                       mem_speed);
+               ret = pcmcia_request_window(link, link->resource[2], mem_speed);
                DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
                if(ret) {
-                       req.Size >>= 1;
+                       j++;
+                       link->resource[2]->start = 0;
+                       link->resource[2]->end = (force_size) ?
+                                       force_size << 20 : MAX_PCMCIA_ADDR;
+                       link->resource[2]->end >>= j;
                } else {
-                       DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
-                       dev->win_size = req.Size;
+                       DEBUG(2, "Got window of size %luKiB", (unsigned long)
+                               resource_size(link->resource[2]) >> 10);
+                       dev->win_size = resource_size(link->resource[2]);
                        break;
                }
-       } while(req.Size >= 0x1000);
+       } while (link->resource[2]->end >= 0x1000);
 
        DEBUG(2, "dev->win_size = %d", dev->win_size);
 
@@ -553,33 +541,31 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
        /* Get write protect status */
-       DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
-       dev->win_base = ioremap(req.Base, req.Size);
+       dev->win_base = ioremap(link->resource[2]->start,
+                               resource_size(link->resource[2]));
        if(!dev->win_base) {
-               dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
-                       req.Base, req.Size);
+               dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
+                       link->resource[2]);
                pcmciamtd_release(link);
                return -ENODEV;
        }
-       DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
-             dev, req.Base, dev->win_base, req.Size);
+       DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+             dev, link->resource[2], dev->win_base);
 
        dev->offset = 0;
        dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
-       dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
+       dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
 
        dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
-       link->conf.Attributes = 0;
        if(setvpp == 2) {
-               link->conf.Vpp = dev->vpp;
+               link->vpp = dev->vpp;
        } else {
-               link->conf.Vpp = 0;
+               link->vpp = 0;
        }
 
-       link->conf.IntType = INT_MEMORY;
-       link->conf.ConfigIndex = 0;
+       link->config_index = 0;
        DEBUG(2, "Setting Configuration");
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret != 0) {
                if (dev->win_base) {
                        iounmap(dev->win_base);
@@ -680,12 +666,6 @@ static int pcmciamtd_resume(struct pcmcia_device *dev)
 }
 
 
-/* This deletes a driver "instance".  The device is de-registered
- * with Card Services.  If it has been released, all local data
- * structures are freed.  Otherwise, the structures will be freed
- * when the device is released.
- */
-
 static void pcmciamtd_detach(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
@@ -703,11 +683,6 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
 }
 
 
-/* pcmciamtd_attach() creates an "instance" of the driver, allocating
- * local data structures for one device.  The device is registered
- * with Card Services.
- */
-
 static int pcmciamtd_probe(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev;
@@ -720,9 +695,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
        dev->p_dev = link;
        link->priv = dev;
 
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY;
-
        return pcmciamtd_config(link);
 }
 
@@ -757,9 +729,7 @@ static struct pcmcia_device_id pcmciamtd_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
 
 static struct pcmcia_driver pcmciamtd_driver = {
-       .drv            = {
-               .name   = "pcmciamtd"
-       },
+       .name           = "pcmciamtd",
        .probe          = pcmciamtd_probe,
        .remove         = pcmciamtd_detach,
        .owner          = THIS_MODULE,
@@ -771,8 +741,6 @@ static struct pcmcia_driver pcmciamtd_driver = {
 
 static int __init init_pcmciamtd(void)
 {
-       info(DRIVER_DESC);
-
        if(bankwidth && bankwidth != 1 && bankwidth != 2) {
                info("bad bankwidth (%d), using default", bankwidth);
                bankwidth = 2;
index 62e68707b07f49a6f07a8f97a7333880f9d7f1db..50ab431b24ebafd456269061ac7a6873c152a57d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -38,6 +37,7 @@
 
 #include "mtdcore.h"
 
+static DEFINE_MUTEX(mtd_blkdevs_mutex);
 static LIST_HEAD(blktrans_majors);
 static DEFINE_MUTEX(blktrans_ref_mutex);
 
@@ -181,7 +181,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
        if (!dev)
                return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
-       lock_kernel();
+       mutex_lock(&mtd_blkdevs_mutex);
        mutex_lock(&dev->lock);
 
        if (!dev->mtd) {
@@ -198,7 +198,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 unlock:
        mutex_unlock(&dev->lock);
        blktrans_dev_put(dev);
-       unlock_kernel();
+       mutex_unlock(&mtd_blkdevs_mutex);
        return ret;
 }
 
@@ -210,7 +210,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
        if (!dev)
                return ret;
 
-       lock_kernel();
+       mutex_lock(&mtd_blkdevs_mutex);
        mutex_lock(&dev->lock);
 
        /* Release one reference, we sure its not the last one here*/
@@ -223,7 +223,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
 unlock:
        mutex_unlock(&dev->lock);
        blktrans_dev_put(dev);
-       unlock_kernel();
+       mutex_unlock(&mtd_blkdevs_mutex);
        return ret;
 }
 
@@ -256,7 +256,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
        if (!dev)
                return ret;
 
-       lock_kernel();
+       mutex_lock(&mtd_blkdevs_mutex);
        mutex_lock(&dev->lock);
 
        if (!dev->mtd)
@@ -271,7 +271,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
        }
 unlock:
        mutex_unlock(&dev->lock);
-       unlock_kernel();
+       mutex_unlock(&mtd_blkdevs_mutex);
        blktrans_dev_put(dev);
        return ret;
 }
index a825002123c84bc0a24ce26e00400be277b09c22..5ef45487b65f01c261222b35d5fd6ecc548bea7e 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/backing-dev.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
@@ -37,6 +37,7 @@
 #include <asm/uaccess.h>
 
 #define MTD_INODE_FS_MAGIC 0x11307854
+static DEFINE_MUTEX(mtd_mutex);
 static struct vfsmount *mtd_inode_mnt __read_mostly;
 
 /*
@@ -90,7 +91,7 @@ static int mtd_open(struct inode *inode, struct file *file)
        if ((file->f_mode & FMODE_WRITE) && (minor & 1))
                return -EACCES;
 
-       lock_kernel();
+       mutex_lock(&mtd_mutex);
        mtd = get_mtd_device(NULL, devnum);
 
        if (IS_ERR(mtd)) {
@@ -138,7 +139,7 @@ static int mtd_open(struct inode *inode, struct file *file)
        file->private_data = mfi;
 
 out:
-       unlock_kernel();
+       mutex_unlock(&mtd_mutex);
        return ret;
 } /* mtd_open */
 
@@ -866,9 +867,9 @@ static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&mtd_mutex);
        ret = mtd_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&mtd_mutex);
 
        return ret;
 }
@@ -892,7 +893,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
        void __user *argp = compat_ptr(arg);
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&mtd_mutex);
 
        switch (cmd) {
        case MEMWRITEOOB32:
@@ -927,7 +928,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
                ret = mtd_ioctl(file, cmd, (unsigned long)argp);
        }
 
-       unlock_kernel();
+       mutex_unlock(&mtd_mutex);
 
        return ret;
 }
index a382e3dd0a5dc8cdcddc2fc5f0b993c3badadd33..6fbeefa3a7662fb5fb85e8bfdbb86e0c63307ab3 100644 (file)
@@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
 static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
 {
        struct bf5xx_nand_info *info = to_nand_info(pdev);
-       struct mtd_info *mtd = NULL;
 
        platform_set_drvdata(pdev, NULL);
 
@@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
         * and their partitions, then go through freeing the
         * resources used
         */
-       mtd = &info->mtd;
-       if (mtd) {
-               nand_release(mtd);
-               kfree(mtd);
-       }
+       nand_release(&info->mtd);
 
        peripheral_free_list(bfin_nfc_pin_req);
        bf5xx_nand_dma_remove(info);
@@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd)
        struct nand_chip *chip = mtd->priv;
        int ret;
 
-       ret = nand_scan_ident(mtd, 1);
+       ret = nand_scan_ident(mtd, 1, NULL);
        if (ret)
                return ret;
 
index fcf8ceb277d44cd3e78b5c5e0249ec1b40d7ab33..214b03afdd482920adda308e51088092d884a2d1 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/completion.h>
 
 #include <asm/mach/flash.h>
 #include <mach/mxc_nand.h>
@@ -67,7 +69,9 @@
 #define NFC_V1_V2_CONFIG1_BIG          (1 << 5)
 #define NFC_V1_V2_CONFIG1_RST          (1 << 6)
 #define NFC_V1_V2_CONFIG1_CE           (1 << 7)
-#define NFC_V1_V2_CONFIG1_ONE_CYCLE    (1 << 8)
+#define NFC_V2_CONFIG1_ONE_CYCLE       (1 << 8)
+#define NFC_V2_CONFIG1_PPB(x)          (((x) & 0x3) << 9)
+#define NFC_V2_CONFIG1_FP_INT          (1 << 11)
 
 #define NFC_V1_V2_CONFIG2_INT          (1 << 15)
 
@@ -149,7 +153,7 @@ struct mxc_nand_host {
        int                     irq;
        int                     eccsize;
 
-       wait_queue_head_t       irq_waitq;
+       struct completion       op_completion;
 
        uint8_t                 *data_buf;
        unsigned int            buf_start;
@@ -162,6 +166,7 @@ struct mxc_nand_host {
        void                    (*send_read_id)(struct mxc_nand_host *);
        uint16_t                (*get_dev_status)(struct mxc_nand_host *);
        int                     (*check_int)(struct mxc_nand_host *);
+       void                    (*irq_control)(struct mxc_nand_host *, int);
 };
 
 /* OOB placement block for use with hardware ecc generation */
@@ -214,9 +219,12 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 {
        struct mxc_nand_host *host = dev_id;
 
-       disable_irq_nosync(irq);
+       if (!host->check_int(host))
+               return IRQ_NONE;
 
-       wake_up(&host->irq_waitq);
+       host->irq_control(host, 0);
+
+       complete(&host->op_completion);
 
        return IRQ_HANDLED;
 }
@@ -243,11 +251,54 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
        if (!(tmp & NFC_V1_V2_CONFIG2_INT))
                return 0;
 
-       writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
+       if (!cpu_is_mx21())
+               writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
 
        return 1;
 }
 
+/*
+ * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
+ * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
+ * driver can enable/disable the irq line rather than simply masking the
+ * interrupts.
+ */
+static void irq_control_mx21(struct mxc_nand_host *host, int activate)
+{
+       if (activate)
+               enable_irq(host->irq);
+       else
+               disable_irq_nosync(host->irq);
+}
+
+static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
+{
+       uint16_t tmp;
+
+       tmp = readw(NFC_V1_V2_CONFIG1);
+
+       if (activate)
+               tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+       else
+               tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
+
+       writew(tmp, NFC_V1_V2_CONFIG1);
+}
+
+static void irq_control_v3(struct mxc_nand_host *host, int activate)
+{
+       uint32_t tmp;
+
+       tmp = readl(NFC_V3_CONFIG2);
+
+       if (activate)
+               tmp &= ~NFC_V3_CONFIG2_INT_MSK;
+       else
+               tmp |= NFC_V3_CONFIG2_INT_MSK;
+
+       writel(tmp, NFC_V3_CONFIG2);
+}
+
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
@@ -257,10 +308,9 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
 
        if (useirq) {
                if (!host->check_int(host)) {
-
-                       enable_irq(host->irq);
-
-                       wait_event(host->irq_waitq, host->check_int(host));
+                       INIT_COMPLETION(host->op_completion);
+                       host->irq_control(host, 1);
+                       wait_for_completion(&host->op_completion);
                }
        } else {
                while (max_retries-- > 0) {
@@ -402,16 +452,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host)
        /* Wait for operation to complete */
        wait_op_done(host, true);
 
+       memcpy(host->data_buf, host->main_area0, 16);
+
        if (this->options & NAND_BUSWIDTH_16) {
-               void __iomem *main_buf = host->main_area0;
                /* compress the ID info */
-               writeb(readb(main_buf + 2), main_buf + 1);
-               writeb(readb(main_buf + 4), main_buf + 2);
-               writeb(readb(main_buf + 6), main_buf + 3);
-               writeb(readb(main_buf + 8), main_buf + 4);
-               writeb(readb(main_buf + 10), main_buf + 5);
+               host->data_buf[1] = host->data_buf[2];
+               host->data_buf[2] = host->data_buf[4];
+               host->data_buf[3] = host->data_buf[6];
+               host->data_buf[4] = host->data_buf[8];
+               host->data_buf[5] = host->data_buf[10];
        }
-       memcpy(host->data_buf, host->main_area0, 16);
 }
 
 static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
@@ -729,27 +779,30 @@ static void preset_v1_v2(struct mtd_info *mtd)
 {
        struct nand_chip *nand_chip = mtd->priv;
        struct mxc_nand_host *host = nand_chip->priv;
-       uint16_t tmp;
+       uint16_t config1 = 0;
 
-       /* enable interrupt, disable spare enable */
-       tmp = readw(NFC_V1_V2_CONFIG1);
-       tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
-       tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
-       if (nand_chip->ecc.mode == NAND_ECC_HW) {
-               tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
-       } else {
-               tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
-       }
+       if (nand_chip->ecc.mode == NAND_ECC_HW)
+               config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
+
+       if (nfc_is_v21())
+               config1 |= NFC_V2_CONFIG1_FP_INT;
+
+       if (!cpu_is_mx21())
+               config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
 
        if (nfc_is_v21() && mtd->writesize) {
+               uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
+
                host->eccsize = get_eccsize(mtd);
                if (host->eccsize == 4)
-                       tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
+                       config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
+
+               config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
        } else {
                host->eccsize = 1;
        }
 
-       writew(tmp, NFC_V1_V2_CONFIG1);
+       writew(config1, NFC_V1_V2_CONFIG1);
        /* preset operation */
 
        /* Unlock the internal RAM Buffer */
@@ -794,6 +847,7 @@ static void preset_v3(struct mtd_info *mtd)
                NFC_V3_CONFIG2_2CMD_PHASES |
                NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
                NFC_V3_CONFIG2_ST_CMD(0x70) |
+               NFC_V3_CONFIG2_INT_MSK |
                NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
 
        if (chip->ecc.mode == NAND_ECC_HW)
@@ -1019,6 +1073,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
                host->send_read_id = send_read_id_v1_v2;
                host->get_dev_status = get_dev_status_v1_v2;
                host->check_int = check_int_v1_v2;
+               if (cpu_is_mx21())
+                       host->irq_control = irq_control_mx21;
+               else
+                       host->irq_control = irq_control_v1_v2;
        }
 
        if (nfc_is_v21()) {
@@ -1057,6 +1115,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
                host->send_read_id = send_read_id_v3;
                host->check_int = check_int_v3;
                host->get_dev_status = get_dev_status_v3;
+               host->irq_control = irq_control_v3;
                oob_smallpage = &nandv2_hw_eccoob_smallpage;
                oob_largepage = &nandv2_hw_eccoob_largepage;
        } else
@@ -1088,14 +1147,34 @@ static int __init mxcnd_probe(struct platform_device *pdev)
                this->options |= NAND_USE_FLASH_BBT;
        }
 
-       init_waitqueue_head(&host->irq_waitq);
+       init_completion(&host->op_completion);
 
        host->irq = platform_get_irq(pdev, 0);
 
+       /*
+        * mask the interrupt. For i.MX21 explicitely call
+        * irq_control_v1_v2 to use the mask bit. We can't call
+        * disable_irq_nosync() for an interrupt we do not own yet.
+        */
+       if (cpu_is_mx21())
+               irq_control_v1_v2(host, 0);
+       else
+               host->irq_control(host, 0);
+
        err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
        if (err)
                goto eirq;
 
+       host->irq_control(host, 0);
+
+       /*
+        * Now that the interrupt is disabled make sure the interrupt
+        * mask bit is cleared on i.MX21. Otherwise we can't read
+        * the interrupt status bit on this machine.
+        */
+       if (cpu_is_mx21())
+               irq_control_v1_v2(host, 1);
+
        /* first scan to find the device and get the page size */
        if (nand_scan_ident(mtd, 1, NULL)) {
                err = -ENXIO;
index 133d51528f8dc0fb79eae4d12230e1a65bd7595e..513e0a76a4a73866d52bba8151e43556a3b30a54 100644 (file)
@@ -413,7 +413,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
                prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT);
        } while (prefetch_status);
        /* disable and stop the PFPW engine */
-       gpmc_prefetch_reset();
+       gpmc_prefetch_reset(info->gpmc_cs);
 
        dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
        return 0;
index 4d89f37802075a26e602cf4ba6f42de54d07cfc8..4d01cda6884463daa844c02fde951970854e972a 100644 (file)
@@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
                goto fail_free_irq;
        }
 
+#ifdef CONFIG_MTD_PARTITIONS
        if (mtd_has_cmdlinepart()) {
                static const char *probes[] = { "cmdlinepart", NULL };
                struct mtd_partition *parts;
@@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        }
 
        return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+#else
+       return 0;
+#endif
 
 fail_free_irq:
        free_irq(irq, info);
@@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        del_mtd_device(mtd);
+#ifdef CONFIG_MTD_PARTITIONS
        del_mtd_partitions(mtd);
+#endif
        irq = platform_get_irq(pdev, 0);
        if (irq >= 0)
                free_irq(irq, info);
index cb443af3d45feee407bb79e8440f439cbdba7bd1..a460f1b748c20fbcb29982925820b79e6a7bbd78 100644 (file)
@@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
 
        do {
                status = readl(base + S5PC110_DMA_TRANS_STATUS);
+               if (status & S5PC110_DMA_TRANS_STATUS_TE) {
+                       writel(S5PC110_DMA_TRANS_CMD_TEC,
+                                       base + S5PC110_DMA_TRANS_CMD);
+                       return -EIO;
+               }
        } while (!(status & S5PC110_DMA_TRANS_STATUS_TD));
 
-       if (status & S5PC110_DMA_TRANS_STATUS_TE) {
-               writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD);
-               writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
-               return -EIO;
-       }
-
        writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
 
        return 0;
@@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
                unsigned char *buffer, int offset, size_t count)
 {
        struct onenand_chip *this = mtd->priv;
-       void __iomem *bufferram;
        void __iomem *p;
        void *buf = (void *) buffer;
        dma_addr_t dma_src, dma_dst;
        int err;
 
-       p = bufferram = this->base + area;
+       p = this->base + area;
        if (ONENAND_CURRENT_BUFFERRAM(this)) {
                if (area == ONENAND_DATARAM)
                        p += this->writesize;
@@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
 normal:
        if (count != mtd->writesize) {
                /* Copy the bufferram to memory to prevent unaligned access */
-               memcpy(this->page_buf, bufferram, mtd->writesize);
+               memcpy(this->page_buf, p, mtd->writesize);
                p = this->page_buf + offset;
        }
 
index f702a163d8dfa429834d78e861f4e75e5210b317..3cf193fb5e00c722b864f194939c525c9cd73f23 100644 (file)
@@ -1,9 +1,5 @@
-menu "UBI - Unsorted block images"
-       depends on MTD
-
-config MTD_UBI
-       tristate "Enable UBI"
-       depends on MTD
+menuconfig MTD_UBI
+       tristate "Enable UBI - Unsorted block images"
        select CRC32
        help
          UBI is a software layer above MTD layer which admits of LVM-like
@@ -12,11 +8,12 @@ config MTD_UBI
          capabilities. Please, consult the MTD web site for more details
          (www.linux-mtd.infradead.org).
 
+if MTD_UBI
+
 config MTD_UBI_WL_THRESHOLD
        int "UBI wear-leveling threshold"
        default 4096
        range 2 65536
-       depends on MTD_UBI
        help
          This parameter defines the maximum difference between the highest
          erase counter value and the lowest erase counter value of eraseblocks
@@ -34,7 +31,6 @@ config MTD_UBI_BEB_RESERVE
        int "Percentage of reserved eraseblocks for bad eraseblocks handling"
        default 1
        range 0 25
-       depends on MTD_UBI
        help
          If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
          reserves some amount of physical eraseblocks to handle new bad
@@ -48,8 +44,6 @@ config MTD_UBI_BEB_RESERVE
 
 config MTD_UBI_GLUEBI
        tristate "MTD devices emulation driver (gluebi)"
-       default n
-       depends on MTD_UBI
        help
           This option enables gluebi - an additional driver which emulates MTD
           devices on top of UBI volumes: for each UBI volumes an MTD device is
@@ -59,4 +53,5 @@ config MTD_UBI_GLUEBI
           software.
 
 source "drivers/mtd/ubi/Kconfig.debug"
-endmenu
+
+endif # MTD_UBI
index 2246f154e2f7a6f57317cf2232070f39ada5d4dc..fad4adc0fe2c07dcac9ce3725ac202b1f314d372 100644 (file)
@@ -1,94 +1,73 @@
 comment "UBI debugging options"
-       depends on MTD_UBI
 
 config MTD_UBI_DEBUG
        bool "UBI debugging"
        depends on SYSFS
-       depends on MTD_UBI
        select DEBUG_FS
-       select KALLSYMS_ALL
+       select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
        help
          This option enables UBI debugging.
 
+if MTD_UBI_DEBUG
+
 config MTD_UBI_DEBUG_MSG
        bool "UBI debugging messages"
-       depends on MTD_UBI_DEBUG
-       default n
        help
          This option enables UBI debugging messages.
 
 config MTD_UBI_DEBUG_PARANOID
        bool "Extra self-checks"
-       default n
-       depends on MTD_UBI_DEBUG
        help
          This option enables extra checks in UBI code. Note this slows UBI down
          significantly.
 
 config MTD_UBI_DEBUG_DISABLE_BGT
        bool "Do not enable the UBI background thread"
-       depends on MTD_UBI_DEBUG
-       default n
        help
          This option switches the background thread off by default. The thread
          may be also be enabled/disabled via UBI sysfs.
 
 config MTD_UBI_DEBUG_EMULATE_BITFLIPS
        bool "Emulate flash bit-flips"
-       depends on MTD_UBI_DEBUG
-       default n
        help
          This option emulates bit-flips with probability 1/50, which in turn
          causes scrubbing. Useful for debugging and stressing UBI.
 
 config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
        bool "Emulate flash write failures"
-       depends on MTD_UBI_DEBUG
-       default n
        help
          This option emulates write failures with probability 1/100. Useful for
          debugging and testing how UBI handlines errors.
 
 config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
        bool "Emulate flash erase failures"
-       depends on MTD_UBI_DEBUG
-       default n
        help
          This option emulates erase failures with probability 1/100. Useful for
          debugging and testing how UBI handlines errors.
 
-menu "Additional UBI debugging messages"
-       depends on MTD_UBI_DEBUG
+comment "Additional UBI debugging messages"
 
 config MTD_UBI_DEBUG_MSG_BLD
        bool "Additional UBI initialization and build messages"
-       default n
-       depends on MTD_UBI_DEBUG
        help
          This option enables detailed UBI initialization and device build
          debugging messages.
 
 config MTD_UBI_DEBUG_MSG_EBA
        bool "Eraseblock association unit messages"
-       default n
-       depends on MTD_UBI_DEBUG
        help
          This option enables debugging messages from the UBI eraseblock
          association unit.
 
 config MTD_UBI_DEBUG_MSG_WL
        bool "Wear-leveling unit messages"
-       default n
-       depends on MTD_UBI_DEBUG
        help
          This option enables debugging messages from the UBI wear-leveling
          unit.
 
 config MTD_UBI_DEBUG_MSG_IO
        bool "Input/output unit messages"
-       default n
-       depends on MTD_UBI_DEBUG
        help
          This option enables debugging messages from the UBI input/output unit.
 
-endmenu # UBI debugging messages
+endif # MTD_UBI_DEBUG
index 78ae89488a4fbc54550bf4a7dd54877035b295ec..5ebe280225d60a69f28bc81c5c4593a47e017365 100644 (file)
@@ -95,8 +95,8 @@ DEFINE_MUTEX(ubi_devices_mutex);
 static DEFINE_SPINLOCK(ubi_devices_lock);
 
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
-                               char *buf)
+static ssize_t ubi_version_show(struct class *class,
+                               struct class_attribute *attr, char *buf)
 {
        return sprintf(buf, "%d\n", UBI_VERSION);
 }
@@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
 
        ubi->bad_peb_count = si->bad_peb_count;
        ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+       ubi->corr_peb_count = si->corr_peb_count;
        ubi->max_ec = si->max_ec;
        ubi->mean_ec = si->mean_ec;
        ubi_msg("max. sequence number:       %llu", si->max_sqnum);
@@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
        ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
        ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
+       ubi_msg("number of corrupted PEBs:   %d", ubi->corr_peb_count);
        ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
        ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);
        ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
index 4dfa6b90c21c30566d35939d7d3837327495f208..af9fb0ff8210d5b3d34c3a2e788123b2a7745aaf 100644 (file)
@@ -798,18 +798,18 @@ static int rename_volumes(struct ubi_device *ubi,
                        goto out_free;
                }
 
-               re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
-               if (!re) {
+               re1 = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
+               if (!re1) {
                        err = -ENOMEM;
                        ubi_close_volume(desc);
                        goto out_free;
                }
 
-               re->remove = 1;
-               re->desc = desc;
-               list_add(&re->list, &rename_list);
+               re1->remove = 1;
+               re1->desc = desc;
+               list_add(&re1->list, &rename_list);
                dbg_msg("will remove volume %d, name \"%s\"",
-                       re->desc->vol->vol_id, re->desc->vol->name);
+                       re1->desc->vol->vol_id, re1->desc->vol->name);
        }
 
        mutex_lock(&ubi->device_mutex);
@@ -1100,4 +1100,5 @@ const struct file_operations ubi_ctrl_cdev_operations = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = ctrl_cdev_ioctl,
        .compat_ioctl   = ctrl_cdev_compat_ioctl,
+       .llseek         = noop_llseek,
 };
index 17a1071297267b7a45e565f71f8bbedb7ab31df6..9eca95074bc2970f650bca1e7c3e9768f3941b93 100644 (file)
@@ -57,6 +57,9 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
 
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  \
+               print_hex_dump(l, ps, pt, r, g, b, len, a)
+
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG
 /* General debugging messages */
 #define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
@@ -172,6 +175,7 @@ static inline int ubi_dbg_is_erase_failure(void)
 #define ubi_dbg_dump_seb(seb, type)      ({})
 #define ubi_dbg_dump_mkvol_req(req)      ({})
 #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  ({})
 
 #define UBI_IO_DEBUG               0
 #define DBG_DISABLE_BGT            0
index fe74749e0dae734271b9a6b9e780f11e5cbb021c..4be671815014ee3b054f2ba8f704781dfbc1f032 100644 (file)
@@ -418,7 +418,7 @@ retry:
                                 * may try to recover data. FIXME: but this is
                                 * not implemented.
                                 */
-                               if (err == UBI_IO_BAD_HDR_READ ||
+                               if (err == UBI_IO_BAD_HDR_EBADMSG ||
                                    err == UBI_IO_BAD_HDR) {
                                        ubi_warn("corrupted VID header at PEB "
                                                 "%d, LEB %d:%d", pnum, vol_id,
@@ -963,7 +963,7 @@ write_error:
 static int is_error_sane(int err)
 {
        if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
-           err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
+           err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT)
                return 0;
        return 1;
 }
@@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi,
 
        ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
                 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+       if (ubi->corr_peb_count)
+               ubi_warn("%d PEBs are corrupted and not used",
+                       ubi->corr_peb_count);
 }
 
 /**
@@ -1263,6 +1266,9 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
        if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
                ubi_err("no enough physical eraseblocks (%d, need %d)",
                        ubi->avail_pebs, EBA_RESERVED_PEBS);
+               if (ubi->corr_peb_count)
+                       ubi_err("%d PEBs are corrupted and not used",
+                               ubi->corr_peb_count);
                err = -ENOSPC;
                goto out_free;
        }
index 332f992f13d982e4d1d46164f673a4f67914ce87..c2960ac9f39c9e863216c91b607e157c0ff65271 100644 (file)
@@ -376,25 +376,6 @@ retry:
        return 0;
 }
 
-/**
- * check_pattern - check if buffer contains only a certain byte pattern.
- * @buf: buffer to check
- * @patt: the pattern to check
- * @size: buffer size in bytes
- *
- * This function returns %1 in there are only @patt bytes in @buf, and %0 if
- * something else was also found.
- */
-static int check_pattern(const void *buf, uint8_t patt, int size)
-{
-       int i;
-
-       for (i = 0; i < size; i++)
-               if (((const uint8_t *)buf)[i] != patt)
-                       return 0;
-       return 1;
-}
-
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
@@ -426,7 +407,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
                if (err)
                        goto out;
 
-               err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+               err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
                if (err == 0) {
                        ubi_err("erased PEB %d, but a non-0xFF byte found",
                                pnum);
@@ -445,7 +426,8 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
                if (err)
                        goto out;
 
-               err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
+               err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+                                       ubi->peb_size);
                if (err == 0) {
                        ubi_err("pattern %x checking failed for PEB %d",
                                patterns[i], pnum);
@@ -517,7 +499,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
         * In this case we probably anyway have garbage in this PEB.
         */
        err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-       if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
+       if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
                /*
                 * The VID header is corrupted, so we can safely erase this
                 * PEB and not afraid that it will be treated as a valid PEB in
@@ -712,47 +694,47 @@ bad:
  *   and corrected by the flash driver; this is harmless but may indicate that
  *   this eraseblock may become bad soon (but may be not);
  * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
- * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
+ * o %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was
+ *   a data integrity error (uncorrectable ECC error in case of NAND);
+ * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
  * o a negative error code in case of failure.
  */
 int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                       struct ubi_ec_hdr *ec_hdr, int verbose)
 {
-       int err, read_err = 0;
+       int err, read_err;
        uint32_t crc, magic, hdr_crc;
 
        dbg_io("read EC header from PEB %d", pnum);
        ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
-       err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
-       if (err) {
-               if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-                       return err;
+       read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+       if (read_err) {
+               if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+                       return read_err;
 
                /*
                 * We read all the data, but either a correctable bit-flip
-                * occurred, or MTD reported about some data integrity error,
-                * like an ECC error in case of NAND. The former is harmless,
-                * the later may mean that the read data is corrupted. But we
-                * have a CRC check-sum and we will detect this. If the EC
-                * header is still OK, we just report this as there was a
-                * bit-flip.
+                * occurred, or MTD reported a data integrity error
+                * (uncorrectable ECC error in case of NAND). The former is
+                * harmless, the later may mean that the read data is
+                * corrupted. But we have a CRC check-sum and we will detect
+                * this. If the EC header is still OK, we just report this as
+                * there was a bit-flip, to force scrubbing.
                 */
-               if (err == -EBADMSG)
-                       read_err = UBI_IO_BAD_HDR_READ;
        }
 
        magic = be32_to_cpu(ec_hdr->magic);
        if (magic != UBI_EC_HDR_MAGIC) {
-               if (read_err)
-                       return read_err;
+               if (read_err == -EBADMSG)
+                       return UBI_IO_BAD_HDR_EBADMSG;
 
                /*
                 * The magic field is wrong. Let's check if we have read all
                 * 0xFF. If yes, this physical eraseblock is assumed to be
                 * empty.
                 */
-               if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
+               if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
                        /* The physical eraseblock is supposedly empty */
                        if (verbose)
                                ubi_warn("no EC header found at PEB %d, "
@@ -760,7 +742,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                        else if (UBI_IO_DEBUG)
                                dbg_msg("no EC header found at PEB %d, "
                                        "only 0xFF bytes", pnum);
-                       return UBI_IO_PEB_EMPTY;
+                       if (!read_err)
+                               return UBI_IO_FF;
+                       else
+                               return UBI_IO_FF_BITFLIPS;
                }
 
                /*
@@ -788,7 +773,11 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                } else if (UBI_IO_DEBUG)
                        dbg_msg("bad EC header CRC at PEB %d, calculated "
                                "%#08x, read %#08x", pnum, crc, hdr_crc);
-               return read_err ?: UBI_IO_BAD_HDR;
+
+               if (!read_err)
+                       return UBI_IO_BAD_HDR;
+               else
+                       return UBI_IO_BAD_HDR_EBADMSG;
        }
 
        /* And of course validate what has just been read from the media */
@@ -975,22 +964,16 @@ bad:
  *
  * This function reads the volume identifier header from physical eraseblock
  * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read
- * volume identifier header. The following codes may be returned:
+ * volume identifier header. The error codes are the same as in
+ * 'ubi_io_read_ec_hdr()'.
  *
- * o %0 if the CRC checksum is correct and the header was successfully read;
- * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
- *   and corrected by the flash driver; this is harmless but may indicate that
- *   this eraseblock may become bad soon;
- * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
- *   error detected);
- * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
- *   header there);
- * o a negative error code in case of failure.
+ * Note, the implementation of this function is also very similar to
+ * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
  */
 int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        struct ubi_vid_hdr *vid_hdr, int verbose)
 {
-       int err, read_err = 0;
+       int err, read_err;
        uint32_t crc, magic, hdr_crc;
        void *p;
 
@@ -998,48 +981,29 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
        ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
 
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
-       err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+       read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
                          ubi->vid_hdr_alsize);
-       if (err) {
-               if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-                       return err;
-
-               /*
-                * We read all the data, but either a correctable bit-flip
-                * occurred, or MTD reported about some data integrity error,
-                * like an ECC error in case of NAND. The former is harmless,
-                * the later may mean the read data is corrupted. But we have a
-                * CRC check-sum and we will identify this. If the VID header is
-                * still OK, we just report this as there was a bit-flip.
-                */
-               if (err == -EBADMSG)
-                       read_err = UBI_IO_BAD_HDR_READ;
-       }
+       if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+               return read_err;
 
        magic = be32_to_cpu(vid_hdr->magic);
        if (magic != UBI_VID_HDR_MAGIC) {
-               if (read_err)
-                       return read_err;
+               if (read_err == -EBADMSG)
+                       return UBI_IO_BAD_HDR_EBADMSG;
 
-               /*
-                * If we have read all 0xFF bytes, the VID header probably does
-                * not exist and the physical eraseblock is assumed to be free.
-                */
-               if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
-                       /* The physical eraseblock is supposedly free */
+               if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
                        if (verbose)
                                ubi_warn("no VID header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
                        else if (UBI_IO_DEBUG)
                                dbg_msg("no VID header found at PEB %d, "
                                        "only 0xFF bytes", pnum);
-                       return UBI_IO_PEB_FREE;
+                       if (!read_err)
+                               return UBI_IO_FF;
+                       else
+                               return UBI_IO_FF_BITFLIPS;
                }
 
-               /*
-                * This is not a valid VID header, and these are not 0xFF
-                * bytes. Report that the header is corrupted.
-                */
                if (verbose) {
                        ubi_warn("bad magic number at PEB %d: %08x instead of "
                                 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1061,20 +1025,18 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                } else if (UBI_IO_DEBUG)
                        dbg_msg("bad CRC at PEB %d, calculated %#08x, "
                                "read %#08x", pnum, crc, hdr_crc);
-               return read_err ?: UBI_IO_BAD_HDR;
+               if (!read_err)
+                       return UBI_IO_BAD_HDR;
+               else
+                       return UBI_IO_BAD_HDR_EBADMSG;
        }
 
-       /* Validate the VID header that we have just read */
        err = validate_vid_hdr(ubi, vid_hdr);
        if (err) {
                ubi_err("validation failed for PEB %d", pnum);
                return -EINVAL;
        }
 
-       /*
-        * If there was a read error (%-EBADMSG), but the header CRC is still
-        * OK, report about a bit-flip to force scrubbing on this PEB.
-        */
        return read_err ? UBI_IO_BITFLIPS : 0;
 }
 
@@ -1383,7 +1345,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
                goto error;
        }
 
-       err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+       err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
        if (err == 0) {
                ubi_err("flash region at PEB %d:%d, length %d does not "
                        "contain all 0xFF bytes", pnum, offset, len);
index 22ad314029452935dfffff32165d49047da2603d..ff2a65c37f69a6c12e7dbbdafb0c8367e951ce49 100644 (file)
@@ -103,3 +103,22 @@ void ubi_calculate_reserved(struct ubi_device *ubi)
        if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
                ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
 }
+
+/**
+ * ubi_check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+int ubi_check_pattern(const void *buf, uint8_t patt, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++)
+               if (((const uint8_t *)buf)[i] != patt)
+                       return 0;
+       return 1;
+}
index 372a15ac9995a64c7fc8f8084c75cb59ba4251d1..3c631863bf40b5b3b5db70e28f4e6b3937e4be49 100644 (file)
@@ -29,7 +29,7 @@
  * objects which are kept in volume RB-tree with root at the @volumes field.
  * The RB-tree is indexed by the volume ID.
  *
- * Found logical eraseblocks are represented by &struct ubi_scan_leb objects.
+ * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
  * These objects are kept in per-volume RB-trees with the root at the
  * corresponding &struct ubi_scan_volume object. To put it differently, we keep
  * an RB-tree of per-volume objects and each of these objects is the root of
  * Corrupted physical eraseblocks are put to the @corr list, free physical
  * eraseblocks are put to the @free list and the physical eraseblock to be
  * erased are put to the @erase list.
+ *
+ * UBI tries to distinguish between 2 types of corruptions.
+ * 1. Corruptions caused by power cuts. These are harmless and expected
+ *    corruptions and UBI tries to handle them gracefully, without printing too
+ *    many warnings and error messages. The idea is that we do not lose
+ *    important data in these case - we may lose only the data which was being
+ *    written to the media just before the power cut happened, and the upper
+ *    layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
+ *    these PEBs to the head of the @erase list and they are scheduled for
+ *    erasure.
+ *
+ * 2. Unexpected corruptions which are not caused by power cuts. During
+ *    scanning, such PEBs are put to the @corr list and UBI preserves them.
+ *    Obviously, this lessens the amount of available PEBs, and if at some
+ *    point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
+ *    informs about such PEBs every time the MTD device is attached.
+ *
+ * However, it is difficult to reliably distinguish between these types of
+ * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
+ * header is corrupted and the data area does not contain all 0xFFs, and there
+ * were not bit-flips or integrity errors while reading the data area. Otherwise
+ * UBI assumes (1.). The assumptions are:
+ *   o if the data area contains only 0xFFs, there is no data, and it is safe
+ *     to just erase this PEB.
+ *   o if the data area has bit-flips and data integrity errors (ECC errors on
+ *     NAND), it is probably a PEB which was being erased when power cut
+ *     happened.
  */
 
 #include <linux/err.h>
@@ -62,26 +89,26 @@ static struct ubi_vid_hdr *vidh;
  * @si: scanning information
  * @pnum: physical eraseblock number to add
  * @ec: erase counter of the physical eraseblock
+ * @to_head: if not zero, add to the head of the list
  * @list: the list to add to
  *
- * This function adds physical eraseblock @pnum to free, erase, corrupted or
- * alien lists. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This function adds physical eraseblock @pnum to free, erase, or alien lists.
+ * If @to_head is not zero, PEB will be added to the head of the list, which
+ * basically means it will be processed first later. E.g., we add corrupted
+ * PEBs (corrupted due to power cuts) to the head of the erase list to make
+ * sure we erase them first and get rid of corruptions ASAP. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
  */
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
                       struct list_head *list)
 {
        struct ubi_scan_leb *seb;
 
        if (list == &si->free) {
                dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
-               si->free_peb_count += 1;
        } else if (list == &si->erase) {
                dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
-               si->erase_peb_count += 1;
-       } else if (list == &si->corr) {
-               dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
-               si->corr_peb_count += 1;
        } else if (list == &si->alien) {
                dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
                si->alien_peb_count += 1;
@@ -94,7 +121,37 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
 
        seb->pnum = pnum;
        seb->ec = ec;
-       list_add_tail(&seb->u.list, list);
+       if (to_head)
+               list_add(&seb->u.list, list);
+       else
+               list_add_tail(&seb->u.list, list);
+       return 0;
+}
+
+/**
+ * add_corrupted - add a corrupted physical eraseblock.
+ * @si: scanning information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
+ * The corruption was presumably not caused by a power cut. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
+{
+       struct ubi_scan_leb *seb;
+
+       dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
+
+       seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+       if (!seb)
+               return -ENOMEM;
+
+       si->corr_peb_count += 1;
+       seb->pnum = pnum;
+       seb->ec = ec;
+       list_add(&seb->u.list, &si->corr);
        return 0;
 }
 
@@ -258,8 +315,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
                 * created before sequence numbers support has been added. At
                 * that times we used 32-bit LEB versions stored in logical
                 * eraseblocks. That was before UBI got into mainline. We do not
-                * support these images anymore. Well, those images will work
-                * still work, but only if no unclean reboots happened.
+                * support these images anymore. Well, those images still work,
+                * but only if no unclean reboots happened.
                 */
                ubi_err("unsupported on-flash UBI format\n");
                return -EINVAL;
@@ -285,19 +342,25 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
                        return 1;
                }
        } else {
-               pnum = seb->pnum;
+               if (!seb->copy_flag) {
+                       /* It is not a copy, so it is newer */
+                       dbg_bld("first PEB %d is newer, copy_flag is unset",
+                               pnum);
+                       return bitflips << 1;
+               }
 
                vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
                if (!vh)
                        return -ENOMEM;
 
+               pnum = seb->pnum;
                err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
                if (err) {
                        if (err == UBI_IO_BITFLIPS)
                                bitflips = 1;
                        else {
                                dbg_err("VID of PEB %d header is bad, but it "
-                                       "was OK earlier", pnum);
+                                       "was OK earlier, err %d", pnum, err);
                                if (err > 0)
                                        err = -EIO;
 
@@ -305,14 +368,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
                        }
                }
 
-               if (!vh->copy_flag) {
-                       /* It is not a copy, so it is newer */
-                       dbg_bld("first PEB %d is newer, copy_flag is unset",
-                               pnum);
-                       err = bitflips << 1;
-                       goto out_free_vidh;
-               }
-
                vid_hdr = vh;
        }
 
@@ -463,18 +518,15 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                        if (err)
                                return err;
 
-                       if (cmp_res & 4)
-                               err = add_to_list(si, seb->pnum, seb->ec,
-                                                 &si->corr);
-                       else
-                               err = add_to_list(si, seb->pnum, seb->ec,
-                                                 &si->erase);
+                       err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
+                                         &si->erase);
                        if (err)
                                return err;
 
                        seb->ec = ec;
                        seb->pnum = pnum;
                        seb->scrub = ((cmp_res & 2) || bitflips);
+                       seb->copy_flag = vid_hdr->copy_flag;
                        seb->sqnum = sqnum;
 
                        if (sv->highest_lnum == lnum)
@@ -487,10 +539,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                         * This logical eraseblock is older than the one found
                         * previously.
                         */
-                       if (cmp_res & 4)
-                               return add_to_list(si, pnum, ec, &si->corr);
-                       else
-                               return add_to_list(si, pnum, ec, &si->erase);
+                       return add_to_list(si, pnum, ec, cmp_res & 4,
+                                          &si->erase);
                }
        }
 
@@ -510,8 +560,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
        seb->ec = ec;
        seb->pnum = pnum;
        seb->lnum = lnum;
-       seb->sqnum = sqnum;
        seb->scrub = bitflips;
+       seb->copy_flag = vid_hdr->copy_flag;
+       seb->sqnum = sqnum;
 
        if (sv->highest_lnum <= lnum) {
                sv->highest_lnum = lnum;
@@ -521,7 +572,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
        sv->leb_count += 1;
        rb_link_node(&seb->u.rb, parent, p);
        rb_insert_color(&seb->u.rb, &sv->root);
-       si->used_peb_count += 1;
        return 0;
 }
 
@@ -668,8 +718,8 @@ out_free:
 struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
                                           struct ubi_scan_info *si)
 {
-       int err = 0, i;
-       struct ubi_scan_leb *seb;
+       int err = 0;
+       struct ubi_scan_leb *seb, *tmp_seb;
 
        if (!list_empty(&si->free)) {
                seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
@@ -678,38 +728,86 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
                return seb;
        }
 
-       for (i = 0; i < 2; i++) {
-               struct list_head *head;
-               struct ubi_scan_leb *tmp_seb;
+       /*
+        * We try to erase the first physical eraseblock from the erase list
+        * and pick it if we succeed, or try to erase the next one if not. And
+        * so forth. We don't want to take care about bad eraseblocks here -
+        * they'll be handled later.
+        */
+       list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
+               if (seb->ec == UBI_SCAN_UNKNOWN_EC)
+                       seb->ec = si->mean_ec;
 
-               if (i == 0)
-                       head = &si->erase;
-               else
-                       head = &si->corr;
+               err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
+               if (err)
+                       continue;
 
+               seb->ec += 1;
+               list_del(&seb->u.list);
+               dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
+               return seb;
+       }
+
+       ubi_err("no free eraseblocks");
+       return ERR_PTR(-ENOSPC);
+}
+
+/**
+ * check_corruption - check the data area of PEB.
+ * @ubi: UBI device description object
+ * @vid_hrd: the (corrupted) VID header of this PEB
+ * @pnum: the physical eraseblock number to check
+ *
+ * This is a helper function which is used to distinguish between VID header
+ * corruptions caused by power cuts and other reasons. If the PEB contains only
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
+ * because of a power cut (%0 is returned in this case). Otherwise, it was
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
+ *
+ * If the corruption reason was a power cut, UBI can safely erase this PEB.
+ * Otherwise, it should preserve it to avoid possibly destroying important
+ * information.
+ */
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+                           int pnum)
+{
+       int err;
+
+       mutex_lock(&ubi->buf_mutex);
+       memset(ubi->peb_buf1, 0x00, ubi->leb_size);
+
+       err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
+                         ubi->leb_size);
+       if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
                /*
-                * We try to erase the first physical eraseblock from the @head
-                * list and pick it if we succeed, or try to erase the
-                * next one if not. And so forth. We don't want to take care
-                * about bad eraseblocks here - they'll be handled later.
+                * Bit-flips or integrity errors while reading the data area.
+                * It is difficult to say for sure what type of corruption is
+                * this, but presumably a power cut happened while this PEB was
+                * erased, so it became unstable and corrupted, and should be
+                * erased.
                 */
-               list_for_each_entry_safe(seb, tmp_seb, head, u.list) {
-                       if (seb->ec == UBI_SCAN_UNKNOWN_EC)
-                               seb->ec = si->mean_ec;
+               return 0;
+       }
 
-                       err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
-                       if (err)
-                               continue;
+       if (err)
+               return err;
 
-                       seb->ec += 1;
-                       list_del(&seb->u.list);
-                       dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
-                       return seb;
-               }
+       if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
+               mutex_unlock(&ubi->buf_mutex);
+               return 0;
        }
 
-       ubi_err("no eraseblocks found");
-       return ERR_PTR(-ENOSPC);
+       ubi_err("PEB %d contains corrupted VID header, and the data does not "
+               "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
+               "header corruption which requires manual inspection", pnum);
+       ubi_dbg_dump_vid_hdr(vid_hdr);
+       dbg_msg("hexdump of PEB %d offset %d, length %d",
+               pnum, ubi->leb_start, ubi->leb_size);
+       ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+                              ubi->peb_buf1, ubi->leb_size, 1);
+       mutex_unlock(&ubi->buf_mutex);
+       return 1;
 }
 
 /**
@@ -725,7 +823,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                      int pnum)
 {
        long long uninitialized_var(ec);
-       int err, bitflips = 0, vol_id, ec_corr = 0;
+       int err, bitflips = 0, vol_id, ec_err = 0;
 
        dbg_bld("scan PEB %d", pnum);
 
@@ -746,22 +844,37 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
        err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
        if (err < 0)
                return err;
-       else if (err == UBI_IO_BITFLIPS)
+       switch (err) {
+       case 0:
+               break;
+       case UBI_IO_BITFLIPS:
                bitflips = 1;
-       else if (err == UBI_IO_PEB_EMPTY)
-               return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
-       else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {
+               break;
+       case UBI_IO_FF:
+               si->empty_peb_count += 1;
+               return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
+                                  &si->erase);
+       case UBI_IO_FF_BITFLIPS:
+               si->empty_peb_count += 1;
+               return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
+                                  &si->erase);
+       case UBI_IO_BAD_HDR_EBADMSG:
+       case UBI_IO_BAD_HDR:
                /*
                 * We have to also look at the VID header, possibly it is not
                 * corrupted. Set %bitflips flag in order to make this PEB be
                 * moved and EC be re-created.
                 */
-               ec_corr = err;
+               ec_err = err;
                ec = UBI_SCAN_UNKNOWN_EC;
                bitflips = 1;
+               break;
+       default:
+               ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+               return -EINVAL;
        }
 
-       if (!ec_corr) {
+       if (!ec_err) {
                int image_seq;
 
                /* Make sure UBI version is OK */
@@ -814,24 +927,67 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
        err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
        if (err < 0)
                return err;
-       else if (err == UBI_IO_BITFLIPS)
+       switch (err) {
+       case 0:
+               break;
+       case UBI_IO_BITFLIPS:
                bitflips = 1;
-       else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||
-                (err == UBI_IO_PEB_FREE && ec_corr)) {
-               /* VID header is corrupted */
-               if (err == UBI_IO_BAD_HDR_READ ||
-                   ec_corr == UBI_IO_BAD_HDR_READ)
-                       si->read_err_count += 1;
-               err = add_to_list(si, pnum, ec, &si->corr);
+               break;
+       case UBI_IO_BAD_HDR_EBADMSG:
+               if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
+                       /*
+                        * Both EC and VID headers are corrupted and were read
+                        * with data integrity error, probably this is a bad
+                        * PEB, bit it is not marked as bad yet. This may also
+                        * be a result of power cut during erasure.
+                        */
+                       si->maybe_bad_peb_count += 1;
+       case UBI_IO_BAD_HDR:
+               if (ec_err)
+                       /*
+                        * Both headers are corrupted. There is a possibility
+                        * that this a valid UBI PEB which has corresponding
+                        * LEB, but the headers are corrupted. However, it is
+                        * impossible to distinguish it from a PEB which just
+                        * contains garbage because of a power cut during erase
+                        * operation. So we just schedule this PEB for erasure.
+                        */
+                       err = 0;
+               else
+                       /*
+                        * The EC was OK, but the VID header is corrupted. We
+                        * have to check what is in the data area.
+                        */
+                       err = check_corruption(ubi, vidh, pnum);
+
+               if (err < 0)
+                       return err;
+               else if (!err)
+                       /* This corruption is caused by a power cut */
+                       err = add_to_list(si, pnum, ec, 1, &si->erase);
+               else
+                       /* This is an unexpected corruption */
+                       err = add_corrupted(si, pnum, ec);
                if (err)
                        return err;
                goto adjust_mean_ec;
-       } else if (err == UBI_IO_PEB_FREE) {
-               /* No VID header - the physical eraseblock is free */
-               err = add_to_list(si, pnum, ec, &si->free);
+       case UBI_IO_FF_BITFLIPS:
+               err = add_to_list(si, pnum, ec, 1, &si->erase);
                if (err)
                        return err;
                goto adjust_mean_ec;
+       case UBI_IO_FF:
+               if (ec_err)
+                       err = add_to_list(si, pnum, ec, 1, &si->erase);
+               else
+                       err = add_to_list(si, pnum, ec, 0, &si->free);
+               if (err)
+                       return err;
+               goto adjust_mean_ec;
+       default:
+               ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+                       err);
+               return -EINVAL;
        }
 
        vol_id = be32_to_cpu(vidh->vol_id);
@@ -843,7 +999,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                case UBI_COMPAT_DELETE:
                        ubi_msg("\"delete\" compatible internal volume %d:%d"
                                " found, will remove it", vol_id, lnum);
-                       err = add_to_list(si, pnum, ec, &si->corr);
+                       err = add_to_list(si, pnum, ec, 1, &si->erase);
                        if (err)
                                return err;
                        return 0;
@@ -858,7 +1014,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                case UBI_COMPAT_PRESERVE:
                        ubi_msg("\"preserve\" compatible internal volume %d:%d"
                                " found", vol_id, lnum);
-                       err = add_to_list(si, pnum, ec, &si->alien);
+                       err = add_to_list(si, pnum, ec, 0, &si->alien);
                        if (err)
                                return err;
                        return 0;
@@ -870,7 +1026,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                }
        }
 
-       if (ec_corr)
+       if (ec_err)
                ubi_warn("valid VID header but corrupted EC header at PEB %d",
                         pnum);
        err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
@@ -878,7 +1034,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                return err;
 
 adjust_mean_ec:
-       if (!ec_corr) {
+       if (!ec_err) {
                si->ec_sum += ec;
                si->ec_count += 1;
                if (ec > si->max_ec)
@@ -904,19 +1060,20 @@ adjust_mean_ec:
 static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
        struct ubi_scan_leb *seb;
-       int max_corr;
+       int max_corr, peb_count;
 
-       max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
-       max_corr = max_corr / 20 ?: 8;
+       peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+       max_corr = peb_count / 20 ?: 8;
 
        /*
-        * Few corrupted PEBs are not a problem and may be just a result of
+        * Few corrupted PEBs is not a problem and may be just a result of
         * unclean reboots. However, many of them may indicate some problems
         * with the flash HW or driver.
         */
-       if (si->corr_peb_count >= 8) {
-               ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
-               printk(KERN_WARNING "corrupted PEBs are:");
+       if (si->corr_peb_count) {
+               ubi_err("%d PEBs are corrupted and preserved",
+                       si->corr_peb_count);
+               printk(KERN_ERR "Corrupted PEBs are:");
                list_for_each_entry(seb, &si->corr, u.list)
                        printk(KERN_CONT " %d", seb->pnum);
                printk(KERN_CONT "\n");
@@ -931,41 +1088,35 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
                }
        }
 
-       if (si->free_peb_count + si->used_peb_count +
-           si->alien_peb_count == 0) {
-               /* No UBI-formatted eraseblocks were found */
-               if (si->corr_peb_count == si->read_err_count &&
-                   si->corr_peb_count < 8) {
-                       /* No or just few corrupted PEBs, and all of them had a
-                        * read error. We assume that those are bad PEBs, which
-                        * were just not marked as bad so far.
-                        *
-                        * This piece of code basically tries to distinguish
-                        * between the following 2 situations:
-                        *
-                        * 1. Flash is empty, but there are few bad PEBs, which
-                        *    are not marked as bad so far, and which were read
-                        *    with error. We want to go ahead and format this
-                        *    flash. While formating, the faulty PEBs will
-                        *    probably be marked as bad.
-                        *
-                        * 2. Flash probably contains non-UBI data and we do
-                        * not want to format it and destroy possibly needed
-                        * data (e.g., consider the case when the bootloader
-                        * MTD partition was accidentally fed to UBI).
-                        */
+       if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
+               /*
+                * All PEBs are empty, or almost all - a couple PEBs look like
+                * they may be bad PEBs which were not marked as bad yet.
+                *
+                * This piece of code basically tries to distinguish between
+                * the following situations:
+                *
+                * 1. Flash is empty, but there are few bad PEBs, which are not
+                *    marked as bad so far, and which were read with error. We
+                *    want to go ahead and format this flash. While formatting,
+                *    the faulty PEBs will probably be marked as bad.
+                *
+                * 2. Flash contains non-UBI data and we do not want to format
+                *    it and destroy possibly important information.
+                */
+               if (si->maybe_bad_peb_count <= 2) {
                        si->is_empty = 1;
                        ubi_msg("empty MTD device detected");
-                       get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq));
+                       get_random_bytes(&ubi->image_seq,
+                                        sizeof(ubi->image_seq));
                } else {
-                       ubi_err("MTD device possibly contains non-UBI data, "
-                               "refusing it");
+                       ubi_err("MTD device is not UBI-formatted and possibly "
+                               "contains non-UBI data - refusing it");
                        return -EINVAL;
                }
+
        }
 
-       if (si->corr_peb_count > 0)
-               ubi_msg("corrupted PEBs will be formatted");
        return 0;
 }
 
index 2576a8d1532b700d659391bbe6d3e1364acbcaef..a3264f0bef2b825d3df88b40480dc390cfa94860 100644 (file)
@@ -30,6 +30,7 @@
  * @pnum: physical eraseblock number
  * @lnum: logical eraseblock number
  * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
  * @sqnum: sequence number
  * @u: unions RB-tree or @list links
  * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
@@ -42,7 +43,8 @@ struct ubi_scan_leb {
        int ec;
        int pnum;
        int lnum;
-       int scrub;
+       unsigned int scrub:1;
+       unsigned int copy_flag:1;
        unsigned long long sqnum;
        union {
                struct rb_node rb;
@@ -91,14 +93,13 @@ struct ubi_scan_volume {
  * @erase: list of physical eraseblocks which have to be erased
  * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
  *         those belonging to "preserve"-compatible internal volumes)
- * @used_peb_count: count of used PEBs
  * @corr_peb_count: count of PEBs in the @corr list
- * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was
- *                  returned)
- * @free_peb_count: count of PEBs in the @free list
- * @erase_peb_count: count of PEBs in the @erase list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ *                   0xFF bytes)
  * @alien_peb_count: count of PEBs in the @alien list
  * @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ *                       as bad yet, but which look like bad
  * @vols_found: number of volumes found during scanning
  * @highest_vol_id: highest volume ID
  * @is_empty: flag indicating whether the MTD device is empty or not
@@ -119,13 +120,11 @@ struct ubi_scan_info {
        struct list_head free;
        struct list_head erase;
        struct list_head alien;
-       int used_peb_count;
        int corr_peb_count;
-       int read_err_count;
-       int free_peb_count;
-       int erase_peb_count;
+       int empty_peb_count;
        int alien_peb_count;
        int bad_peb_count;
+       int maybe_bad_peb_count;
        int vols_found;
        int highest_vol_id;
        int is_empty;
index 0359e0cce4827ea7dd778d188b5ff7d6dde5b9d3..0b0149c41fe3c7da9fd0b393b9a76c3cb90996c3 100644 (file)
 /*
  * Error codes returned by the I/O sub-system.
  *
- * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- *                   %0xFF bytes
- * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- *                  valid erase counter header, and the rest are %0xFF bytes
+ * UBI_IO_FF: the read region of flash contains only 0xFFs
+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
+ *                     integrity error reported by the MTD driver
+ *                     (uncorrectable ECC error in case of NAND)
  * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
- * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read
- *                     error reported by the flash driver
+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
+ *                         data integrity error reported by the MTD driver
+ *                         (uncorrectable ECC error in case of NAND)
  * UBI_IO_BITFLIPS: bit-flips were detected and corrected
+ *
+ * Note, it is probably better to have bit-flip and ebadmsg as flags which can
+ * be or'ed with other error code. But this is a big change because there are
+ * may callers, so it does not worth the risk of introducing a bug
  */
 enum {
-       UBI_IO_PEB_EMPTY = 1,
-       UBI_IO_PEB_FREE,
+       UBI_IO_FF = 1,
+       UBI_IO_FF_BITFLIPS,
        UBI_IO_BAD_HDR,
-       UBI_IO_BAD_HDR_READ,
-       UBI_IO_BITFLIPS
+       UBI_IO_BAD_HDR_EBADMSG,
+       UBI_IO_BITFLIPS,
 };
 
 /*
@@ -356,6 +361,8 @@ struct ubi_wl_entry;
  * @peb_size: physical eraseblock size
  * @bad_peb_count: count of bad physical eraseblocks
  * @good_peb_count: count of good physical eraseblocks
+ * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
+ *                  used by UBI)
  * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
  * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
  * @min_io_size: minimal input/output unit size of the underlying MTD device
@@ -442,6 +449,7 @@ struct ubi_device {
        int peb_size;
        int bad_peb_count;
        int good_peb_count;
+       int corr_peb_count;
        int erroneous_peb_count;
        int max_erroneous;
        int min_io_size;
@@ -506,6 +514,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
                      int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
 void ubi_calculate_reserved(struct ubi_device *ubi);
+int ubi_check_pattern(const void *buf, uint8_t patt, int size);
 
 /* eba.c */
 int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
index e42afab9a9fe2c290585a0f3111ca2543581a7ee..c47620dfc722c33417b33d8f8a1608f1478a0241 100644 (file)
@@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        /* Reserve physical eraseblocks */
        if (vol->reserved_pebs > ubi->avail_pebs) {
                dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+               if (ubi->corr_peb_count)
+                       dbg_err("%d PEBs are corrupted and not used",
+                               ubi->corr_peb_count);
                err = -ENOSPC;
                goto out_unlock;
        }
@@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                if (pebs > ubi->avail_pebs) {
                        dbg_err("not enough PEBs: requested %d, available %d",
                                pebs, ubi->avail_pebs);
+                       if (ubi->corr_peb_count)
+                               dbg_err("%d PEBs are corrupted and not used",
+                                       ubi->corr_peb_count);
                        spin_unlock(&ubi->volumes_lock);
                        err = -ENOSPC;
                        goto out_free;
index 14c10bed94eee690633f7bdf37c07ac08165c833..fcdb7f65fe0beb3388b60daeab433733d4f1ecc7 100644 (file)
@@ -366,7 +366,7 @@ write_error:
                 * Probably this physical eraseblock went bad, try to pick
                 * another one.
                 */
-               list_add_tail(&new_seb->u.list, &si->corr);
+               list_add(&new_seb->u.list, &si->erase);
                goto retry;
        }
        kfree(new_seb);
@@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
        ubi->vol_count += 1;
        vol->ubi = ubi;
 
-       if (reserved_pebs > ubi->avail_pebs)
+       if (reserved_pebs > ubi->avail_pebs) {
                ubi_err("not enough PEBs, required %d, available %d",
                        reserved_pebs, ubi->avail_pebs);
+               if (ubi->corr_peb_count)
+                       ubi_err("%d PEBs are corrupted and not used",
+                               ubi->corr_peb_count);
+       }
        ubi->rsvd_pebs += reserved_pebs;
        ubi->avail_pebs -= reserved_pebs;
 
@@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
                        return PTR_ERR(ubi->vtbl);
        }
 
-       ubi->avail_pebs = ubi->good_peb_count;
+       ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
 
        /*
         * The layout volume is OK, initialize the corresponding in-RAM data
index ee7b1d8fbb92c9d03fbe8026100378e100b4ffc1..655bbbe415d99b89074e1344953f8e60f10ac0be 100644 (file)
@@ -745,7 +745,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 
        err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0);
        if (err && err != UBI_IO_BITFLIPS) {
-               if (err == UBI_IO_PEB_FREE) {
+               if (err == UBI_IO_FF) {
                        /*
                         * We are trying to move PEB without a VID header. UBI
                         * always write VID headers shortly after the PEB was
@@ -759,6 +759,16 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                        dbg_wl("PEB %d has no VID header", e1->pnum);
                        protect = 1;
                        goto out_not_moved;
+               } else if (err == UBI_IO_FF_BITFLIPS) {
+                       /*
+                        * The same situation as %UBI_IO_FF, but bit-flips were
+                        * detected. It is better to schedule this PEB for
+                        * scrubbing.
+                        */
+                       dbg_wl("PEB %d has no VID header but has bit-flips",
+                              e1->pnum);
+                       scrubbing = 1;
+                       goto out_not_moved;
                }
 
                ubi_err("error %d while reading VID header from PEB %d",
@@ -1212,7 +1222,8 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum)
 retry:
        spin_lock(&ubi->wl_lock);
        e = ubi->lookuptbl[pnum];
-       if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub)) {
+       if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub) ||
+                                  in_wl_tree(e, &ubi->erroneous)) {
                spin_unlock(&ubi->wl_lock);
                return 0;
        }
@@ -1467,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
                ubi->lookuptbl[e->pnum] = e;
        }
 
-       list_for_each_entry(seb, &si->corr, u.list) {
-               cond_resched();
-
-               e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-               if (!e)
-                       goto out_free;
-
-               e->pnum = seb->pnum;
-               e->ec = seb->ec;
-               ubi->lookuptbl[e->pnum] = e;
-               if (schedule_erase(ubi, e, 0)) {
-                       kmem_cache_free(ubi_wl_entry_slab, e);
-                       goto out_free;
-               }
-       }
-
        ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
                ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
                        cond_resched();
@@ -1509,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
        if (ubi->avail_pebs < WL_RESERVED_PEBS) {
                ubi_err("no enough physical eraseblocks (%d, need %d)",
                        ubi->avail_pebs, WL_RESERVED_PEBS);
+               if (ubi->corr_peb_count)
+                       ubi_err("%d PEBs are corrupted and not used",
+                               ubi->corr_peb_count);
                goto out_free;
        }
        ubi->avail_pebs -= WL_RESERVED_PEBS;
index 70705d1306b93e161260852d39f6adf6fe308226..eca55c52bdfdf2ae8c8445bfac2901cfd9d99bd3 100644 (file)
@@ -522,7 +522,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
        lp->tx_len              = lp->exec_box->data[9];   /* Transmit list count */
        lp->rx_len              = lp->exec_box->data[11];  /* Receive list count */
 
-       init_MUTEX_LOCKED(&lp->cmd_mutex);
+       sema_init(&lp->cmd_mutex, 0);
        init_completion(&lp->execution_cmd);
        init_completion(&lp->xceiver_cmd);
 
index c754d88e5ec92d0af82d80094a4576256a50dc61..179871d9e71f9a1f111645f58c68b7fea55b0861 100644 (file)
@@ -633,7 +633,11 @@ struct vortex_private {
                open:1,
                medialock:1,
                must_free_region:1,                             /* Flag: if zero, Cardbus owns the I/O region */
-               large_frames:1;                 /* accept large frames */
+               large_frames:1,                 /* accept large frames */
+               handling_irq:1;                 /* private in_irq indicator */
+       /* {get|set}_wol operations are already serialized by rtnl.
+        * no additional locking is required for the enable_wol and acpi_set_WOL()
+        */
        int drv_flags;
        u16 status_enable;
        u16 intr_enable;
@@ -646,7 +650,7 @@ struct vortex_private {
        u16 io_size;                                            /* Size of PCI region (for release_region) */
 
        /* Serialises access to hardware other than MII and variables below.
-        * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */
+        * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */
        spinlock_t lock;
 
        spinlock_t mii_lock;            /* Serialises access to MII */
@@ -1993,10 +1997,9 @@ vortex_error(struct net_device *dev, int status)
                }
        }
 
-       if (status & RxEarly) {                         /* Rx early is unused. */
-               vortex_rx(dev);
+       if (status & RxEarly)                           /* Rx early is unused. */
                iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
-       }
+
        if (status & StatsFull) {                       /* Empty statistics. */
                static int DoneDidThat;
                if (vortex_debug > 4)
@@ -2133,6 +2136,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
                           dev->name, vp->cur_tx);
        }
 
+       /*
+        * We can't allow a recursion from our interrupt handler back into the
+        * tx routine, as they take the same spin lock, and that causes
+        * deadlock.  Just return NETDEV_TX_BUSY and let the stack try again in
+        * a bit
+        */
+       if (vp->handling_irq)
+               return NETDEV_TX_BUSY;
+
        if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
                if (vortex_debug > 0)
                        pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
@@ -2288,7 +2300,12 @@ vortex_interrupt(int irq, void *dev_id)
                if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
                        if (status == 0xffff)
                                break;
+                       if (status & RxEarly)
+                               vortex_rx(dev);
+                       spin_unlock(&vp->window_lock);
                        vortex_error(dev, status);
+                       spin_lock(&vp->window_lock);
+                       window_set(vp, 7);
                }
 
                if (--work_done < 0) {
@@ -2335,11 +2352,13 @@ boomerang_interrupt(int irq, void *dev_id)
 
        ioaddr = vp->ioaddr;
 
+
        /*
         * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
         * and boomerang_start_xmit
         */
        spin_lock(&vp->lock);
+       vp->handling_irq = 1;
 
        status = ioread16(ioaddr + EL3_STATUS);
 
@@ -2447,6 +2466,7 @@ boomerang_interrupt(int irq, void *dev_id)
                pr_debug("%s: exiting interrupt, status %4.4x.\n",
                           dev->name, status);
 handler_exit:
+       vp->handling_irq = 0;
        spin_unlock(&vp->lock);
        return IRQ_HANDLED;
 }
@@ -2922,28 +2942,31 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct vortex_private *vp = netdev_priv(dev);
 
-       spin_lock_irq(&vp->lock);
+       if (!VORTEX_PCI(vp))
+               return;
+
        wol->supported = WAKE_MAGIC;
 
        wol->wolopts = 0;
        if (vp->enable_wol)
                wol->wolopts |= WAKE_MAGIC;
-       spin_unlock_irq(&vp->lock);
 }
 
 static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct vortex_private *vp = netdev_priv(dev);
+
+       if (!VORTEX_PCI(vp))
+               return -EOPNOTSUPP;
+
        if (wol->wolopts & ~WAKE_MAGIC)
                return -EINVAL;
 
-       spin_lock_irq(&vp->lock);
        if (wol->wolopts & WAKE_MAGIC)
                vp->enable_wol = 1;
        else
                vp->enable_wol = 0;
        acpi_set_WOL(dev);
-       spin_unlock_irq(&vp->lock);
 
        return 0;
 }
@@ -2971,7 +2994,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        int err;
        struct vortex_private *vp = netdev_priv(dev);
-       unsigned long flags;
        pci_power_t state = 0;
 
        if(VORTEX_PCI(vp))
@@ -2981,9 +3003,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        if(state != 0)
                pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
-       spin_lock_irqsave(&vp->lock, flags);
        err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
-       spin_unlock_irqrestore(&vp->lock, flags);
        if(state != 0)
                pci_set_power_state(VORTEX_PCI(vp), state);
 
@@ -3188,6 +3208,9 @@ static void acpi_set_WOL(struct net_device *dev)
                        return;
                }
 
+               if (VORTEX_PCI(vp)->current_state < PCI_D3hot)
+                       return;
+
                /* Change the power state to D3; RxEnable doesn't take effect. */
                pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
        }
index 5a6895320b48a8d7774acfb4e6b239713cc6bd9d..77efe462b9215914dd1071c8875635ebabff6d09 100644 (file)
@@ -2,6 +2,9 @@
 # Network device configuration
 #
 
+config HAVE_NET_MACB
+       bool
+
 menuconfig NETDEVICES
        default y if UML
        depends on NET
@@ -221,7 +224,7 @@ config MII
 
 config MACB
        tristate "Atmel MACB support"
-       depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9
+       depends on HAVE_NET_MACB
        select PHYLIB
        help
          The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -928,6 +931,16 @@ config SMC91X
          The module will be called smc91x.  If you want to compile it as a
          module, say M here and read <file:Documentation/kbuild/modules.txt>.
 
+config PXA168_ETH
+       tristate "Marvell pxa168 ethernet support"
+       depends on CPU_PXA168
+       select PHYLIB
+       help
+         This driver supports the pxa168 Ethernet ports.
+
+         To compile this driver as a module, choose M here. The module
+         will be called pxa168_eth.
+
 config NET_NETX
        tristate "NetX Ethernet support"
        select MII
@@ -2418,7 +2431,7 @@ config UGETH_TX_ON_DEMAND
 
 config MV643XX_ETH
        tristate "Marvell Discovery (643XX) and Orion ethernet support"
-       depends on MV64X60 || PPC32 || PLAT_ORION
+       depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
        select INET_LRO
        select PHYLIB
        help
@@ -2793,7 +2806,7 @@ config NIU
 
 config PASEMI_MAC
        tristate "PA Semi 1/10Gbit MAC"
-       depends on PPC_PASEMI && PCI
+       depends on PPC_PASEMI && PCI && INET
        select PHYLIB
        select INET_LRO
        help
index 56e8c27f77cebe9ef3b9ac3c1284f7e2975f8448..3e8f150c4b14b0034edb3632b9de33b1338b9635 100644 (file)
@@ -244,6 +244,7 @@ obj-$(CONFIG_MYRI10GE) += myri10ge/
 obj-$(CONFIG_SMC91X) += smc91x.o
 obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_SMSC911X) += smsc911x.o
+obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
 obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
index 0a0e0cd81a23a1fd5a16581fca361d7742bfaed4..20f97e7017ceffa5bc85f87f77036d679bc1355e 100644 (file)
@@ -3,6 +3,7 @@
 #
 config ATALK
        tristate "Appletalk protocol support"
+       depends on BKL # waiting to be removed from net/appletalk/ddp.c
        select LLC
        ---help---
          AppleTalk is the protocol that Apple computers can use to communicate
index 63b9ba0cc67e13c408686442f1e2fe984ee9b462..c73be2848319deecd38a3d6f5e8e45ed8637e6f9 100644 (file)
@@ -1251,6 +1251,12 @@ static void atl1_free_ring_resources(struct atl1_adapter *adapter)
 
        rrd_ring->desc = NULL;
        rrd_ring->dma = 0;
+
+       adapter->cmb.dma = 0;
+       adapter->cmb.cmb = NULL;
+
+       adapter->smb.dma = 0;
+       adapter->smb.smb = NULL;
 }
 
 static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
@@ -2847,10 +2853,11 @@ static int atl1_resume(struct pci_dev *pdev)
        pci_enable_wake(pdev, PCI_D3cold, 0);
 
        atl1_reset_hw(&adapter->hw);
-       adapter->cmb.cmb->int_stats = 0;
 
-       if (netif_running(netdev))
+       if (netif_running(netdev)) {
+               adapter->cmb.cmb->int_stats = 0;
                atl1_up(adapter);
+       }
        netif_device_attach(netdev);
 
        return 0;
index 37617abc164769aa5f8be38a797ea4337a3585e0..efeffdf9e5fab30d2bd97a07e5e866fec60ed595 100644 (file)
@@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget)
                b44_tx(bp);
                /* spin_unlock(&bp->tx_lock); */
        }
+       if (bp->istat & ISTAT_RFO) {    /* fast recovery, in ~20msec */
+               bp->istat &= ~ISTAT_RFO;
+               b44_disable_ints(bp);
+               ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */
+               b44_init_rings(bp);
+               b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
+               netif_wake_queue(bp->dev);
+       }
+
        spin_unlock_irqrestore(&bp->lock, flags);
 
        work_done = 0;
@@ -2161,8 +2170,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
        dev->irq = sdev->irq;
        SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
 
-       netif_carrier_off(dev);
-
        err = ssb_bus_powerup(sdev->bus, 0);
        if (err) {
                dev_err(sdev->dev,
@@ -2204,6 +2211,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
                goto err_out_powerdown;
        }
 
+       netif_carrier_off(dev);
+
        ssb_set_drvdata(sdev, dev);
 
        /* Chip reset provides power to the b44 MAC & PCI cores, which
index 99197bd54da558ef26cf8a62a54af19aaa02e0f8..53306bf3f401bee193fc89f5c6c4d1b35759ecb0 100644 (file)
@@ -181,6 +181,7 @@ struct be_drvr_stats {
        u64 be_rx_bytes_prev;
        u64 be_rx_pkts;
        u32 be_rx_rate;
+       u32 be_rx_mcast_pkt;
        /* number of non ether type II frames dropped where
         * frame len > length field of Mac Hdr */
        u32 be_802_3_dropped_frames;
index 3d305494a6066fb987510abebe34a1332f80c114..34abcc9403d6b76428416412904b4c06ff8d593b 100644 (file)
@@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
        while ((compl = be_mcc_compl_get(adapter))) {
                if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
                        /* Interpret flags as an async trailer */
-                       BUG_ON(!is_link_state_evt(compl->flags));
-
-                       /* Interpret compl as a async link evt */
-                       be_async_link_state_process(adapter,
+                       if (is_link_state_evt(compl->flags))
+                               be_async_link_state_process(adapter,
                                (struct be_async_event_link_state *) compl);
                } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
                                *status = be_mcc_compl_process(adapter, compl);
@@ -207,7 +205,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
 
                if (msecs > 4000) {
                        dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
-                       be_dump_ue(adapter);
+                       be_detect_dump_ue(adapter);
                        return -1;
                }
 
index bdc10a28cfda9feb11ffdecee141a6e333a9e92d..ad1e6fac60c58869e074609cee3e363672bfecd9 100644 (file)
@@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
 extern int be_cmd_get_phy_info(struct be_adapter *adapter,
                struct be_dma_mem *cmd);
 extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
-extern void be_dump_ue(struct be_adapter *adapter);
+extern void be_detect_dump_ue(struct be_adapter *adapter);
 
index cd16243c7c364a858d849ac3f70ac10bbbfcb966..13f0abbc520550b0b22ef48d0ed2a4da56d69187 100644 (file)
@@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = {
        {DRVSTAT_INFO(be_rx_events)},
        {DRVSTAT_INFO(be_tx_compl)},
        {DRVSTAT_INFO(be_rx_compl)},
+       {DRVSTAT_INFO(be_rx_mcast_pkt)},
        {DRVSTAT_INFO(be_ethrx_post_fail)},
        {DRVSTAT_INFO(be_802_3_dropped_frames)},
        {DRVSTAT_INFO(be_802_3_malformed_frames)},
index 5d38046402b235d255b529bb96c3cd07806fe3a9..a2ec5df0d73340bf82e45ab3d50f25402fcaa9b6 100644 (file)
 #define FLASH_FCoE_BIOS_START_g3           (13631488)
 #define FLASH_REDBOOT_START_g3             (262144)
 
-
-
+/************* Rx Packet Type Encoding **************/
+#define BE_UNICAST_PACKET              0
+#define BE_MULTICAST_PACKET            1
+#define BE_BROADCAST_PACKET            2
+#define BE_RSVD_PACKET                 3
 
 /*
  * BE descriptors: host memory data structures whose formats
index 74e146f470c60e9df5ff01806623a0aaaaa0ec82..6eda7a02225623943a35293cada545b8d20d752b 100644 (file)
@@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter)
        dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
        dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
        dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
+       dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt;
 
        /* bad pkts received */
        dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter)
        /* no space available in linux */
        dev_stats->tx_dropped = 0;
 
-       dev_stats->multicast = port_stats->rx_multicast_frames;
        dev_stats->collisions = 0;
 
        /* detailed tx_errors */
@@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter)
 }
 
 static void be_rx_stats_update(struct be_adapter *adapter,
-               u32 pktsize, u16 numfrags)
+               u32 pktsize, u16 numfrags, u8 pkt_type)
 {
        struct be_drvr_stats *stats = drvr_stats(adapter);
 
@@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter,
        stats->be_rx_frags += numfrags;
        stats->be_rx_bytes += pktsize;
        stats->be_rx_pkts++;
+
+       if (pkt_type == BE_MULTICAST_PACKET)
+               stats->be_rx_mcast_pkt++;
 }
 
 static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
        u16 rxq_idx, i, j;
        u32 pktsize, hdr_len, curr_frag_len, size;
        u8 *start;
+       u8 pkt_type;
 
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
        pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
+       pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
 
        page_info = get_rx_page_info(adapter, rxq_idx);
 
@@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
        BUG_ON(j > MAX_SKB_FRAGS);
 
 done:
-       be_rx_stats_update(adapter, pktsize, num_rcvd);
+       be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type);
 }
 
 /* Process the RX completion indicated by rxcp when GRO is disabled */
@@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
        u16 i, rxq_idx = 0, vid, j;
        u8 vtm;
+       u8 pkt_type;
 
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
        /* Is it a flush compl that has no data */
@@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
        vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
+       pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
 
        /* vlanf could be wrongly set in some cards.
         * ignore if vtm is not set */
@@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
                vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
        }
 
-       be_rx_stats_update(adapter, pkt_size, num_rcvd);
+       be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type);
 }
 
 static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
@@ -1743,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
        return 1;
 }
 
-static inline bool be_detect_ue(struct be_adapter *adapter)
-{
-       u32 online0 = 0, online1 = 0;
-
-       pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0);
-
-       pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1);
-
-       if (!online0 || !online1) {
-               adapter->ue_detected = true;
-               dev_err(&adapter->pdev->dev,
-                       "UE Detected!! online0=%d online1=%d\n",
-                       online0, online1);
-               return true;
-       }
-
-       return false;
-}
-
-void be_dump_ue(struct be_adapter *adapter)
+void be_detect_dump_ue(struct be_adapter *adapter)
 {
        u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask;
        u32 i;
@@ -1779,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter)
        ue_status_lo = (ue_status_lo & (~ue_status_lo_mask));
        ue_status_hi = (ue_status_hi & (~ue_status_hi_mask));
 
+       if (ue_status_lo || ue_status_hi) {
+               adapter->ue_detected = true;
+               dev_err(&adapter->pdev->dev, "UE Detected!!\n");
+       }
+
        if (ue_status_lo) {
                for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) {
                        if (ue_status_lo & 1)
@@ -1814,10 +1807,8 @@ static void be_worker(struct work_struct *work)
                adapter->rx_post_starved = false;
                be_post_rx_frags(adapter);
        }
-       if (!adapter->ue_detected) {
-               if (be_detect_ue(adapter))
-                       be_dump_ue(adapter);
-       }
+       if (!adapter->ue_detected)
+               be_detect_dump_ue(adapter);
 
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
 }
index 012613fde3f4d61f1217603a3bd811673f43d324..03d063554b7f46103cd4c9d20a7dacab215cafeb 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/blackfin.h>
 #include <asm/cacheflush.h>
 #include <asm/portmux.h>
+#include <mach/pll.h>
 
 #include "bfin_mac.h"
 
index 53af9c93e75c3bca661abfb8dce7aabe96589f52..0c2d96ed561c46ebd63f3c03c119c0751b5204e1 100644 (file)
@@ -20,8 +20,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.52.53-3"
-#define DRV_MODULE_RELDATE      "2010/18/04"
+#define DRV_MODULE_VERSION      "1.52.53-4"
+#define DRV_MODULE_RELDATE      "2010/16/08"
 #define BNX2X_BC_VER            0x040200
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
index b4ec2b02a465cf7d822f23700c119d6e93a2121b..f8c3f08e4ce73fb4d5d37739fa7dd18cfc557da7 100644 (file)
@@ -4328,10 +4328,12 @@ static int bnx2x_init_port(struct bnx2x *bp)
                val |= aeu_gpio_mask;
                REG_WR(bp, offset, val);
                }
+               bp->port.need_hw_lock = 1;
                break;
 
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+               bp->port.need_hw_lock = 1;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
                /* add SPIO 5 to group 0 */
                {
                u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
@@ -4341,7 +4343,10 @@ static int bnx2x_init_port(struct bnx2x *bp)
                REG_WR(bp, reg_addr, val);
                }
                break;
-
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+               bp->port.need_hw_lock = 1;
+               break;
        default:
                break;
        }
index 822f586d72afa67d8abd5c606f38b11f60f0147d..0ddf4c66afe21aa99679a3fb31b1e932dc51612c 100644 (file)
@@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
        if (!(dev->flags & IFF_MASTER))
                goto out;
 
+       if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
+               goto out;
+
        read_lock(&bond->lock);
        slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev),
                                        orig_dev);
index c746b331771d38f38771c89aa492ede20cbdf711..26bb118c45334074ef4c8a51deda39e4161fba44 100644 (file)
@@ -362,6 +362,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
                goto out;
        }
 
+       if (!pskb_may_pull(skb, arp_hdr_len(bond_dev)))
+               goto out;
+
        if (skb->len < sizeof(struct arp_pkt)) {
                pr_debug("Packet is too small to be an ARP\n");
                goto out;
index 2cc4cfc31892cd85458dec20b6c46401fdb90d9b..e953c6ad6e6d1ea3fd7e22fddc8f5f27ba1f8b38 100644 (file)
@@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
         *       so it can wait
         */
        bond_for_each_slave(bond, slave, i) {
+               unsigned long trans_start = dev_trans_start(slave->dev);
+
                if (slave->link != BOND_LINK_UP) {
-                       if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) &&
-                           time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) {
+                       if (time_in_range(jiffies,
+                               trans_start - delta_in_ticks,
+                               trans_start + delta_in_ticks) &&
+                           time_in_range(jiffies,
+                               slave->dev->last_rx - delta_in_ticks,
+                               slave->dev->last_rx + delta_in_ticks)) {
 
                                slave->link  = BOND_LINK_UP;
                                slave->state = BOND_STATE_ACTIVE;
@@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
                         * when the source ip is 0, so don't take the link down
                         * if we don't know our ip yet
                         */
-                       if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) ||
-                           (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) {
+                       if (!time_in_range(jiffies,
+                               trans_start - delta_in_ticks,
+                               trans_start + 2 * delta_in_ticks) ||
+                           !time_in_range(jiffies,
+                               slave->dev->last_rx - delta_in_ticks,
+                               slave->dev->last_rx + 2 * delta_in_ticks)) {
 
                                slave->link  = BOND_LINK_DOWN;
                                slave->state = BOND_STATE_BACKUP;
@@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 {
        struct slave *slave;
        int i, commit = 0;
+       unsigned long trans_start;
 
        bond_for_each_slave(bond, slave, i) {
                slave->new_link = BOND_LINK_NOCHANGE;
 
                if (slave->link != BOND_LINK_UP) {
-                       if (time_before_eq(jiffies, slave_last_rx(bond, slave) +
-                                          delta_in_ticks)) {
+                       if (time_in_range(jiffies,
+                               slave_last_rx(bond, slave) - delta_in_ticks,
+                               slave_last_rx(bond, slave) + delta_in_ticks)) {
+
                                slave->new_link = BOND_LINK_UP;
                                commit++;
                        }
@@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
                 * active.  This avoids bouncing, as the last receive
                 * times need a full ARP monitor cycle to be updated.
                 */
-               if (!time_after_eq(jiffies, slave->jiffies +
-                                  2 * delta_in_ticks))
+               if (time_in_range(jiffies,
+                                 slave->jiffies - delta_in_ticks,
+                                 slave->jiffies + 2 * delta_in_ticks))
                        continue;
 
                /*
@@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
                 */
                if (slave->state == BOND_STATE_BACKUP &&
                    !bond->current_arp_slave &&
-                   time_after(jiffies, slave_last_rx(bond, slave) +
-                              3 * delta_in_ticks)) {
+                   !time_in_range(jiffies,
+                       slave_last_rx(bond, slave) - delta_in_ticks,
+                       slave_last_rx(bond, slave) + 3 * delta_in_ticks)) {
+
                        slave->new_link = BOND_LINK_DOWN;
                        commit++;
                }
@@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
                 * - (more than 2*delta since receive AND
                 *    the bond has an IP address)
                 */
+               trans_start = dev_trans_start(slave->dev);
                if ((slave->state == BOND_STATE_ACTIVE) &&
-                   (time_after_eq(jiffies, dev_trans_start(slave->dev) +
-                                   2 * delta_in_ticks) ||
-                     (time_after_eq(jiffies, slave_last_rx(bond, slave)
-                                    + 2 * delta_in_ticks)))) {
+                   (!time_in_range(jiffies,
+                       trans_start - delta_in_ticks,
+                       trans_start + 2 * delta_in_ticks) ||
+                    !time_in_range(jiffies,
+                       slave_last_rx(bond, slave) - delta_in_ticks,
+                       slave_last_rx(bond, slave) + 2 * delta_in_ticks))) {
+
                        slave->new_link = BOND_LINK_DOWN;
                        commit++;
                }
@@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
 {
        struct slave *slave;
        int i;
+       unsigned long trans_start;
 
        bond_for_each_slave(bond, slave, i) {
                switch (slave->new_link) {
@@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
                        continue;
 
                case BOND_LINK_UP:
+                       trans_start = dev_trans_start(slave->dev);
                        if ((!bond->curr_active_slave &&
-                            time_before_eq(jiffies,
-                                           dev_trans_start(slave->dev) +
-                                           delta_in_ticks)) ||
+                            time_in_range(jiffies,
+                                          trans_start - delta_in_ticks,
+                                          trans_start + delta_in_ticks)) ||
                            bond->curr_active_slave != slave) {
                                slave->link = BOND_LINK_UP;
                                bond->current_arp_slave = NULL;
@@ -5142,6 +5164,15 @@ int bond_create(struct net *net, const char *name)
                res = dev_alloc_name(bond_dev, "bond%d");
                if (res < 0)
                        goto out;
+       } else {
+               /*
+                * If we're given a name to register
+                * we need to ensure that its not already
+                * registered
+                */
+               res = -EEXIST;
+               if (__dev_get_by_name(net, name) != NULL)
+                       goto out;
        }
 
        res = register_netdevice(bond_dev);
index 631a6242b0112aec566b9df0916eb9b1d1552be5..75bfc3a9d95f3f118e6eae1cdc649fd0a442baeb 100644 (file)
@@ -15,7 +15,7 @@ config CAIF_TTY
 
 config CAIF_SPI_SLAVE
        tristate "CAIF SPI transport driver for slave interface"
-       depends on CAIF
+       depends on CAIF && HAS_DMA
        default n
        ---help---
        The CAIF Link layer SPI Protocol driver for Slave SPI interface.
index f5058ff2b210da07dd1411bdd8a12f1dafe9ddb2..8427533fe313c35cb38727e533cd77dd35cdb4af 100644 (file)
@@ -240,13 +240,15 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
 static const struct file_operations dbgfs_state_fops = {
        .open = dbgfs_open,
        .read = dbgfs_state,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations dbgfs_frame_fops = {
        .open = dbgfs_open,
        .read = dbgfs_frame,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static inline void dev_debugfs_add(struct cfspi *cfspi)
index ad19585d960be79c0ec350c312fce978afaf2a9b..f208712c0b90d6b675f1ef1179f5825ae9f9f911 100644 (file)
@@ -2296,6 +2296,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
        case CHELSIO_GET_QSET_NUM:{
                struct ch_reg edata;
 
+               memset(&edata, 0, sizeof(struct ch_reg));
+
                edata.cmd = CHELSIO_GET_QSET_NUM;
                edata.val = pi->nqsets;
                if (copy_to_user(useraddr, &edata, sizeof(edata)))
index c327527fbbc854d6cf4f63d0457221cf434869e6..e2bf10d90add64cb445545c570df20021b75d326 100644 (file)
@@ -2026,6 +2026,7 @@ static const struct file_operations mem_debugfs_fops = {
        .owner   = THIS_MODULE,
        .open    = mem_open,
        .read    = mem_read,
+       .llseek  = default_llseek,
 };
 
 static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
index a4a0d2b6eb1c60e116811b31378a426ad00a44e2..d3d4a57e24505f9c36af9ef139bfc9133788a4bd 100644 (file)
@@ -936,12 +936,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        ew32(IMC, 0xffffffff);
        icr = er32(ICR);
 
-       /* Install any alternate MAC address into RAR0 */
-       ret_val = e1000_check_alt_mac_addr_generic(hw);
-       if (ret_val)
-               return ret_val;
+       if (hw->mac.type == e1000_82571) {
+               /* Install any alternate MAC address into RAR0 */
+               ret_val = e1000_check_alt_mac_addr_generic(hw);
+               if (ret_val)
+                       return ret_val;
 
-       e1000e_set_laa_state_82571(hw, true);
+               e1000e_set_laa_state_82571(hw, true);
+       }
 
        /* Reinitialize the 82571 serdes link state machine */
        if (hw->phy.media_type == e1000_media_type_internal_serdes)
@@ -1618,14 +1620,16 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
 
-       /*
-        * If there's an alternate MAC address place it in RAR0
-        * so that it will override the Si installed default perm
-        * address.
-        */
-       ret_val = e1000_check_alt_mac_addr_generic(hw);
-       if (ret_val)
-               goto out;
+       if (hw->mac.type == e1000_82571) {
+               /*
+                * If there's an alternate MAC address place it in RAR0
+                * so that it will override the Si installed default perm
+                * address.
+                */
+               ret_val = e1000_check_alt_mac_addr_generic(hw);
+               if (ret_val)
+                       goto out;
+       }
 
        ret_val = e1000_read_mac_addr_generic(hw);
 
@@ -1833,6 +1837,7 @@ struct e1000_info e1000_82573_info = {
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_SWSM_ON_LOAD,
+       .flags2                 = FLAG2_DISABLE_ASPM_L1,
        .pba                    = 20,
        .max_hw_frame_size      = ETH_FRAME_LEN + ETH_FCS_LEN,
        .get_variants           = e1000_get_variants_82571,
index 307a72f483ee644fb1199776e4b0521739badb46..93b3bedae8d2b2457a88f52b4664fe1b4b6b7dd8 100644 (file)
 #define E1000_FLASH_UPDATES  2000
 
 /* NVM Word Offsets */
+#define NVM_COMPAT                 0x0003
 #define NVM_ID_LED_SETTINGS        0x0004
 #define NVM_INIT_CONTROL2_REG      0x000F
 #define NVM_INIT_CONTROL3_PORT_B   0x0014
 /* Mask bits for fields in Word 0x1a of the NVM */
 #define NVM_WORD1A_ASPM_MASK  0x000C
 
+/* Mask bits for fields in Word 0x03 of the EEPROM */
+#define NVM_COMPAT_LOM    0x0800
+
 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
 #define NVM_SUM                    0xBABA
 
index 66ed08f726fb9bcdd13225086d05f3dcf437da6a..ba302a5c2c30e14c2be16333f38adb2a2668a89c 100644 (file)
@@ -57,6 +57,7 @@ enum e1e_registers {
        E1000_SCTL     = 0x00024, /* SerDes Control - RW */
        E1000_FCAL     = 0x00028, /* Flow Control Address Low - RW */
        E1000_FCAH     = 0x0002C, /* Flow Control Address High -RW */
+       E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */
        E1000_FEXTNVM  = 0x00028, /* Future Extended NVM - RW */
        E1000_FCT      = 0x00030, /* Flow Control Type - RW */
        E1000_VET      = 0x00038, /* VLAN Ether Type - RW */
index 63930d12711cf44ceb3334e5334fef5089ecb2e2..57b5435599ab1d61c58e393d04e0a2f3912d66fc 100644 (file)
 #define E1000_FEXTNVM_SW_CONFIG                1
 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
 
+#define E1000_FEXTNVM4_BEACON_DURATION_MASK    0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
+
 #define PCIE_ICH8_SNOOP_ALL            PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES          7
 
 /* SMBus Address Phy Register */
 #define HV_SMB_ADDR            PHY_REG(768, 26)
+#define HV_SMB_ADDR_MASK       0x007F
 #define HV_SMB_ADDR_PEC_EN     0x0200
 #define HV_SMB_ADDR_VALID      0x0080
 
@@ -237,6 +242,8 @@ static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
 static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
+static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
+static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
 
 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
 {
@@ -272,7 +279,7 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
 static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       u32 ctrl;
+       u32 ctrl, fwsm;
        s32 ret_val = 0;
 
        phy->addr                     = 1;
@@ -294,7 +301,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
         * disabled, then toggle the LANPHYPC Value bit to force
         * the interconnect to PCIe mode.
         */
-       if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+       fwsm = er32(FWSM);
+       if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
                ctrl = er32(CTRL);
                ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
                ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
@@ -303,6 +311,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
                ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
                ew32(CTRL, ctrl);
                msleep(50);
+
+               /*
+                * Gate automatic PHY configuration by hardware on
+                * non-managed 82579
+                */
+               if (hw->mac.type == e1000_pch2lan)
+                       e1000_gate_hw_phy_config_ich8lan(hw, true);
        }
 
        /*
@@ -315,6 +330,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
        if (ret_val)
                goto out;
 
+       /* Ungate automatic PHY configuration on non-managed 82579 */
+       if ((hw->mac.type == e1000_pch2lan)  &&
+           !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+               msleep(10);
+               e1000_gate_hw_phy_config_ich8lan(hw, false);
+       }
+
        phy->id = e1000_phy_unknown;
        ret_val = e1000e_get_phy_id(hw);
        if (ret_val)
@@ -561,13 +583,10 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
        if (mac->type == e1000_ich8lan)
                e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
 
-       /* Disable PHY configuration by hardware, config by software */
-       if (mac->type == e1000_pch2lan) {
-               u32 extcnf_ctrl = er32(EXTCNF_CTRL);
-
-               extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
-               ew32(EXTCNF_CTRL, extcnf_ctrl);
-       }
+       /* Gate automatic PHY configuration by hardware on managed 82579 */
+       if ((mac->type == e1000_pch2lan) &&
+           (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+               e1000_gate_hw_phy_config_ich8lan(hw, true);
 
        return 0;
 }
@@ -652,6 +671,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        goto out;
        }
 
+       if (hw->mac.type == e1000_pch2lan) {
+               ret_val = e1000_k1_workaround_lv(hw);
+               if (ret_val)
+                       goto out;
+       }
+
        /*
         * Check if there was DownShift, must be checked
         * immediately after link-up
@@ -894,6 +919,34 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
        return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? 0 : E1000_BLK_PHY_RESET;
 }
 
+/**
+ *  e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states
+ *  @hw: pointer to the HW structure
+ *
+ *  Assumes semaphore already acquired.
+ *
+ **/
+static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
+{
+       u16 phy_data;
+       u32 strap = er32(STRAP);
+       s32 ret_val = 0;
+
+       strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+
+       ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
+       if (ret_val)
+               goto out;
+
+       phy_data &= ~HV_SMB_ADDR_MASK;
+       phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
+       phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+       ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
+
+out:
+       return ret_val;
+}
+
 /**
  *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
  *  @hw:   pointer to the HW structure
@@ -903,7 +956,6 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
  **/
 static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 {
-       struct e1000_adapter *adapter = hw->adapter;
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
        s32 ret_val = 0;
@@ -921,7 +973,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
                if (phy->type != e1000_phy_igp_3)
                        return ret_val;
 
-               if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) {
+               if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) ||
+                   (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) {
                        sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
                        break;
                }
@@ -961,21 +1014,16 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
        cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
        cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
 
-       if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
-           ((hw->mac.type == e1000_pchlan) ||
-            (hw->mac.type == e1000_pch2lan))) {
+       if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+           (hw->mac.type == e1000_pchlan)) ||
+            (hw->mac.type == e1000_pch2lan)) {
                /*
                 * HW configures the SMBus address and LEDs when the
                 * OEM and LCD Write Enable bits are set in the NVM.
                 * When both NVM bits are cleared, SW will configure
                 * them instead.
                 */
-               data = er32(STRAP);
-               data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
-               reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
-               reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
-               ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
-                                                       reg_data);
+               ret_val = e1000_write_smbus_addr(hw);
                if (ret_val)
                        goto out;
 
@@ -1440,10 +1488,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
                        goto out;
 
                /* Enable jumbo frame workaround in the PHY */
-               e1e_rphy(hw, PHY_REG(769, 20), &data);
-               ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
-               if (ret_val)
-                       goto out;
                e1e_rphy(hw, PHY_REG(769, 23), &data);
                data &= ~(0x7F << 5);
                data |= (0x37 << 5);
@@ -1452,7 +1496,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
                        goto out;
                e1e_rphy(hw, PHY_REG(769, 16), &data);
                data &= ~(1 << 13);
-               data |= (1 << 12);
                ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
                if (ret_val)
                        goto out;
@@ -1477,7 +1520,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 
                mac_reg = er32(RCTL);
                mac_reg &= ~E1000_RCTL_SECRC;
-               ew32(FFLT_DBG, mac_reg);
+               ew32(RCTL, mac_reg);
 
                ret_val = e1000e_read_kmrn_reg(hw,
                                                E1000_KMRNCTRLSTA_CTRL_OFFSET,
@@ -1503,17 +1546,12 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
                        goto out;
 
                /* Write PHY register values back to h/w defaults */
-               e1e_rphy(hw, PHY_REG(769, 20), &data);
-               ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
-               if (ret_val)
-                       goto out;
                e1e_rphy(hw, PHY_REG(769, 23), &data);
                data &= ~(0x7F << 5);
                ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
                if (ret_val)
                        goto out;
                e1e_rphy(hw, PHY_REG(769, 16), &data);
-               data &= ~(1 << 12);
                data |= (1 << 13);
                ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
                if (ret_val)
@@ -1558,6 +1596,69 @@ out:
        return ret_val;
 }
 
+/**
+ *  e1000_k1_gig_workaround_lv - K1 Si workaround
+ *  @hw:   pointer to the HW structure
+ *
+ *  Workaround to set the K1 beacon duration for 82579 parts
+ **/
+static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
+{
+       s32 ret_val = 0;
+       u16 status_reg = 0;
+       u32 mac_reg;
+
+       if (hw->mac.type != e1000_pch2lan)
+               goto out;
+
+       /* Set K1 beacon duration based on 1Gbps speed or otherwise */
+       ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
+       if (ret_val)
+               goto out;
+
+       if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
+           == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
+               mac_reg = er32(FEXTNVM4);
+               mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
+
+               if (status_reg & HV_M_STATUS_SPEED_1000)
+                       mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
+               else
+                       mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
+
+               ew32(FEXTNVM4, mac_reg);
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
+ *  @hw:   pointer to the HW structure
+ *  @gate: boolean set to true to gate, false to ungate
+ *
+ *  Gate/ungate the automatic PHY configuration via hardware; perform
+ *  the configuration via software instead.
+ **/
+static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
+{
+       u32 extcnf_ctrl;
+
+       if (hw->mac.type != e1000_pch2lan)
+               return;
+
+       extcnf_ctrl = er32(EXTCNF_CTRL);
+
+       if (gate)
+               extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+       else
+               extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+
+       ew32(EXTCNF_CTRL, extcnf_ctrl);
+       return;
+}
+
 /**
  *  e1000_lan_init_done_ich8lan - Check for PHY config completion
  *  @hw: pointer to the HW structure
@@ -1602,6 +1703,9 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
        if (e1000_check_reset_block(hw))
                goto out;
 
+       /* Allow time for h/w to get to quiescent state after reset */
+       msleep(10);
+
        /* Perform any necessary post-reset workarounds */
        switch (hw->mac.type) {
        case e1000_pchlan:
@@ -1630,6 +1734,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
        /* Configure the LCD with the OEM bits in NVM */
        ret_val = e1000_oem_bits_config_ich8lan(hw, true);
 
+       /* Ungate automatic PHY configuration on non-managed 82579 */
+       if ((hw->mac.type == e1000_pch2lan) &&
+           !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+               msleep(10);
+               e1000_gate_hw_phy_config_ich8lan(hw, false);
+       }
+
 out:
        return ret_val;
 }
@@ -1646,6 +1757,11 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
 
+       /* Gate automatic PHY configuration by hardware on non-managed 82579 */
+       if ((hw->mac.type == e1000_pch2lan) &&
+           !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+               e1000_gate_hw_phy_config_ich8lan(hw, true);
+
        ret_val = e1000e_phy_hw_reset_generic(hw);
        if (ret_val)
                goto out;
@@ -2910,6 +3026,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
                 * external PHY is reset.
                 */
                ctrl |= E1000_CTRL_PHY_RST;
+
+               /*
+                * Gate automatic PHY configuration by hardware on
+                * non-managed 82579
+                */
+               if ((hw->mac.type == e1000_pch2lan) &&
+                   !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+                       e1000_gate_hw_phy_config_ich8lan(hw, true);
        }
        ret_val = e1000_acquire_swflag_ich8lan(hw);
        e_dbg("Issuing a global reset to ich8lan\n");
@@ -3460,13 +3584,20 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
 void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
 {
        u32 phy_ctrl;
+       s32 ret_val;
 
        phy_ctrl = er32(PHY_CTRL);
        phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
        ew32(PHY_CTRL, phy_ctrl);
 
-       if (hw->mac.type >= e1000_pchlan)
-               e1000_phy_hw_reset_ich8lan(hw);
+       if (hw->mac.type >= e1000_pchlan) {
+               e1000_oem_bits_config_ich8lan(hw, true);
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return;
+               e1000_write_smbus_addr(hw);
+               hw->phy.ops.release(hw);
+       }
 }
 
 /**
index df4a2792293123eba7b1b6f3a589220ce1185ea1..0fd4eb5ac5fb9241f57061ee5eb76dff06e8afbf 100644 (file)
@@ -183,6 +183,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
        u16 offset, nvm_alt_mac_addr_offset, nvm_data;
        u8 alt_mac_addr[ETH_ALEN];
 
+       ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data);
+       if (ret_val)
+               goto out;
+
+       /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
+       if (!((nvm_data & NVM_COMPAT_LOM) ||
+             (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
+             (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)))
+               goto out;
+
        ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
                                 &nvm_alt_mac_addr_offset);
        if (ret_val) {
index 2b8ef44bd2b1629c5d203206479a3b8bab510fab..e561d15c3eb161558f9a7da3825f3cc6c90840c7 100644 (file)
@@ -2704,6 +2704,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        u32 psrctl = 0;
        u32 pages = 0;
 
+       /* Workaround Si errata on 82579 - configure jumbo frame flow */
+       if (hw->mac.type == e1000_pch2lan) {
+               s32 ret_val;
+
+               if (adapter->netdev->mtu > ETH_DATA_LEN)
+                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
+               else
+                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
+       }
+
        /* Program MC offset vector base */
        rctl = er32(RCTL);
        rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
@@ -2744,16 +2754,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
                e1e_wphy(hw, 22, phy_data);
        }
 
-       /* Workaround Si errata on 82579 - configure jumbo frame flow */
-       if (hw->mac.type == e1000_pch2lan) {
-               s32 ret_val;
-
-               if (rctl & E1000_RCTL_LPE)
-                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
-               else
-                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
-       }
-
        /* Setup buffer sizes */
        rctl &= ~E1000_RCTL_SZ_4096;
        rctl |= E1000_RCTL_BSEX;
@@ -4833,6 +4833,15 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                return -EINVAL;
        }
 
+       /* Jumbo frame workaround on 82579 requires CRC be stripped */
+       if ((adapter->hw.mac.type == e1000_pch2lan) &&
+           !(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
+           (new_mtu > ETH_DATA_LEN)) {
+               e_err("Jumbo Frames not supported on 82579 when CRC "
+                     "stripping is disabled.\n");
+               return -EINVAL;
+       }
+
        /* 82573 Errata 17 */
        if (((adapter->hw.mac.type == e1000_82573) ||
             (adapter->hw.mac.type == e1000_82574)) &&
index 99a929964e3cebde15667e59d913debd6d205b20..1846623c6ae65d18b6223ada9be4531809f64a99 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0105"
+#define DRV_VERSION    "EHEA_0106"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -400,6 +400,7 @@ struct ehea_port_res {
        u32 poll_counter;
        struct net_lro_mgr lro_mgr;
        struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
+       int sq_restart_flag;
 };
 
 
index 897719b49f96859b11a1f01f4f45e46c03c4cd71..6372610ed24093b8ed99fdf002e44442be49f696 100644 (file)
@@ -533,8 +533,15 @@ static inline void ehea_fill_skb(struct net_device *dev,
        int length = cqe->num_bytes_transfered - 4;     /*remove CRC */
 
        skb_put(skb, length);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
        skb->protocol = eth_type_trans(skb, dev);
+
+       /* The packet was not an IPV4 packet so a complemented checksum was
+          calculated. The value is found in the Internet Checksum field. */
+       if (cqe->status & EHEA_CQE_BLIND_CKSUM) {
+               skb->ip_summed = CHECKSUM_COMPLETE;
+               skb->csum = csum_unfold(~cqe->inet_checksum_value);
+       } else
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
 static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
@@ -776,6 +783,53 @@ static int ehea_proc_rwqes(struct net_device *dev,
        return processed;
 }
 
+#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull
+
+static void reset_sq_restart_flag(struct ehea_port *port)
+{
+       int i;
+
+       for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+               struct ehea_port_res *pr = &port->port_res[i];
+               pr->sq_restart_flag = 0;
+       }
+}
+
+static void check_sqs(struct ehea_port *port)
+{
+       struct ehea_swqe *swqe;
+       int swqe_index;
+       int i, k;
+
+       for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+               struct ehea_port_res *pr = &port->port_res[i];
+               k = 0;
+               swqe = ehea_get_swqe(pr->qp, &swqe_index);
+               memset(swqe, 0, SWQE_HEADER_SIZE);
+               atomic_dec(&pr->swqe_avail);
+
+               swqe->tx_control |= EHEA_SWQE_PURGE;
+               swqe->wr_id = SWQE_RESTART_CHECK;
+               swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
+               swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT;
+               swqe->immediate_data_length = 80;
+
+               ehea_post_swqe(pr->qp, swqe);
+
+               while (pr->sq_restart_flag == 0) {
+                       msleep(5);
+                       if (++k == 100) {
+                               ehea_error("HW/SW queues out of sync");
+                               ehea_schedule_port_reset(pr->port);
+                               return;
+                       }
+               }
+       }
+
+       return;
+}
+
+
 static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
 {
        struct sk_buff *skb;
@@ -793,6 +847,13 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
 
                cqe_counter++;
                rmb();
+
+               if (cqe->wr_id == SWQE_RESTART_CHECK) {
+                       pr->sq_restart_flag = 1;
+                       swqe_av++;
+                       break;
+               }
+
                if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
                        ehea_error("Bad send completion status=0x%04X",
                                   cqe->status);
@@ -2675,8 +2736,10 @@ static void ehea_flush_sq(struct ehea_port *port)
                int k = 0;
                while (atomic_read(&pr->swqe_avail) < swqe_max) {
                        msleep(5);
-                       if (++k == 20)
+                       if (++k == 20) {
+                               ehea_error("WARNING: sq not flushed completely");
                                break;
+                       }
                }
        }
 }
@@ -2917,6 +2980,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
                                        port_napi_disable(port);
                                        mutex_unlock(&port->port_lock);
                                }
+                               reset_sq_restart_flag(port);
                        }
 
                        /* Unregister old memory region */
@@ -2951,6 +3015,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
                                                mutex_lock(&port->port_lock);
                                                port_napi_enable(port);
                                                ret = ehea_restart_qps(dev);
+                                               check_sqs(port);
                                                if (!ret)
                                                        netif_wake_queue(dev);
                                                mutex_unlock(&port->port_lock);
index f608a6c54af5845727494c9749e2b786390dfa78..38104734a3be82b0fb4480526295510a4769e8bf 100644 (file)
@@ -150,6 +150,7 @@ struct ehea_rwqe {
 #define EHEA_CQE_TYPE_RQ           0x60
 #define EHEA_CQE_STAT_ERR_MASK     0x700F
 #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF
+#define EHEA_CQE_BLIND_CKSUM       0x8000
 #define EHEA_CQE_STAT_ERR_TCP      0x4000
 #define EHEA_CQE_STAT_ERR_IP       0x2000
 #define EHEA_CQE_STAT_ERR_CRC      0x1000
index dda2c7944da9a45872d55f626503d15c67c67641..0cb1cf9cf4b0c2c38abd69f964838f276c1a6ff9 100644 (file)
@@ -555,6 +555,8 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp)
        equalizer_t *eql;
        master_config_t mc;
 
+       memset(&mc, 0, sizeof(master_config_t));
+
        if (eql_is_master(dev)) {
                eql = netdev_priv(dev);
                mc.max_slaves = eql->max_slaves;
index 768b840aeb6b7b0bf2ceec87469bb0b4925b5d20..cce32d43175f5c3ed5f6e7ef2ebd56eede8e9139 100644 (file)
@@ -678,24 +678,37 @@ static int fec_enet_mii_probe(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct phy_device *phy_dev = NULL;
-       int ret;
+       char mdio_bus_id[MII_BUS_ID_SIZE];
+       char phy_name[MII_BUS_ID_SIZE + 3];
+       int phy_id;
 
        fep->phy_dev = NULL;
 
-       /* find the first phy */
-       phy_dev = phy_find_first(fep->mii_bus);
-       if (!phy_dev) {
-               printk(KERN_ERR "%s: no PHY found\n", dev->name);
-               return -ENODEV;
+       /* check for attached phy */
+       for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+               if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+                       continue;
+               if (fep->mii_bus->phy_map[phy_id] == NULL)
+                       continue;
+               if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+                       continue;
+               strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+               break;
        }
 
-       /* attach the mac to the phy */
-       ret = phy_connect_direct(dev, phy_dev,
-                            &fec_enet_adjust_link, 0,
-                            PHY_INTERFACE_MODE_MII);
-       if (ret) {
-               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-               return ret;
+       if (phy_id >= PHY_MAX_ADDR) {
+               printk(KERN_INFO "%s: no PHY, assuming direct connection "
+                       "to switch\n", dev->name);
+               strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
+               phy_id = 0;
+       }
+
+       snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+       phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+               PHY_INTERFACE_MODE_MII);
+       if (IS_ERR(phy_dev)) {
+               printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+               return PTR_ERR(phy_dev);
        }
 
        /* mask with MAC supported features */
@@ -738,7 +751,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
        fep->mii_bus->read = fec_enet_mdio_read;
        fep->mii_bus->write = fec_enet_mdio_write;
        fep->mii_bus->reset = fec_enet_mdio_reset;
-       snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+       snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1);
        fep->mii_bus->priv = fep;
        fep->mii_bus->parent = &pdev->dev;
 
@@ -1311,6 +1324,9 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_mii_init;
 
+       /* Carrier starts down, phylib will bring it up */
+       netif_carrier_off(ndev);
+
        ret = register_netdev(ndev);
        if (ret)
                goto failed_register;
index 4b52c767ad056ced9aafcafea8299384b807c169..3e5d0b6b6516133039192fa5dfd1fdf88660d81b 100644 (file)
@@ -608,7 +608,7 @@ static int sixpack_open(struct tty_struct *tty)
 
        spin_lock_init(&sp->lock);
        atomic_set(&sp->refcnt, 1);
-       init_MUTEX_LOCKED(&sp->dead_sem);
+       sema_init(&sp->dead_sem, 0);
 
        /* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
 
index 66e88bd59caada26f9cdaa4b6dbb7c1a78026e1f..4c628393c8b157cbc09de52d902b5fa8c3d370a3 100644 (file)
@@ -747,7 +747,7 @@ static int mkiss_open(struct tty_struct *tty)
 
        spin_lock_init(&ax->buflock);
        atomic_set(&ax->refcnt, 1);
-       init_MUTEX_LOCKED(&ax->dead_sem);
+       sema_init(&ax->dead_sem, 0);
 
        ax->tty = tty;
        tty->disc_data = ax;
index 3506fd6ad7263be467b9128938b248bbaf3dd054..519e19e23955a3c3a86d8e04f615b67daa7a996e 100644 (file)
@@ -2928,7 +2928,7 @@ static int __devinit emac_probe(struct platform_device *ofdev,
        if (dev->emac_irq != NO_IRQ)
                irq_dispose_mapping(dev->emac_irq);
  err_free:
-       kfree(ndev);
+       free_netdev(ndev);
  err_gone:
        /* if we were on the bootlist, remove us as we won't show up and
         * wake up all waiters to notify them in case they were waiting
@@ -2971,7 +2971,7 @@ static int __devexit emac_remove(struct platform_device *ofdev)
        if (dev->emac_irq != NO_IRQ)
                irq_dispose_mapping(dev->emac_irq);
 
-       kfree(dev->ndev);
+       free_netdev(dev->ndev);
 
        return 0;
 }
index 3995fafc1e08bb3adb8658bd4d0098c4aff09f60..8c6c1e2a87503e2f647fedd44c77dbb2ffcfb3c9 100644 (file)
@@ -238,7 +238,7 @@ void emac_dbg_dump_all(void)
 }
 
 #if defined(CONFIG_MAGIC_SYSRQ)
-static void emac_sysrq_handler(int key, struct tty_struct *tty)
+static void emac_sysrq_handler(int key)
 {
        emac_dbg_dump_all();
 }
index 2602852cc55a6037c5160575f3620632397fcd2c..4734c939ad03574a63e6dd0bc9ccf6d8cf29c06a 100644 (file)
@@ -1113,7 +1113,8 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
        struct ibmveth_adapter *adapter = netdev_priv(dev);
        struct vio_dev *viodev = adapter->vdev;
        int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
-       int i;
+       int i, rc;
+       int need_restart = 0;
 
        if (new_mtu < IBMVETH_MAX_MTU)
                return -EINVAL;
@@ -1127,35 +1128,32 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 
        /* Deactivate all the buffer pools so that the next loop can activate
           only the buffer pools necessary to hold the new MTU */
-       for (i = 0; i < IbmVethNumBufferPools; i++)
-               if (adapter->rx_buff_pool[i].active) {
-                       ibmveth_free_buffer_pool(adapter,
-                                                &adapter->rx_buff_pool[i]);
-                       adapter->rx_buff_pool[i].active = 0;
-               }
+       if (netif_running(adapter->netdev)) {
+               need_restart = 1;
+               adapter->pool_config = 1;
+               ibmveth_close(adapter->netdev);
+               adapter->pool_config = 0;
+       }
 
        /* Look for an active buffer pool that can hold the new MTU */
        for(i = 0; i<IbmVethNumBufferPools; i++) {
                adapter->rx_buff_pool[i].active = 1;
 
                if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
-                       if (netif_running(adapter->netdev)) {
-                               adapter->pool_config = 1;
-                               ibmveth_close(adapter->netdev);
-                               adapter->pool_config = 0;
-                               dev->mtu = new_mtu;
-                               vio_cmo_set_dev_desired(viodev,
-                                               ibmveth_get_desired_dma
-                                               (viodev));
-                               return ibmveth_open(adapter->netdev);
-                       }
                        dev->mtu = new_mtu;
                        vio_cmo_set_dev_desired(viodev,
                                                ibmveth_get_desired_dma
                                                (viodev));
+                       if (need_restart) {
+                               return ibmveth_open(adapter->netdev);
+                       }
                        return 0;
                }
        }
+
+       if (need_restart && (rc = ibmveth_open(adapter->netdev)))
+               return rc;
+
        return -EINVAL;
 }
 
index 1b051dab7b298a761a5d9e4f2ff38af16f062238..51d74447f8f8cb7d428c7bbdf22b14f71cdfc4aa 100644 (file)
@@ -909,7 +909,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
        dev->tx_skb = NULL;
 
        spin_lock_init(&dev->tx_lock);
-       init_MUTEX(&dev->fsm.sem);
+       sema_init(&dev->fsm.sem, 1);
 
        dev->drv = drv;
        dev->netdev = ndev;
index b4fb07a6f13ffd489c957816eebb4f831157ccd1..51919fcd50c26e2c0c6b8c23ba393887eca50254 100644 (file)
@@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
                ks8851_wrreg16(ks, KS_RXQCR,
                               ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
 
-               if (rxlen > 0) {
-                       skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
-                       if (!skb) {
-                               /* todo - dump frame and move on */
-                       }
+               if (rxlen > 4) {
+                       unsigned int rxalign;
+
+                       rxlen -= 4;
+                       rxalign = ALIGN(rxlen, 4);
+                       skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign);
+                       if (skb) {
 
-                       /* two bytes to ensure ip is aligned, and four bytes
-                        * for the status header and 4 bytes of garbage */
-                       skb_reserve(skb, 2 + 4 + 4);
+                               /* 4 bytes of status header + 4 bytes of
+                                * garbage: we put them before ethernet
+                                * header, so that they are copied,
+                                * but ignored.
+                                */
 
-                       rxpkt = skb_put(skb, rxlen - 4) - 8;
+                               rxpkt = skb_put(skb, rxlen) - 8;
 
-                       /* align the packet length to 4 bytes, and add 4 bytes
-                        * as we're getting the rx status header as well */
-                       ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
+                               ks8851_rdfifo(ks, rxpkt, rxalign + 8);
 
-                       if (netif_msg_pktdata(ks))
-                               ks8851_dbg_dumpkkt(ks, rxpkt);
+                               if (netif_msg_pktdata(ks))
+                                       ks8851_dbg_dumpkkt(ks, rxpkt);
 
-                       skb->protocol = eth_type_trans(skb, ks->netdev);
-                       netif_rx(skb);
+                               skb->protocol = eth_type_trans(skb, ks->netdev);
+                               netif_rx(skb);
 
-                       ks->netdev->stats.rx_packets++;
-                       ks->netdev->stats.rx_bytes += rxlen - 4;
+                               ks->netdev->stats.rx_packets++;
+                               ks->netdev->stats.rx_bytes += rxlen;
+                       }
                }
 
                ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
index c7b624711f5ecfc51981845857bda27ef264fa3e..87f0a93b165c33478e1d59aa5e23942afaccc80f 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/tcp.h>      /* needed for sizeof(tcphdr) */
@@ -902,8 +903,8 @@ temac_poll_controller(struct net_device *ndev)
        disable_irq(lp->tx_irq);
        disable_irq(lp->rx_irq);
 
-       ll_temac_rx_irq(lp->tx_irq, lp);
-       ll_temac_tx_irq(lp->rx_irq, lp);
+       ll_temac_rx_irq(lp->tx_irq, ndev);
+       ll_temac_tx_irq(lp->rx_irq, ndev);
 
        enable_irq(lp->tx_irq);
        enable_irq(lp->rx_irq);
index 5ae28c975b384bf64ff7a7dc763a3d1766669b5a..8cf9d4f56bb2223893dd912e1d475a48fc30f683 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/phy.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/of_mdio.h>
 
index ffa1b9ce1cc5a8f4c474136940df4de36d853c55..6dca3574e35507a94ca7e5b1b518a06199e99e03 100644 (file)
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 73
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.73"
+#define _NETXEN_NIC_LINUX_SUBVERSION 74
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.74"
 
 #define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
 #define _major(v)      (((v) >> 24) & 0xff)
index c865dda2adf15f8b59a579640d416099e9fabc0c..b075a35b85d4ef09cfab1b2df3b42be0313c2516 100644 (file)
@@ -1540,7 +1540,6 @@ netxen_process_rcv(struct netxen_adapter *adapter,
        if (pkt_offset)
                skb_pull(skb, pkt_offset);
 
-       skb->truesize = skb->len + sizeof(struct sk_buff);
        skb->protocol = eth_type_trans(skb, netdev);
 
        napi_gro_receive(&sds_ring->napi, skb);
@@ -1602,8 +1601,6 @@ netxen_process_lro(struct netxen_adapter *adapter,
 
        skb_put(skb, lro_length + data_offset);
 
-       skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
-
        skb_pull(skb, l2_hdr_offset);
        skb->protocol = eth_type_trans(skb, netdev);
 
@@ -1805,8 +1802,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
        netxen_ctx_msg msg = 0;
        struct list_head *head;
 
-       spin_lock(&rds_ring->lock);
-
        producer = rds_ring->producer;
 
        head = &rds_ring->free_list;
@@ -1853,8 +1848,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
                                        NETXEN_RCV_PRODUCER_OFFSET), msg);
                }
        }
-
-       spin_unlock(&rds_ring->lock);
 }
 
 static void
index fd86e18604e636a5b1ede55a077d56dd2ba06713..73d31459223098c8e3727a0565ed12805d58e388 100644 (file)
@@ -2032,8 +2032,6 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
        struct netxen_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
-       memset(stats, 0, sizeof(*stats));
-
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes;
@@ -2133,9 +2131,16 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void netxen_nic_poll_controller(struct net_device *netdev)
 {
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
        struct netxen_adapter *adapter = netdev_priv(netdev);
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
        disable_irq(adapter->irq);
-       netxen_intr(adapter->irq, adapter);
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               netxen_intr(adapter->irq, sds_ring);
+       }
        enable_irq(adapter->irq);
 }
 #endif
index bc695d53cdccbcca3eb1c2ccb30018acb3c8bde6..fe6983af6918fe37cdb5589907346557ddeeb8df 100644 (file)
@@ -7269,32 +7269,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np,
        struct niu_parent *parent = np->parent;
        struct niu_tcam_entry *tp;
        int i, idx, cnt;
-       u16 n_entries;
        unsigned long flags;
-
+       int ret = 0;
 
        /* put the tcam size here */
        nfc->data = tcam_get_size(np);
 
        niu_lock_parent(np, flags);
-       n_entries = nfc->rule_cnt;
        for (cnt = 0, i = 0; i < nfc->data; i++) {
                idx = tcam_get_index(np, i);
                tp = &parent->tcam[idx];
                if (!tp->valid)
                        continue;
+               if (cnt == nfc->rule_cnt) {
+                       ret = -EMSGSIZE;
+                       break;
+               }
                rule_locs[cnt] = i;
                cnt++;
        }
        niu_unlock_parent(np, flags);
 
-       if (n_entries != cnt) {
-               /* print warning, this should not happen */
-               netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n",
-                           np->parent->index, __func__, n_entries, cnt);
-       }
-
-       return 0;
+       return ret;
 }
 
 static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
index c683f77c6f424ebbc873d76f0e07cb386484ea70..ff824e11f0b6865a74a0f55de50f7a02d659e75c 100644 (file)
@@ -87,7 +87,6 @@ earlier 3Com products.
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -280,25 +279,15 @@ static int tc574_probe(struct pcmcia_device *link)
        spin_lock_init(&lp->window_lock);
        link->resource[0]->end = 32;
        link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->conf.ConfigIndex = 1;
+       link->config_flags |= CONF_ENABLE_IRQ;
+       link->config_index = 1;
 
        dev->netdev_ops = &el3_netdev_ops;
        SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
        dev->watchdog_timeo = TX_TIMEOUT;
 
        return tc574_config(link);
-} /* tc574_attach */
-
-/*
-
-       This deletes a driver "instance".  The device is de-registered
-       with Card Services.  If it has been released, all local data
-       structures are freed.  Otherwise, the structures will be freed
-       when the device is released.
-
-*/
+}
 
 static void tc574_detach(struct pcmcia_device *link)
 {
@@ -313,12 +302,6 @@ static void tc574_detach(struct pcmcia_device *link)
        free_netdev(dev);
 } /* tc574_detach */
 
-/*
-       tc574_config() is scheduled to run after a CARD_INSERTION event
-       is received, to configure the PCMCIA socket, and to make the
-       ethernet device available to the system.
-*/
-
 static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 
 static int tc574_config(struct pcmcia_device *link)
@@ -352,7 +335,7 @@ static int tc574_config(struct pcmcia_device *link)
        if (ret)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -465,12 +448,6 @@ failed:
 
 } /* tc574_config */
 
-/*
-       After a card is removed, tc574_release() will unregister the net
-       device, and release the PCMCIA configuration.  If the device is
-       still open, this will be postponed until it is closed.
-*/
-
 static void tc574_release(struct pcmcia_device *link)
 {
        pcmcia_disable_device(link);
@@ -1198,9 +1175,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
 
 static struct pcmcia_driver tc574_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "3c574_cs",
-       },
+       .name           = "3c574_cs",
        .probe          = tc574_probe,
        .remove         = tc574_detach,
        .id_table       = tc574_ids,
index 61f9cf2100ffd8bfdff824ccfa2c3f3013a8eb1f..a07e22295330dadf2407f558e8500231e8990035 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -176,14 +175,6 @@ static const struct ethtool_ops netdev_ethtool_ops;
 
 static void tc589_detach(struct pcmcia_device *p_dev);
 
-/*======================================================================
-
-    tc589_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static const struct net_device_ops el3_netdev_ops = {
        .ndo_open               = el3_open,
        .ndo_stop               = el3_close,
@@ -216,9 +207,8 @@ static int tc589_probe(struct pcmcia_device *link)
     link->resource[0]->end = 16;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
 
     dev->netdev_ops = &el3_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -226,16 +216,7 @@ static int tc589_probe(struct pcmcia_device *link)
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
     return tc589_config(link);
-} /* tc589_attach */
-
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
+}
 
 static void tc589_detach(struct pcmcia_device *link)
 {
@@ -250,14 +231,6 @@ static void tc589_detach(struct pcmcia_device *link)
     free_netdev(dev);
 } /* tc589_detach */
 
-/*======================================================================
-
-    tc589_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int tc589_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -294,7 +267,7 @@ static int tc589_config(struct pcmcia_device *link)
     if (ret)
            goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -352,14 +325,6 @@ failed:
     return -ENODEV;
 } /* tc589_config */
 
-/*======================================================================
-
-    After a card is removed, tc589_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void tc589_release(struct pcmcia_device *link)
 {
        pcmcia_disable_device(link);
@@ -955,9 +920,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
 
 static struct pcmcia_driver tc589_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "3c589_cs",
-       },
+       .name           = "3c589_cs",
        .probe          = tc589_probe,
        .remove         = tc589_detach,
        .id_table       = tc589_ids,
index 5f05ffb240cc899eb79537ffe8074ceb97d3da11..9e8b28b271ae9e48e4a798a4806a4a8c7853299a 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -140,14 +139,6 @@ static const struct net_device_ops axnet_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/*======================================================================
-
-    axnet_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int axnet_probe(struct pcmcia_device *link)
 {
     axnet_dev_t *info;
@@ -166,8 +157,7 @@ static int axnet_probe(struct pcmcia_device *link)
     info = PRIV(dev);
     info->p_dev = link;
     link->priv = dev;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &axnet_netdev_ops;
 
@@ -177,15 +167,6 @@ static int axnet_probe(struct pcmcia_device *link)
     return axnet_config(link);
 } /* axnet_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void axnet_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -231,7 +212,7 @@ static int get_prom(struct pcmcia_device *link)
     };
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
        return 0;
 
     axnet_reset_8390(dev);
@@ -248,14 +229,6 @@ static int get_prom(struct pcmcia_device *link)
     return 1;
 } /* get_prom */
 
-/*======================================================================
-
-    axnet_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
@@ -286,35 +259,16 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
-static int axnet_configcheck(struct pcmcia_device *p_dev,
-                            cistpl_cftable_entry_t *cfg,
-                            cistpl_cftable_entry_t *dflt,
-                            unsigned int vcc,
-                            void *priv_data)
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       int i;
-       cistpl_io_t *io = &cfg->io;
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       if (cfg->index == 0 || cfg->io.nwin == 0)
+       p_dev->config_index = 0x05;
+       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
                return -ENODEV;
 
-       p_dev->conf.ConfigIndex = 0x05;
-       /* For multifunction cards, by convention, we configure the
-          network function with window 0, and serial with window 1 */
-       if (io->nwin > 1) {
-               i = (io->win[1].len > io->win[0].len);
-               p_dev->resource[1]->start = io->win[1-i].base;
-               p_dev->resource[1]->end = io->win[1-i].len;
-       } else {
-               i = p_dev->resource[1]->end = 0;
-       }
-       p_dev->resource[0]->start = io->win[i].base;
-       p_dev->resource[0]->end = io->win[i].len;
-       p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-       if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-               return try_io_port(p_dev);
-
-       return -ENODEV;
+       return try_io_port(p_dev);
 }
 
 static int axnet_config(struct pcmcia_device *link)
@@ -326,20 +280,19 @@ static int axnet_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
 
     /* don't trust the CIS on this; Linksys got it wrong */
-    link->conf.Present = 0x63;
+    link->config_regs = 0x63;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
     if (ret != 0)
        goto failed;
 
     if (!link->irq)
            goto failed;
+
+    if (resource_size(link->resource[1]) == 8)
+       link->config_flags |= CONF_ENABLE_SPKR;
     
-    if (resource_size(link->resource[1]) == 8) {
-       link->conf.Attributes |= CONF_ENABLE_SPKR;
-       link->conf.Status = CCSR_AUDIO_ENA;
-    }
-    
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -414,14 +367,6 @@ failed:
     return -ENODEV;
 } /* axnet_config */
 
-/*======================================================================
-
-    After a card is removed, axnet_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void axnet_release(struct pcmcia_device *link)
 {
        pcmcia_disable_device(link);
@@ -783,9 +728,7 @@ MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
 
 static struct pcmcia_driver axnet_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "axnet_cs",
-       },
+       .name           = "axnet_cs",
        .probe          = axnet_probe,
        .remove         = axnet_detach,
        .id_table       = axnet_ids,
index 3c400cfa82ae2e88c0e67c3f0582f75491be925e..b706a72494774a73dd0514e85f5a37ea52985b05 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -123,14 +122,6 @@ typedef struct com20020_dev_t {
     struct net_device       *dev;
 } com20020_dev_t;
 
-/*======================================================================
-
-    com20020_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int com20020_probe(struct pcmcia_device *p_dev)
 {
     com20020_dev_t *info;
@@ -160,8 +151,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)
 
     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     p_dev->resource[0]->end = 16;
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
 
     info->dev = dev;
     p_dev->priv = info;
@@ -174,15 +164,6 @@ fail_alloc_info:
     return -ENOMEM;
 } /* com20020_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void com20020_detach(struct pcmcia_device *link)
 {
     struct com20020_dev_t *info = link->priv;
@@ -221,14 +202,6 @@ static void com20020_detach(struct pcmcia_device *link)
 
 } /* com20020_detach */
 
-/*======================================================================
-
-    com20020_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
 static int com20020_config(struct pcmcia_device *link)
 {
     struct arcnet_local *lp;
@@ -282,7 +255,7 @@ static int com20020_config(struct pcmcia_device *link)
 
     dev->irq = link->irq;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -316,14 +289,6 @@ failed:
     return -ENODEV;
 } /* com20020_config */
 
-/*======================================================================
-
-    After a card is removed, com20020_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void com20020_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "com20020_release\n");
@@ -366,9 +331,7 @@ MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
 
 static struct pcmcia_driver com20020_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "com20020_cs",
-       },
+       .name           = "com20020_cs",
        .probe          = com20020_probe,
        .remove         = com20020_detach,
        .id_table       = com20020_ids,
index 98fffb03ecd7f4714c068d7a47c5acf667423cac..1c327598bbe80efaa346d4f460ce54461f898368 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/ioport.h>
 #include <linux/crc32.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -252,8 +251,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -313,7 +311,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
        ret = pcmcia_request_io(link);
        if (ret == 0) {
            /* calculate ConfigIndex value */
-           link->conf.ConfigIndex = 
+           link->config_index =
                ((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
            return ret;
        }
@@ -321,11 +319,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
     return ret;        /* RequestIO failed */
 }
 
-static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
-                          cistpl_cftable_entry_t *cfg,
-                          cistpl_cftable_entry_t *dflt,
-                          unsigned int vcc,
-                          void *priv_data)
+static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
        return 0; /* strange, but that's what the code did already before... */
 }
@@ -362,28 +356,28 @@ static int fmvj18x_config(struct pcmcia_device *link)
                link->card_id == PRODID_TDK_NP9610 ||
                link->card_id == PRODID_TDK_MN3200) {
                /* MultiFunction Card */
-               link->conf.ConfigBase = 0x800;
-               link->conf.ConfigIndex = 0x47;
+               link->config_base = 0x800;
+               link->config_index = 0x47;
                link->resource[1]->end = 8;
            }
            break;
        case MANFID_NEC:
            cardtype = NEC; /* MultiFunction Card */
-           link->conf.ConfigBase = 0x800;
-           link->conf.ConfigIndex = 0x47;
+           link->config_base = 0x800;
+           link->config_index = 0x47;
            link->resource[1]->end = 8;
            break;
        case MANFID_KME:
            cardtype = KME; /* MultiFunction Card */
-           link->conf.ConfigBase = 0x800;
-           link->conf.ConfigIndex = 0x47;
+           link->config_base = 0x800;
+           link->config_index = 0x47;
            link->resource[1]->end = 8;
            break;
        case MANFID_CONTEC:
            cardtype = CONTEC;
            break;
        case MANFID_FUJITSU:
-           if (link->conf.ConfigBase == 0x0fe0)
+           if (link->config_base == 0x0fe0)
                cardtype = MBH10302;
            else if (link->card_id == PRODID_FUJITSU_MBH10302) 
                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
@@ -403,10 +397,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
        case MANFID_FUJITSU:
            if (link->card_id == PRODID_FUJITSU_MBH10304) {
                cardtype = XXX10304;    /* MBH10304 with buggy CIS */
-               link->conf.ConfigIndex = 0x20;
+               link->config_index = 0x20;
            } else {
                cardtype = MBH10302;    /* NextCom NC5310, etc. */
-               link->conf.ConfigIndex = 1;
+               link->config_index = 1;
            }
            break;
        case MANFID_UNGERMANN:
@@ -414,7 +408,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
            break;
        default:
            cardtype = MBH10302;
-           link->conf.ConfigIndex = 1;
+           link->config_index = 1;
        }
     }
 
@@ -432,7 +426,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
     ret = pcmcia_request_irq(link, fjn_interrupt);
     if (ret)
            goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -544,20 +538,18 @@ failed:
 
 static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
-    win_req_t req;
     u_char __iomem *base;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
        return -1;
 
-    base = ioremap(req.Base, req.Size);
-    pcmcia_map_mem_page(link, link->win, 0);
+    base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+    pcmcia_map_mem_page(link, link->resource[2], 0);
 
     /*
      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
@@ -582,7 +574,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
     }
 
     iounmap(base);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i != 0x200) ? 0 : -1;
 
 } /* fmvj18x_get_hwinfo */
@@ -590,27 +582,26 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 
 static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
-    win_req_t req;
     int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
     local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[3]->start = link->resource[3]->end = 0;
+    i = pcmcia_request_window(link, link->resource[3], 0);
     if (i != 0)
        return -1;
 
-    lp->base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(link->resource[3]->start,
+                      resource_size(link->resource[3]));
     if (lp->base == NULL) {
        printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
        return -1;
     }
 
-    i = pcmcia_map_mem_page(link, link->win, 0);
+    i = pcmcia_map_mem_page(link, link->resource[3], 0);
     if (i != 0) {
        iounmap(lp->base);
        lp->base = NULL;
@@ -638,7 +629,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
     u_char __iomem *tmp;
-    int j;
 
     dev_dbg(&link->dev, "fmvj18x_release\n");
 
@@ -646,7 +636,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
        tmp = lp->base;
        lp->base = NULL;    /* set NULL before iounmap */
        iounmap(tmp);
-       j = pcmcia_release_window(link, link->win);
     }
 
     pcmcia_disable_device(link);
@@ -708,9 +697,7 @@ MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
 
 static struct pcmcia_driver fmvj18x_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "fmvj18x_cs",
-       },
+       .name           = "fmvj18x_cs",
        .probe          = fmvj18x_probe,
        .remove         = fmvj18x_detach,
        .id_table       = fmvj18x_ids,
index b0d06a3d962fc235fdc22c8f5af840272a5574d3..bf7dff96d881d20ade26849c61604882709e4fd2 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/trdevice.h>
 #include <linux/ibmtr.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -102,9 +101,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 typedef struct ibmtr_dev_t {
        struct pcmcia_device    *p_dev;
-    struct net_device  *dev;
-    window_handle_t     sram_win_handle;
-    struct tok_info    *ti;
+       struct net_device       *dev;
+       struct tok_info         *ti;
 } ibmtr_dev_t;
 
 static void netdev_get_drvinfo(struct net_device *dev,
@@ -123,14 +121,6 @@ static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
        return tok_interrupt(irq, dev);
 };
 
-/*======================================================================
-
-    ibmtr_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int __devinit ibmtr_attach(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info;
@@ -153,9 +143,8 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[0]->end = 4;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_regs = PRESENT_OPTION;
 
     info->dev = dev;
 
@@ -164,15 +153,6 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
     return ibmtr_config(link);
 } /* ibmtr_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void ibmtr_detach(struct pcmcia_device *link)
 {
     struct ibmtr_dev_t *info = link->priv;
@@ -197,26 +177,17 @@ static void ibmtr_detach(struct pcmcia_device *link)
     kfree(info);
 } /* ibmtr_detach */
 
-/*======================================================================
-
-    ibmtr_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    token-ring device available to the system.
-
-======================================================================*/
-
 static int __devinit ibmtr_config(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
-    win_req_t req;
     int i, ret;
 
     dev_dbg(&link->dev, "ibmtr_config\n");
 
-    link->conf.ConfigIndex = 0x61;
     link->io_lines = 16;
+    link->config_index = 0x61;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
@@ -240,39 +211,39 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
 
     /* Allocate the MMIO memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; 
-    req.Size = 0x2000;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[2]->flags |= WIN_USE_WAIT;
+    link->resource[2]->start = 0;
+    link->resource[2]->end = 0x2000;
+    ret = pcmcia_request_window(link, link->resource[2], 250);
     if (ret)
            goto failed;
 
-    ret = pcmcia_map_mem_page(link, link->win, mmiobase);
+    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
     if (ret)
            goto failed;
-    ti->mmio = ioremap(req.Base, req.Size);
+    ti->mmio = ioremap(link->resource[2]->start,
+                   resource_size(link->resource[2]));
 
     /* Allocate the SRAM memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0;
-    req.Size = sramsize * 1024;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &info->sram_win_handle);
+    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0;
+    link->resource[3]->end = sramsize * 1024;
+    ret = pcmcia_request_window(link, link->resource[3], 250);
     if (ret)
            goto failed;
 
-    ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase);
+    ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
     if (ret)
            goto failed;
 
     ti->sram_base = srambase >> 12;
-    ti->sram_virt = ioremap(req.Base, req.Size);
-    ti->sram_phys = req.Base;
+    ti->sram_virt = ioremap(link->resource[3]->start,
+                   resource_size(link->resource[3]));
+    ti->sram_phys = link->resource[3]->start;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -301,14 +272,6 @@ failed:
     return -ENODEV;
 } /* ibmtr_config */
 
-/*======================================================================
-
-    After a card is removed, ibmtr_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void ibmtr_release(struct pcmcia_device *link)
 {
        ibmtr_dev_t *info = link->priv;
@@ -316,7 +279,7 @@ static void ibmtr_release(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "ibmtr_release\n");
 
-       if (link->win) {
+       if (link->resource[2]->end) {
                struct tok_info *ti = netdev_priv(dev);
                iounmap(ti->mmio);
        }
@@ -398,9 +361,7 @@ MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
 
 static struct pcmcia_driver ibmtr_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "ibmtr_cs",
-       },
+       .name           = "ibmtr_cs",
        .probe          = ibmtr_attach,
        .remove         = ibmtr_detach,
        .id_table       = ibmtr_ids,
index 68f2deeb3ade11722dc5333386f4afd56cc98eb3..1eca4f5a6e78b3824d3129a28a535764c0eefb98 100644 (file)
@@ -146,7 +146,6 @@ Include Files
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
@@ -435,13 +434,6 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/* ----------------------------------------------------------------------------
-nmclan_attach
-       Creates an "instance" of the driver, allocating local data
-       structures for one device.  The device is registered with Card
-       Services.
----------------------------------------------------------------------------- */
-
 static int nmclan_probe(struct pcmcia_device *link)
 {
     mace_private *lp;
@@ -460,10 +452,9 @@ static int nmclan_probe(struct pcmcia_device *link)
     spin_lock_init(&lp->bank_lock);
     link->resource[0]->end = 32;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
+    link->config_regs = PRESENT_OPTION;
 
     lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
@@ -474,14 +465,6 @@ static int nmclan_probe(struct pcmcia_device *link)
     return nmclan_config(link);
 } /* nmclan_attach */
 
-/* ----------------------------------------------------------------------------
-nmclan_detach
-       This deletes a driver "instance".  The device is de-registered
-       with Card Services.  If it has been released, all local data
-       structures are freed.  Otherwise, the structures will be freed
-       when the device is released.
----------------------------------------------------------------------------- */
-
 static void nmclan_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -625,13 +608,6 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
   return 0;
 } /* mace_init */
 
-/* ----------------------------------------------------------------------------
-nmclan_config
-       This routine is scheduled to run after a CARD_INSERTION event
-       is received, to configure the PCMCIA socket, and to make the
-       ethernet device available to the system.
----------------------------------------------------------------------------- */
-
 static int nmclan_config(struct pcmcia_device *link)
 {
   struct net_device *dev = link->priv;
@@ -650,7 +626,7 @@ static int nmclan_config(struct pcmcia_device *link)
   ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
   if (ret)
          goto failed;
-  ret = pcmcia_request_configuration(link, &link->conf);
+  ret = pcmcia_enable_device(link);
   if (ret)
          goto failed;
 
@@ -712,12 +688,6 @@ failed:
        return -ENODEV;
 } /* nmclan_config */
 
-/* ----------------------------------------------------------------------------
-nmclan_release
-       After a card is removed, nmclan_release() will unregister the
-       net device, and release the PCMCIA configuration.  If the device
-       is still open, this will be postponed until it is closed.
----------------------------------------------------------------------------- */
 static void nmclan_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "nmclan_release\n");
@@ -1535,9 +1505,7 @@ MODULE_DEVICE_TABLE(pcmcia, nmclan_ids);
 
 static struct pcmcia_driver nmclan_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "nmclan_cs",
-       },
+       .name           = "nmclan_cs",
        .probe          = nmclan_probe,
        .remove         = nmclan_detach,
        .id_table       = nmclan_ids,
index c3edfe4c26516fc14780ee19183fc6db95fbf273..5d7d1d3088ae148b6491fc07482b0970178b9466 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -238,14 +237,6 @@ static const struct net_device_ops pcnet_netdev_ops = {
 #endif
 };
 
-/*======================================================================
-
-    pcnet_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int pcnet_probe(struct pcmcia_device *link)
 {
     pcnet_dev_t *info;
@@ -260,23 +251,13 @@ static int pcnet_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = dev;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     dev->netdev_ops = &pcnet_netdev_ops;
 
     return pcnet_config(link);
 } /* pcnet_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void pcnet_detach(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
@@ -300,22 +281,22 @@ static void pcnet_detach(struct pcmcia_device *link)
 static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    win_req_t req;
     u_char __iomem *base, *virt;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
        return NULL;
 
-    virt = ioremap(req.Base, req.Size);
+    virt = ioremap(link->resource[2]->start,
+           resource_size(link->resource[2]));
     for (i = 0; i < NR_INFO; i++) {
-       pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1));
-       base = &virt[hw_info[i].offset & (req.Size-1)];
+       pcmcia_map_mem_page(link, link->resource[2],
+               hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+       base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
        if ((readb(base+0) == hw_info[i].a0) &&
            (readb(base+2) == hw_info[i].a1) &&
            (readb(base+4) == hw_info[i].a2)) {
@@ -326,7 +307,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
     }
 
     iounmap(virt);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
 
@@ -421,7 +402,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
     int i, j;
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
        return NULL;
 
     outb_p(0x01, ioaddr + EN0_DCFG);   /* Set word-wide access. */
@@ -463,14 +444,6 @@ static hw_info_t *get_hwired(struct pcmcia_device *link)
     return &default_info;
 } /* get_hwired */
 
-/*======================================================================
-
-    pcnet_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
@@ -502,100 +475,105 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
-static int pcnet_confcheck(struct pcmcia_device *p_dev,
-                          cistpl_cftable_entry_t *cfg,
-                          cistpl_cftable_entry_t *dflt,
-                          unsigned int vcc,
-                          void *priv_data)
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       int *has_shmem = priv_data;
-       int i;
-       cistpl_io_t *io = &cfg->io;
+       int *priv = priv_data;
+       int try = (*priv & 0x1);
+
+       *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
 
-       if (cfg->index == 0 || cfg->io.nwin == 0)
+       if (p_dev->config_index == 0)
                return -EINVAL;
 
-       /* For multifunction cards, by convention, we configure the
-          network function with window 0, and serial with window 1 */
-       if (io->nwin > 1) {
-               i = (io->win[1].len > io->win[0].len);
-               p_dev->resource[1]->start = io->win[1-i].base;
-               p_dev->resource[1]->end = io->win[1-i].len;
-       } else {
-               i = p_dev->resource[1]->end = 0;
+       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+               return -EINVAL;
+
+       if (try)
+               p_dev->io_lines = 16;
+       return try_io_port(p_dev);
+}
+
+static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
+                                  int *has_shmem, int try)
+{
+       struct net_device *dev = link->priv;
+       hw_info_t *local_hw_info;
+       pcnet_dev_t *info = PRIV(dev);
+       int priv = try;
+       int ret;
+
+       ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
+       if (ret) {
+               dev_warn(&link->dev, "no useable port range found\n");
+               return NULL;
        }
+       *has_shmem = (priv & 0x10);
 
-       *has_shmem = ((cfg->mem.nwin == 1) &&
-                     (cfg->mem.win[0].len >= 0x4000));
-       p_dev->resource[0]->start = io->win[i].base;
-       p_dev->resource[0]->end = io->win[i].len;
-       p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-       if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-               return try_io_port(p_dev);
+       if (!link->irq)
+               return NULL;
 
-       return 0;
+       if (resource_size(link->resource[1]) == 8)
+               link->config_flags |= CONF_ENABLE_SPKR;
+
+       if ((link->manf_id == MANFID_IBM) &&
+           (link->card_id == PRODID_IBM_HOME_AND_AWAY))
+               link->config_index |= 0x10;
+
+       ret = pcmcia_enable_device(link);
+       if (ret)
+               return NULL;
+
+       dev->irq = link->irq;
+       dev->base_addr = link->resource[0]->start;
+
+       if (info->flags & HAS_MISC_REG) {
+               if ((if_port == 1) || (if_port == 2))
+                       dev->if_port = if_port;
+               else
+                       dev_notice(&link->dev, "invalid if_port requested\n");
+       } else
+               dev->if_port = 0;
+
+       if ((link->config_base == 0x03c0) &&
+           (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
+               dev_info(&link->dev,
+                       "this is an AX88190 card - use axnet_cs instead.\n");
+               return NULL;
+       }
+
+       local_hw_info = get_hwinfo(link);
+       if (!local_hw_info)
+               local_hw_info = get_prom(link);
+       if (!local_hw_info)
+               local_hw_info = get_dl10019(link);
+       if (!local_hw_info)
+               local_hw_info = get_ax88190(link);
+       if (!local_hw_info)
+               local_hw_info = get_hwired(link);
+
+       return local_hw_info;
 }
 
 static int pcnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    int ret, start_pg, stop_pg, cm_offset;
+    int start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
     hw_info_t *local_hw_info;
 
     dev_dbg(&link->dev, "pcnet_config\n");
 
-    ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
-    if (ret)
-       goto failed;
-
-    if (!link->irq)
-           goto failed;
-
-    if (resource_size(link->resource[1]) == 8) {
-       link->conf.Attributes |= CONF_ENABLE_SPKR;
-       link->conf.Status = CCSR_AUDIO_ENA;
-    }
-    if ((link->manf_id == MANFID_IBM) &&
-       (link->card_id == PRODID_IBM_HOME_AND_AWAY))
-       link->conf.ConfigIndex |= 0x10;
-
-    ret = pcmcia_request_configuration(link, &link->conf);
-    if (ret)
-           goto failed;
-    dev->irq = link->irq;
-    dev->base_addr = link->resource[0]->start;
-    if (info->flags & HAS_MISC_REG) {
-       if ((if_port == 1) || (if_port == 2))
-           dev->if_port = if_port;
-       else
-           printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
-    } else {
-       dev->if_port = 0;
-    }
-
-    if ((link->conf.ConfigBase == 0x03c0) &&
-       (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
-       printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
-       printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
-       goto failed;
-    }
-
-    local_hw_info = get_hwinfo(link);
-    if (local_hw_info == NULL)
-       local_hw_info = get_prom(link);
-    if (local_hw_info == NULL)
-       local_hw_info = get_dl10019(link);
-    if (local_hw_info == NULL)
-       local_hw_info = get_ax88190(link);
-    if (local_hw_info == NULL)
-       local_hw_info = get_hwired(link);
-
-    if (local_hw_info == NULL) {
-       printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
-              " address for io base %#3lx\n", dev->base_addr);
-       goto failed;
+    local_hw_info = pcnet_try_config(link, &has_shmem, 0);
+    if (!local_hw_info) {
+           /* check whether forcing io_lines to 16 helps... */
+           pcmcia_disable_device(link);
+           local_hw_info = pcnet_try_config(link, &has_shmem, 1);
+           if (local_hw_info == NULL) {
+                   dev_notice(&link->dev, "unable to read hardware net"
+                           " address for io base %#3lx\n", dev->base_addr);
+                   goto failed;
+           }
     }
 
     info->flags = local_hw_info->flags;
@@ -662,14 +640,6 @@ failed:
     return -ENODEV;
 } /* pcnet_config */
 
-/*======================================================================
-
-    After a card is removed, pcnet_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void pcnet_release(struct pcmcia_device *link)
 {
        pcnet_dev_t *info = PRIV(link->priv);
@@ -682,15 +652,6 @@ static void pcnet_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-======================================================================*/
-
 static int pcnet_suspend(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
@@ -1459,7 +1420,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    win_req_t req;
     int i, window_size, offset, ret;
 
     window_size = (stop_pg - start_pg) << 8;
@@ -1470,22 +1430,22 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     window_size = roundup_pow_of_two(window_size);
 
     /* Allocate a memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; req.Size = window_size;
-    req.AccessSpeed = mem_speed;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0; link->resource[3]->end = window_size;
+    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
     if (ret)
            goto failed;
 
     offset = (start_pg << 8) + cm_offset;
     offset -= offset % window_size;
-    ret = pcmcia_map_mem_page(link, link->win, offset);
+    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
     if (ret)
            goto failed;
 
     /* Try scribbling on the buffer */
-    info->base = ioremap(req.Base, window_size);
+    info->base = ioremap(link->resource[3]->start,
+                       resource_size(link->resource[3]));
     for (i = 0; i < (TX_PAGES<<8); i += 2)
        __raw_writew((i>>1), info->base+offset+i);
     udelay(100);
@@ -1494,19 +1454,20 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     pcnet_reset_8390(dev);
     if (i != (TX_PAGES<<8)) {
        iounmap(info->base);
-       pcmcia_release_window(link, link->win);
-       info->base = NULL; link->win = 0;
+       pcmcia_release_window(link, link->resource[3]);
+       info->base = NULL;
        goto failed;
     }
 
     ei_status.mem = info->base + offset;
-    ei_status.priv = req.Size;
+    ei_status.priv = resource_size(link->resource[3]);
     dev->mem_start = (u_long)ei_status.mem;
-    dev->mem_end = dev->mem_start + req.Size;
+    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
 
     ei_status.tx_start_page = start_pg;
     ei_status.rx_start_page = start_pg + TX_PAGES;
-    ei_status.stop_page = start_pg + ((req.Size - offset) >> 8);
+    ei_status.stop_page = start_pg + (
+           (resource_size(link->resource[3]) - offset) >> 8);
 
     /* set up block i/o functions */
     ei_status.get_8390_hdr = &shmem_get_8390_hdr;
@@ -1637,6 +1598,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
        PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
        PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
+       PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616),
        PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
        PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
        PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
@@ -1744,9 +1706,7 @@ MODULE_FIRMWARE("cis/PE-200.cis");
 MODULE_FIRMWARE("cis/tamarack.cis");
 
 static struct pcmcia_driver pcnet_driver = {
-       .drv            = {
-               .name   = "pcnet_cs",
-       },
+       .name           = "pcnet_cs",
        .probe          = pcnet_probe,
        .remove         = pcnet_detach,
        .owner          = THIS_MODULE,
index 377367d03b419dd7907262bfaedaf3acc0d60aca..0af2fc8ec164a7b2a200ee0452777538d93d4b4e 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/jiffies.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -300,14 +299,6 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/*======================================================================
-
-  smc91c92_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-======================================================================*/
-
 static int smc91c92_probe(struct pcmcia_device *link)
 {
     struct smc_private *smc;
@@ -324,10 +315,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
-    link->resource[0]->end = 16;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
@@ -343,15 +330,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
     return smc91c92_config(link);
 } /* smc91c92_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void smc91c92_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -412,26 +390,28 @@ static int mhz_3288_power(struct pcmcia_device *link)
     mdelay(200);
 
     /* Now read and write the COR... */
-    tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
+    tmp = readb(smc->base + link->config_base + CISREG_COR);
     udelay(5);
-    writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
+    writeb(tmp, smc->base + link->config_base + CISREG_COR);
 
     return 0;
 }
 
-static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cf,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        int k;
-       p_dev->resource[1]->start = cf->io.win[0].base;
+       p_dev->io_lines = 16;
+       p_dev->resource[1]->start = p_dev->resource[0]->start;
+       p_dev->resource[1]->end = 8;
+       p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = 16;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
        for (k = 0; k < 0x400; k += 0x10) {
                if (k & 0x80)
                        continue;
                p_dev->resource[0]->start = k ^ 0x300;
-               p_dev->io_lines = 16;
                if (!pcmcia_request_io(p_dev))
                        return 0;
        }
@@ -442,14 +422,11 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    win_req_t req;
     unsigned int offset;
     int i;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
-    link->conf.Status = CCSR_AUDIO_ENA;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->end = 8;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ |
+           CONF_AUTO_SET_IO;
 
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
@@ -459,16 +436,16 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     dev->base_addr = link->resource[0]->start;
 
     /* Allocate a memory window, for accessing the ISR */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
            return -ENODEV;
 
-    smc->base = ioremap(req.Base, req.Size);
-    offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
-    i = pcmcia_map_mem_page(link, link->win, offset);
+    smc->base = ioremap(link->resource[2]->start,
+                   resource_size(link->resource[2]));
+    offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0;
+    i = pcmcia_map_mem_page(link, link->resource[2], offset);
     if ((i == 0) &&
        (smc->manfid == MANFID_MEGAHERTZ) &&
        (smc->cardid == PRODID_MEGAHERTZ_EM3288))
@@ -591,14 +568,12 @@ static int mot_setup(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int smc_configcheck(struct pcmcia_device *p_dev,
-                          cistpl_cftable_entry_t *cf,
-                          cistpl_cftable_entry_t *dflt,
-                          unsigned int vcc,
-                          void *priv_data)
+static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-       p_dev->resource[0]->start = cf->io.win[0].base;
-       p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+       p_dev->resource[0]->end = 16;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
        return pcmcia_request_io(p_dev);
 }
 
@@ -607,7 +582,8 @@ static int smc_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     int i;
 
-    link->resource[0]->end = 16;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, smc_configcheck, NULL);
     if (!i)
            dev->base_addr = link->resource[0]->start;
@@ -640,15 +616,14 @@ static int osi_config(struct pcmcia_device *link)
     static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
-    link->conf.Status = CCSR_AUDIO_ENA;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ;
     link->resource[0]->end = 64;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->end = 8;
 
     /* Enable Hard Decode, LAN, Modem */
-    link->conf.ConfigIndex = 0x23;
     link->io_lines = 16;
+    link->config_index = 0x23;
 
     for (i = j = 0; j < 4; j++) {
        link->resource[1]->start = com[j];
@@ -658,7 +633,7 @@ static int osi_config(struct pcmcia_device *link)
     }
     if (i != 0) {
        /* Fallback: turn off hard decode */
-       link->conf.ConfigIndex = 0x03;
+       link->config_index = 0x03;
        link->resource[1]->end = 0;
        i = pcmcia_request_io(link);
     }
@@ -817,27 +792,16 @@ static int check_sig(struct pcmcia_device *link)
     }
 
     if (width) {
-           modconf_t mod = {
-                   .Attributes = CONF_IO_CHANGE_WIDTH,
-           };
            printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
 
            smc91c92_suspend(link);
-           pcmcia_modify_configuration(link, &mod);
+           pcmcia_fixup_iowidth(link);
            smc91c92_resume(link);
            return check_sig(link);
     }
     return -ENODEV;
 }
 
-/*======================================================================
-
-    smc91c92_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int smc91c92_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -869,7 +833,7 @@ static int smc91c92_config(struct pcmcia_device *link)
     i = pcmcia_request_irq(link, smc_interrupt);
     if (i)
            goto config_failed;
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i)
            goto config_failed;
 
@@ -988,18 +952,10 @@ config_failed:
     return -ENODEV;
 } /* smc91c92_config */
 
-/*======================================================================
-
-    After a card is removed, smc91c92_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void smc91c92_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "smc91c92_release\n");
-       if (link->win) {
+       if (link->resource[2]->end) {
                struct net_device *dev = link->priv;
                struct smc_private *smc = netdev_priv(dev);
                iounmap(smc->base);
@@ -2101,9 +2057,7 @@ MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids);
 
 static struct pcmcia_driver smc91c92_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "smc91c92_cs",
-       },
+       .name           = "smc91c92_cs",
        .probe          = smc91c92_probe,
        .remove         = smc91c92_detach,
        .id_table       = smc91c92_ids,
index f5819526b5ee90c25a8630a63fc81f04b64ffb0e..1fece617c069b68ddb6b384741bf43519d52b99c 100644 (file)
@@ -82,7 +82,6 @@
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -267,33 +266,11 @@ static unsigned mii_rd(unsigned int ioaddr, u_char phyaddr, u_char phyreg);
 static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg,
                   unsigned data, int len);
 
-/*
- * The event() function is this driver's Card Services event handler.
- * It will be called by Card Services when an appropriate card status
- * event is received.  The config() and release() entry points are
- * used to configure or release a socket, in response to card insertion
- * and ejection events.  They are invoked from the event handler.
- */
-
 static int has_ce2_string(struct pcmcia_device * link);
 static int xirc2ps_config(struct pcmcia_device * link);
 static void xirc2ps_release(struct pcmcia_device * link);
-
-/****************
- * The attach() and detach() entry points are used to create and destroy
- * "instances" of the driver, where each instance represents everything
- * needed to manage one actual PCMCIA card.
- */
-
 static void xirc2ps_detach(struct pcmcia_device *p_dev);
 
-/****************
- * You'll also need to prototype all the functions that will actually
- * be used to talk to your device.  See 'pcmem_cs' for a good example
- * of a fully self-sufficient driver; the other drivers rely more or
- * less on other parts of the kernel.
- */
-
 static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
 
 typedef struct local_info_t {
@@ -501,16 +478,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/****************
- * xirc2ps_attach() creates an "instance" of the driver, allocating
- * local data structures for one device.  The device is registered
- * with Card Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a
- * card insertion event.
- */
-
 static int
 xirc2ps_probe(struct pcmcia_device *link)
 {
@@ -529,9 +496,7 @@ xirc2ps_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
+    link->config_index = 1;
 
     /* Fill in card specific entries */
     dev->netdev_ops = &netdev_ops;
@@ -542,13 +507,6 @@ xirc2ps_probe(struct pcmcia_device *link)
     return xirc2ps_config(link);
 } /* xirc2ps_attach */
 
-/****************
- *  This deletes a driver "instance".  The device is de-registered
- *  with Card Services.  If it has been released, all local data
- *  structures are freed.  Otherwise, the structures will be freed
- *  when the device is released.
- */
-
 static void
 xirc2ps_detach(struct pcmcia_device *link)
 {
@@ -667,44 +625,53 @@ has_ce2_string(struct pcmcia_device * p_dev)
 }
 
 static int
-xirc2ps_config_modem(struct pcmcia_device *p_dev,
-                    cistpl_cftable_entry_t *cf,
-                    cistpl_cftable_entry_t *dflt,
-                    unsigned int vcc,
-                    void *priv_data)
+xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data)
 {
        unsigned int ioaddr;
 
-       if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
-               for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-                       p_dev->resource[1]->start = cf->io.win[0].base;
-                       p_dev->resource[0]->start = ioaddr;
-                       if (!pcmcia_request_io(p_dev))
-                               return 0;
-               }
+       if ((p_dev->resource[0]->start & 0xf) == 8)
+               return -ENODEV;
+
+       p_dev->resource[0]->end = 16;
+       p_dev->resource[1]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+       p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->io_lines = 10;
+
+       p_dev->resource[1]->start = p_dev->resource[0]->start;
+       for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+               p_dev->resource[0]->start = ioaddr;
+               if (!pcmcia_request_io(p_dev))
+                       return 0;
        }
        return -ENODEV;
 }
 
 static int
-xirc2ps_config_check(struct pcmcia_device *p_dev,
-                    cistpl_cftable_entry_t *cf,
-                    cistpl_cftable_entry_t *dflt,
-                    unsigned int vcc,
-                    void *priv_data)
+xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        int *pass = priv_data;
+       resource_size_t tmp = p_dev->resource[1]->start;
 
-       if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
-               p_dev->resource[1]->start = cf->io.win[0].base;
-               p_dev->resource[0]->start = p_dev->resource[1]->start
-                       + (*pass ? (cf->index & 0x20 ? -24:8)
-                          : (cf->index & 0x20 ?   8:-24));
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -ENODEV;
+       tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8)
+               : (p_dev->config_index & 0x20 ?   8 : -24));
+
+       if ((p_dev->resource[0]->start & 0xf) == 8)
+               return -ENODEV;
+
+       p_dev->resource[0]->end = 18;
+       p_dev->resource[1]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+       p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->io_lines = 10;
 
+       p_dev->resource[1]->start = p_dev->resource[0]->start;
+       p_dev->resource[0]->start = tmp;
+       return pcmcia_request_io(p_dev);
 }
 
 
@@ -727,11 +694,6 @@ static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev,
 };
 
 
-/****************
- * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * ethernet device available to the system.
- */
 static int
 xirc2ps_config(struct pcmcia_device * link)
 {
@@ -807,32 +769,24 @@ xirc2ps_config(struct pcmcia_device * link)
        goto failure;
     }
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-    link->io_lines = 10;
     if (local->modem) {
        int pass;
+       link->config_flags |= CONF_AUTO_SET_IO;
 
-       if (do_sound) {
-           link->conf.Attributes |= CONF_ENABLE_SPKR;
-           link->conf.Status |= CCSR_AUDIO_ENA;
-       }
-       link->resource[1]->end = 8;
-       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
        if (local->dingo) {
            /* Take the Modem IO port from the CIS and scan for a free
             * Ethernet port */
-           link->resource[0]->end = 16; /* no Mako stuff anymore */
            if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
                    goto port_found;
        } else {
-           link->resource[0]->end = 18;
            /* We do 2 passes here: The first one uses the regular mapping and
             * the second tries again, thereby considering that the 32 ports are
             * mirrored every 32 bytes. Actually we use a mirrored port for
             * the Mako if (on the first pass) the COR bit 5 is set.
             */
            for (pass=0; pass < 2; pass++)
-                   if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
+                   if (!pcmcia_loop_config(link, xirc2ps_config_check,
+                                                   &pass))
                            goto port_found;
            /* if special option:
             * try to configure as Ethernet only.
@@ -840,7 +794,9 @@ xirc2ps_config(struct pcmcia_device * link)
        }
        printk(KNOT_XIRC "no ports available\n");
     } else {
+       link->io_lines = 10;
        link->resource[0]->end = 16;
+       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
        for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
            link->resource[0]->start = ioaddr;
            if (!(err = pcmcia_request_io(link)))
@@ -861,16 +817,14 @@ xirc2ps_config(struct pcmcia_device * link)
     if ((err=pcmcia_request_irq(link, xirc2ps_interrupt)))
        goto config_error;
 
-    /****************
-     * This actually configures the PCMCIA socket -- setting up
-     * the I/O windows and the interrupt mapping.
-     */
-    if ((err=pcmcia_request_configuration(link, &link->conf)))
+    link->config_flags |= CONF_ENABLE_IRQ;
+    if (do_sound)
+           link->config_flags |= CONF_ENABLE_SPKR;
+
+    if ((err = pcmcia_enable_device(link)))
        goto config_error;
 
     if (local->dingo) {
-       win_req_t req;
-
        /* Reset the modem's BAR to the correct value
         * This is necessary because in the RequestConfiguration call,
         * the base address of the ethernet port (BasePort1) is written
@@ -890,14 +844,14 @@ xirc2ps_config(struct pcmcia_device * link)
         * is at 0x0800. So we allocate a window into the attribute
         * memory and write direct to the CIS registers
         */
-       req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-       req.Base = req.Size = 0;
-       req.AccessSpeed = 0;
-       if ((err = pcmcia_request_window(link, &req, &link->win)))
+       link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM |
+                                       WIN_ENABLE;
+       link->resource[2]->start = link->resource[2]->end = 0;
+       if ((err = pcmcia_request_window(link, link->resource[2], 0)))
            goto config_error;
 
-       local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
-       if ((err = pcmcia_map_mem_page(link, link->win, 0)))
+       local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800;
+       if ((err = pcmcia_map_mem_page(link, link->resource[2], 0)))
            goto config_error;
 
        /* Setup the CCRs; there are no infos in the CIS about the Ethernet
@@ -978,17 +932,12 @@ xirc2ps_config(struct pcmcia_device * link)
     return -ENODEV;
 } /* xirc2ps_config */
 
-/****************
- * After a card is removed, xirc2ps_release() will unregister the net
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 xirc2ps_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "release\n");
 
-       if (link->win) {
+       if (link->resource[2]->end) {
                struct net_device *dev = link->priv;
                local_info_t *local = netdev_priv(dev);
                if (local->dingo)
@@ -1830,9 +1779,7 @@ MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids);
 
 static struct pcmcia_driver xirc2ps_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "xirc2ps_cs",
-       },
+       .name           = "xirc2ps_cs",
        .probe          = xirc2ps_probe,
        .remove         = xirc2ps_detach,
        .id_table       = xirc2ps_ids,
index 6a6b8199a0d6862467260384e32979584f24d95a..6c58da2b882c845e453ddd7b6bb0b544f4705b83 100644 (file)
@@ -308,7 +308,7 @@ static int mdio_bus_suspend(struct device *dev)
         * may call phy routines that try to grab the same lock, and that may
         * lead to a deadlock.
         */
-       if (phydev->attached_dev)
+       if (phydev->attached_dev && phydev->adjust_link)
                phy_stop_machine(phydev);
 
        if (!mdio_bus_phy_may_suspend(phydev))
@@ -331,7 +331,7 @@ static int mdio_bus_resume(struct device *dev)
                return ret;
 
 no_resume:
-       if (phydev->attached_dev)
+       if (phydev->attached_dev && phydev->adjust_link)
                phy_start_machine(phydev, NULL);
 
        return 0;
index c0761197c07e6a94e67e3d0d4f417d888e2ec68f..16ddc77313cb08348b3cdbdb7016bd5c56fb9304 100644 (file)
@@ -466,6 +466,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 
        phydev->interface = interface;
 
+       phydev->state = PHY_READY;
+
        /* Do initial configuration here, now that
         * we have certain key parameters
         * (dev_flags and interface) */
index af50a530daee25bf3debf8493690861c2ea2fcc2..78d70a6481bfa7f986e165e427b8c76bd75ae835 100644 (file)
@@ -184,7 +184,7 @@ ppp_asynctty_open(struct tty_struct *tty)
        tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
 
        atomic_set(&ap->refcnt, 1);
-       init_MUTEX_LOCKED(&ap->dead_sem);
+       sema_init(&ap->dead_sem, 0);
 
        ap->chan.private = ap;
        ap->chan.ops = &async_ops;
index 6695a51e09e9b86340aa0cee342f2fb8d99e1159..4bddb2afdd158aafccca77fa300b6c2743577727 100644 (file)
@@ -856,7 +856,8 @@ static const struct file_operations ppp_device_fops = {
        .poll           = ppp_poll,
        .unlocked_ioctl = ppp_ioctl,
        .open           = ppp_open,
-       .release        = ppp_release
+       .release        = ppp_release,
+       .llseek         = noop_llseek,
 };
 
 static __net_init int ppp_init_net(struct net *net)
@@ -1314,8 +1315,13 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
        hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
        i = 0;
        list_for_each_entry(pch, &ppp->channels, clist) {
-               navail += pch->avail = (pch->chan != NULL);
-               pch->speed = pch->chan->speed;
+               if (pch->chan) {
+                       pch->avail = 1;
+                       navail++;
+                       pch->speed = pch->chan->speed;
+               } else {
+                       pch->avail = 0;
+               }
                if (pch->avail) {
                        if (skb_queue_empty(&pch->file.xq) ||
                                !pch->had_frag) {
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
new file mode 100644 (file)
index 0000000..85eddda
--- /dev/null
@@ -0,0 +1,1666 @@
+/*
+ * PXA168 ethernet driver.
+ * Most of the code is derived from mv643xx ethernet driver.
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ *             Sachin Sanap <ssanap@marvell.com>
+ *             Philip Rakity <prakity@marvell.com>
+ *             Mark Brown <markb@marvell.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.
+ *
+ * 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/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/etherdevice.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <linux/pxa168_eth.h>
+
+#define DRIVER_NAME    "pxa168-eth"
+#define DRIVER_VERSION "0.3"
+
+/*
+ * Registers
+ */
+
+#define PHY_ADDRESS            0x0000
+#define SMI                    0x0010
+#define PORT_CONFIG            0x0400
+#define PORT_CONFIG_EXT                0x0408
+#define PORT_COMMAND           0x0410
+#define PORT_STATUS            0x0418
+#define HTPR                   0x0428
+#define SDMA_CONFIG            0x0440
+#define SDMA_CMD               0x0448
+#define INT_CAUSE              0x0450
+#define INT_W_CLEAR            0x0454
+#define INT_MASK               0x0458
+#define ETH_F_RX_DESC_0                0x0480
+#define ETH_C_RX_DESC_0                0x04A0
+#define ETH_C_TX_DESC_1                0x04E4
+
+/* smi register */
+#define SMI_BUSY               (1 << 28)       /* 0 - Write, 1 - Read  */
+#define SMI_R_VALID            (1 << 27)       /* 0 - Write, 1 - Read  */
+#define SMI_OP_W               (0 << 26)       /* Write operation      */
+#define SMI_OP_R               (1 << 26)       /* Read operation */
+
+#define PHY_WAIT_ITERATIONS    10
+
+#define PXA168_ETH_PHY_ADDR_DEFAULT    0
+/* RX & TX descriptor command */
+#define BUF_OWNED_BY_DMA       (1 << 31)
+
+/* RX descriptor status */
+#define RX_EN_INT              (1 << 23)
+#define RX_FIRST_DESC          (1 << 17)
+#define RX_LAST_DESC           (1 << 16)
+#define RX_ERROR               (1 << 15)
+
+/* TX descriptor command */
+#define TX_EN_INT              (1 << 23)
+#define TX_GEN_CRC             (1 << 22)
+#define TX_ZERO_PADDING                (1 << 18)
+#define TX_FIRST_DESC          (1 << 17)
+#define TX_LAST_DESC           (1 << 16)
+#define TX_ERROR               (1 << 15)
+
+/* SDMA_CMD */
+#define SDMA_CMD_AT            (1 << 31)
+#define SDMA_CMD_TXDL          (1 << 24)
+#define SDMA_CMD_TXDH          (1 << 23)
+#define SDMA_CMD_AR            (1 << 15)
+#define SDMA_CMD_ERD           (1 << 7)
+
+/* Bit definitions of the Port Config Reg */
+#define PCR_HS                 (1 << 12)
+#define PCR_EN                 (1 << 7)
+#define PCR_PM                 (1 << 0)
+
+/* Bit definitions of the Port Config Extend Reg */
+#define PCXR_2BSM              (1 << 28)
+#define PCXR_DSCP_EN           (1 << 21)
+#define PCXR_MFL_1518          (0 << 14)
+#define PCXR_MFL_1536          (1 << 14)
+#define PCXR_MFL_2048          (2 << 14)
+#define PCXR_MFL_64K           (3 << 14)
+#define PCXR_FLP               (1 << 11)
+#define PCXR_PRIO_TX_OFF       3
+#define PCXR_TX_HIGH_PRI       (7 << PCXR_PRIO_TX_OFF)
+
+/* Bit definitions of the SDMA Config Reg */
+#define SDCR_BSZ_OFF           12
+#define SDCR_BSZ8              (3 << SDCR_BSZ_OFF)
+#define SDCR_BSZ4              (2 << SDCR_BSZ_OFF)
+#define SDCR_BSZ2              (1 << SDCR_BSZ_OFF)
+#define SDCR_BSZ1              (0 << SDCR_BSZ_OFF)
+#define SDCR_BLMR              (1 << 6)
+#define SDCR_BLMT              (1 << 7)
+#define SDCR_RIFB              (1 << 9)
+#define SDCR_RC_OFF            2
+#define SDCR_RC_MAX_RETRANS    (0xf << SDCR_RC_OFF)
+
+/*
+ * Bit definitions of the Interrupt Cause Reg
+ * and Interrupt MASK Reg is the same
+ */
+#define ICR_RXBUF              (1 << 0)
+#define ICR_TXBUF_H            (1 << 2)
+#define ICR_TXBUF_L            (1 << 3)
+#define ICR_TXEND_H            (1 << 6)
+#define ICR_TXEND_L            (1 << 7)
+#define ICR_RXERR              (1 << 8)
+#define ICR_TXERR_H            (1 << 10)
+#define ICR_TXERR_L            (1 << 11)
+#define ICR_TX_UDR             (1 << 13)
+#define ICR_MII_CH             (1 << 28)
+
+#define ALL_INTS (ICR_TXBUF_H  | ICR_TXBUF_L  | ICR_TX_UDR |\
+                               ICR_TXERR_H  | ICR_TXERR_L |\
+                               ICR_TXEND_H  | ICR_TXEND_L |\
+                               ICR_RXBUF | ICR_RXERR  | ICR_MII_CH)
+
+#define ETH_HW_IP_ALIGN                2       /* hw aligns IP header */
+
+#define NUM_RX_DESCS           64
+#define NUM_TX_DESCS           64
+
+#define HASH_ADD               0
+#define HASH_DELETE            1
+#define HASH_ADDR_TABLE_SIZE   0x4000  /* 16K (1/2K address - PCR_HS == 1) */
+#define HOP_NUMBER             12
+
+/* Bit definitions for Port status */
+#define PORT_SPEED_100         (1 << 0)
+#define FULL_DUPLEX            (1 << 1)
+#define FLOW_CONTROL_ENABLED   (1 << 2)
+#define LINK_UP                        (1 << 3)
+
+/* Bit definitions for work to be done */
+#define WORK_LINK              (1 << 0)
+#define WORK_TX_DONE           (1 << 1)
+
+/*
+ * Misc definitions.
+ */
+#define SKB_DMA_REALIGN                ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES)
+
+struct rx_desc {
+       u32 cmd_sts;            /* Descriptor command status            */
+       u16 byte_cnt;           /* Descriptor buffer byte count         */
+       u16 buf_size;           /* Buffer size                          */
+       u32 buf_ptr;            /* Descriptor buffer pointer            */
+       u32 next_desc_ptr;      /* Next descriptor pointer              */
+};
+
+struct tx_desc {
+       u32 cmd_sts;            /* Command/status field                 */
+       u16 reserved;
+       u16 byte_cnt;           /* buffer byte count                    */
+       u32 buf_ptr;            /* pointer to buffer for this descriptor */
+       u32 next_desc_ptr;      /* Pointer to next descriptor           */
+};
+
+struct pxa168_eth_private {
+       int port_num;           /* User Ethernet port number    */
+
+       int rx_resource_err;    /* Rx ring resource error flag */
+
+       /* Next available and first returning Rx resource */
+       int rx_curr_desc_q, rx_used_desc_q;
+
+       /* Next available and first returning Tx resource */
+       int tx_curr_desc_q, tx_used_desc_q;
+
+       struct rx_desc *p_rx_desc_area;
+       dma_addr_t rx_desc_dma;
+       int rx_desc_area_size;
+       struct sk_buff **rx_skb;
+
+       struct tx_desc *p_tx_desc_area;
+       dma_addr_t tx_desc_dma;
+       int tx_desc_area_size;
+       struct sk_buff **tx_skb;
+
+       struct work_struct tx_timeout_task;
+
+       struct net_device *dev;
+       struct napi_struct napi;
+       u8 work_todo;
+       int skb_size;
+
+       struct net_device_stats stats;
+       /* Size of Tx Ring per queue */
+       int tx_ring_size;
+       /* Number of tx descriptors in use */
+       int tx_desc_count;
+       /* Size of Rx Ring per queue */
+       int rx_ring_size;
+       /* Number of rx descriptors in use */
+       int rx_desc_count;
+
+       /*
+        * Used in case RX Ring is empty, which can occur when
+        * system does not have resources (skb's)
+        */
+       struct timer_list timeout;
+       struct mii_bus *smi_bus;
+       struct phy_device *phy;
+
+       /* clock */
+       struct clk *clk;
+       struct pxa168_eth_platform_data *pd;
+       /*
+        * Ethernet controller base address.
+        */
+       void __iomem *base;
+
+       /* Pointer to the hardware address filter table */
+       void *htpr;
+       dma_addr_t htpr_dma;
+};
+
+struct addr_table_entry {
+       __le32 lo;
+       __le32 hi;
+};
+
+/* Bit fields of a Hash Table Entry */
+enum hash_table_entry {
+       HASH_ENTRY_VALID = 1,
+       SKIP = 2,
+       HASH_ENTRY_RECEIVE_DISCARD = 4,
+       HASH_ENTRY_RECEIVE_DISCARD_BIT = 2
+};
+
+static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
+static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd);
+static int pxa168_init_hw(struct pxa168_eth_private *pep);
+static void eth_port_reset(struct net_device *dev);
+static void eth_port_start(struct net_device *dev);
+static int pxa168_eth_open(struct net_device *dev);
+static int pxa168_eth_stop(struct net_device *dev);
+static int ethernet_phy_setup(struct net_device *dev);
+
+static inline u32 rdl(struct pxa168_eth_private *pep, int offset)
+{
+       return readl(pep->base + offset);
+}
+
+static inline void wrl(struct pxa168_eth_private *pep, int offset, u32 data)
+{
+       writel(data, pep->base + offset);
+}
+
+static void abort_dma(struct pxa168_eth_private *pep)
+{
+       int delay;
+       int max_retries = 40;
+
+       do {
+               wrl(pep, SDMA_CMD, SDMA_CMD_AR | SDMA_CMD_AT);
+               udelay(100);
+
+               delay = 10;
+               while ((rdl(pep, SDMA_CMD) & (SDMA_CMD_AR | SDMA_CMD_AT))
+                      && delay-- > 0) {
+                       udelay(10);
+               }
+       } while (max_retries-- > 0 && delay <= 0);
+
+       if (max_retries <= 0)
+               printk(KERN_ERR "%s : DMA Stuck\n", __func__);
+}
+
+static int ethernet_phy_get(struct pxa168_eth_private *pep)
+{
+       unsigned int reg_data;
+
+       reg_data = rdl(pep, PHY_ADDRESS);
+
+       return (reg_data >> (5 * pep->port_num)) & 0x1f;
+}
+
+static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr)
+{
+       u32 reg_data;
+       int addr_shift = 5 * pep->port_num;
+
+       reg_data = rdl(pep, PHY_ADDRESS);
+       reg_data &= ~(0x1f << addr_shift);
+       reg_data |= (phy_addr & 0x1f) << addr_shift;
+       wrl(pep, PHY_ADDRESS, reg_data);
+}
+
+static void ethernet_phy_reset(struct pxa168_eth_private *pep)
+{
+       int data;
+
+       data = phy_read(pep->phy, MII_BMCR);
+       if (data < 0)
+               return;
+
+       data |= BMCR_RESET;
+       if (phy_write(pep->phy, MII_BMCR, data) < 0)
+               return;
+
+       do {
+               data = phy_read(pep->phy, MII_BMCR);
+       } while (data >= 0 && data & BMCR_RESET);
+}
+
+static void rxq_refill(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct sk_buff *skb;
+       struct rx_desc *p_used_rx_desc;
+       int used_rx_desc;
+
+       while (pep->rx_desc_count < pep->rx_ring_size) {
+               int size;
+
+               skb = dev_alloc_skb(pep->skb_size);
+               if (!skb)
+                       break;
+               if (SKB_DMA_REALIGN)
+                       skb_reserve(skb, SKB_DMA_REALIGN);
+               pep->rx_desc_count++;
+               /* Get 'used' Rx descriptor */
+               used_rx_desc = pep->rx_used_desc_q;
+               p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc];
+               size = skb->end - skb->data;
+               p_used_rx_desc->buf_ptr = dma_map_single(NULL,
+                                                        skb->data,
+                                                        size,
+                                                        DMA_FROM_DEVICE);
+               p_used_rx_desc->buf_size = size;
+               pep->rx_skb[used_rx_desc] = skb;
+
+               /* Return the descriptor to DMA ownership */
+               wmb();
+               p_used_rx_desc->cmd_sts = BUF_OWNED_BY_DMA | RX_EN_INT;
+               wmb();
+
+               /* Move the used descriptor pointer to the next descriptor */
+               pep->rx_used_desc_q = (used_rx_desc + 1) % pep->rx_ring_size;
+
+               /* Any Rx return cancels the Rx resource error status */
+               pep->rx_resource_err = 0;
+
+               skb_reserve(skb, ETH_HW_IP_ALIGN);
+       }
+
+       /*
+        * If RX ring is empty of SKB, set a timer to try allocating
+        * again at a later time.
+        */
+       if (pep->rx_desc_count == 0) {
+               pep->timeout.expires = jiffies + (HZ / 10);
+               add_timer(&pep->timeout);
+       }
+}
+
+static inline void rxq_refill_timer_wrapper(unsigned long data)
+{
+       struct pxa168_eth_private *pep = (void *)data;
+       napi_schedule(&pep->napi);
+}
+
+static inline u8 flip_8_bits(u8 x)
+{
+       return (((x) & 0x01) << 3) | (((x) & 0x02) << 1)
+           | (((x) & 0x04) >> 1) | (((x) & 0x08) >> 3)
+           | (((x) & 0x10) << 3) | (((x) & 0x20) << 1)
+           | (((x) & 0x40) >> 1) | (((x) & 0x80) >> 3);
+}
+
+static void nibble_swap_every_byte(unsigned char *mac_addr)
+{
+       int i;
+       for (i = 0; i < ETH_ALEN; i++) {
+               mac_addr[i] = ((mac_addr[i] & 0x0f) << 4) |
+                               ((mac_addr[i] & 0xf0) >> 4);
+       }
+}
+
+static void inverse_every_nibble(unsigned char *mac_addr)
+{
+       int i;
+       for (i = 0; i < ETH_ALEN; i++)
+               mac_addr[i] = flip_8_bits(mac_addr[i]);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will calculate the hash function of the address.
+ * Inputs
+ * mac_addr_orig    - MAC address.
+ * Outputs
+ * return the calculated entry.
+ */
+static u32 hash_function(unsigned char *mac_addr_orig)
+{
+       u32 hash_result;
+       u32 addr0;
+       u32 addr1;
+       u32 addr2;
+       u32 addr3;
+       unsigned char mac_addr[ETH_ALEN];
+
+       /* Make a copy of MAC address since we are going to performe bit
+        * operations on it
+        */
+       memcpy(mac_addr, mac_addr_orig, ETH_ALEN);
+
+       nibble_swap_every_byte(mac_addr);
+       inverse_every_nibble(mac_addr);
+
+       addr0 = (mac_addr[5] >> 2) & 0x3f;
+       addr1 = (mac_addr[5] & 0x03) | (((mac_addr[4] & 0x7f)) << 2);
+       addr2 = ((mac_addr[4] & 0x80) >> 7) | mac_addr[3] << 1;
+       addr3 = (mac_addr[2] & 0xff) | ((mac_addr[1] & 1) << 8);
+
+       hash_result = (addr0 << 9) | (addr1 ^ addr2 ^ addr3);
+       hash_result = hash_result & 0x07ff;
+       return hash_result;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will add/del an entry to the address table.
+ * Inputs
+ * pep - ETHERNET .
+ * mac_addr - MAC address.
+ * skip - if 1, skip this address.Used in case of deleting an entry which is a
+ *       part of chain in the hash table.We cant just delete the entry since
+ *       that will break the chain.We need to defragment the tables time to
+ *       time.
+ * rd   - 0 Discard packet upon match.
+ *     - 1 Receive packet upon match.
+ * Outputs
+ * address table entry is added/deleted.
+ * 0 if success.
+ * -ENOSPC if table full
+ */
+static int add_del_hash_entry(struct pxa168_eth_private *pep,
+                             unsigned char *mac_addr,
+                             u32 rd, u32 skip, int del)
+{
+       struct addr_table_entry *entry, *start;
+       u32 new_high;
+       u32 new_low;
+       u32 i;
+
+       new_low = (((mac_addr[1] >> 4) & 0xf) << 15)
+           | (((mac_addr[1] >> 0) & 0xf) << 11)
+           | (((mac_addr[0] >> 4) & 0xf) << 7)
+           | (((mac_addr[0] >> 0) & 0xf) << 3)
+           | (((mac_addr[3] >> 4) & 0x1) << 31)
+           | (((mac_addr[3] >> 0) & 0xf) << 27)
+           | (((mac_addr[2] >> 4) & 0xf) << 23)
+           | (((mac_addr[2] >> 0) & 0xf) << 19)
+           | (skip << SKIP) | (rd << HASH_ENTRY_RECEIVE_DISCARD_BIT)
+           | HASH_ENTRY_VALID;
+
+       new_high = (((mac_addr[5] >> 4) & 0xf) << 15)
+           | (((mac_addr[5] >> 0) & 0xf) << 11)
+           | (((mac_addr[4] >> 4) & 0xf) << 7)
+           | (((mac_addr[4] >> 0) & 0xf) << 3)
+           | (((mac_addr[3] >> 5) & 0x7) << 0);
+
+       /*
+        * Pick the appropriate table, start scanning for free/reusable
+        * entries at the index obtained by hashing the specified MAC address
+        */
+       start = (struct addr_table_entry *)(pep->htpr);
+       entry = start + hash_function(mac_addr);
+       for (i = 0; i < HOP_NUMBER; i++) {
+               if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) {
+                       break;
+               } else {
+                       /* if same address put in same position */
+                       if (((le32_to_cpu(entry->lo) & 0xfffffff8) ==
+                               (new_low & 0xfffffff8)) &&
+                               (le32_to_cpu(entry->hi) == new_high)) {
+                               break;
+                       }
+               }
+               if (entry == start + 0x7ff)
+                       entry = start;
+               else
+                       entry++;
+       }
+
+       if (((le32_to_cpu(entry->lo) & 0xfffffff8) != (new_low & 0xfffffff8)) &&
+           (le32_to_cpu(entry->hi) != new_high) && del)
+               return 0;
+
+       if (i == HOP_NUMBER) {
+               if (!del) {
+                       printk(KERN_INFO "%s: table section is full, need to "
+                                       "move to 16kB implementation?\n",
+                                        __FILE__);
+                       return -ENOSPC;
+               } else
+                       return 0;
+       }
+
+       /*
+        * Update the selected entry
+        */
+       if (del) {
+               entry->hi = 0;
+               entry->lo = 0;
+       } else {
+               entry->hi = cpu_to_le32(new_high);
+               entry->lo = cpu_to_le32(new_low);
+       }
+
+       return 0;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ *  Create an addressTable entry from MAC address info
+ *  found in the specifed net_device struct
+ *
+ *  Input : pointer to ethernet interface network device structure
+ *  Output : N/A
+ */
+static void update_hash_table_mac_address(struct pxa168_eth_private *pep,
+                                         unsigned char *oaddr,
+                                         unsigned char *addr)
+{
+       /* Delete old entry */
+       if (oaddr)
+               add_del_hash_entry(pep, oaddr, 1, 0, HASH_DELETE);
+       /* Add new entry */
+       add_del_hash_entry(pep, addr, 1, 0, HASH_ADD);
+}
+
+static int init_hash_table(struct pxa168_eth_private *pep)
+{
+       /*
+        * Hardware expects CPU to build a hash table based on a predefined
+        * hash function and populate it based on hardware address. The
+        * location of the hash table is identified by 32-bit pointer stored
+        * in HTPR internal register. Two possible sizes exists for the hash
+        * table 8kB (256kB of DRAM required (4 x 64 kB banks)) and 1/2kB
+        * (16kB of DRAM required (4 x 4 kB banks)).We currently only support
+        * 1/2kB.
+        */
+       /* TODO: Add support for 8kB hash table and alternative hash
+        * function.Driver can dynamically switch to them if the 1/2kB hash
+        * table is full.
+        */
+       if (pep->htpr == NULL) {
+               pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
+                                             HASH_ADDR_TABLE_SIZE,
+                                             &pep->htpr_dma, GFP_KERNEL);
+               if (pep->htpr == NULL)
+                       return -ENOMEM;
+       }
+       memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
+       wrl(pep, HTPR, pep->htpr_dma);
+       return 0;
+}
+
+static void pxa168_eth_set_rx_mode(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct netdev_hw_addr *ha;
+       u32 val;
+
+       val = rdl(pep, PORT_CONFIG);
+       if (dev->flags & IFF_PROMISC)
+               val |= PCR_PM;
+       else
+               val &= ~PCR_PM;
+       wrl(pep, PORT_CONFIG, val);
+
+       /*
+        * Remove the old list of MAC address and add dev->addr
+        * and multicast address.
+        */
+       memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
+       update_hash_table_mac_address(pep, NULL, dev->dev_addr);
+
+       netdev_for_each_mc_addr(ha, dev)
+               update_hash_table_mac_address(pep, NULL, ha->addr);
+}
+
+static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *sa = addr;
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       unsigned char oldMac[ETH_ALEN];
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EINVAL;
+       memcpy(oldMac, dev->dev_addr, ETH_ALEN);
+       memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
+       netif_addr_lock_bh(dev);
+       update_hash_table_mac_address(pep, oldMac, dev->dev_addr);
+       netif_addr_unlock_bh(dev);
+       return 0;
+}
+
+static void eth_port_start(struct net_device *dev)
+{
+       unsigned int val = 0;
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       int tx_curr_desc, rx_curr_desc;
+
+       /* Perform PHY reset, if there is a PHY. */
+       if (pep->phy != NULL) {
+               struct ethtool_cmd cmd;
+
+               pxa168_get_settings(pep->dev, &cmd);
+               ethernet_phy_reset(pep);
+               pxa168_set_settings(pep->dev, &cmd);
+       }
+
+       /* Assignment of Tx CTRP of given queue */
+       tx_curr_desc = pep->tx_curr_desc_q;
+       wrl(pep, ETH_C_TX_DESC_1,
+           (u32) (pep->tx_desc_dma + tx_curr_desc * sizeof(struct tx_desc)));
+
+       /* Assignment of Rx CRDP of given queue */
+       rx_curr_desc = pep->rx_curr_desc_q;
+       wrl(pep, ETH_C_RX_DESC_0,
+           (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
+
+       wrl(pep, ETH_F_RX_DESC_0,
+           (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
+
+       /* Clear all interrupts */
+       wrl(pep, INT_CAUSE, 0);
+
+       /* Enable all interrupts for receive, transmit and error. */
+       wrl(pep, INT_MASK, ALL_INTS);
+
+       val = rdl(pep, PORT_CONFIG);
+       val |= PCR_EN;
+       wrl(pep, PORT_CONFIG, val);
+
+       /* Start RX DMA engine */
+       val = rdl(pep, SDMA_CMD);
+       val |= SDMA_CMD_ERD;
+       wrl(pep, SDMA_CMD, val);
+}
+
+static void eth_port_reset(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       unsigned int val = 0;
+
+       /* Stop all interrupts for receive, transmit and error. */
+       wrl(pep, INT_MASK, 0);
+
+       /* Clear all interrupts */
+       wrl(pep, INT_CAUSE, 0);
+
+       /* Stop RX DMA */
+       val = rdl(pep, SDMA_CMD);
+       val &= ~SDMA_CMD_ERD;   /* abort dma command */
+
+       /* Abort any transmit and receive operations and put DMA
+        * in idle state.
+        */
+       abort_dma(pep);
+
+       /* Disable port */
+       val = rdl(pep, PORT_CONFIG);
+       val &= ~PCR_EN;
+       wrl(pep, PORT_CONFIG, val);
+}
+
+/*
+ * txq_reclaim - Free the tx desc data for completed descriptors
+ * If force is non-zero, frees uncompleted descriptors as well
+ */
+static int txq_reclaim(struct net_device *dev, int force)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct tx_desc *desc;
+       u32 cmd_sts;
+       struct sk_buff *skb;
+       int tx_index;
+       dma_addr_t addr;
+       int count;
+       int released = 0;
+
+       netif_tx_lock(dev);
+
+       pep->work_todo &= ~WORK_TX_DONE;
+       while (pep->tx_desc_count > 0) {
+               tx_index = pep->tx_used_desc_q;
+               desc = &pep->p_tx_desc_area[tx_index];
+               cmd_sts = desc->cmd_sts;
+               if (!force && (cmd_sts & BUF_OWNED_BY_DMA)) {
+                       if (released > 0) {
+                               goto txq_reclaim_end;
+                       } else {
+                               released = -1;
+                               goto txq_reclaim_end;
+                       }
+               }
+               pep->tx_used_desc_q = (tx_index + 1) % pep->tx_ring_size;
+               pep->tx_desc_count--;
+               addr = desc->buf_ptr;
+               count = desc->byte_cnt;
+               skb = pep->tx_skb[tx_index];
+               if (skb)
+                       pep->tx_skb[tx_index] = NULL;
+
+               if (cmd_sts & TX_ERROR) {
+                       if (net_ratelimit())
+                               printk(KERN_ERR "%s: Error in TX\n", dev->name);
+                       dev->stats.tx_errors++;
+               }
+               dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
+               if (skb)
+                       dev_kfree_skb_irq(skb);
+               released++;
+       }
+txq_reclaim_end:
+       netif_tx_unlock(dev);
+       return released;
+}
+
+static void pxa168_eth_tx_timeout(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       printk(KERN_INFO "%s: TX timeout  desc_count %d\n",
+              dev->name, pep->tx_desc_count);
+
+       schedule_work(&pep->tx_timeout_task);
+}
+
+static void pxa168_eth_tx_timeout_task(struct work_struct *work)
+{
+       struct pxa168_eth_private *pep = container_of(work,
+                                                struct pxa168_eth_private,
+                                                tx_timeout_task);
+       struct net_device *dev = pep->dev;
+       pxa168_eth_stop(dev);
+       pxa168_eth_open(dev);
+}
+
+static int rxq_process(struct net_device *dev, int budget)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
+       unsigned int received_packets = 0;
+       struct sk_buff *skb;
+
+       while (budget-- > 0) {
+               int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
+               struct rx_desc *rx_desc;
+               unsigned int cmd_sts;
+
+               /* Do not process Rx ring in case of Rx ring resource error */
+               if (pep->rx_resource_err)
+                       break;
+               rx_curr_desc = pep->rx_curr_desc_q;
+               rx_used_desc = pep->rx_used_desc_q;
+               rx_desc = &pep->p_rx_desc_area[rx_curr_desc];
+               cmd_sts = rx_desc->cmd_sts;
+               rmb();
+               if (cmd_sts & (BUF_OWNED_BY_DMA))
+                       break;
+               skb = pep->rx_skb[rx_curr_desc];
+               pep->rx_skb[rx_curr_desc] = NULL;
+
+               rx_next_curr_desc = (rx_curr_desc + 1) % pep->rx_ring_size;
+               pep->rx_curr_desc_q = rx_next_curr_desc;
+
+               /* Rx descriptors exhausted. */
+               /* Set the Rx ring resource error flag */
+               if (rx_next_curr_desc == rx_used_desc)
+                       pep->rx_resource_err = 1;
+               pep->rx_desc_count--;
+               dma_unmap_single(NULL, rx_desc->buf_ptr,
+                                rx_desc->buf_size,
+                                DMA_FROM_DEVICE);
+               received_packets++;
+               /*
+                * Update statistics.
+                * Note byte count includes 4 byte CRC count
+                */
+               stats->rx_packets++;
+               stats->rx_bytes += rx_desc->byte_cnt;
+               /*
+                * In case received a packet without first / last bits on OR
+                * the error summary bit is on, the packets needs to be droped.
+                */
+               if (((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
+                    (RX_FIRST_DESC | RX_LAST_DESC))
+                   || (cmd_sts & RX_ERROR)) {
+
+                       stats->rx_dropped++;
+                       if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
+                           (RX_FIRST_DESC | RX_LAST_DESC)) {
+                               if (net_ratelimit())
+                                       printk(KERN_ERR
+                                              "%s: Rx pkt on multiple desc\n",
+                                              dev->name);
+                       }
+                       if (cmd_sts & RX_ERROR)
+                               stats->rx_errors++;
+                       dev_kfree_skb_irq(skb);
+               } else {
+                       /*
+                        * The -4 is for the CRC in the trailer of the
+                        * received packet
+                        */
+                       skb_put(skb, rx_desc->byte_cnt - 4);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_receive_skb(skb);
+               }
+               dev->last_rx = jiffies;
+       }
+       /* Fill RX ring with skb's */
+       rxq_refill(dev);
+       return received_packets;
+}
+
+static int pxa168_eth_collect_events(struct pxa168_eth_private *pep,
+                                    struct net_device *dev)
+{
+       u32 icr;
+       int ret = 0;
+
+       icr = rdl(pep, INT_CAUSE);
+       if (icr == 0)
+               return IRQ_NONE;
+
+       wrl(pep, INT_CAUSE, ~icr);
+       if (icr & (ICR_TXBUF_H | ICR_TXBUF_L)) {
+               pep->work_todo |= WORK_TX_DONE;
+               ret = 1;
+       }
+       if (icr & ICR_RXBUF)
+               ret = 1;
+       if (icr & ICR_MII_CH) {
+               pep->work_todo |= WORK_LINK;
+               ret = 1;
+       }
+       return ret;
+}
+
+static void handle_link_event(struct pxa168_eth_private *pep)
+{
+       struct net_device *dev = pep->dev;
+       u32 port_status;
+       int speed;
+       int duplex;
+       int fc;
+
+       port_status = rdl(pep, PORT_STATUS);
+       if (!(port_status & LINK_UP)) {
+               if (netif_carrier_ok(dev)) {
+                       printk(KERN_INFO "%s: link down\n", dev->name);
+                       netif_carrier_off(dev);
+                       txq_reclaim(dev, 1);
+               }
+               return;
+       }
+       if (port_status & PORT_SPEED_100)
+               speed = 100;
+       else
+               speed = 10;
+
+       duplex = (port_status & FULL_DUPLEX) ? 1 : 0;
+       fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0;
+       printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
+              "flow control %sabled\n", dev->name,
+              speed, duplex ? "full" : "half", fc ? "en" : "dis");
+       if (!netif_carrier_ok(dev))
+               netif_carrier_on(dev);
+}
+
+static irqreturn_t pxa168_eth_int_handler(int irq, void *dev_id)
+{
+       struct net_device *dev = (struct net_device *)dev_id;
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       if (unlikely(!pxa168_eth_collect_events(pep, dev)))
+               return IRQ_NONE;
+       /* Disable interrupts */
+       wrl(pep, INT_MASK, 0);
+       napi_schedule(&pep->napi);
+       return IRQ_HANDLED;
+}
+
+static void pxa168_eth_recalc_skb_size(struct pxa168_eth_private *pep)
+{
+       int skb_size;
+
+       /*
+        * Reserve 2+14 bytes for an ethernet header (the hardware
+        * automatically prepends 2 bytes of dummy data to each
+        * received packet), 16 bytes for up to four VLAN tags, and
+        * 4 bytes for the trailing FCS -- 36 bytes total.
+        */
+       skb_size = pep->dev->mtu + 36;
+
+       /*
+        * Make sure that the skb size is a multiple of 8 bytes, as
+        * the lower three bits of the receive descriptor's buffer
+        * size field are ignored by the hardware.
+        */
+       pep->skb_size = (skb_size + 7) & ~7;
+
+       /*
+        * If NET_SKB_PAD is smaller than a cache line,
+        * netdev_alloc_skb() will cause skb->data to be misaligned
+        * to a cache line boundary.  If this is the case, include
+        * some extra space to allow re-aligning the data area.
+        */
+       pep->skb_size += SKB_DMA_REALIGN;
+
+}
+
+static int set_port_config_ext(struct pxa168_eth_private *pep)
+{
+       int skb_size;
+
+       pxa168_eth_recalc_skb_size(pep);
+       if  (pep->skb_size <= 1518)
+               skb_size = PCXR_MFL_1518;
+       else if (pep->skb_size <= 1536)
+               skb_size = PCXR_MFL_1536;
+       else if (pep->skb_size <= 2048)
+               skb_size = PCXR_MFL_2048;
+       else
+               skb_size = PCXR_MFL_64K;
+
+       /* Extended Port Configuration */
+       wrl(pep,
+           PORT_CONFIG_EXT, PCXR_2BSM | /* Two byte prefix aligns IP hdr */
+           PCXR_DSCP_EN |               /* Enable DSCP in IP */
+           skb_size | PCXR_FLP |        /* do not force link pass */
+           PCXR_TX_HIGH_PRI);           /* Transmit - high priority queue */
+
+       return 0;
+}
+
+static int pxa168_init_hw(struct pxa168_eth_private *pep)
+{
+       int err = 0;
+
+       /* Disable interrupts */
+       wrl(pep, INT_MASK, 0);
+       wrl(pep, INT_CAUSE, 0);
+       /* Write to ICR to clear interrupts. */
+       wrl(pep, INT_W_CLEAR, 0);
+       /* Abort any transmit and receive operations and put DMA
+        * in idle state.
+        */
+       abort_dma(pep);
+       /* Initialize address hash table */
+       err = init_hash_table(pep);
+       if (err)
+               return err;
+       /* SDMA configuration */
+       wrl(pep, SDMA_CONFIG, SDCR_BSZ8 |       /* Burst size = 32 bytes */
+           SDCR_RIFB |                         /* Rx interrupt on frame */
+           SDCR_BLMT |                         /* Little endian transmit */
+           SDCR_BLMR |                         /* Little endian receive */
+           SDCR_RC_MAX_RETRANS);               /* Max retransmit count */
+       /* Port Configuration */
+       wrl(pep, PORT_CONFIG, PCR_HS);          /* Hash size is 1/2kb */
+       set_port_config_ext(pep);
+
+       return err;
+}
+
+static int rxq_init(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct rx_desc *p_rx_desc;
+       int size = 0, i = 0;
+       int rx_desc_num = pep->rx_ring_size;
+
+       /* Allocate RX skb rings */
+       pep->rx_skb = kmalloc(sizeof(*pep->rx_skb) * pep->rx_ring_size,
+                            GFP_KERNEL);
+       if (!pep->rx_skb) {
+               printk(KERN_ERR "%s: Cannot alloc RX skb ring\n", dev->name);
+               return -ENOMEM;
+       }
+       /* Allocate RX ring */
+       pep->rx_desc_count = 0;
+       size = pep->rx_ring_size * sizeof(struct rx_desc);
+       pep->rx_desc_area_size = size;
+       pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                               &pep->rx_desc_dma, GFP_KERNEL);
+       if (!pep->p_rx_desc_area) {
+               printk(KERN_ERR "%s: Cannot alloc RX ring (size %d bytes)\n",
+                      dev->name, size);
+               goto out;
+       }
+       memset((void *)pep->p_rx_desc_area, 0, size);
+       /* initialize the next_desc_ptr links in the Rx descriptors ring */
+       p_rx_desc = (struct rx_desc *)pep->p_rx_desc_area;
+       for (i = 0; i < rx_desc_num; i++) {
+               p_rx_desc[i].next_desc_ptr = pep->rx_desc_dma +
+                   ((i + 1) % rx_desc_num) * sizeof(struct rx_desc);
+       }
+       /* Save Rx desc pointer to driver struct. */
+       pep->rx_curr_desc_q = 0;
+       pep->rx_used_desc_q = 0;
+       pep->rx_desc_area_size = rx_desc_num * sizeof(struct rx_desc);
+       return 0;
+out:
+       kfree(pep->rx_skb);
+       return -ENOMEM;
+}
+
+static void rxq_deinit(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       int curr;
+
+       /* Free preallocated skb's on RX rings */
+       for (curr = 0; pep->rx_desc_count && curr < pep->rx_ring_size; curr++) {
+               if (pep->rx_skb[curr]) {
+                       dev_kfree_skb(pep->rx_skb[curr]);
+                       pep->rx_desc_count--;
+               }
+       }
+       if (pep->rx_desc_count)
+               printk(KERN_ERR
+                      "Error in freeing Rx Ring. %d skb's still\n",
+                      pep->rx_desc_count);
+       /* Free RX ring */
+       if (pep->p_rx_desc_area)
+               dma_free_coherent(pep->dev->dev.parent, pep->rx_desc_area_size,
+                                 pep->p_rx_desc_area, pep->rx_desc_dma);
+       kfree(pep->rx_skb);
+}
+
+static int txq_init(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct tx_desc *p_tx_desc;
+       int size = 0, i = 0;
+       int tx_desc_num = pep->tx_ring_size;
+
+       pep->tx_skb = kmalloc(sizeof(*pep->tx_skb) * pep->tx_ring_size,
+                            GFP_KERNEL);
+       if (!pep->tx_skb) {
+               printk(KERN_ERR "%s: Cannot alloc TX skb ring\n", dev->name);
+               return -ENOMEM;
+       }
+       /* Allocate TX ring */
+       pep->tx_desc_count = 0;
+       size = pep->tx_ring_size * sizeof(struct tx_desc);
+       pep->tx_desc_area_size = size;
+       pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                               &pep->tx_desc_dma, GFP_KERNEL);
+       if (!pep->p_tx_desc_area) {
+               printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
+                      dev->name, size);
+               goto out;
+       }
+       memset((void *)pep->p_tx_desc_area, 0, pep->tx_desc_area_size);
+       /* Initialize the next_desc_ptr links in the Tx descriptors ring */
+       p_tx_desc = (struct tx_desc *)pep->p_tx_desc_area;
+       for (i = 0; i < tx_desc_num; i++) {
+               p_tx_desc[i].next_desc_ptr = pep->tx_desc_dma +
+                   ((i + 1) % tx_desc_num) * sizeof(struct tx_desc);
+       }
+       pep->tx_curr_desc_q = 0;
+       pep->tx_used_desc_q = 0;
+       pep->tx_desc_area_size = tx_desc_num * sizeof(struct tx_desc);
+       return 0;
+out:
+       kfree(pep->tx_skb);
+       return -ENOMEM;
+}
+
+static void txq_deinit(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       /* Free outstanding skb's on TX ring */
+       txq_reclaim(dev, 1);
+       BUG_ON(pep->tx_used_desc_q != pep->tx_curr_desc_q);
+       /* Free TX ring */
+       if (pep->p_tx_desc_area)
+               dma_free_coherent(pep->dev->dev.parent, pep->tx_desc_area_size,
+                                 pep->p_tx_desc_area, pep->tx_desc_dma);
+       kfree(pep->tx_skb);
+}
+
+static int pxa168_eth_open(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       int err;
+
+       err = request_irq(dev->irq, pxa168_eth_int_handler,
+                         IRQF_DISABLED, dev->name, dev);
+       if (err) {
+               dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+               return -EAGAIN;
+       }
+       pep->rx_resource_err = 0;
+       err = rxq_init(dev);
+       if (err != 0)
+               goto out_free_irq;
+       err = txq_init(dev);
+       if (err != 0)
+               goto out_free_rx_skb;
+       pep->rx_used_desc_q = 0;
+       pep->rx_curr_desc_q = 0;
+
+       /* Fill RX ring with skb's */
+       rxq_refill(dev);
+       pep->rx_used_desc_q = 0;
+       pep->rx_curr_desc_q = 0;
+       netif_carrier_off(dev);
+       eth_port_start(dev);
+       napi_enable(&pep->napi);
+       return 0;
+out_free_rx_skb:
+       rxq_deinit(dev);
+out_free_irq:
+       free_irq(dev->irq, dev);
+       return err;
+}
+
+static int pxa168_eth_stop(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       eth_port_reset(dev);
+
+       /* Disable interrupts */
+       wrl(pep, INT_MASK, 0);
+       wrl(pep, INT_CAUSE, 0);
+       /* Write to ICR to clear interrupts. */
+       wrl(pep, INT_W_CLEAR, 0);
+       napi_disable(&pep->napi);
+       del_timer_sync(&pep->timeout);
+       netif_carrier_off(dev);
+       free_irq(dev->irq, dev);
+       rxq_deinit(dev);
+       txq_deinit(dev);
+
+       return 0;
+}
+
+static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
+{
+       int retval;
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       if ((mtu > 9500) || (mtu < 68))
+               return -EINVAL;
+
+       dev->mtu = mtu;
+       retval = set_port_config_ext(pep);
+
+       if (!netif_running(dev))
+               return 0;
+
+       /*
+        * Stop and then re-open the interface. This will allocate RX
+        * skbs of the new MTU.
+        * There is a possible danger that the open will not succeed,
+        * due to memory being full.
+        */
+       pxa168_eth_stop(dev);
+       if (pxa168_eth_open(dev)) {
+               dev_printk(KERN_ERR, &dev->dev,
+                          "fatal error on re-opening device after "
+                          "MTU change\n");
+       }
+
+       return 0;
+}
+
+static int eth_alloc_tx_desc_index(struct pxa168_eth_private *pep)
+{
+       int tx_desc_curr;
+
+       tx_desc_curr = pep->tx_curr_desc_q;
+       pep->tx_curr_desc_q = (tx_desc_curr + 1) % pep->tx_ring_size;
+       BUG_ON(pep->tx_curr_desc_q == pep->tx_used_desc_q);
+       pep->tx_desc_count++;
+
+       return tx_desc_curr;
+}
+
+static int pxa168_rx_poll(struct napi_struct *napi, int budget)
+{
+       struct pxa168_eth_private *pep =
+           container_of(napi, struct pxa168_eth_private, napi);
+       struct net_device *dev = pep->dev;
+       int work_done = 0;
+
+       if (unlikely(pep->work_todo & WORK_LINK)) {
+               pep->work_todo &= ~(WORK_LINK);
+               handle_link_event(pep);
+       }
+       /*
+        * We call txq_reclaim every time since in NAPI interupts are disabled
+        * and due to this we miss the TX_DONE interrupt,which is not updated in
+        * interrupt status register.
+        */
+       txq_reclaim(dev, 0);
+       if (netif_queue_stopped(dev)
+           && pep->tx_ring_size - pep->tx_desc_count > 1) {
+               netif_wake_queue(dev);
+       }
+       work_done = rxq_process(dev, budget);
+       if (work_done < budget) {
+               napi_complete(napi);
+               wrl(pep, INT_MASK, ALL_INTS);
+       }
+
+       return work_done;
+}
+
+static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
+       struct tx_desc *desc;
+       int tx_index;
+       int length;
+
+       tx_index = eth_alloc_tx_desc_index(pep);
+       desc = &pep->p_tx_desc_area[tx_index];
+       length = skb->len;
+       pep->tx_skb[tx_index] = skb;
+       desc->byte_cnt = length;
+       desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+       wmb();
+       desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
+                       TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
+       wmb();
+       wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD);
+
+       stats->tx_bytes += skb->len;
+       stats->tx_packets++;
+       dev->trans_start = jiffies;
+       if (pep->tx_ring_size - pep->tx_desc_count <= 1) {
+               /* We handled the current skb, but now we are out of space.*/
+               netif_stop_queue(dev);
+       }
+
+       return NETDEV_TX_OK;
+}
+
+static int smi_wait_ready(struct pxa168_eth_private *pep)
+{
+       int i = 0;
+
+       /* wait for the SMI register to become available */
+       for (i = 0; rdl(pep, SMI) & SMI_BUSY; i++) {
+               if (i == PHY_WAIT_ITERATIONS)
+                       return -ETIMEDOUT;
+               msleep(10);
+       }
+
+       return 0;
+}
+
+static int pxa168_smi_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+       struct pxa168_eth_private *pep = bus->priv;
+       int i = 0;
+       int val;
+
+       if (smi_wait_ready(pep)) {
+               printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n");
+               return -ETIMEDOUT;
+       }
+       wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) | SMI_OP_R);
+       /* now wait for the data to be valid */
+       for (i = 0; !((val = rdl(pep, SMI)) & SMI_R_VALID); i++) {
+               if (i == PHY_WAIT_ITERATIONS) {
+                       printk(KERN_WARNING
+                               "pxa168_eth: SMI bus read not valid\n");
+                       return -ENODEV;
+               }
+               msleep(10);
+       }
+
+       return val & 0xffff;
+}
+
+static int pxa168_smi_write(struct mii_bus *bus, int phy_addr, int regnum,
+                           u16 value)
+{
+       struct pxa168_eth_private *pep = bus->priv;
+
+       if (smi_wait_ready(pep)) {
+               printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) |
+           SMI_OP_W | (value & 0xffff));
+
+       if (smi_wait_ready(pep)) {
+               printk(KERN_ERR "pxa168_eth: SMI bus busy timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr,
+                              int cmd)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       if (pep->phy != NULL)
+               return phy_mii_ioctl(pep->phy, ifr, cmd);
+
+       return -EOPNOTSUPP;
+}
+
+static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr)
+{
+       struct mii_bus *bus = pep->smi_bus;
+       struct phy_device *phydev;
+       int start;
+       int num;
+       int i;
+
+       if (phy_addr == PXA168_ETH_PHY_ADDR_DEFAULT) {
+               /* Scan entire range */
+               start = ethernet_phy_get(pep);
+               num = 32;
+       } else {
+               /* Use phy addr specific to platform */
+               start = phy_addr & 0x1f;
+               num = 1;
+       }
+       phydev = NULL;
+       for (i = 0; i < num; i++) {
+               int addr = (start + i) & 0x1f;
+               if (bus->phy_map[addr] == NULL)
+                       mdiobus_scan(bus, addr);
+
+               if (phydev == NULL) {
+                       phydev = bus->phy_map[addr];
+                       if (phydev != NULL)
+                               ethernet_phy_set_addr(pep, addr);
+               }
+       }
+
+       return phydev;
+}
+
+static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex)
+{
+       struct phy_device *phy = pep->phy;
+       ethernet_phy_reset(pep);
+
+       phy_attach(pep->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_MII);
+
+       if (speed == 0) {
+               phy->autoneg = AUTONEG_ENABLE;
+               phy->speed = 0;
+               phy->duplex = 0;
+               phy->supported &= PHY_BASIC_FEATURES;
+               phy->advertising = phy->supported | ADVERTISED_Autoneg;
+       } else {
+               phy->autoneg = AUTONEG_DISABLE;
+               phy->advertising = 0;
+               phy->speed = speed;
+               phy->duplex = duplex;
+       }
+       phy_start_aneg(phy);
+}
+
+static int ethernet_phy_setup(struct net_device *dev)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       if (pep->pd->init)
+               pep->pd->init();
+       pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f);
+       if (pep->phy != NULL)
+               phy_init(pep, pep->pd->speed, pep->pd->duplex);
+       update_hash_table_mac_address(pep, NULL, dev->dev_addr);
+
+       return 0;
+}
+
+static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+       int err;
+
+       err = phy_read_status(pep->phy);
+       if (err == 0)
+               err = phy_ethtool_gset(pep->phy, cmd);
+
+       return err;
+}
+
+static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       return phy_ethtool_sset(pep->phy, cmd);
+}
+
+static void pxa168_get_drvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *info)
+{
+       strncpy(info->driver, DRIVER_NAME, 32);
+       strncpy(info->version, DRIVER_VERSION, 32);
+       strncpy(info->fw_version, "N/A", 32);
+       strncpy(info->bus_info, "N/A", 32);
+}
+
+static u32 pxa168_get_link(struct net_device *dev)
+{
+       return !!netif_carrier_ok(dev);
+}
+
+static const struct ethtool_ops pxa168_ethtool_ops = {
+       .get_settings = pxa168_get_settings,
+       .set_settings = pxa168_set_settings,
+       .get_drvinfo = pxa168_get_drvinfo,
+       .get_link = pxa168_get_link,
+};
+
+static const struct net_device_ops pxa168_eth_netdev_ops = {
+       .ndo_open = pxa168_eth_open,
+       .ndo_stop = pxa168_eth_stop,
+       .ndo_start_xmit = pxa168_eth_start_xmit,
+       .ndo_set_rx_mode = pxa168_eth_set_rx_mode,
+       .ndo_set_mac_address = pxa168_eth_set_mac_address,
+       .ndo_validate_addr = eth_validate_addr,
+       .ndo_do_ioctl = pxa168_eth_do_ioctl,
+       .ndo_change_mtu = pxa168_eth_change_mtu,
+       .ndo_tx_timeout = pxa168_eth_tx_timeout,
+};
+
+static int pxa168_eth_probe(struct platform_device *pdev)
+{
+       struct pxa168_eth_private *pep = NULL;
+       struct net_device *dev = NULL;
+       struct resource *res;
+       struct clk *clk;
+       int err;
+
+       printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n");
+
+       clk = clk_get(&pdev->dev, "MFUCLK");
+       if (IS_ERR(clk)) {
+               printk(KERN_ERR "%s: Fast Ethernet failed to get clock\n",
+                       DRIVER_NAME);
+               return -ENODEV;
+       }
+       clk_enable(clk);
+
+       dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
+       if (!dev) {
+               err = -ENOMEM;
+               goto err_clk;
+       }
+
+       platform_set_drvdata(pdev, dev);
+       pep = netdev_priv(dev);
+       pep->dev = dev;
+       pep->clk = clk;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               err = -ENODEV;
+               goto err_netdev;
+       }
+       pep->base = ioremap(res->start, res->end - res->start + 1);
+       if (pep->base == NULL) {
+               err = -ENOMEM;
+               goto err_netdev;
+       }
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       BUG_ON(!res);
+       dev->irq = res->start;
+       dev->netdev_ops = &pxa168_eth_netdev_ops;
+       dev->watchdog_timeo = 2 * HZ;
+       dev->base_addr = 0;
+       SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops);
+
+       INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
+
+       printk(KERN_INFO "%s:Using random mac address\n", DRIVER_NAME);
+       random_ether_addr(dev->dev_addr);
+
+       pep->pd = pdev->dev.platform_data;
+       pep->rx_ring_size = NUM_RX_DESCS;
+       if (pep->pd->rx_queue_size)
+               pep->rx_ring_size = pep->pd->rx_queue_size;
+
+       pep->tx_ring_size = NUM_TX_DESCS;
+       if (pep->pd->tx_queue_size)
+               pep->tx_ring_size = pep->pd->tx_queue_size;
+
+       pep->port_num = pep->pd->port_number;
+       /* Hardware supports only 3 ports */
+       BUG_ON(pep->port_num > 2);
+       netif_napi_add(dev, &pep->napi, pxa168_rx_poll, pep->rx_ring_size);
+
+       memset(&pep->timeout, 0, sizeof(struct timer_list));
+       init_timer(&pep->timeout);
+       pep->timeout.function = rxq_refill_timer_wrapper;
+       pep->timeout.data = (unsigned long)pep;
+
+       pep->smi_bus = mdiobus_alloc();
+       if (pep->smi_bus == NULL) {
+               err = -ENOMEM;
+               goto err_base;
+       }
+       pep->smi_bus->priv = pep;
+       pep->smi_bus->name = "pxa168_eth smi";
+       pep->smi_bus->read = pxa168_smi_read;
+       pep->smi_bus->write = pxa168_smi_write;
+       snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
+       pep->smi_bus->parent = &pdev->dev;
+       pep->smi_bus->phy_mask = 0xffffffff;
+       err = mdiobus_register(pep->smi_bus);
+       if (err)
+               goto err_free_mdio;
+
+       pxa168_init_hw(pep);
+       err = ethernet_phy_setup(dev);
+       if (err)
+               goto err_mdiobus;
+       SET_NETDEV_DEV(dev, &pdev->dev);
+       err = register_netdev(dev);
+       if (err)
+               goto err_mdiobus;
+       return 0;
+
+err_mdiobus:
+       mdiobus_unregister(pep->smi_bus);
+err_free_mdio:
+       mdiobus_free(pep->smi_bus);
+err_base:
+       iounmap(pep->base);
+err_netdev:
+       free_netdev(dev);
+err_clk:
+       clk_disable(clk);
+       clk_put(clk);
+       return err;
+}
+
+static int pxa168_eth_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct pxa168_eth_private *pep = netdev_priv(dev);
+
+       if (pep->htpr) {
+               dma_free_coherent(pep->dev->dev.parent, HASH_ADDR_TABLE_SIZE,
+                                 pep->htpr, pep->htpr_dma);
+               pep->htpr = NULL;
+       }
+       if (pep->clk) {
+               clk_disable(pep->clk);
+               clk_put(pep->clk);
+               pep->clk = NULL;
+       }
+       if (pep->phy != NULL)
+               phy_detach(pep->phy);
+
+       iounmap(pep->base);
+       pep->base = NULL;
+       mdiobus_unregister(pep->smi_bus);
+       mdiobus_free(pep->smi_bus);
+       unregister_netdev(dev);
+       flush_scheduled_work();
+       free_netdev(dev);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static void pxa168_eth_shutdown(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       eth_port_reset(dev);
+}
+
+#ifdef CONFIG_PM
+static int pxa168_eth_resume(struct platform_device *pdev)
+{
+       return -ENOSYS;
+}
+
+static int pxa168_eth_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       return -ENOSYS;
+}
+
+#else
+#define pxa168_eth_resume NULL
+#define pxa168_eth_suspend NULL
+#endif
+
+static struct platform_driver pxa168_eth_driver = {
+       .probe = pxa168_eth_probe,
+       .remove = pxa168_eth_remove,
+       .shutdown = pxa168_eth_shutdown,
+       .resume = pxa168_eth_resume,
+       .suspend = pxa168_eth_suspend,
+       .driver = {
+                  .name = DRIVER_NAME,
+                  },
+};
+
+static int __init pxa168_init_module(void)
+{
+       return platform_driver_register(&pxa168_eth_driver);
+}
+
+static void __exit pxa168_cleanup_module(void)
+{
+       platform_driver_unregister(&pxa168_eth_driver);
+}
+
+module_init(pxa168_init_module);
+module_exit(pxa168_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Ethernet driver for Marvell PXA168");
+MODULE_ALIAS("platform:pxa168_eth");
index 75ba744b173c89d0f598d1d61183fd5d9dca1675..2c7cf0b64811ed72d4d6368c02d46fa966e7de2f 100644 (file)
@@ -1316,7 +1316,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
                return -ENOMEM;
        }
 
-       skb_reserve(skb, 2);
+       skb_reserve(skb, NET_IP_ALIGN);
 
        dma = pci_map_single(pdev, skb->data,
                        rds_ring->dma_size, PCI_DMA_FROMDEVICE);
@@ -1404,7 +1404,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
        if (pkt_offset)
                skb_pull(skb, pkt_offset);
 
-       skb->truesize = skb->len + sizeof(struct sk_buff);
        skb->protocol = eth_type_trans(skb, netdev);
 
        napi_gro_receive(&sds_ring->napi, skb);
@@ -1466,8 +1465,6 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
 
        skb_put(skb, lro_length + data_offset);
 
-       skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
-
        skb_pull(skb, l2_hdr_offset);
        skb->protocol = eth_type_trans(skb, netdev);
 
@@ -1700,8 +1697,6 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
        if (pkt_offset)
                skb_pull(skb, pkt_offset);
 
-       skb->truesize = skb->len + sizeof(struct sk_buff);
-
        if (!qlcnic_check_loopback_buff(skb->data))
                adapter->diag_cnt++;
 
index bf6d87adda4fff7a5aa1d1e20728383d08e621f1..66eea59720209f85278cf223b6d723f879337aac 100644 (file)
@@ -1983,8 +1983,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
-       memset(stats, 0, sizeof(*stats));
-
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
@@ -2190,9 +2188,16 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev)
 {
+       int ring;
+       struct qlcnic_host_sds_ring *sds_ring;
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+
        disable_irq(adapter->irq);
-       qlcnic_intr(adapter->irq, adapter);
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               qlcnic_intr(adapter->irq, sds_ring);
+       }
        enable_irq(adapter->irq);
 }
 #endif
index 8d63f69b27d912de7dca94d980276963f25c7fe7..5f89e83501f4f5c1892ac15a84681a76ade08c19 100644 (file)
@@ -3919,12 +3919,12 @@ static int ql_adapter_down(struct ql_adapter *qdev)
        for (i = 0; i < qdev->rss_ring_count; i++)
                netif_napi_del(&qdev->rx_ring[i].napi);
 
-       ql_free_rx_buffers(qdev);
-
        status = ql_adapter_reset(qdev);
        if (status)
                netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n",
                          qdev->func);
+       ql_free_rx_buffers(qdev);
+
        return status;
 }
 
index 078bbf4e6f1933f3ee1e95e2c0dccfea92157088..992db2fa136e9c5e6f5130c053393aa662d4e5c9 100644 (file)
@@ -1212,7 +1212,8 @@ static void rtl8169_update_counters(struct net_device *dev)
        if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
                return;
 
-       counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
+       counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters),
+                                     &paddr, GFP_KERNEL);
        if (!counters)
                return;
 
@@ -1233,7 +1234,8 @@ static void rtl8169_update_counters(struct net_device *dev)
        RTL_W32(CounterAddrLow, 0);
        RTL_W32(CounterAddrHigh, 0);
 
-       pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
+       dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters,
+                         paddr);
 }
 
 static void rtl8169_get_ethtool_stats(struct net_device *dev,
@@ -2934,7 +2936,7 @@ static const struct rtl_cfg_info {
                .hw_start       = rtl_hw_start_8168,
                .region         = 2,
                .align          = 8,
-               .intr_event     = SYSErr | LinkChg | RxOverflow |
+               .intr_event     = SYSErr | RxFIFOOver | LinkChg | RxOverflow |
                                  TxErr | TxOK | RxOK | RxErr,
                .napi_event     = TxErr | TxOK | RxOK | RxOverflow,
                .features       = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
@@ -3292,15 +3294,15 @@ static int rtl8169_open(struct net_device *dev)
 
        /*
         * Rx and Tx desscriptors needs 256 bytes alignment.
-        * pci_alloc_consistent provides more.
+        * dma_alloc_coherent provides more.
         */
-       tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
-                                              &tp->TxPhyAddr);
+       tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
+                                            &tp->TxPhyAddr, GFP_KERNEL);
        if (!tp->TxDescArray)
                goto err_pm_runtime_put;
 
-       tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
-                                              &tp->RxPhyAddr);
+       tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
+                                            &tp->RxPhyAddr, GFP_KERNEL);
        if (!tp->RxDescArray)
                goto err_free_tx_0;
 
@@ -3334,12 +3336,12 @@ out:
 err_release_ring_2:
        rtl8169_rx_clear(tp);
 err_free_rx_1:
-       pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
-                           tp->RxPhyAddr);
+       dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+                         tp->RxPhyAddr);
        tp->RxDescArray = NULL;
 err_free_tx_0:
-       pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
-                           tp->TxPhyAddr);
+       dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+                         tp->TxPhyAddr);
        tp->TxDescArray = NULL;
 err_pm_runtime_put:
        pm_runtime_put_noidle(&pdev->dev);
@@ -3975,7 +3977,7 @@ static void rtl8169_free_rx_skb(struct rtl8169_private *tp,
 {
        struct pci_dev *pdev = tp->pci_dev;
 
-       pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz,
+       dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz,
                         PCI_DMA_FROMDEVICE);
        dev_kfree_skb(*sk_buff);
        *sk_buff = NULL;
@@ -4000,7 +4002,7 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
 static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
                                            struct net_device *dev,
                                            struct RxDesc *desc, int rx_buf_sz,
-                                           unsigned int align)
+                                           unsigned int align, gfp_t gfp)
 {
        struct sk_buff *skb;
        dma_addr_t mapping;
@@ -4008,13 +4010,13 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
 
        pad = align ? align : NET_IP_ALIGN;
 
-       skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
+       skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp);
        if (!skb)
                goto err_out;
 
        skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
 
-       mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
+       mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz,
                                 PCI_DMA_FROMDEVICE);
 
        rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
@@ -4039,7 +4041,7 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp)
 }
 
 static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
-                          u32 start, u32 end)
+                          u32 start, u32 end, gfp_t gfp)
 {
        u32 cur;
 
@@ -4054,7 +4056,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
 
                skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
                                           tp->RxDescArray + i,
-                                          tp->rx_buf_sz, tp->align);
+                                          tp->rx_buf_sz, tp->align, gfp);
                if (!skb)
                        break;
 
@@ -4082,7 +4084,7 @@ static int rtl8169_init_ring(struct net_device *dev)
        memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
        memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
 
-       if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+       if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC)
                goto err_out;
 
        rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
@@ -4099,7 +4101,8 @@ static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb,
 {
        unsigned int len = tx_skb->len;
 
-       pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+       dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len,
+                        PCI_DMA_TODEVICE);
        desc->opts1 = 0x00;
        desc->opts2 = 0x00;
        desc->addr = 0x00;
@@ -4243,7 +4246,8 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
                txd = tp->TxDescArray + entry;
                len = frag->size;
                addr = ((void *) page_address(frag->page)) + frag->page_offset;
-               mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE);
+               mapping = dma_map_single(&tp->pci_dev->dev, addr, len,
+                                        PCI_DMA_TODEVICE);
 
                /* anti gcc 2.95.3 bugware (sic) */
                status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
@@ -4313,7 +4317,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
                tp->tx_skb[entry].skb = skb;
        }
 
-       mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
+       mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len,
+                                PCI_DMA_TODEVICE);
 
        tp->tx_skb[entry].len = len;
        txd->addr = cpu_to_le64(mapping);
@@ -4477,8 +4482,8 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
        if (!skb)
                goto out;
 
-       pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
-                                   PCI_DMA_FROMDEVICE);
+       dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size,
+                               PCI_DMA_FROMDEVICE);
        skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
        *sk_buff = skb;
        done = true;
@@ -4549,11 +4554,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
                        rtl8169_rx_csum(skb, desc);
 
                        if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
-                               pci_dma_sync_single_for_device(pdev, addr,
+                               dma_sync_single_for_device(&pdev->dev, addr,
                                        pkt_size, PCI_DMA_FROMDEVICE);
                                rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
                        } else {
-                               pci_unmap_single(pdev, addr, tp->rx_buf_sz,
+                               dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz,
                                                 PCI_DMA_FROMDEVICE);
                                tp->Rx_skbuff[entry] = NULL;
                        }
@@ -4583,7 +4588,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
        count = cur_rx - tp->cur_rx;
        tp->cur_rx = cur_rx;
 
-       delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+       delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC);
        if (!delta && count)
                netif_info(tp, intr, dev, "no Rx buffer allocated\n");
        tp->dirty_rx += delta;
@@ -4625,8 +4630,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
                }
 
                /* Work around for rx fifo overflow */
-               if (unlikely(status & RxFIFOOver) &&
-               (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+               if (unlikely(status & RxFIFOOver)) {
                        netif_stop_queue(dev);
                        rtl8169_tx_timeout(dev);
                        break;
@@ -4770,10 +4774,10 @@ static int rtl8169_close(struct net_device *dev)
 
        free_irq(dev->irq, dev);
 
-       pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
-                           tp->RxPhyAddr);
-       pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
-                           tp->TxPhyAddr);
+       dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+                         tp->RxPhyAddr);
+       dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+                         tp->TxPhyAddr);
        tp->TxDescArray = NULL;
        tp->RxDescArray = NULL;
 
index 07eb884ff982405c3d15204a04d6188394e329f3..44150f2f7bfd6b206b17e0a64064d5996d0033ea 100644 (file)
@@ -384,7 +384,7 @@ static void rionet_remove(struct rio_dev *rdev)
        free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
                                        __ilog2(sizeof(void *)) + 4 : 0);
        unregister_netdev(ndev);
-       kfree(ndev);
+       free_netdev(ndev);
 
        list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
                list_del(&peer->node);
index cc4bd8c65f8b6a58846065430f8b89c1be6a4bc3..9265315baa0b29bdc2c7a9e20db20462dcf52ae5 100644 (file)
@@ -804,7 +804,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)
 err_out_free_page:
        free_page((unsigned long) sp->srings);
 err_out_free_dev:
-       kfree(dev);
+       free_netdev(dev);
 
 err_out:
        return err;
index f5a9eb1df59332f0d105d7ee83380471a0ff48f1..79fd02bc69fd0854f14e0fdac452980cd7fed74b 100644 (file)
@@ -1437,7 +1437,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
 
 static int sh_eth_drv_probe(struct platform_device *pdev)
 {
-       int ret, i, devno = 0;
+       int ret, devno = 0;
        struct resource *res;
        struct net_device *ndev = NULL;
        struct sh_eth_private *mdp;
index 40e5c46e7571ad46f1c7abf655d0235f89762bfd..465ae7e84507385b079c7922cb7360cec428a30f 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/seq_file.h>
 #include <linux/mii.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 #include <asm/irq.h>
 
 #include "skge.h"
@@ -3868,6 +3869,8 @@ static void __devinit skge_show_addr(struct net_device *dev)
        netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr);
 }
 
+static int only_32bit_dma;
+
 static int __devinit skge_probe(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
@@ -3889,7 +3892,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+       if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
                using_dac = 1;
                err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
        } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
@@ -4147,8 +4150,21 @@ static struct pci_driver skge_driver = {
        .shutdown =     skge_shutdown,
 };
 
+static struct dmi_system_id skge_32bit_dma_boards[] = {
+       {
+               .ident = "Gigabyte nForce boards",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"),
+                       DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+               },
+       },
+       {}
+};
+
 static int __init skge_init_module(void)
 {
+       if (dmi_check_system(skge_32bit_dma_boards))
+               only_32bit_dma = 1;
        skge_debug_init();
        return pci_register_driver(&skge_driver);
 }
index 10cf0cbc218507111b26959f119645672fcd5666..726df611ee17da997b31a8219de2554080fdeed7 100644 (file)
@@ -72,6 +72,7 @@ static const char version[] =
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/crc32.h>
index 0909ae934ad0fcee52c5eb67101240e77fb70dde..8150ba1541161ab2e7781ade13be970540f835ec 100644 (file)
@@ -58,6 +58,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(SMSC_DRV_VERSION);
+MODULE_ALIAS("platform:smsc911x");
 
 #if USE_DEBUG > 0
 static int debug = 16;
index bbb7951b9c4c34bb3992deed9c7a8e84ff52f68e..ea0461eb2dbe4314c223ab2ad47f17ea9b90e740 100644 (file)
@@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev)
        if (!netif_running(dev))
                return 0;
 
-       spin_lock(&priv->lock);
-
        if (priv->shutdown) {
                /* Re-open the interface and re-init the MAC/DMA
-                  and the rings. */
+                  and the rings (i.e. on hibernation stage) */
                stmmac_open(dev);
-               goto out_resume;
+               return 0;
        }
 
+       spin_lock(&priv->lock);
+
        /* Power Down bit, into the PM register, is cleared
         * automatically as soon as a magic packet or a Wake-up frame
         * is received. Anyway, it's better to manually clear
@@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev)
 
        netif_start_queue(dev);
 
-out_resume:
        spin_unlock(&priv->lock);
        return 0;
 }
index bc3af78a869ff52881077b89cf6e5e544b6e8a91..1ec4b9e0239a8ff8c0d3cb18882ff517ef528881 100644 (file)
@@ -4666,7 +4666,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                                       desc_idx, *post_ptr);
                drop_it_no_recycle:
                        /* Other statistics kept track of by card. */
-                       tp->net_stats.rx_dropped++;
+                       tp->rx_dropped++;
                        goto next_pkt;
                }
 
@@ -4726,7 +4726,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                if (len > (tp->dev->mtu + ETH_HLEN) &&
                    skb->protocol != htons(ETH_P_8021Q)) {
                        dev_kfree_skb(skb);
-                       goto next_pkt;
+                       goto drop_it_no_recycle;
                }
 
                if (desc->type_flags & RXD_FLAG_VLAN &&
@@ -9240,6 +9240,8 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
        stats->rx_missed_errors = old_stats->rx_missed_errors +
                get_stat64(&hw_stats->rx_discards);
 
+       stats->rx_dropped = tp->rx_dropped;
+
        return stats;
 }
 
index 4937bd19096413bae1115b82cc63ce5123207536..be7ff138a7f98d58a4f4d4c8ff7fe70bb83911d9 100644 (file)
@@ -2759,7 +2759,7 @@ struct tg3 {
 
 
        /* begin "everything else" cacheline(s) section */
-       struct rtnl_link_stats64        net_stats;
+       unsigned long                   rx_dropped;
        struct rtnl_link_stats64        net_stats_prev;
        struct tg3_ethtool_stats        estats;
        struct tg3_ethtool_stats        estats_prev;
index 5efa57757a2c8507f5bcf0d0d7f3ac5d1b5a26c3..6888e3d41462081952c7320b501736f03230ba78 100644 (file)
@@ -243,6 +243,7 @@ enum {
        NWayState               = (1 << 14) | (1 << 13) | (1 << 12),
        NWayRestart             = (1 << 12),
        NonselPortActive        = (1 << 9),
+       SelPortActive           = (1 << 8),
        LinkFailStatus          = (1 << 2),
        NetCxnErr               = (1 << 1),
 };
@@ -363,7 +364,9 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, };
 
 /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/
 static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
-static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */
+static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
 
@@ -1064,6 +1067,9 @@ static void de21041_media_timer (unsigned long data)
        unsigned int carrier;
        unsigned long flags;
 
+       /* clear port active bits */
+       dw32(SIAStatus, NonselPortActive | SelPortActive);
+
        carrier = (status & NetCxnErr) ? 0 : 1;
 
        if (carrier) {
@@ -1158,14 +1164,29 @@ no_link_yet:
 static void de_media_interrupt (struct de_private *de, u32 status)
 {
        if (status & LinkPass) {
+               /* Ignore if current media is AUI or BNC and we can't use TP */
+               if ((de->media_type == DE_MEDIA_AUI ||
+                    de->media_type == DE_MEDIA_BNC) &&
+                   (de->media_lock ||
+                    !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO)))
+                       return;
+               /* If current media is not TP, change it to TP */
+               if ((de->media_type == DE_MEDIA_AUI ||
+                    de->media_type == DE_MEDIA_BNC)) {
+                       de->media_type = DE_MEDIA_TP_AUTO;
+                       de_stop_rxtx(de);
+                       de_set_media(de);
+                       de_start_rxtx(de);
+               }
                de_link_up(de);
                mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
                return;
        }
 
        BUG_ON(!(status & LinkFail));
-
-       if (netif_carrier_ok(de->dev)) {
+       /* Mark the link as down only if current media is TP */
+       if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI &&
+           de->media_type != DE_MEDIA_BNC) {
                de_link_down(de);
                mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
        }
@@ -1229,6 +1250,7 @@ static void de_adapter_sleep (struct de_private *de)
        if (de->de21040)
                return;
 
+       dw32(CSR13, 0); /* Reset phy */
        pci_read_config_dword(de->pdev, PCIPM, &pmctl);
        pmctl |= PM_Sleep;
        pci_write_config_dword(de->pdev, PCIPM, pmctl);
@@ -1574,12 +1596,15 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd)
                return 0; /* nothing to change */
 
        de_link_down(de);
+       mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
        de_stop_rxtx(de);
 
        de->media_type = new_media;
        de->media_lock = media_lock;
        de->media_advertise = ecmd->advertising;
        de_set_media(de);
+       if (netif_running(de->dev))
+               de_start_rxtx(de);
 
        return 0;
 }
@@ -1911,8 +1936,14 @@ fill_defaults:
        for (i = 0; i < DE_MAX_MEDIA; i++) {
                if (de->media[i].csr13 == 0xffff)
                        de->media[i].csr13 = t21041_csr13[i];
-               if (de->media[i].csr14 == 0xffff)
-                       de->media[i].csr14 = t21041_csr14[i];
+               if (de->media[i].csr14 == 0xffff) {
+                       /* autonegotiation is broken at least on some chip
+                          revisions - rev. 0x21 works, 0x11 does not */
+                       if (de->pdev->revision < 0x20)
+                               de->media[i].csr14 = t21041_csr14_brk[i];
+                       else
+                               de->media[i].csr14 = t21041_csr14[i];
+               }
                if (de->media[i].csr15 == 0xffff)
                        de->media[i].csr15 = t21041_csr15[i];
        }
@@ -2158,6 +2189,8 @@ static int de_resume (struct pci_dev *pdev)
                dev_err(&dev->dev, "pci_enable_device failed in resume\n");
                goto out;
        }
+       pci_set_master(pdev);
+       de_init_rings(de);
        de_init_hw(de);
 out_attach:
        netif_device_attach(dev);
index 6efca66b87663a84ec7f36529c190aa5a107d401..1cd752f9a6e1e8586f3eda9fcb854ac0226de67a 100644 (file)
@@ -1652,6 +1652,8 @@ static int hso_get_count(struct hso_serial *serial,
        struct uart_icount cnow;
        struct hso_tiocmget  *tiocmget = serial->tiocmget;
 
+       memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
        if (!tiocmget)
                 return -ENOENT;
        spin_lock_irq(&serial->serial_lock);
index 08e7b6abacdd29f3fc78678834ed54feeabe6c6d..b2bcf99e6f087ab1dfca2aef092233eea9aa5fe6 100644 (file)
@@ -58,6 +58,7 @@
 #define USB_PRODUCT_IPHONE      0x1290
 #define USB_PRODUCT_IPHONE_3G   0x1292
 #define USB_PRODUCT_IPHONE_3GS  0x1294
+#define USB_PRODUCT_IPHONE_4   0x1297
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -92,6 +93,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
@@ -424,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = {
        .ndo_get_stats = &ipheth_stats,
 };
 
-static struct device_type ipheth_type = {
-       .name   = "wwan",
-};
-
 static int ipheth_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
 {
@@ -445,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf,
 
        netdev->netdev_ops = &ipheth_netdev_ops;
        netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
-       strcpy(netdev->name, "wwan%d");
+       strcpy(netdev->name, "eth%d");
 
        dev = netdev_priv(netdev);
        dev->udev = udev;
@@ -495,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf,
 
        SET_NETDEV_DEV(netdev, &intf->dev);
        SET_ETHTOOL_OPS(netdev, &ops);
-       SET_NETDEV_DEVTYPE(netdev, &ipheth_type);
 
        retval = register_netdev(netdev);
        if (retval) {
index fd69095ef6e33d61698556abac79a4e84429c8fe..f53412368ce1e1745a7796a8cc8181b16027e797 100644 (file)
@@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
        netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
 
        dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
-               NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG;
+               NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM;
 
        ret = register_netdev(dev);
        if (ret < 0)
index 04c6cd4333f1ec83d69be506b040b75183cdfb81..10bafd59f9c336e36fbec4c6703530ce54a92a36 100644 (file)
@@ -575,7 +575,7 @@ static int cosa_probe(int base, int irq, int dma)
 
                /* Initialize the chardev data structures */
                mutex_init(&chan->rlock);
-               init_MUTEX(&chan->wsem);
+               sema_init(&chan->wsem, 1);
 
                /* Register the network interface */
                if (!(chan->netdev = alloc_hdlcdev(chan))) {
index b1aec3e1892f3953a1f1c7af5e839685eb7f1f3b..9c70b5fa3f51e03b0ea51c84d844df4c22089ad3 100644 (file)
@@ -119,6 +119,7 @@ const struct file_operations i2400m_rx_stats_fops = {
        .open =         i2400m_stats_open,
        .read =         i2400m_rx_stats_read,
        .write =        i2400m_rx_stats_write,
+       .llseek =       default_llseek,
 };
 
 
@@ -171,6 +172,7 @@ const struct file_operations i2400m_tx_stats_fops = {
        .open =         i2400m_stats_open,
        .read =         i2400m_tx_stats_read,
        .write =        i2400m_tx_stats_write,
+       .llseek =       default_llseek,
 };
 
 
index 8cc9e319f4356da8904cbf4e7a495d59eba94645..1737d1488b35704f3196975a76bcc919e943808b 100644 (file)
@@ -1244,16 +1244,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
        int i, result;
        struct device *dev = i2400m_dev(i2400m);
        const struct i2400m_msg_hdr *msg_hdr;
-       size_t pl_itr, pl_size, skb_len;
+       size_t pl_itr, pl_size;
        unsigned long flags;
-       unsigned num_pls, single_last;
+       unsigned num_pls, single_last, skb_len;
 
        skb_len = skb->len;
-       d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n",
+       d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n",
                  i2400m, skb, skb_len);
        result = -EIO;
        msg_hdr = (void *) skb->data;
-       result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len);
+       result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len);
        if (result < 0)
                goto error_msg_hdr_check;
        result = -EIO;
@@ -1261,10 +1261,10 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
        pl_itr = sizeof(*msg_hdr) +     /* Check payload descriptor(s) */
                num_pls * sizeof(msg_hdr->pld[0]);
        pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN);
-       if (pl_itr > skb->len) {        /* got all the payload descriptors? */
+       if (pl_itr > skb_len) { /* got all the payload descriptors? */
                dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
                        "%u payload descriptors (%zu each, total %zu)\n",
-                       skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
+                       skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
                goto error_pl_descr_short;
        }
        /* Walk each payload payload--check we really got it */
@@ -1272,7 +1272,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
                /* work around old gcc warnings */
                pl_size = i2400m_pld_size(&msg_hdr->pld[i]);
                result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i],
-                                                 pl_itr, skb->len);
+                                                 pl_itr, skb_len);
                if (result < 0)
                        goto error_pl_descr_check;
                single_last = num_pls == 1 || i == num_pls - 1;
@@ -1290,16 +1290,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
        if (i < i2400m->rx_pl_min)
                i2400m->rx_pl_min = i;
        i2400m->rx_num++;
-       i2400m->rx_size_acc += skb->len;
-       if (skb->len < i2400m->rx_size_min)
-               i2400m->rx_size_min = skb->len;
-       if (skb->len > i2400m->rx_size_max)
-               i2400m->rx_size_max = skb->len;
+       i2400m->rx_size_acc += skb_len;
+       if (skb_len < i2400m->rx_size_min)
+               i2400m->rx_size_min = skb_len;
+       if (skb_len > i2400m->rx_size_max)
+               i2400m->rx_size_max = skb_len;
        spin_unlock_irqrestore(&i2400m->rx_lock, flags);
 error_pl_descr_check:
 error_pl_descr_short:
 error_msg_hdr_check:
-       d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n",
+       d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n",
                i2400m, skb, skb_len, result);
        return result;
 }
index a105087af9639884c1ca773ba96cf096fdde7954..f9aa1bc0a94756465bbd4d8ac7660cb3b95718c7 100644 (file)
@@ -732,7 +732,7 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan)
 
        /* Nothing to do for ADMtek BBP */
        } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK)
-               wiphy_debug(dev->wiphy, "unsupported bbp type %d\n",
+               wiphy_debug(dev->wiphy, "unsupported BBP type %d\n",
                            priv->bbp_type);
 
        ADM8211_RESTORE();
@@ -1032,7 +1032,7 @@ static int adm8211_hw_init_bbp(struct ieee80211_hw *dev)
                        break;
                }
        } else
-               wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type);
+               wiphy_debug(dev->wiphy, "unsupported BBP %d\n", priv->bbp_type);
 
        ADM8211_CSR_WRITE(SYNRF, 0);
 
@@ -1525,7 +1525,7 @@ static int adm8211_start(struct ieee80211_hw *dev)
        retval = request_irq(priv->pdev->irq, adm8211_interrupt,
                             IRQF_SHARED, "adm8211", dev);
        if (retval) {
-               wiphy_err(dev->wiphy, "failed to register irq handler\n");
+               wiphy_err(dev->wiphy, "failed to register IRQ handler\n");
                goto fail;
        }
 
@@ -1902,7 +1902,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
                goto err_free_eeprom;
        }
 
-       wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n",
+       wiphy_info(dev->wiphy, "hwaddr %pM, Rev 0x%02x\n",
                   dev->wiphy->perm_addr, pdev->revision);
 
        return 0;
index 1d05445d4ba397cb04545d1ba105e1040c864176..ce77575e88b3182b0ad06592ba391488d5ca228f 100644 (file)
@@ -4430,21 +4430,24 @@ static const struct file_operations proc_statsdelta_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_statsdelta_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_stats_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_stats_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_status_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_status_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_SSID_ops = {
@@ -4452,7 +4455,8 @@ static const struct file_operations proc_SSID_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_SSID_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_BSSList_ops = {
@@ -4460,7 +4464,8 @@ static const struct file_operations proc_BSSList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_BSSList_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_APList_ops = {
@@ -4468,7 +4473,8 @@ static const struct file_operations proc_APList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_APList_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_config_ops = {
@@ -4476,7 +4482,8 @@ static const struct file_operations proc_config_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_config_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_wepkey_ops = {
@@ -4484,7 +4491,8 @@ static const struct file_operations proc_wepkey_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_wepkey_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static struct proc_dir_entry *airo_entry;
index 9a121a5b787cb2468005e914e81a15eee55e312f..df2484d4547489c64404c0a8ab3e8579fb7cceba 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -54,58 +53,21 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the airo_cs
-   event handler.
-*/
-
 static int airo_config(struct pcmcia_device *link);
 static void airo_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void airo_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
        struct net_device *eth_dev;
 } local_info_t;
 
-/*======================================================================
-
-  airo_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-  The dev_link structure is initialized, but we don't actually
-  configure the card at this point -- we wait until we receive a
-  card insertion event.
-
-  ======================================================================*/
-
 static int airo_probe(struct pcmcia_device *p_dev)
 {
        local_info_t *local;
 
        dev_dbg(&p_dev->dev, "airo_attach()\n");
 
-       /*
-         General socket configuration defaults can go here.  In this
-         client, we assume very little, and rely on the CIS for almost
-         everything.  In most clients, many details (i.e., number, sizes,
-         and attributes of IO windows) are fixed by the nature of the
-         device, and can be hard-wired here.
-       */
-       p_dev->conf.Attributes = 0;
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
        /* Allocate space for private device-specific data */
        local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
        if (!local) {
@@ -117,15 +79,6 @@ static int airo_probe(struct pcmcia_device *p_dev)
        return airo_config(p_dev);
 } /* airo_attach */
 
-/*======================================================================
-
-  This deletes a driver "instance".  The device is de-registered
-  with Card Services.  If it has been released, all local data
-  structures are freed.  Otherwise, the structures will be freed
-  when the device is released.
-
-  ======================================================================*/
-
 static void airo_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "airo_detach\n");
@@ -140,60 +93,12 @@ static void airo_detach(struct pcmcia_device *link)
        kfree(link->priv);
 } /* airo_detach */
 
-/*======================================================================
-
-  airo_config() is scheduled to run after a CARD_INSERTION event
-  is received, to configure the PCMCIA socket, and to make the
-  device available to the system.
-
-  ======================================================================*/
-
-static int airo_cs_config_check(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* This reserves IO space but doesn't actually enable it */
-       if (pcmcia_request_io(p_dev) != 0)
-               return -ENODEV;
-
-       /* If we got this far, we're cool! */
-       return 0;
+       return pcmcia_request_io(p_dev);
 }
 
 
@@ -206,20 +111,9 @@ static int airo_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "airo_config\n");
 
-       /*
-        * In this loop, we scan the CIS for configuration table
-        * entries, each of which describes a valid card
-        * configuration, including voltage, IO window, memory window,
-        * and interrupt settings.
-        *
-        * We make no assumptions about the card to be configured: we
-        * use just the information available in the CIS.  In an ideal
-        * world, this would work for any PCMCIA card, but it requires
-        * a complete and accurate CIS.  In practice, a driver usually
-        * "knows" most of these things without consulting the CIS,
-        * and most client drivers will only use the CIS to fill in
-        * implementation-defined details.
-        */
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+               CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
        if (ret)
                goto failed;
@@ -227,12 +121,7 @@ static int airo_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-         This actually configures the PCMCIA socket -- setting up
-         the I/O windows and the interrupt mapping, and putting the
-         card and host interface into "Memory and IO" mode.
-       */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
        ((local_info_t *)link->priv)->eth_dev =
@@ -241,17 +130,6 @@ static int airo_config(struct pcmcia_device *link)
        if (!((local_info_t *)link->priv)->eth_dev)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x: ",
-              link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-       printk(", irq %d", link->irq);
-       if (link->resource[0])
-               printk(" & %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
        return 0;
 
  failed:
@@ -259,14 +137,6 @@ static int airo_config(struct pcmcia_device *link)
        return -ENODEV;
 } /* airo_config */
 
-/*======================================================================
-
-  After a card is removed, airo_release() will unregister the
-  device, and release the PCMCIA configuration.  If the device is
-  still open, this will be postponed until it is closed.
-
-  ======================================================================*/
-
 static void airo_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "airo_release\n");
@@ -305,9 +175,7 @@ MODULE_DEVICE_TABLE(pcmcia, airo_ids);
 
 static struct pcmcia_driver airo_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "airo_cs",
-       },
+       .name           = "airo_cs",
        .probe          = airo_probe,
        .remove         = airo_detach,
        .id_table       = airo_ids,
@@ -315,12 +183,12 @@ static struct pcmcia_driver airo_driver = {
        .resume         = airo_resume,
 };
 
-static int airo_cs_init(void)
+static int __init airo_cs_init(void)
 {
        return pcmcia_register_driver(&airo_driver);
 }
 
-static void airo_cs_cleanup(void)
+static void __exit airo_cs_cleanup(void)
 {
        pcmcia_unregister_driver(&airo_driver);
 }
index d5140a87f0737d92adde6ce9bb725d679be16538..1128fa8c9ed5ef3d0b9be5191edc4bd7320baf90 100644 (file)
@@ -655,7 +655,7 @@ static int at76_get_hw_config(struct at76_priv *priv)
 exit:
        kfree(hwcfg);
        if (ret < 0)
-               wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n",
+               wiphy_err(priv->hw->wiphy, "cannot get HW Config (error %d)\n",
                          ret);
 
        return ret;
@@ -960,7 +960,7 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv)
                           sizeof(struct mib_mac_addr));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (mac_addr) failed: %d\n", ret);
+                         "at76_get_mib (MAC_ADDR) failed: %d\n", ret);
                goto exit;
        }
 
@@ -989,7 +989,7 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
                           sizeof(struct mib_mac_wep));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (mac_wep) failed: %d\n", ret);
+                         "at76_get_mib (MAC_WEP) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1026,7 +1026,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
                           sizeof(struct mib_mac_mgmt));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (mac_mgmt) failed: %d\n", ret);
+                         "at76_get_mib (MAC_MGMT) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1062,7 +1062,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
        ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (mac) failed: %d\n", ret);
+                         "at76_get_mib (MAC) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1099,7 +1099,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv)
        ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (phy) failed: %d\n", ret);
+                         "at76_get_mib (PHY) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1132,7 +1132,7 @@ static void at76_dump_mib_local(struct at76_priv *priv)
        ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (local) failed: %d\n", ret);
+                         "at76_get_mib (LOCAL) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1158,7 +1158,7 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
                           sizeof(struct mib_mdomain));
        if (ret < 0) {
                wiphy_err(priv->hw->wiphy,
-                         "at76_get_mib (mdomain) failed: %d\n", ret);
+                         "at76_get_mib (MDOMAIN) failed: %d\n", ret);
                goto exit;
        }
 
@@ -1229,7 +1229,7 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
        struct sk_buff *skb = priv->rx_skb;
 
        if (!priv->rx_urb) {
-               wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n",
+               wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is NULL\n",
                          __func__);
                return -EFAULT;
        }
@@ -1792,7 +1792,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
                wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret);
                if (ret == -EINVAL)
                        wiphy_err(priv->hw->wiphy,
-                                 "-einval: tx urb %p hcpriv %p complete %p\n",
+                                 "-EINVAL: tx urb %p hcpriv %p complete %p\n",
                                  priv->tx_urb,
                                  priv->tx_urb->hcpriv, priv->tx_urb->complete);
        }
@@ -2310,7 +2310,7 @@ static int at76_init_new_device(struct at76_priv *priv,
 
        priv->mac80211_registered = 1;
 
-       wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n",
+       wiphy_info(priv->hw->wiphy, "USB %s, MAC %pM, firmware %d.%d.%d-%d\n",
                   dev_name(&interface->dev), priv->mac_addr,
                   priv->fw_version.major, priv->fw_version.minor,
                   priv->fw_version.patch, priv->fw_version.build);
index c67b05f3bcbdcace54e806ccdf69de5793766d0c..debfb0fbc7c5e7316931b2e0ac0c4913ff7428d6 100644 (file)
@@ -245,7 +245,7 @@ static void __ar9170_dump_txstats(struct ar9170 *ar)
 {
        int i;
 
-       wiphy_debug(ar->hw->wiphy, "qos queue stats\n");
+       wiphy_debug(ar->hw->wiphy, "QoS queue stats\n");
 
        for (i = 0; i < __AR9170_NUM_TXQ; i++)
                wiphy_debug(ar->hw->wiphy,
@@ -387,7 +387,7 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
                if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
 #ifdef AR9170_QUEUE_DEBUG
                        wiphy_debug(ar->hw->wiphy,
-                                   "skip frame => da %pm != %pm\n",
+                                   "skip frame => DA %pM != %pM\n",
                                    mac, ieee80211_get_DA(hdr));
                        ar9170_print_txheader(ar, skb);
 #endif /* AR9170_QUEUE_DEBUG */
index 373dcfec689c40c2bf1be9af2b9bddb7a15dcacb..d77ce9906b6ccb1bf1031b1260dfd2510fd9e116 100644 (file)
@@ -1327,6 +1327,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
                        PCI_DMA_TODEVICE);
 
        rate = ieee80211_get_tx_rate(sc->hw, info);
+       if (!rate) {
+               ret = -EINVAL;
+               goto err_unmap;
+       }
 
        if (info->flags & IEEE80211_TX_CTL_NO_ACK)
                flags |= AR5K_TXDESC_NOACK;
index 4cccc29964f6ddd0c7665369b034651d099a90cc..fb339c3852ee6859b327a5d366165b1c45d8eea5 100644 (file)
@@ -271,6 +271,7 @@ static const struct file_operations fops_beacon = {
        .write = write_file_beacon,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -290,6 +291,7 @@ static const struct file_operations fops_reset = {
        .write = write_file_reset,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 
@@ -369,6 +371,7 @@ static const struct file_operations fops_debug = {
        .write = write_file_debug,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -480,6 +483,7 @@ static const struct file_operations fops_antenna = {
        .write = write_file_antenna,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -591,6 +595,7 @@ static const struct file_operations fops_frameerrors = {
        .write = write_file_frameerrors,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -748,6 +753,7 @@ static const struct file_operations fops_ani = {
        .write = write_file_ani,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -811,6 +817,7 @@ static const struct file_operations fops_queue = {
        .write = write_file_queue,
        .open = ath5k_debugfs_open,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
index cc648b6ae31cef3b3a650ab7414b76fa061173e4..a3d95cca8f0c5be9a32c76d57082da1206cd44d1 100644 (file)
@@ -543,7 +543,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
        if (conf_is_ht40(conf))
                return clockrate * 2;
 
-       return clockrate * 2;
+       return clockrate;
 }
 
 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
index b883b174385b822e98cb46e0f83b8024159cf18c..057fb69ddf7fbc56e76b010a1cc21833fdc2b078 100644 (file)
@@ -797,7 +797,7 @@ static bool ar9300_uncompress_block(struct ath_hw *ah,
                length = block[it+1];
                length &= 0xff;
 
-               if (length > 0 && spot >= 0 && spot+length < mdataSize) {
+               if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
                        ath_print(common, ATH_DBG_EEPROM,
                                  "Restore at %d: spot=%d "
                                  "offset=%d length=%d\n",
index 54aae931424e69aa5cecc534ee0b8f03303383c7..cf500bf25ad578d6c205c63bd70a9d281a72a7b5 100644 (file)
@@ -71,7 +71,8 @@ static const struct file_operations fops_debug = {
        .read = read_file_debug,
        .write = write_file_debug,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 #endif
@@ -116,7 +117,8 @@ static const struct file_operations fops_tx_chainmask = {
        .read = read_file_tx_chainmask,
        .write = write_file_tx_chainmask,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -158,7 +160,8 @@ static const struct file_operations fops_rx_chainmask = {
        .read = read_file_rx_chainmask,
        .write = write_file_rx_chainmask,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -259,7 +262,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
 static const struct file_operations fops_dma = {
        .read = read_file_dma,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 
@@ -375,7 +379,8 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
 static const struct file_operations fops_interrupt = {
        .read = read_file_interrupt,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
@@ -464,7 +469,8 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
 static const struct file_operations fops_rcstat = {
        .read = read_file_rcstat,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
@@ -623,7 +629,8 @@ static const struct file_operations fops_wiphy = {
        .read = read_file_wiphy,
        .write = write_file_wiphy,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 #define PR(str, elem)                                                  \
@@ -702,7 +709,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
 static const struct file_operations fops_xmit = {
        .read = read_file_xmit,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -814,7 +822,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
 static const struct file_operations fops_recv = {
        .read = read_file_recv,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
@@ -852,7 +861,8 @@ static const struct file_operations fops_regidx = {
        .read = read_file_regidx,
        .write = write_file_regidx,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static ssize_t read_file_regval(struct file *file, char __user *user_buf,
@@ -894,7 +904,8 @@ static const struct file_operations fops_regval = {
        .read = read_file_regval,
        .write = write_file_regval,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 int ath9k_init_debug(struct ath_hw *ah)
index 7f48df1e2903008f0a68bf991817bee64edf5b81..0b09db0f8e7d99b1c22c94803884a67043e2187e 100644 (file)
@@ -62,7 +62,7 @@
 
 #define SD_NO_CTL               0xE0
 #define NO_CTL                  0xff
-#define CTL_MODE_M              7
+#define CTL_MODE_M              0xf
 #define CTL_11A                 0
 #define CTL_11B                 1
 #define CTL_11G                 2
index 7d09b4b17bbd4b5e1146fa295ea6a22ffb571014..bc2ca7d898e9c269c565cd71c0eaa6928fde4f21 100644 (file)
@@ -536,7 +536,8 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
 static const struct file_operations fops_tgt_stats = {
        .read = read_file_tgt_stats,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -584,7 +585,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 static const struct file_operations fops_xmit = {
        .read = read_file_xmit,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -613,7 +615,8 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
 static const struct file_operations fops_recv = {
        .read = read_file_recv,
        .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 int ath9k_htc_init_debug(struct ath_hw *ah)
index a1c39526161a9d663964638ebdc4206e95928b8a..345dd9721b415972d82d8309ce04aeec6c6bbc37 100644 (file)
@@ -31,7 +31,6 @@ enum ctl_group {
 #define NO_CTL 0xff
 #define SD_NO_CTL               0xE0
 #define NO_CTL                  0xff
-#define CTL_MODE_M              7
 #define CTL_11A                 0
 #define CTL_11B                 1
 #define CTL_11G                 2
index 3b632161c10696ee7ae896db24c11d4886395486..c96e19da29496407385ee8e51b19f46b21e230d4 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,58 +63,21 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the atmel_cs
-   event handler.
-*/
-
 static int atmel_config(struct pcmcia_device *link);
 static void atmel_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void atmel_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
        struct net_device *eth_dev;
 } local_info_t;
 
-/*======================================================================
-
-  atmel_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-  The dev_link structure is initialized, but we don't actually
-  configure the card at this point -- we wait until we receive a
-  card insertion event.
-
-  ======================================================================*/
-
 static int atmel_probe(struct pcmcia_device *p_dev)
 {
        local_info_t *local;
 
        dev_dbg(&p_dev->dev, "atmel_attach()\n");
 
-       /*
-         General socket configuration defaults can go here.  In this
-         client, we assume very little, and rely on the CIS for almost
-         everything.  In most clients, many details (i.e., number, sizes,
-         and attributes of IO windows) are fixed by the nature of the
-         device, and can be hard-wired here.
-       */
-       p_dev->conf.Attributes = 0;
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
        /* Allocate space for private device-specific data */
        local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
        if (!local) {
@@ -127,15 +89,6 @@ static int atmel_probe(struct pcmcia_device *p_dev)
        return atmel_config(p_dev);
 } /* atmel_attach */
 
-/*======================================================================
-
-  This deletes a driver "instance".  The device is de-registered
-  with Card Services.  If it has been released, all local data
-  structures are freed.  Otherwise, the structures will be freed
-  when the device is released.
-
-  ======================================================================*/
-
 static void atmel_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "atmel_detach\n");
@@ -145,14 +98,6 @@ static void atmel_detach(struct pcmcia_device *link)
        kfree(link->priv);
 }
 
-/*======================================================================
-
-  atmel_config() is scheduled to run after a CARD_INSERTION event
-  is received, to configure the PCMCIA socket, and to make the
-  device available to the system.
-
-  ======================================================================*/
-
 /* Call-back function to interrogate PCMCIA-specific information
    about the current existance of the card */
 static int card_present(void *arg)
@@ -165,47 +110,11 @@ static int card_present(void *arg)
        return 0;
 }
 
-static int atmel_config_check(struct pcmcia_device *p_dev,
-                             cistpl_cftable_entry_t *cfg,
-                             cistpl_cftable_entry_t *dflt,
-                             unsigned int vcc,
-                             void *priv_data)
+static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-       }
-
-       /* This reserves IO space but doesn't actually enable it */
        return pcmcia_request_io(p_dev);
 }
 
@@ -220,18 +129,9 @@ static int atmel_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "atmel_config\n");
 
-       /*
-         In this loop, we scan the CIS for configuration table entries,
-         each of which describes a valid card configuration, including
-         voltage, IO window, memory window, and interrupt settings.
-
-         We make no assumptions about the card to be configured: we use
-         just the information available in the CIS.  In an ideal world,
-         this would work for any PCMCIA card, but it requires a complete
-         and accurate CIS.  In practice, a driver usually "knows" most of
-         these things without consulting the CIS, and most client drivers
-         will only use the CIS to fill in implementation-defined details.
-       */
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+               CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
        if (pcmcia_loop_config(link, atmel_config_check, NULL))
                goto failed;
 
@@ -240,12 +140,7 @@ static int atmel_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       /*
-         This actually configures the PCMCIA socket -- setting up
-         the I/O windows and the interrupt mapping, and putting the
-         card and host interface into "Memory and IO" mode.
-       */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -267,14 +162,6 @@ static int atmel_config(struct pcmcia_device *link)
        return -ENODEV;
 }
 
-/*======================================================================
-
-  After a card is removed, atmel_release() will unregister the
-  device, and release the PCMCIA configuration.  If the device is
-  still open, this will be postponed until it is closed.
-
-  ======================================================================*/
-
 static void atmel_release(struct pcmcia_device *link)
 {
        struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
@@ -353,9 +240,7 @@ MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
 
 static struct pcmcia_driver atmel_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "atmel_cs",
-        },
+       .name           = "atmel_cs",
        .probe          = atmel_probe,
        .remove         = atmel_detach,
        .id_table       = atmel_ids,
@@ -363,12 +248,12 @@ static struct pcmcia_driver atmel_driver = {
        .resume         = atmel_resume,
 };
 
-static int atmel_cs_init(void)
+static int __init atmel_cs_init(void)
 {
         return pcmcia_register_driver(&atmel_driver);
 }
 
-static void atmel_cs_cleanup(void)
+static void __exit atmel_cs_cleanup(void)
 {
         pcmcia_unregister_driver(&atmel_driver);
 }
index 80b19a44a407ea40bd79a2ed157ea463aad846a2..59f59fa40334f75715259f6456b32b9fd3b4ebce 100644 (file)
@@ -627,6 +627,7 @@ out_unlock:
                        .open   = b43_debugfs_open,             \
                        .read   = b43_debugfs_read,             \
                        .write  = b43_debugfs_write,            \
+                       .llseek = generic_file_llseek,          \
                },                                              \
                .file_struct_offset = offsetof(struct b43_dfsentry, \
                                               file_##name),    \
index dfbc41d431ffae744fca15a2a90506ee5e6abb01..7dcba5fafdc7fe04820bde7a10571f327fd6796d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -63,7 +62,6 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
 static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 {
        struct ssb_bus *ssb;
-       win_req_t win;
        int err = -ENOMEM;
        int res = 0;
 
@@ -73,30 +71,28 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 
        err = -ENODEV;
 
-       dev->conf.Attributes = CONF_ENABLE_IRQ;
-       dev->conf.IntType = INT_MEMORY_AND_IO;
+       dev->config_flags |= CONF_ENABLE_IRQ;
 
-       win.Attributes =  WIN_ENABLE | WIN_DATA_WIDTH_16 |
+       dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
                         WIN_USE_WAIT;
-       win.Base = 0;
-       win.Size = SSB_CORE_SIZE;
-       win.AccessSpeed = 250;
-       res = pcmcia_request_window(dev, &win, &dev->win);
+       dev->resource[2]->start = 0;
+       dev->resource[2]->end = SSB_CORE_SIZE;
+       res = pcmcia_request_window(dev, dev->resource[2], 250);
        if (res != 0)
                goto err_kfree_ssb;
 
-       res = pcmcia_map_mem_page(dev, dev->win, 0);
+       res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
        if (res != 0)
                goto err_disable;
 
        if (!dev->irq)
                goto err_disable;
 
-       res = pcmcia_request_configuration(dev, &dev->conf);
+       res = pcmcia_enable_device(dev);
        if (res != 0)
                goto err_disable;
 
-       err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+       err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
        if (err)
                goto err_disable;
        dev->priv = ssb;
@@ -125,9 +121,7 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
 
 static struct pcmcia_driver b43_pcmcia_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-                               .name = "b43-pcmcia",
-                       },
+       .name           = "b43-pcmcia",
        .id_table       = b43_pcmcia_tbl,
        .probe          = b43_pcmcia_probe,
        .remove         = __devexit_p(b43_pcmcia_remove),
index 1f85ac569fec0065868fb4341971dfec9c83480f..f232618f2cd1097b462b0c88a634becbde71c93a 100644 (file)
@@ -334,6 +334,7 @@ out_unlock:
                        .open   = b43legacy_debugfs_open,               \
                        .read   = b43legacy_debugfs_read,               \
                        .write  = b43legacy_debugfs_write,              \
+                       .llseek = generic_file_llseek,                  \
                },                                              \
                .file_struct_offset = offsetof(struct b43legacy_dfsentry, \
                                               file_##name),    \
index ba54d1b04d22a7e50ae244bb2b905c84d44c1986..bd8a4134edebcae378d89fa9add3c2ae7f4dea9f 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -437,7 +436,6 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
        int ret;
 
        PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
        ret = prism2_config(p_dev);
        if (ret) {
@@ -468,74 +466,11 @@ static void prism2_detach(struct pcmcia_device *link)
 }
 
 
-/* run after a CARD_INSERTION event is received to configure the PCMCIA
- * socket and make the device available to the system */
-
-static int prism2_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cfg,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
-              "(default 0x%02X)\n", cfg->index, dflt->index);
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
-                   10000 && !ignore_cis_vcc) {
-                       PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping"
-                              " this entry\n");
-                       return -ENODEV;
-               }
-       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
-                   10000 && !ignore_cis_vcc) {
-                       PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch "
-                              "- skipping this entry\n");
-                       return -ENODEV;
-               }
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
-              "dflt->io.nwin=%d\n",
-              cfg->io.nwin, dflt->io.nwin);
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-       }
-
-       /* This reserves IO space but doesn't actually enable it */
        return pcmcia_request_io(p_dev);
 }
 
@@ -557,6 +492,10 @@ static int prism2_config(struct pcmcia_device *link)
        }
 
        /* Look for an appropriate configuration table entry in the CIS */
+       link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
+               CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+       if (ignore_cis_vcc)
+               link->config_flags &= ~CONF_AUTO_CHECK_VCC;
        ret = pcmcia_loop_config(link, prism2_config_check, NULL);
        if (ret) {
                if (!ignore_cis_vcc)
@@ -588,12 +527,7 @@ static int prism2_config(struct pcmcia_device *link)
        if (ret)
                goto failed_unlock;
 
-       /*
-        * This actually configures the PCMCIA socket -- setting up
-        * the I/O windows and the interrupt mapping, and putting the
-        * card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed_unlock;
 
@@ -602,20 +536,6 @@ static int prism2_config(struct pcmcia_device *link)
 
        spin_unlock_irqrestore(&local->irq_init_lock, flags);
 
-       /* Finally, report what we've done */
-       printk(KERN_INFO "%s: index 0x%02x: ",
-              dev_info, link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp / 10,
-                      link->conf.Vpp % 10);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %d", link->irq);
-       if (link->resource[0])
-               printk(" & %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        local->shutdown = 0;
 
        sandisk_enable_wireless(dev);
@@ -627,7 +547,7 @@ static int prism2_config(struct pcmcia_device *link)
        return ret;
 
  failed_unlock:
-        spin_unlock_irqrestore(&local->irq_init_lock, flags);
+       spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
        kfree(hw_priv);
        prism2_release((u_long)link);
@@ -779,9 +699,7 @@ MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
 
 
 static struct pcmcia_driver hostap_driver = {
-       .drv            = {
-               .name   = "hostap_cs",
-       },
+       .name           = "hostap_cs",
        .probe          = hostap_cs_probe,
        .remove         = prism2_detach,
        .owner          = THIS_MODULE,
index 1189dbb6e2a62abcdc090ca5eea61a9eb5824aa7..996e9d7d7586b240847526bec92e721ef8a20d9c 100644 (file)
@@ -2723,14 +2723,6 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
 
                packet = &priv->rx_buffers[i];
 
-               /* Sync the DMA for the STATUS buffer so CPU is sure to get
-                * the correct values */
-               pci_dma_sync_single_for_cpu(priv->pci_dev,
-                                           sq->nic +
-                                           sizeof(struct ipw2100_status) * i,
-                                           sizeof(struct ipw2100_status),
-                                           PCI_DMA_FROMDEVICE);
-
                /* Sync the DMA for the RX buffer so CPU is sure to get
                 * the correct values */
                pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr,
index fec026212326dce857220196dd312c3b2d5b6c69..0b779a41a1426b9153a55f30a59a052a9e66f618 100644 (file)
@@ -265,7 +265,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 128,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -297,7 +297,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 128,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
index 8e84a08ff9519ae28031853c62cf3941adf0e93e..293e1dbc166c4cb5027ad3cef324d07ab1f1164a 100644 (file)
@@ -873,6 +873,7 @@ static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
        .read = iwl3945_sta_dbgfs_stats_table_read,
        .open = iwl3945_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static void iwl3945_add_debugfs(void *priv, void *priv_sta,
index 6950a783913b83561839f20a08657857ee242a86..8ccfcd08218d894895524c3995fca28f2695aa6c 100644 (file)
@@ -2731,7 +2731,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
        .led_compensation = 64,
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .tx_power_by_driver = true,
 };
@@ -2752,7 +2752,7 @@ static struct iwl_cfg iwl3945_abg_cfg = {
        .led_compensation = 64,
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .tx_power_by_driver = true,
 };
index d6da356608fa46efe34a317bdda60c6680b65d7e..d92b729092336523a5c0a2a541bfbd7cb1b4b640 100644 (file)
@@ -2322,7 +2322,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
        .led_compensation = 61,
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .temperature_kelvin = true,
        .max_event_log_size = 512,
        .tx_power_by_driver = true,
index aacf3770f075b4abd1de4a474f79cc60eb42c9cc..48bdcd8d2e94c3355c877a55d8e7815249350fdc 100644 (file)
@@ -510,7 +510,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -541,7 +541,7 @@ struct iwl_cfg iwl5100_bgn_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -570,7 +570,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -601,7 +601,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -632,7 +632,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -663,7 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -693,7 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
index af4fd50f3405db334ce2e44e1ce648c7c510ed7c..cee06b968de807a642adb4db4e08e62cfe2237ab 100644 (file)
@@ -388,7 +388,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -424,7 +424,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -459,7 +459,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -496,7 +496,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -532,7 +532,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -570,7 +570,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -606,7 +606,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -644,7 +644,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -680,7 +680,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -721,7 +721,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -756,7 +756,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -791,7 +791,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -828,7 +828,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1500,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -866,7 +866,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1500,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -902,7 +902,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1500,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -940,7 +940,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
index 9dd9e64c2b0b1a69f11a6d40a5e0e2cbc84d8b22..8fd00a6e512019075e966a038d2c5d09539ccf85 100644 (file)
@@ -1411,7 +1411,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        clear_bit(STATUS_SCAN_HW, &priv->status);
        clear_bit(STATUS_SCANNING, &priv->status);
        /* inform mac80211 scan aborted */
-       queue_work(priv->workqueue, &priv->scan_completed);
+       queue_work(priv->workqueue, &priv->abort_scan);
 }
 
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
index 23e5c42e7d7eb31798aa72f7e995f3537d98a86f..a4378ba31ef6c8092d7a9830ae6956a022ea1eea 100644 (file)
@@ -2873,6 +2873,7 @@ static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
        .write = rs_sta_dbgfs_scale_table_write,
        .read = rs_sta_dbgfs_scale_table_read,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
                        char __user *user_buf, size_t count, loff_t *ppos)
@@ -2915,6 +2916,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
        .read = rs_sta_dbgfs_stats_table_read,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
@@ -2946,6 +2948,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
 static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
        .read = rs_sta_dbgfs_rate_scale_data_read,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static void rs_add_debugfs(void *priv, void *priv_sta,
index c1882fd8345d43dd630718c1f9475533511e5f7c..10d7b9b7f064f529af9d0cdc6aa2b0a144d9438d 100644 (file)
@@ -3667,6 +3667,49 @@ out_exit:
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
+static void iwlagn_configure_filter(struct ieee80211_hw *hw,
+                                   unsigned int changed_flags,
+                                   unsigned int *total_flags,
+                                   u64 multicast)
+{
+       struct iwl_priv *priv = hw->priv;
+       __le32 filter_or = 0, filter_nand = 0;
+
+#define CHK(test, flag)        do { \
+       if (*total_flags & (test))              \
+               filter_or |= (flag);            \
+       else                                    \
+               filter_nand |= (flag);          \
+       } while (0)
+
+       IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+                       changed_flags, *total_flags);
+
+       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+       mutex_lock(&priv->mutex);
+
+       priv->staging_rxon.filter_flags &= ~filter_nand;
+       priv->staging_rxon.filter_flags |= filter_or;
+
+       iwlcore_commit_rxon(priv);
+
+       mutex_unlock(&priv->mutex);
+
+       /*
+        * Receiving all multicast frames is always enabled by the
+        * default flags setup in iwl_connection_init_rx_config()
+        * since we currently do not support programming multicast
+        * filters into the device.
+        */
+       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
 static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct iwl_priv *priv = hw->priv;
@@ -3867,7 +3910,7 @@ static struct ieee80211_ops iwl_hw_ops = {
        .add_interface = iwl_mac_add_interface,
        .remove_interface = iwl_mac_remove_interface,
        .config = iwl_mac_config,
-       .configure_filter = iwl_configure_filter,
+       .configure_filter = iwlagn_configure_filter,
        .set_key = iwl_mac_set_key,
        .update_tkip_key = iwl_mac_update_tkip_key,
        .conf_tx = iwl_mac_conf_tx,
index 2c03c6e20a72d73ded70f8c96d37bfce6aa8e263..e23c4060a0f093e966ca355af1d466880f65b0ee 100644 (file)
@@ -1328,51 +1328,6 @@ out:
 EXPORT_SYMBOL(iwl_apm_init);
 
 
-
-void iwl_configure_filter(struct ieee80211_hw *hw,
-                         unsigned int changed_flags,
-                         unsigned int *total_flags,
-                         u64 multicast)
-{
-       struct iwl_priv *priv = hw->priv;
-       __le32 filter_or = 0, filter_nand = 0;
-
-#define CHK(test, flag)        do { \
-       if (*total_flags & (test))              \
-               filter_or |= (flag);            \
-       else                                    \
-               filter_nand |= (flag);          \
-       } while (0)
-
-       IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
-                       changed_flags, *total_flags);
-
-       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
-       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
-
-#undef CHK
-
-       mutex_lock(&priv->mutex);
-
-       priv->staging_rxon.filter_flags &= ~filter_nand;
-       priv->staging_rxon.filter_flags |= filter_or;
-
-       iwlcore_commit_rxon(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       /*
-        * Receiving all multicast frames is always enabled by the
-        * default flags setup in iwl_connection_init_rx_config()
-        * since we currently do not support programming multicast
-        * filters into the device.
-        */
-       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
-                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
-}
-EXPORT_SYMBOL(iwl_configure_filter);
-
 int iwl_set_hw_params(struct iwl_priv *priv)
 {
        priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
@@ -2658,6 +2613,11 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return -EINVAL;
 
+       if (test_bit(STATUS_SCANNING, &priv->status)) {
+               IWL_DEBUG_INFO(priv, "scan in progress.\n");
+               return -EINVAL;
+       }
+
        if (mode >= IWL_MAX_FORCE_RESET) {
                IWL_DEBUG_INFO(priv, "invalid reset request.\n");
                return -EINVAL;
index 4a71dfb10a15d0f6ebf4007944d011d249333902..5e6ee3da6bbf740846033e4a57e44956e326a73c 100644 (file)
@@ -372,9 +372,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
                           u32 decrypt_res,
                           struct ieee80211_rx_status *stats);
 void iwl_irq_handle_error(struct iwl_priv *priv);
-void iwl_configure_filter(struct ieee80211_hw *hw,
-                         unsigned int changed_flags,
-                         unsigned int *total_flags, u64 multicast);
 int iwl_set_hw_params(struct iwl_priv *priv);
 void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwl_bss_info_changed(struct ieee80211_hw *hw,
index e96a1bb12783db78efc0d07a2794599525f9f830..a32d5d3376497bdcd3e5a82386785bb31d9caf5f 100644 (file)
@@ -87,6 +87,7 @@ static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .read = iwl_dbgfs_##name##_read,                                \
        .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
@@ -94,6 +95,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .write = iwl_dbgfs_##name##_write,                              \
        .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
 };
 
 
@@ -104,6 +106,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .write = iwl_dbgfs_##name##_write,                              \
        .read = iwl_dbgfs_##name##_read,                                \
        .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
 };
 
 static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
index f35bcad56e36bd68779edb3acf930d6b7595359a..2e97cd2fa98a6e0c7d9cdc6d98582ac54fe28459 100644 (file)
@@ -1049,7 +1049,8 @@ struct iwl_event_log {
 #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
 
 /* timer constants use to monitor and recover stuck tx queues in mSecs */
-#define IWL_MONITORING_PERIOD  (1000)
+#define IWL_DEF_MONITORING_PERIOD      (1000)
+#define IWL_LONG_MONITORING_PERIOD     (5000)
 #define IWL_ONE_HUNDRED_MSECS   (100)
 #define IWL_SIXTY_SECS          (60000)
 
index 70c4b8fba0ee89093c56c056e7152b927da5a37c..d31661c1ce778259996b5428f9cff95b87f1a3db 100644 (file)
@@ -3018,7 +3018,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        clear_bit(STATUS_SCANNING, &priv->status);
 
        /* inform mac80211 scan aborted */
-       queue_work(priv->workqueue, &priv->scan_completed);
+       queue_work(priv->workqueue, &priv->abort_scan);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3391,6 +3391,55 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
 
        return 0;
 }
+
+static void iwl3945_configure_filter(struct ieee80211_hw *hw,
+                                    unsigned int changed_flags,
+                                    unsigned int *total_flags,
+                                    u64 multicast)
+{
+       struct iwl_priv *priv = hw->priv;
+       __le32 filter_or = 0, filter_nand = 0;
+
+#define CHK(test, flag)        do { \
+       if (*total_flags & (test))              \
+               filter_or |= (flag);            \
+       else                                    \
+               filter_nand |= (flag);          \
+       } while (0)
+
+       IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+                       changed_flags, *total_flags);
+
+       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+       mutex_lock(&priv->mutex);
+
+       priv->staging_rxon.filter_flags &= ~filter_nand;
+       priv->staging_rxon.filter_flags |= filter_or;
+
+       /*
+        * Committing directly here breaks for some reason,
+        * but we'll eventually commit the filter flags
+        * change anyway.
+        */
+
+       mutex_unlock(&priv->mutex);
+
+       /*
+        * Receiving all multicast frames is always enabled by the
+        * default flags setup in iwl_connection_init_rx_config()
+        * since we currently do not support programming multicast
+        * filters into the device.
+        */
+       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+
 /*****************************************************************************
  *
  * sysfs attributes
@@ -3796,7 +3845,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .add_interface = iwl_mac_add_interface,
        .remove_interface = iwl_mac_remove_interface,
        .config = iwl_mac_config,
-       .configure_filter = iwl_configure_filter,
+       .configure_filter = iwl3945_configure_filter,
        .set_key = iwl3945_mac_set_key,
        .conf_tx = iwl_mac_conf_tx,
        .reset_tsf = iwl_mac_reset_tsf,
index 53b0b7711f02a4c595d95fd0a92ef62753b33f65..0a0cc9667cd667c6468e7a749d0ab2de9fa89991 100644 (file)
@@ -402,24 +402,28 @@ static const struct file_operations iwm_debugfs_txq_fops = {
        .owner =        THIS_MODULE,
        .open =         iwm_generic_open,
        .read =         iwm_debugfs_txq_read,
+       .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_tx_credit_fops = {
        .owner =        THIS_MODULE,
        .open =         iwm_generic_open,
        .read =         iwm_debugfs_tx_credit_read,
+       .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_rx_ticket_fops = {
        .owner =        THIS_MODULE,
        .open =         iwm_generic_open,
        .read =         iwm_debugfs_rx_ticket_read,
+       .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_fw_err_fops = {
        .owner =        THIS_MODULE,
        .open =         iwm_generic_open,
        .read =         iwm_debugfs_fw_err_read,
+       .llseek =       default_llseek,
 };
 
 void iwm_debugfs_init(struct iwm_priv *iwm)
index edcb52330cf5ebbfca816cf6975b49221a1a0a4d..56383e7be8350757dca6f7cafcd7b81a657e7529 100644 (file)
@@ -364,6 +364,7 @@ static const struct file_operations iwm_debugfs_sdio_fops = {
        .owner =        THIS_MODULE,
        .open =         iwm_debugfs_sdio_open,
        .read =         iwm_debugfs_sdio_read,
+       .llseek =       default_llseek,
 };
 
 static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
index 651a79c8de8a0d5cb59372a37720fddbc5dfd70c..fbf3b0332bb76c4957d066f90478106ae001d42a 100644 (file)
@@ -696,6 +696,7 @@ out_unlock:
        .open = open_file_generic, \
        .read = (fread), \
        .write = (fwrite), \
+       .llseek = generic_file_llseek, \
 }
 
 struct lbs_debugfs_files {
@@ -961,6 +962,7 @@ static const struct file_operations lbs_debug_fops = {
        .open = open_file_generic,
        .write = lbs_debugfs_write,
        .read = lbs_debugfs_read,
+       .llseek = default_llseek,
 };
 
 /**
index 9c298396be50b7fe5d0d6f8c6b102ecef441b3f7..ff1280f413362847b364fa8a5cf4f680a21fd354 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/firmware.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -761,15 +760,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
 }
 
 
-/********************************************************************/
-/* Card Services                                                    */
-/********************************************************************/
-
-/*
- * After a card is removed, if_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void if_cs_release(struct pcmcia_device *p_dev)
 {
        struct if_cs_card *card = p_dev->priv;
@@ -785,31 +775,12 @@ static void if_cs_release(struct pcmcia_device *p_dev)
 }
 
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event.
- */
-
-static int if_cs_ioprobe(struct pcmcia_device *p_dev,
-                        cistpl_cftable_entry_t *cfg,
-                        cistpl_cftable_entry_t *dflt,
-                        unsigned int vcc,
-                        void *priv_data)
+static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
        p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
-       /* IO window settings */
-       if (cfg->io.nwin != 1) {
+       if (p_dev->resource[1]->end) {
                lbs_pr_err("wrong CIS (check number of IO windows)\n");
                return -ENODEV;
        }
@@ -835,15 +806,13 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
        card->p_dev = p_dev;
        p_dev->priv = card;
 
-       p_dev->conf.Attributes = 0;
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
+       p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
        if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
                lbs_pr_err("error in pcmcia_loop_config\n");
                goto out1;
        }
 
-
        /*
         * Allocate an interrupt line.  Note that this does not assign
         * a handler to the interrupt, unless the 'Handler' member of
@@ -861,14 +830,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
                goto out1;
        }
 
-       /*
-        * This actually configures the PCMCIA socket -- setting up
-        * the I/O windows and the interrupt mapping, and putting the
-        * card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+       ret = pcmcia_enable_device(p_dev);
        if (ret) {
-               lbs_pr_err("error in pcmcia_request_configuration\n");
+               lbs_pr_err("error in pcmcia_enable_device\n");
                goto out2;
        }
 
@@ -962,12 +926,6 @@ out:
 }
 
 
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
 static void if_cs_detach(struct pcmcia_device *p_dev)
 {
        struct if_cs_card *card = p_dev->priv;
@@ -1000,9 +958,7 @@ MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
 
 static struct pcmcia_driver lbs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = DRV_NAME,
-       },
+       .name           = DRV_NAME,
        .probe          = if_cs_probe,
        .remove         = if_cs_detach,
        .id_table       = if_cs_ids,
index ba854c70ab9455b8e18a63fa254e18671f447232..87b634978b357797ed6ceb22f7dec9643f6c7054 100644 (file)
@@ -128,7 +128,7 @@ struct if_sdio_card {
        bool                    helper_allocated;
        bool                    firmware_allocated;
 
-       u8                      buffer[65536];
+       u8                      buffer[65536] __attribute__((aligned(4)));
 
        spinlock_t              lock;
        struct if_sdio_packet   *packets;
index 01ad7f77383a8f18a58a69dc6648ba907618e069..86fa8abdd66fda1cba26ef0e2bfe90a249d14128 100644 (file)
@@ -486,7 +486,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
        struct ieee80211_rx_status rx_status;
 
        if (data->idle) {
-               wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n");
+               wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
                return false;
        }
 
index d761ed2d8af46b8d8be19eab01101dc511321b00..f152a25be59f7020998d35ceb72ba55100ebff2b 100644 (file)
@@ -910,14 +910,14 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
 
        rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
        if (rxq->rxd == NULL) {
-               wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n");
+               wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n");
                return -ENOMEM;
        }
        memset(rxq->rxd, 0, size);
 
        rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
        if (rxq->buf == NULL) {
-               wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n");
+               wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
                pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
                return -ENOMEM;
        }
@@ -1145,14 +1145,14 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 
        txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
        if (txq->txd == NULL) {
-               wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n");
+               wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n");
                return -ENOMEM;
        }
        memset(txq->txd, 0, size);
 
        txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
        if (txq->skb == NULL) {
-               wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n");
+               wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
                pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
                return -ENOMEM;
        }
@@ -1573,7 +1573,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
                                        PCI_DMA_BIDIRECTIONAL);
 
        if (!timeout) {
-               wiphy_err(hw->wiphy, "command %s timeout after %u ms\n",
+               wiphy_err(hw->wiphy, "Command %s timeout after %u ms\n",
                          mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
                          MWL8K_CMD_TIMEOUT_MS);
                rc = -ETIMEDOUT;
@@ -1584,11 +1584,11 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
 
                rc = cmd->result ? -EINVAL : 0;
                if (rc)
-                       wiphy_err(hw->wiphy, "command %s error 0x%x\n",
+                       wiphy_err(hw->wiphy, "Command %s error 0x%x\n",
                                  mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
                                  le16_to_cpu(cmd->result));
                else if (ms > 2000)
-                       wiphy_notice(hw->wiphy, "command %s took %d ms\n",
+                       wiphy_notice(hw->wiphy, "Command %s took %d ms\n",
                                     mwl8k_cmd_name(cmd->code,
                                                    buf, sizeof(buf)),
                                     ms);
@@ -3210,7 +3210,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
        rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
                         IRQF_SHARED, MWL8K_NAME, hw);
        if (rc) {
-               wiphy_err(hw->wiphy, "failed to register irq handler\n");
+               wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
                return -EIO;
        }
 
@@ -3926,7 +3926,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 
        priv->sram = pci_iomap(pdev, 0, 0x10000);
        if (priv->sram == NULL) {
-               wiphy_err(hw->wiphy, "cannot map device sram\n");
+               wiphy_err(hw->wiphy, "Cannot map device SRAM\n");
                goto err_iounmap;
        }
 
@@ -3938,7 +3938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
        if (priv->regs == NULL) {
                priv->regs = pci_iomap(pdev, 2, 0x10000);
                if (priv->regs == NULL) {
-                       wiphy_err(hw->wiphy, "cannot map device registers\n");
+                       wiphy_err(hw->wiphy, "Cannot map device registers\n");
                        goto err_iounmap;
                }
        }
@@ -3950,14 +3950,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
        /* Ask userland hotplug daemon for the device firmware */
        rc = mwl8k_request_firmware(priv);
        if (rc) {
-               wiphy_err(hw->wiphy, "firmware files not found\n");
+               wiphy_err(hw->wiphy, "Firmware files not found\n");
                goto err_stop_firmware;
        }
 
        /* Load firmware into hardware */
        rc = mwl8k_load_firmware(hw);
        if (rc) {
-               wiphy_err(hw->wiphy, "cannot start firmware\n");
+               wiphy_err(hw->wiphy, "Cannot start firmware\n");
                goto err_stop_firmware;
        }
 
@@ -4047,7 +4047,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
        rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
                         IRQF_SHARED, MWL8K_NAME, hw);
        if (rc) {
-               wiphy_err(hw->wiphy, "failed to register irq handler\n");
+               wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
                goto err_free_queues;
        }
 
@@ -4067,7 +4067,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
                rc = mwl8k_cmd_get_hw_spec_sta(hw);
        }
        if (rc) {
-               wiphy_err(hw->wiphy, "cannot initialise firmware\n");
+               wiphy_err(hw->wiphy, "Cannot initialise firmware\n");
                goto err_free_irq;
        }
 
@@ -4081,14 +4081,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
        /* Turn radio off */
        rc = mwl8k_cmd_radio_disable(hw);
        if (rc) {
-               wiphy_err(hw->wiphy, "cannot disable\n");
+               wiphy_err(hw->wiphy, "Cannot disable\n");
                goto err_free_irq;
        }
 
        /* Clear MAC address */
        rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
        if (rc) {
-               wiphy_err(hw->wiphy, "cannot clear mac address\n");
+               wiphy_err(hw->wiphy, "Cannot clear MAC address\n");
                goto err_free_irq;
        }
 
@@ -4098,7 +4098,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 
        rc = ieee80211_register_hw(hw);
        if (rc) {
-               wiphy_err(hw->wiphy, "cannot register device\n");
+               wiphy_err(hw->wiphy, "Cannot register device\n");
                goto err_free_queues;
        }
 
index ef46a2d885392f49f1803fbb47bb2f6a6b2f7fdc..71b3d68b9403a8c4c142b776179c1edef9328ebd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -93,14 +92,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
 /* PCMCIA stuff                                                    */
 /********************************************************************/
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event.  */
 static int
 orinoco_cs_probe(struct pcmcia_device *link)
 {
@@ -117,23 +108,9 @@ orinoco_cs_probe(struct pcmcia_device *link)
        card->p_dev = link;
        link->priv = priv;
 
-       /* General socket configuration defaults can go here.  In this
-        * client, we assume very little, and rely on the CIS for
-        * almost everything.  In most clients, many details (i.e.,
-        * number, sizes, and attributes of IO windows) are fixed by
-        * the nature of the device, and can be hard-wired here. */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        return orinoco_cs_config(link);
 }                              /* orinoco_cs_attach */
 
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
 static void orinoco_cs_detach(struct pcmcia_device *link)
 {
        struct orinoco_private *priv = link->priv;
@@ -145,76 +122,12 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
        free_orinocodev(priv);
 }                              /* orinoco_cs_detach */
 
-/*
- * orinoco_cs_config() is scheduled to run after a CARD_INSERTION
- * event is received, to configure the PCMCIA socket, and to make the
- * device available to the system.
- */
-
-static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
-                                  cistpl_cftable_entry_t *cfg,
-                                  cistpl_cftable_entry_t *dflt,
-                                  unsigned int vcc,
-                                  void *priv_data)
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               goto next_entry;
-
-       /* Use power settings for Vcc and Vpp if present */
-       /* Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                       DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-                             __func__, vcc,
-                             cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                       if (!ignore_cis_vcc)
-                               goto next_entry;
-               }
-       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                       DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-                             __func__, vcc,
-                             dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                       if (!ignore_cis_vcc)
-                               goto next_entry;
-               }
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(p_dev) != 0)
-                       goto next_entry;
-       }
-       return 0;
-
-next_entry:
-       pcmcia_disable_device(p_dev);
-       return -ENODEV;
+       return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -225,20 +138,10 @@ orinoco_cs_config(struct pcmcia_device *link)
        int ret;
        void __iomem *mem;
 
-       /*
-        * In this loop, we scan the CIS for configuration table
-        * entries, each of which describes a valid card
-        * configuration, including voltage, IO window, memory window,
-        * and interrupt settings.
-        *
-        * We make no assumptions about the card to be configured: we
-        * use just the information available in the CIS.  In an ideal
-        * world, this would work for any PCMCIA card, but it requires
-        * a complete and accurate CIS.  In practice, a driver usually
-        * "knows" most of these things without consulting the CIS,
-        * and most client drivers will only use the CIS to fill in
-        * implementation-defined details.
-        */
+       link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+               CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+       if (ignore_cis_vcc)
+               link->config_flags &= ~CONF_AUTO_CHECK_VCC;
        ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
        if (ret) {
                if (!ignore_cis_vcc)
@@ -262,12 +165,7 @@ orinoco_cs_config(struct pcmcia_device *link)
 
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
-       /*
-        * This actually configures the PCMCIA socket -- setting up
-        * the I/O windows and the interrupt mapping, and putting the
-        * card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -291,11 +189,6 @@ orinoco_cs_config(struct pcmcia_device *link)
        return -ENODEV;
 }                              /* orinoco_cs_config */
 
-/*
- * After a card is removed, orinoco_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 orinoco_cs_release(struct pcmcia_device *link)
 {
@@ -344,12 +237,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
 /* Module initialization                                           */
 /********************************************************************/
 
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
-       " (David Gibson <hermes@gibson.dropbear.id.au>, "
-       "Pavel Roskin <proski@gnu.org>, et al)";
-
 static struct pcmcia_device_id orinoco_cs_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
        PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
@@ -441,9 +328,7 @@ MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
 
 static struct pcmcia_driver orinoco_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = DRIVER_NAME,
-       },
+       .name           = DRIVER_NAME,
        .probe          = orinoco_cs_probe,
        .remove         = orinoco_cs_detach,
        .id_table       = orinoco_cs_ids,
@@ -454,8 +339,6 @@ static struct pcmcia_driver orinoco_driver = {
 static int __init
 init_orinoco_cs(void)
 {
-       printk(KERN_DEBUG "%s\n", version);
-
        return pcmcia_register_driver(&orinoco_driver);
 }
 
index 873877e17e1bf6bce4debd49b75f359a8d39b1ec..fb859a5ad2eb8a5c2e02f349cf4002caac32fc49 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -154,14 +153,6 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
 /* PCMCIA stuff                                                    */
 /********************************************************************/
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event.  */
 static int
 spectrum_cs_probe(struct pcmcia_device *link)
 {
@@ -179,23 +170,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
        card->p_dev = link;
        link->priv = priv;
 
-       /* General socket configuration defaults can go here.  In this
-        * client, we assume very little, and rely on the CIS for
-        * almost everything.  In most clients, many details (i.e.,
-        * number, sizes, and attributes of IO windows) are fixed by
-        * the nature of the device, and can be hard-wired here. */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        return spectrum_cs_config(link);
 }                              /* spectrum_cs_attach */
 
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
 static void spectrum_cs_detach(struct pcmcia_device *link)
 {
        struct orinoco_private *priv = link->priv;
@@ -207,76 +184,13 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
        free_orinocodev(priv);
 }                              /* spectrum_cs_detach */
 
-/*
- * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
- * event is received, to configure the PCMCIA socket, and to make the
- * device available to the system.
- */
-
 static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
-                                   cistpl_cftable_entry_t *cfg,
-                                   cistpl_cftable_entry_t *dflt,
-                                   unsigned int vcc,
                                    void *priv_data)
 {
-       if (cfg->index == 0)
-               goto next_entry;
-
-       /* Use power settings for Vcc and Vpp if present */
-       /* Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                       DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-                             __func__, vcc,
-                             cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                       if (!ignore_cis_vcc)
-                               goto next_entry;
-               }
-       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                       DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-                             __func__, vcc,
-                             dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                       if (!ignore_cis_vcc)
-                               goto next_entry;
-               }
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(p_dev) != 0)
-                       goto next_entry;
-       }
-       return 0;
-
-next_entry:
-       pcmcia_disable_device(p_dev);
-       return -ENODEV;
+       return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -287,20 +201,10 @@ spectrum_cs_config(struct pcmcia_device *link)
        int ret;
        void __iomem *mem;
 
-       /*
-        * In this loop, we scan the CIS for configuration table
-        * entries, each of which describes a valid card
-        * configuration, including voltage, IO window, memory window,
-        * and interrupt settings.
-        *
-        * We make no assumptions about the card to be configured: we
-        * use just the information available in the CIS.  In an ideal
-        * world, this would work for any PCMCIA card, but it requires
-        * a complete and accurate CIS.  In practice, a driver usually
-        * "knows" most of these things without consulting the CIS,
-        * and most client drivers will only use the CIS to fill in
-        * implementation-defined details.
-        */
+       link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+               CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+       if (ignore_cis_vcc)
+               link->config_flags &= ~CONF_AUTO_CHECK_VCC;
        ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
        if (ret) {
                if (!ignore_cis_vcc)
@@ -325,12 +229,7 @@ spectrum_cs_config(struct pcmcia_device *link)
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
        hw->eeprom_pda = true;
 
-       /*
-        * This actually configures the PCMCIA socket -- setting up
-        * the I/O windows and the interrupt mapping, and putting the
-        * card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -358,11 +257,6 @@ spectrum_cs_config(struct pcmcia_device *link)
        return -ENODEV;
 }                              /* spectrum_cs_config */
 
-/*
- * After a card is removed, spectrum_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 spectrum_cs_release(struct pcmcia_device *link)
 {
@@ -407,12 +301,6 @@ spectrum_cs_resume(struct pcmcia_device *link)
 /* Module initialization                                           */
 /********************************************************************/
 
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
-       " (Pavel Roskin <proski@gnu.org>,"
-       " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
-
 static struct pcmcia_device_id spectrum_cs_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
        PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
@@ -423,9 +311,7 @@ MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
 
 static struct pcmcia_driver orinoco_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = DRIVER_NAME,
-       },
+       .name           = DRIVER_NAME,
        .probe          = spectrum_cs_probe,
        .remove         = spectrum_cs_detach,
        .suspend        = spectrum_cs_suspend,
@@ -436,8 +322,6 @@ static struct pcmcia_driver orinoco_driver = {
 static int __init
 init_spectrum_cs(void)
 {
-       printk(KERN_DEBUG "%s\n", version);
-
        return pcmcia_register_driver(&orinoco_driver);
 }
 
index d687cb7f2a599c28d04d6c875f5b4b2796604cdf..78347041ec40a3c51d094328495c8d86cb5c5a3b 100644 (file)
@@ -167,7 +167,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
        }
 
        if (j == 0) {
-               wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n",
+               wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n",
                          (band == IEEE80211_BAND_2GHZ) ? 2 : 5);
 
                ret = -ENODATA;
@@ -695,12 +695,12 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                u8 perm_addr[ETH_ALEN];
 
                wiphy_warn(dev->wiphy,
-                          "invalid hwaddr! using randomly generated mac addr\n");
+                          "Invalid hwaddr! Using randomly generated MAC addr\n");
                random_ether_addr(perm_addr);
                SET_IEEE80211_PERM_ADDR(dev, perm_addr);
        }
 
-       wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n",
+       wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
                   dev->wiphy->perm_addr, priv->version,
                   p54_rf_chips[priv->rxhw]);
 
index 47006bca485216609afb0f51a201c4d2ef1ef04a..15b20c29a6042ae6e3dc5c99dae07e8c317127ca 100644 (file)
@@ -125,7 +125,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
 
        if (fw_version)
                wiphy_info(priv->hw->wiphy,
-                          "fw rev %s - softmac protocol %x.%x\n",
+                          "FW rev %s - Softmac protocol %x.%x\n",
                           fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
 
        if (priv->fw_var < 0x500)
index ea91f5cce6b3f62d31f8c5d45609e650a2cc40a7..3837e1eec5f4a56fdbf80a2b8f13984f3d15742b 100644 (file)
@@ -58,7 +58,7 @@ static void p54_update_leds(struct work_struct *work)
        err = p54_set_leds(priv);
        if (err && net_ratelimit())
                wiphy_err(priv->hw->wiphy,
-                         "failed to update leds (%d).\n", err);
+                         "failed to update LEDs (%d).\n", err);
 
        if (rerun)
                ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
@@ -103,7 +103,7 @@ static int p54_register_led(struct p54_common *priv,
        err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev);
        if (err)
                wiphy_err(priv->hw->wiphy,
-                         "failed to register %s led.\n", name);
+                         "Failed to register %s LED.\n", name);
        else
                led->registered = 1;
 
index 822f8dc26e9c051d3b9ee34e79ef715b0f204067..1eacba4daa5bb1d35edc265ac8862c464eac4387 100644 (file)
@@ -466,7 +466,7 @@ static int p54p_open(struct ieee80211_hw *dev)
        P54P_READ(dev_int);
 
        if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-               wiphy_err(dev->wiphy, "cannot boot firmware!\n");
+               wiphy_err(dev->wiphy, "Cannot boot firmware!\n");
                p54p_stop(dev);
                return -ETIMEDOUT;
        }
index 427b46f558ed4f57b0066a2ae312be0d0e82c7ae..0e937dc0c9c41df6cff985c6b538f6cb17cf1091 100644 (file)
@@ -446,7 +446,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
        }
 
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-            (!payload->status))
+            !(payload->status & P54_TX_FAILED))
                info->flags |= IEEE80211_TX_STAT_ACK;
        if (payload->status & P54_TX_PSM_CANCELLED)
                info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
@@ -540,7 +540,7 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
        case P54_TRAP_BEACON_TX:
                break;
        case P54_TRAP_RADAR:
-               wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq);
+               wiphy_info(priv->hw->wiphy, "radar (freq:%d MHz)\n", freq);
                break;
        case P54_TRAP_NO_BEACON:
                if (priv->vif)
index 88560d0ae50a2457d1373103db85b98ebb61211e..46da03753fd5ee25874c92752bbc241b0e3a0fef 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/ethtool.h>
 #include <linux/ieee80211.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -169,13 +168,6 @@ static int bc;
  */
 static char *phy_addr = NULL;
 
-
-/* A struct pcmcia_device structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a struct pcmcia_device structure can be used to point to
-   a device-specific private data structure, like this.
-*/
 static unsigned int ray_mem_speed = 500;
 
 /* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
@@ -290,14 +282,6 @@ static const struct net_device_ops ray_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/*=============================================================================
-    ray_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-=============================================================================*/
 static int ray_probe(struct pcmcia_device *p_dev)
 {
        ray_dev_t *local;
@@ -318,9 +302,8 @@ static int ray_probe(struct pcmcia_device *p_dev)
        p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
        /* General socket configuration */
-       p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
-       p_dev->conf.ConfigIndex = 1;
+       p_dev->config_flags |= CONF_ENABLE_IRQ;
+       p_dev->config_index = 1;
 
        p_dev->priv = dev;
 
@@ -353,12 +336,6 @@ fail_alloc_dev:
        return -ENOMEM;
 } /* ray_attach */
 
-/*=============================================================================
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-=============================================================================*/
 static void ray_detach(struct pcmcia_device *link)
 {
        struct net_device *dev;
@@ -381,17 +358,11 @@ static void ray_detach(struct pcmcia_device *link)
        dev_dbg(&link->dev, "ray_cs ray_detach ending\n");
 } /* ray_detach */
 
-/*=============================================================================
-    ray_config() is run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-=============================================================================*/
 #define MAX_TUPLE_SIZE 128
 static int ray_config(struct pcmcia_device *link)
 {
        int ret = 0;
        int i;
-       win_req_t req;
        struct net_device *dev = (struct net_device *)link->priv;
        ray_dev_t *local = netdev_priv(dev);
 
@@ -412,54 +383,50 @@ static int ray_config(struct pcmcia_device *link)
                goto failed;
        dev->irq = link->irq;
 
-       /* This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
 /*** Set up 32k window for shared memory (transmit and control) ************/
-       req.Attributes =
-           WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-       req.Base = 0;
-       req.Size = 0x8000;
-       req.AccessSpeed = ray_mem_speed;
-       ret = pcmcia_request_window(link, &req, &link->win);
+       link->resource[2]->flags |= WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+       link->resource[2]->start = 0;
+       link->resource[2]->end = 0x8000;
+       ret = pcmcia_request_window(link, link->resource[2], ray_mem_speed);
        if (ret)
                goto failed;
-       ret = pcmcia_map_mem_page(link, link->win, 0);
+       ret = pcmcia_map_mem_page(link, link->resource[2], 0);
        if (ret)
                goto failed;
-       local->sram = ioremap(req.Base, req.Size);
+       local->sram = ioremap(link->resource[2]->start,
+                       resource_size(link->resource[2]));
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
-       req.Attributes =
+       link->resource[3]->flags |=
            WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-       req.Base = 0;
-       req.Size = 0x4000;
-       req.AccessSpeed = ray_mem_speed;
-       ret = pcmcia_request_window(link, &req, &local->rmem_handle);
+       link->resource[3]->start = 0;
+       link->resource[3]->end = 0x4000;
+       ret = pcmcia_request_window(link, link->resource[3], ray_mem_speed);
        if (ret)
                goto failed;
-       ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000);
+       ret = pcmcia_map_mem_page(link, link->resource[3], 0x8000);
        if (ret)
                goto failed;
-       local->rmem = ioremap(req.Base, req.Size);
+       local->rmem = ioremap(link->resource[3]->start,
+                       resource_size(link->resource[3]));
 
 /*** Set up window for attribute memory ***********************************/
-       req.Attributes =
+       link->resource[4]->flags |=
            WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
-       req.Base = 0;
-       req.Size = 0x1000;
-       req.AccessSpeed = ray_mem_speed;
-       ret = pcmcia_request_window(link, &req, &local->amem_handle);
+       link->resource[4]->start = 0;
+       link->resource[4]->end = 0x1000;
+       ret = pcmcia_request_window(link, link->resource[4], ray_mem_speed);
        if (ret)
                goto failed;
-       ret = pcmcia_map_mem_page(link, local->amem_handle, 0);
+       ret = pcmcia_map_mem_page(link, link->resource[4], 0);
        if (ret)
                goto failed;
-       local->amem = ioremap(req.Base, req.Size);
+       local->amem = ioremap(link->resource[4]->start,
+                       resource_size(link->resource[4]));
 
        dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
        dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
@@ -775,11 +742,7 @@ static void join_net(u_long data)
        local->card_status = CARD_DOING_ACQ;
 }
 
-/*============================================================================
-    After a card is removed, ray_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-=============================================================================*/
+
 static void ray_release(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
@@ -2802,6 +2765,7 @@ static ssize_t ray_cs_essid_proc_write(struct file *file,
 static const struct file_operations ray_cs_essid_proc_fops = {
        .owner          = THIS_MODULE,
        .write          = ray_cs_essid_proc_write,
+       .llseek         = noop_llseek,
 };
 
 static ssize_t int_proc_write(struct file *file, const char __user *buffer,
@@ -2835,6 +2799,7 @@ static ssize_t int_proc_write(struct file *file, const char __user *buffer,
 static const struct file_operations int_proc_fops = {
        .owner          = THIS_MODULE,
        .write          = int_proc_write,
+       .llseek         = noop_llseek,
 };
 #endif
 
@@ -2847,9 +2812,7 @@ MODULE_DEVICE_TABLE(pcmcia, ray_ids);
 
 static struct pcmcia_driver ray_driver = {
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "ray_cs",
-               },
+       .name = "ray_cs",
        .probe = ray_probe,
        .remove = ray_detach,
        .id_table = ray_ids,
index 9f01ddb197485b801e183743999ca822b7a53c7b..e79848fbcca1e1e5397410745589703e3cad903a 100644 (file)
@@ -25,8 +25,6 @@ struct beacon_rx {
 typedef struct ray_dev_t {
     int card_status;
     int authentication_state;
-    window_handle_t amem_handle;   /* handle to window for attribute memory  */
-    window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
     void __iomem *sram;            /* pointer to beginning of shared RAM     */
     void __iomem *amem;            /* pointer to attribute mem window        */
     void __iomem *rmem;            /* pointer to receive buffer window       */
index b0498e7e7aae95a733eef24bbb139ee0486c690b..cea81e4c5c82d7b40c9a6987f36b749b9c69ecc7 100644 (file)
@@ -315,6 +315,7 @@ static const struct file_operations rt2x00debug_fop_queue_dump = {
        .poll           = rt2x00debug_poll_queue_dump,
        .open           = rt2x00debug_open_queue_dump,
        .release        = rt2x00debug_release_queue_dump,
+       .llseek         = default_llseek,
 };
 
 static ssize_t rt2x00debug_read_queue_stats(struct file *file,
@@ -371,6 +372,7 @@ static const struct file_operations rt2x00debug_fop_queue_stats = {
        .read           = rt2x00debug_read_queue_stats,
        .open           = rt2x00debug_file_open,
        .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
 };
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
@@ -423,6 +425,7 @@ static const struct file_operations rt2x00debug_fop_crypto_stats = {
        .read           = rt2x00debug_read_crypto_stats,
        .open           = rt2x00debug_file_open,
        .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
 };
 #endif
 
@@ -509,6 +512,7 @@ static const struct file_operations rt2x00debug_fop_##__name = {\
        .write          = rt2x00debug_write_##__name,           \
        .open           = rt2x00debug_file_open,                \
        .release        = rt2x00debug_file_release,             \
+       .llseek         = generic_file_llseek,                  \
 };
 
 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
@@ -542,6 +546,7 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
        .read           = rt2x00debug_read_dev_flags,
        .open           = rt2x00debug_file_open,
        .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
 };
 
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
index b50c39aaec0522e63c89b30ad6cc6433747b6853..30107ce78dfb6cc8613c83c5ca525a5e8bf42314 100644 (file)
@@ -445,7 +445,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
                                             &priv->rx_ring_dma);
 
        if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
-               wiphy_err(dev->wiphy, "cannot allocate rx ring\n");
+               wiphy_err(dev->wiphy, "Cannot allocate RX ring\n");
                return -ENOMEM;
        }
 
@@ -502,7 +502,7 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,
 
        ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
        if (!ring || (unsigned long)ring & 0xFF) {
-               wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n",
+               wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n",
                          prio);
                return -ENOMEM;
        }
@@ -568,7 +568,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
        ret = request_irq(priv->pdev->irq, rtl8180_interrupt,
                          IRQF_SHARED, KBUILD_MODNAME, dev);
        if (ret) {
-               wiphy_err(dev->wiphy, "failed to register irq handler\n");
+               wiphy_err(dev->wiphy, "failed to register IRQ handler\n");
                goto err_free_rings;
        }
 
index 5738a55c1b06b4c9bd7a8c30323266b0af2151b4..98e0351c1dd6923214b17919161793c873d89967 100644 (file)
@@ -573,7 +573,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
        } while (--i);
 
        if (!i) {
-               wiphy_err(dev->wiphy, "reset timeout!\n");
+               wiphy_err(dev->wiphy, "Reset timeout!\n");
                return -ETIMEDOUT;
        }
 
@@ -1526,7 +1526,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
        mutex_init(&priv->conf_mutex);
        skb_queue_head_init(&priv->b_tx_status.queue);
 
-       wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n",
+       wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
                   mac_addr, chip_name, priv->asic_rev, priv->rf->name,
                   priv->rfkill_mask);
 
index fd96f9112322439f7bf3f72716f943459a9c347c..97eebdcf7eb9f432729c18a3ad090fe8934e0171 100644 (file)
@@ -366,7 +366,7 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
                rtl8225_write(dev, 0x02, 0x044d);
                msleep(100);
                if (!(rtl8225_read(dev, 6) & (1 << 7)))
-                       wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+                       wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
                                   rtl8225_read(dev, 6));
        }
 
@@ -735,7 +735,7 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
                rtl8225_write(dev, 0x02, 0x044D);
                msleep(100);
                if (!(rtl8225_read(dev, 6) & (1 << 7)))
-                       wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+                       wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
                                   rtl8225_read(dev, 6));
        }
 
index 5e4465ac08fadbbb435db0ad890edc4d610e2ae6..fa620a5e53036a148ad0a99369b4a4dc3b8cc8de 100644 (file)
@@ -50,6 +50,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
        .open = wl1251_open_file_generic,                               \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_ADD(name, parent)                                      \
@@ -86,6 +87,7 @@ static ssize_t sub## _ ##name## _read(struct file *file,              \
 static const struct file_operations sub## _ ##name## _ops = {          \
        .read = sub## _ ##name## _read,                                 \
        .open = wl1251_open_file_generic,                               \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_FWSTATS_ADD(sub, name)                         \
@@ -236,6 +238,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
 static const struct file_operations tx_queue_len_ops = {
        .read = tx_queue_len_read,
        .open = wl1251_open_file_generic,
+       .llseek = generic_file_llseek,
 };
 
 static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
@@ -257,6 +260,7 @@ static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
 static const struct file_operations tx_queue_status_ops = {
        .read = tx_queue_status_read,
        .open = wl1251_open_file_generic,
+       .llseek = generic_file_llseek,
 };
 
 static void wl1251_debugfs_delete_files(struct wl1251 *wl)
index c239ef4d0b8dedf5932eac4c041073e05a90e782..66c2b90ddfd461df7471aef34e7c3335c84a360b 100644 (file)
@@ -51,6 +51,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
        .open = wl1271_open_file_generic,                               \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_ADD(name, parent)                                      \
@@ -87,6 +88,7 @@ static ssize_t sub## _ ##name## _read(struct file *file,              \
 static const struct file_operations sub## _ ##name## _ops = {          \
        .read = sub## _ ##name## _read,                                 \
        .open = wl1271_open_file_generic,                               \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_FWSTATS_ADD(sub, name)                         \
@@ -237,6 +239,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
 static const struct file_operations tx_queue_len_ops = {
        .read = tx_queue_len_read,
        .open = wl1271_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
@@ -291,7 +294,8 @@ out:
 static const struct file_operations gpio_power_ops = {
        .read = gpio_power_read,
        .write = gpio_power_write,
-       .open = wl1271_open_file_generic
+       .open = wl1271_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static void wl1271_debugfs_delete_files(struct wl1271 *wl)
index a1cc2d498a1c01bd19b0174d1497d8bd0c0c8a8b..ca3f8961fa27fd07a6d31f44740b77467fe5df93 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 #define WL3501_RESUME  0
 #define WL3501_SUSPEND 1
 
-/*
- * The event() function is this driver's Card Services event handler.  It will
- * be called by Card Services when an appropriate card status event is
- * received. The config() and release() entry points are used to configure or
- * release a socket, in response to card insertion and ejection events.  They
- * are invoked from the wl24 event handler.
- */
 static int wl3501_config(struct pcmcia_device *link);
 static void wl3501_release(struct pcmcia_device *link);
 
@@ -1869,15 +1861,6 @@ static const struct net_device_ops wl3501_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-/**
- * wl3501_attach - creates an "instance" of the driver
- *
- * Creates an "instance" of the driver, allocating local data structures for
- * one device.  The device is registered with Card Services.
- *
- * The dev_link structure is initialized, but we don't actually configure the
- * card at this point -- we wait until we receive a card insertion event.
- */
 static int wl3501_probe(struct pcmcia_device *p_dev)
 {
        struct net_device *dev;
@@ -1888,9 +1871,8 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
        p_dev->resource[0]->flags       = IO_DATA_PATH_WIDTH_8;
 
        /* General socket configuration */
-       p_dev->conf.Attributes  = CONF_ENABLE_IRQ;
-       p_dev->conf.IntType     = INT_MEMORY_AND_IO;
-       p_dev->conf.ConfigIndex = 1;
+       p_dev->config_flags     = CONF_ENABLE_IRQ;
+       p_dev->config_index     = 1;
 
        dev = alloc_etherdev(sizeof(struct wl3501_card));
        if (!dev)
@@ -1914,14 +1896,6 @@ out_link:
        return -ENOMEM;
 }
 
-/**
- * wl3501_config - configure the PCMCIA socket and make eth device available
- * @link - FILL_IN
- *
- * wl3501_config() is scheduled to run after a CARD_INSERTION event is
- * received, to configure the PCMCIA socket, and to make the ethernet device
- * available to the system.
- */
 static int wl3501_config(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
@@ -1952,10 +1926,7 @@ static int wl3501_config(struct pcmcia_device *link)
        if (ret)
                goto failed;
 
-       /* This actually configures the PCMCIA socket -- setting up the I/O
-        * windows and the interrupt mapping.  */
-
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -2010,14 +1981,6 @@ failed:
        return -ENODEV;
 }
 
-/**
- * wl3501_release - unregister the net, release PCMCIA configuration
- * @arg - link
- *
- * After a card is removed, wl3501_release() will unregister the net device,
- * and release the PCMCIA configuration.  If the device is still open, this
- * will be postponed until it is closed.
- */
 static void wl3501_release(struct pcmcia_device *link)
 {
        pcmcia_disable_device(link);
@@ -2056,9 +2019,7 @@ MODULE_DEVICE_TABLE(pcmcia, wl3501_ids);
 
 static struct pcmcia_driver wl3501_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "wl3501_cs",
-       },
+       .name           = "wl3501_cs",
        .probe          = wl3501_probe,
        .remove         = wl3501_detach,
        .id_table       = wl3501_ids,
index a9352b2c7ac430d4e4aafac3d65a1b46005ea505..b7e755f4178ad885332ccaaeeb5eda492e6dfcfd 100644 (file)
@@ -141,16 +141,6 @@ static struct notifier_block module_load_nb = {
        .notifier_call = module_load_notify,
 };
 
-
-static void end_sync(void)
-{
-       end_cpu_work();
-       /* make sure we don't leak task structs */
-       process_task_mortuary();
-       process_task_mortuary();
-}
-
-
 int sync_start(void)
 {
        int err;
@@ -158,7 +148,7 @@ int sync_start(void)
        if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
                return -ENOMEM;
 
-       start_cpu_work();
+       mutex_lock(&buffer_mutex);
 
        err = task_handoff_register(&task_free_nb);
        if (err)
@@ -173,7 +163,10 @@ int sync_start(void)
        if (err)
                goto out4;
 
+       start_cpu_work();
+
 out:
+       mutex_unlock(&buffer_mutex);
        return err;
 out4:
        profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
@@ -182,7 +175,6 @@ out3:
 out2:
        task_handoff_unregister(&task_free_nb);
 out1:
-       end_sync();
        free_cpumask_var(marked_cpus);
        goto out;
 }
@@ -190,11 +182,20 @@ out1:
 
 void sync_stop(void)
 {
+       /* flush buffers */
+       mutex_lock(&buffer_mutex);
+       end_cpu_work();
        unregister_module_notifier(&module_load_nb);
        profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
        profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
        task_handoff_unregister(&task_free_nb);
-       end_sync();
+       mutex_unlock(&buffer_mutex);
+       flush_scheduled_work();
+
+       /* make sure we don't leak task structs */
+       process_task_mortuary();
+       process_task_mortuary();
+
        free_cpumask_var(marked_cpus);
 }
 
index 219f79e2210a3fcd561b94456c4960a0a1fbacd9..f179ac2ea80149423034d66a90b1e81251c5069b 100644 (file)
@@ -120,8 +120,6 @@ void end_cpu_work(void)
 
                cancel_delayed_work(&b->work);
        }
-
-       flush_scheduled_work();
 }
 
 /*
index b336cd9ee7a114c54d6b7b85d48cacc6f3ed1a6d..f9bda64fcd1b62771880d5d823b53f797cb9c7f0 100644 (file)
@@ -225,26 +225,17 @@ post_sync:
        mutex_unlock(&start_mutex);
 }
 
-int oprofile_set_backtrace(unsigned long val)
+int oprofile_set_ulong(unsigned long *addr, unsigned long val)
 {
-       int err = 0;
+       int err = -EBUSY;
 
        mutex_lock(&start_mutex);
-
-       if (oprofile_started) {
-               err = -EBUSY;
-               goto out;
-       }
-
-       if (!oprofile_ops.backtrace) {
-               err = -EINVAL;
-               goto out;
+       if (!oprofile_started) {
+               *addr = val;
+               err = 0;
        }
-
-       oprofile_backtrace_depth = val;
-
-out:
        mutex_unlock(&start_mutex);
+
        return err;
 }
 
@@ -257,16 +248,9 @@ static int __init oprofile_init(void)
                printk(KERN_INFO "oprofile: using timer interrupt.\n");
                err = oprofile_timer_init(&oprofile_ops);
                if (err)
-                       goto out_arch;
+                       return err;
        }
-       err = oprofilefs_register();
-       if (err)
-               goto out_arch;
-       return 0;
-
-out_arch:
-       oprofile_arch_exit();
-       return err;
+       return oprofilefs_register();
 }
 
 
index 47e12cb4ee8ba7464e4b0c7ef955be71b1caa201..177b73de5e5f158cbb31fe27f8e31b9363c3a255 100644 (file)
@@ -37,7 +37,7 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root);
 int oprofile_timer_init(struct oprofile_operations *ops);
 void oprofile_timer_exit(void);
 
-int oprofile_set_backtrace(unsigned long depth);
+int oprofile_set_ulong(unsigned long *addr, unsigned long val);
 int oprofile_set_timeout(unsigned long time);
 
 #endif /* OPROF_H */
index bbd7516e0869461c141659004580d509ec5e97a5..89f63456646fa4c67b6ee74f7c657917be05a425 100644 (file)
@@ -59,6 +59,7 @@ static ssize_t timeout_write(struct file *file, char const __user *buf,
 static const struct file_operations timeout_fops = {
        .read           = timeout_read,
        .write          = timeout_write,
+       .llseek         = default_llseek,
 };
 
 #endif
@@ -79,21 +80,25 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou
        if (*offset)
                return -EINVAL;
 
+       if (!oprofile_ops.backtrace)
+               return -EINVAL;
+
        retval = oprofilefs_ulong_from_user(&val, buf, count);
        if (retval)
                return retval;
 
-       retval = oprofile_set_backtrace(val);
-
+       retval = oprofile_set_ulong(&oprofile_backtrace_depth, val);
        if (retval)
                return retval;
+
        return count;
 }
 
 
 static const struct file_operations depth_fops = {
        .read           = depth_read,
-       .write          = depth_write
+       .write          = depth_write,
+       .llseek         = default_llseek,
 };
 
 
@@ -105,6 +110,7 @@ static ssize_t pointer_size_read(struct file *file, char __user *buf, size_t cou
 
 static const struct file_operations pointer_size_fops = {
        .read           = pointer_size_read,
+       .llseek         = default_llseek,
 };
 
 
@@ -116,6 +122,7 @@ static ssize_t cpu_type_read(struct file *file, char __user *buf, size_t count,
 
 static const struct file_operations cpu_type_fops = {
        .read           = cpu_type_read,
+       .llseek         = default_llseek,
 };
 
 
@@ -151,6 +158,7 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co
 static const struct file_operations enable_fops = {
        .read           = enable_read,
        .write          = enable_write,
+       .llseek         = default_llseek,
 };
 
 
@@ -163,6 +171,7 @@ static ssize_t dump_write(struct file *file, char const __user *buf, size_t coun
 
 static const struct file_operations dump_fops = {
        .write          = dump_write,
+       .llseek         = noop_llseek,
 };
 
 void oprofile_create_files(struct super_block *sb, struct dentry *root)
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
new file mode 100644 (file)
index 0000000..9046f7b
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2010 ARM Ltd.
+ *
+ * Perf-events backend for OProfile.
+ */
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/oprofile.h>
+#include <linux/slab.h>
+
+/*
+ * Per performance monitor configuration as set via oprofilefs.
+ */
+struct op_counter_config {
+       unsigned long count;
+       unsigned long enabled;
+       unsigned long event;
+       unsigned long unit_mask;
+       unsigned long kernel;
+       unsigned long user;
+       struct perf_event_attr attr;
+};
+
+static int oprofile_perf_enabled;
+static DEFINE_MUTEX(oprofile_perf_mutex);
+
+static struct op_counter_config *counter_config;
+static struct perf_event **perf_events[nr_cpumask_bits];
+static int num_counters;
+
+/*
+ * Overflow callback for oprofile.
+ */
+static void op_overflow_handler(struct perf_event *event, int unused,
+                       struct perf_sample_data *data, struct pt_regs *regs)
+{
+       int id;
+       u32 cpu = smp_processor_id();
+
+       for (id = 0; id < num_counters; ++id)
+               if (perf_events[cpu][id] == event)
+                       break;
+
+       if (id != num_counters)
+               oprofile_add_sample(regs, id);
+       else
+               pr_warning("oprofile: ignoring spurious overflow "
+                               "on cpu %u\n", cpu);
+}
+
+/*
+ * Called by oprofile_perf_setup to create perf attributes to mirror the oprofile
+ * settings in counter_config. Attributes are created as `pinned' events and
+ * so are permanently scheduled on the PMU.
+ */
+static void op_perf_setup(void)
+{
+       int i;
+       u32 size = sizeof(struct perf_event_attr);
+       struct perf_event_attr *attr;
+
+       for (i = 0; i < num_counters; ++i) {
+               attr = &counter_config[i].attr;
+               memset(attr, 0, size);
+               attr->type              = PERF_TYPE_RAW;
+               attr->size              = size;
+               attr->config            = counter_config[i].event;
+               attr->sample_period     = counter_config[i].count;
+               attr->pinned            = 1;
+       }
+}
+
+static int op_create_counter(int cpu, int event)
+{
+       struct perf_event *pevent;
+
+       if (!counter_config[event].enabled || perf_events[cpu][event])
+               return 0;
+
+       pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
+                                                 cpu, NULL,
+                                                 op_overflow_handler);
+
+       if (IS_ERR(pevent))
+               return PTR_ERR(pevent);
+
+       if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
+               perf_event_release_kernel(pevent);
+               pr_warning("oprofile: failed to enable event %d "
+                               "on CPU %d\n", event, cpu);
+               return -EBUSY;
+       }
+
+       perf_events[cpu][event] = pevent;
+
+       return 0;
+}
+
+static void op_destroy_counter(int cpu, int event)
+{
+       struct perf_event *pevent = perf_events[cpu][event];
+
+       if (pevent) {
+               perf_event_release_kernel(pevent);
+               perf_events[cpu][event] = NULL;
+       }
+}
+
+/*
+ * Called by oprofile_perf_start to create active perf events based on the
+ * perviously configured attributes.
+ */
+static int op_perf_start(void)
+{
+       int cpu, event, ret = 0;
+
+       for_each_online_cpu(cpu) {
+               for (event = 0; event < num_counters; ++event) {
+                       ret = op_create_counter(cpu, event);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * Called by oprofile_perf_stop at the end of a profiling run.
+ */
+static void op_perf_stop(void)
+{
+       int cpu, event;
+
+       for_each_online_cpu(cpu)
+               for (event = 0; event < num_counters; ++event)
+                       op_destroy_counter(cpu, event);
+}
+
+static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_counters; i++) {
+               struct dentry *dir;
+               char buf[4];
+
+               snprintf(buf, sizeof buf, "%d", i);
+               dir = oprofilefs_mkdir(sb, root, buf);
+               oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
+               oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
+               oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
+               oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
+               oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
+               oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+       }
+
+       return 0;
+}
+
+static int oprofile_perf_setup(void)
+{
+       spin_lock(&oprofilefs_lock);
+       op_perf_setup();
+       spin_unlock(&oprofilefs_lock);
+       return 0;
+}
+
+static int oprofile_perf_start(void)
+{
+       int ret = -EBUSY;
+
+       mutex_lock(&oprofile_perf_mutex);
+       if (!oprofile_perf_enabled) {
+               ret = 0;
+               op_perf_start();
+               oprofile_perf_enabled = 1;
+       }
+       mutex_unlock(&oprofile_perf_mutex);
+       return ret;
+}
+
+static void oprofile_perf_stop(void)
+{
+       mutex_lock(&oprofile_perf_mutex);
+       if (oprofile_perf_enabled)
+               op_perf_stop();
+       oprofile_perf_enabled = 0;
+       mutex_unlock(&oprofile_perf_mutex);
+}
+
+#ifdef CONFIG_PM
+
+static int oprofile_perf_suspend(struct platform_device *dev, pm_message_t state)
+{
+       mutex_lock(&oprofile_perf_mutex);
+       if (oprofile_perf_enabled)
+               op_perf_stop();
+       mutex_unlock(&oprofile_perf_mutex);
+       return 0;
+}
+
+static int oprofile_perf_resume(struct platform_device *dev)
+{
+       mutex_lock(&oprofile_perf_mutex);
+       if (oprofile_perf_enabled && op_perf_start())
+               oprofile_perf_enabled = 0;
+       mutex_unlock(&oprofile_perf_mutex);
+       return 0;
+}
+
+static struct platform_driver oprofile_driver = {
+       .driver         = {
+               .name           = "oprofile-perf",
+       },
+       .resume         = oprofile_perf_resume,
+       .suspend        = oprofile_perf_suspend,
+};
+
+static struct platform_device *oprofile_pdev;
+
+static int __init init_driverfs(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&oprofile_driver);
+       if (ret)
+               return ret;
+
+       oprofile_pdev = platform_device_register_simple(
+                               oprofile_driver.driver.name, 0, NULL, 0);
+       if (IS_ERR(oprofile_pdev)) {
+               ret = PTR_ERR(oprofile_pdev);
+               platform_driver_unregister(&oprofile_driver);
+       }
+
+       return ret;
+}
+
+static void exit_driverfs(void)
+{
+       platform_device_unregister(oprofile_pdev);
+       platform_driver_unregister(&oprofile_driver);
+}
+
+#else
+
+static inline int  init_driverfs(void) { return 0; }
+static inline void exit_driverfs(void) { }
+
+#endif /* CONFIG_PM */
+
+void oprofile_perf_exit(void)
+{
+       int cpu, id;
+       struct perf_event *event;
+
+       for_each_possible_cpu(cpu) {
+               for (id = 0; id < num_counters; ++id) {
+                       event = perf_events[cpu][id];
+                       if (event)
+                               perf_event_release_kernel(event);
+               }
+
+               kfree(perf_events[cpu]);
+       }
+
+       kfree(counter_config);
+       exit_driverfs();
+}
+
+int __init oprofile_perf_init(struct oprofile_operations *ops)
+{
+       int cpu, ret = 0;
+
+       ret = init_driverfs();
+       if (ret)
+               return ret;
+
+       memset(&perf_events, 0, sizeof(perf_events));
+
+       num_counters = perf_num_counters();
+       if (num_counters <= 0) {
+               pr_info("oprofile: no performance counters\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       counter_config = kcalloc(num_counters,
+                       sizeof(struct op_counter_config), GFP_KERNEL);
+
+       if (!counter_config) {
+               pr_info("oprofile: failed to allocate %d "
+                               "counters\n", num_counters);
+               ret = -ENOMEM;
+               num_counters = 0;
+               goto out;
+       }
+
+       for_each_possible_cpu(cpu) {
+               perf_events[cpu] = kcalloc(num_counters,
+                               sizeof(struct perf_event *), GFP_KERNEL);
+               if (!perf_events[cpu]) {
+                       pr_info("oprofile: failed to allocate %d perf events "
+                                       "for cpu %d\n", num_counters, cpu);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       ops->create_files       = oprofile_perf_create_files;
+       ops->setup              = oprofile_perf_setup;
+       ops->start              = oprofile_perf_start;
+       ops->stop               = oprofile_perf_stop;
+       ops->shutdown           = oprofile_perf_stop;
+       ops->cpu_type           = op_name_from_perf_id();
+
+       if (!ops->cpu_type)
+               ret = -ENODEV;
+       else
+               pr_info("oprofile: using %s\n", ops->cpu_type);
+
+out:
+       if (ret)
+               oprofile_perf_exit();
+
+       return ret;
+}
index 2766a6d3c2e9c8fe2f7ab2a2d1f3457275693f80..95f711b251adf33a80dd69eab2a6b792a11313ac 100644 (file)
@@ -91,16 +91,20 @@ static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count
 
 static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset)
 {
-       unsigned long *value = file->private_data;
+       unsigned long value;
        int retval;
 
        if (*offset)
                return -EINVAL;
 
-       retval = oprofilefs_ulong_from_user(value, buf, count);
+       retval = oprofilefs_ulong_from_user(&value, buf, count);
+       if (retval)
+               return retval;
 
+       retval = oprofile_set_ulong(file->private_data, value);
        if (retval)
                return retval;
+
        return count;
 }
 
@@ -117,59 +121,52 @@ static const struct file_operations ulong_fops = {
        .read           = ulong_read_file,
        .write          = ulong_write_file,
        .open           = default_open,
+       .llseek         = default_llseek,
 };
 
 
 static const struct file_operations ulong_ro_fops = {
        .read           = ulong_read_file,
        .open           = default_open,
+       .llseek         = default_llseek,
 };
 
 
-static struct dentry *__oprofilefs_create_file(struct super_block *sb,
+static int __oprofilefs_create_file(struct super_block *sb,
        struct dentry *root, char const *name, const struct file_operations *fops,
-       int perm)
+       int perm, void *priv)
 {
        struct dentry *dentry;
        struct inode *inode;
 
        dentry = d_alloc_name(root, name);
        if (!dentry)
-               return NULL;
+               return -ENOMEM;
        inode = oprofilefs_get_inode(sb, S_IFREG | perm);
        if (!inode) {
                dput(dentry);
-               return NULL;
+               return -ENOMEM;
        }
        inode->i_fop = fops;
        d_add(dentry, inode);
-       return dentry;
+       dentry->d_inode->i_private = priv;
+       return 0;
 }
 
 
 int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root,
        char const *name, unsigned long *val)
 {
-       struct dentry *d = __oprofilefs_create_file(sb, root, name,
-                                                    &ulong_fops, 0644);
-       if (!d)
-               return -EFAULT;
-
-       d->d_inode->i_private = val;
-       return 0;
+       return __oprofilefs_create_file(sb, root, name,
+                                       &ulong_fops, 0644, val);
 }
 
 
 int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root,
        char const *name, unsigned long *val)
 {
-       struct dentry *d = __oprofilefs_create_file(sb, root, name,
-                                                    &ulong_ro_fops, 0444);
-       if (!d)
-               return -EFAULT;
-
-       d->d_inode->i_private = val;
-       return 0;
+       return __oprofilefs_create_file(sb, root, name,
+                                       &ulong_ro_fops, 0444, val);
 }
 
 
@@ -183,37 +180,29 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun
 static const struct file_operations atomic_ro_fops = {
        .read           = atomic_read_file,
        .open           = default_open,
+       .llseek         = default_llseek,
 };
 
 
 int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
        char const *name, atomic_t *val)
 {
-       struct dentry *d = __oprofilefs_create_file(sb, root, name,
-                                                    &atomic_ro_fops, 0444);
-       if (!d)
-               return -EFAULT;
-
-       d->d_inode->i_private = val;
-       return 0;
+       return __oprofilefs_create_file(sb, root, name,
+                                       &atomic_ro_fops, 0444, val);
 }
 
 
 int oprofilefs_create_file(struct super_block *sb, struct dentry *root,
        char const *name, const struct file_operations *fops)
 {
-       if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
-               return -EFAULT;
-       return 0;
+       return __oprofilefs_create_file(sb, root, name, fops, 0644, NULL);
 }
 
 
 int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root,
        char const *name, const struct file_operations *fops, int perm)
 {
-       if (!__oprofilefs_create_file(sb, root, name, fops, perm))
-               return -EFAULT;
-       return 0;
+       return __oprofilefs_create_file(sb, root, name, fops, perm, NULL);
 }
 
 
index 23e50f4a27c5b8719ac745223b2455d39bea0ad6..787ebdeae31032b853e6e2fce73750f4bf5e4e91 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -81,14 +80,6 @@ static void parport_detach(struct pcmcia_device *p_dev);
 static int parport_config(struct pcmcia_device *link);
 static void parport_cs_release(struct pcmcia_device *);
 
-/*======================================================================
-
-    parport_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int parport_probe(struct pcmcia_device *link)
 {
     parport_info_t *info;
@@ -101,23 +92,11 @@ static int parport_probe(struct pcmcia_device *link)
     link->priv = info;
     info->p_dev = link;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return parport_config(link);
 } /* parport_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void parport_detach(struct pcmcia_device *link)
 {
     dev_dbg(&link->dev, "parport_detach\n");
@@ -127,36 +106,14 @@ static void parport_detach(struct pcmcia_device *link)
     kfree(link->priv);
 } /* parport_detach */
 
-/*======================================================================
-
-    parport_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    parport device available to the system.
-
-======================================================================*/
-
-static int parport_config_check(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               if (epp_mode)
-                       p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin == 2) {
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               if (pcmcia_request_io(p_dev) != 0)
-                       return -ENODEV;
-               return 0;
-       }
-       return -ENODEV;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int parport_config(struct pcmcia_device *link)
@@ -167,13 +124,16 @@ static int parport_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "parport_config\n");
 
+    if (epp_mode)
+           link->config_index |= FORCE_EPP_MODE;
+
     ret = pcmcia_loop_config(link, parport_config_check, NULL);
     if (ret)
            goto failed;
 
     if (!link->irq)
            goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -202,14 +162,6 @@ failed:
     return -ENODEV;
 } /* parport_config */
 
-/*======================================================================
-
-    After a card is removed, parport_cs_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void parport_cs_release(struct pcmcia_device *link)
 {
        parport_info_t *info = link->priv;
@@ -236,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, parport_ids);
 
 static struct pcmcia_driver parport_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "parport_cs",
-       },
+       .name           = "parport_cs",
        .probe          = parport_probe,
        .remove         = parport_detach,
        .id_table       = parport_ids,
index dffa5d4fb2986f89b6ab26882bd9de63df81e2e1..a2d9d1e59260eab17097e0a12f16908eed26c552 100644 (file)
@@ -306,7 +306,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        spin_lock_init(&tmp->pardevice_lock);
        tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
        tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-       init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
+       sema_init(&tmp->ieee1284.irq, 0);
        tmp->spintime = parport_default_spintime;
        atomic_set (&tmp->ref_count, 1);
        INIT_LIST_HEAD(&tmp->full_list);
index 0a19708074c2b5265379ec816e777771823ab861..0157708d474da57ad0532a3bb8bbbd90f0204aeb 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/tboot.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <asm/iommu_table.h>
 
 #define PREFIX "DMAR: "
 
@@ -687,7 +688,7 @@ failed:
        return 0;
 }
 
-void __init detect_intel_iommu(void)
+int __init detect_intel_iommu(void)
 {
        int ret;
 
@@ -723,6 +724,8 @@ void __init detect_intel_iommu(void)
        }
        early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
        dmar_tbl = NULL;
+
+       return ret ? 1 : -ENODEV;
 }
 
 
@@ -1221,9 +1224,9 @@ const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
        }
 }
 
-void dmar_msi_unmask(unsigned int irq)
+void dmar_msi_unmask(struct irq_data *data)
 {
-       struct intel_iommu *iommu = get_irq_data(irq);
+       struct intel_iommu *iommu = irq_data_get_irq_data(data);
        unsigned long flag;
 
        /* unmask it */
@@ -1234,10 +1237,10 @@ void dmar_msi_unmask(unsigned int irq)
        spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
-void dmar_msi_mask(unsigned int irq)
+void dmar_msi_mask(struct irq_data *data)
 {
        unsigned long flag;
-       struct intel_iommu *iommu = get_irq_data(irq);
+       struct intel_iommu *iommu = irq_data_get_irq_data(data);
 
        /* mask it */
        spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1455,3 +1458,4 @@ int __init dmar_ir_support(void)
                return 0;
        return dmar->flags & 0x1;
 }
+IOMMU_INIT_POST(detect_intel_iommu);
index 45fcc1e96df9ac08718696e7ea8a8f487f33072f..3bc72d18b121d3cff5ebcb7c8c05a5a06cdff78a 100644 (file)
@@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
        acpi_handle chandle, handle;
        struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
-                 OSC_SHPC_NATIVE_HP_CONTROL |
-                 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+       flags &= OSC_SHPC_NATIVE_HP_CONTROL;
        if (!flags) {
                err("Invalid flags %u specified!\n", flags);
                return -EINVAL;
@@ -360,7 +358,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
                acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
                dbg("Trying to get hotplug control for %s\n",
                                (char *)string.pointer);
-               status = acpi_pci_osc_control_set(handle, flags);
+               status = acpi_pci_osc_control_set(handle, &flags, flags);
                if (ACPI_SUCCESS(status))
                        goto got_one;
                if (status == AE_SUPPORT)
index 56215322930ad143c5d0d3adba42823d70f77c12..4cb30447a4860cf684155f18c79faad88f3989c6 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include "cpqphp.h"
 
+static DEFINE_MUTEX(cpqphp_mutex);
 static int show_ctrl (struct controller *ctrl, char *buf)
 {
        char *out = buf;
@@ -147,7 +148,7 @@ static int open(struct inode *inode, struct file *file)
        struct ctrl_dbg *dbg;
        int retval = -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&cpqphp_mutex);
        dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
        if (!dbg)
                goto exit;
@@ -160,7 +161,7 @@ static int open(struct inode *inode, struct file *file)
        file->private_data = dbg;
        retval = 0;
 exit:
-       unlock_kernel();
+       mutex_unlock(&cpqphp_mutex);
        return retval;
 }
 
@@ -169,7 +170,7 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
        struct ctrl_dbg *dbg;
        loff_t new = -1;
 
-       lock_kernel();
+       mutex_lock(&cpqphp_mutex);
        dbg = file->private_data;
 
        switch (whence) {
@@ -181,10 +182,10 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
                break;
        }
        if (new < 0 || new > dbg->size) {
-               unlock_kernel();
+               mutex_unlock(&cpqphp_mutex);
                return -EINVAL;
        }
-       unlock_kernel();
+       mutex_unlock(&cpqphp_mutex);
        return (file->f_pos = new);
 }
 
index 4ed76b47b6dcbd6358e083b11d5f8e823daa9cdb..73d5139892639bf798767ee927c9f6f4c26da013 100644 (file)
@@ -176,19 +176,11 @@ static inline void pciehp_firmware_init(void)
 {
        pciehp_acpi_slot_detection_init();
 }
-
-static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
-       int retval;
-       u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
-                    OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-       retval = acpi_get_hp_hw_control_from_firmware(dev, flags);
-       if (retval)
-               return retval;
-       return pciehp_acpi_slot_detection_check(dev);
-}
 #else
 #define pciehp_firmware_init()                         do {} while (0)
-#define pciehp_get_hp_hw_control_from_firmware(dev)    0
+static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev)
+{
+       return 0;
+}
 #endif                                 /* CONFIG_ACPI */
 #endif                         /* _PCIEHP_H */
index 1f4000a5a108fa8d9f57383ffc03f9313c9fc2c0..2574700db461559717a95e0623c1c58c5821c687 100644 (file)
@@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev)
        acpi_handle handle;
        struct dummy_slot *slot, *tmp;
        struct pci_dev *pdev = dev->port;
-       /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
-       if (pciehp_get_hp_hw_control_from_firmware(pdev))
-               return -ENODEV;
+
        pos = pci_pcie_cap(pdev);
        if (!pos)
                return -ENODEV;
index 3588ea61b0dd244df58ac3fdc92adc61cdc512be..aa5f3ff629ff4b798d3b2e473e3e6dfb025be823 100644 (file)
@@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644);
 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
-MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
+MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing");
 
 #define PCIE_MODULE_NAME "pciehp"
 
@@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev)
                dev_info(&dev->device,
                         "Bypassing BIOS check for pciehp use on %s\n",
                         pci_name(dev->port));
-       else if (pciehp_get_hp_hw_control_from_firmware(dev->port))
+       else if (pciehp_acpi_slot_detection_check(dev->port))
                goto err_out_none;
 
        ctrl = pcie_init(dev);
index 98abf8b912943f12b6cbcdfe90e4779f3650294e..834842aa5bbf7926b61810cce47c47cb158b1f83 100644 (file)
@@ -57,28 +57,22 @@ void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
        *msg = cfg->msg;
 }
 
-void mask_ht_irq(unsigned int irq)
+void mask_ht_irq(struct irq_data *data)
 {
-       struct ht_irq_cfg *cfg;
-       struct ht_irq_msg msg;
-
-       cfg = get_irq_data(irq);
+       struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+       struct ht_irq_msg msg = cfg->msg;
 
-       msg = cfg->msg;
        msg.address_lo |= 1;
-       write_ht_irq_msg(irq, &msg);
+       write_ht_irq_msg(data->irq, &msg);
 }
 
-void unmask_ht_irq(unsigned int irq)
+void unmask_ht_irq(struct irq_data *data)
 {
-       struct ht_irq_cfg *cfg;
-       struct ht_irq_msg msg;
-
-       cfg = get_irq_data(irq);
+       struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+       struct ht_irq_msg msg = cfg->msg;
 
-       msg = cfg->msg;
        msg.address_lo &= ~1;
-       write_ht_irq_msg(irq, &msg);
+       write_ht_irq_msg(data->irq, &msg);
 }
 
 /**
index c3ceebb5be84168ae71b845bdc52b3c9a6b557b3..4789f8e8bf7ad91cae0b0a1043349ac96ea5fa64 100644 (file)
 #define DMA_32BIT_PFN          IOVA_PFN(DMA_BIT_MASK(32))
 #define DMA_64BIT_PFN          IOVA_PFN(DMA_BIT_MASK(64))
 
+/* page table handling */
+#define LEVEL_STRIDE           (9)
+#define LEVEL_MASK             (((u64)1 << LEVEL_STRIDE) - 1)
+
+static inline int agaw_to_level(int agaw)
+{
+       return agaw + 2;
+}
+
+static inline int agaw_to_width(int agaw)
+{
+       return 30 + agaw * LEVEL_STRIDE;
+}
+
+static inline int width_to_agaw(int width)
+{
+       return (width - 30) / LEVEL_STRIDE;
+}
+
+static inline unsigned int level_to_offset_bits(int level)
+{
+       return (level - 1) * LEVEL_STRIDE;
+}
+
+static inline int pfn_level_offset(unsigned long pfn, int level)
+{
+       return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
+}
+
+static inline unsigned long level_mask(int level)
+{
+       return -1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long level_size(int level)
+{
+       return 1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long align_to_level(unsigned long pfn, int level)
+{
+       return (pfn + level_size(level) - 1) & level_mask(level);
+}
 
 /* VT-d pages must always be _smaller_ than MM pages. Otherwise things
    are never going to work. */
@@ -434,8 +477,6 @@ void free_iova_mem(struct iova *iova)
 }
 
 
-static inline int width_to_agaw(int width);
-
 static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
 {
        unsigned long sagaw;
@@ -646,51 +687,6 @@ out:
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-/* page table handling */
-#define LEVEL_STRIDE           (9)
-#define LEVEL_MASK             (((u64)1 << LEVEL_STRIDE) - 1)
-
-static inline int agaw_to_level(int agaw)
-{
-       return agaw + 2;
-}
-
-static inline int agaw_to_width(int agaw)
-{
-       return 30 + agaw * LEVEL_STRIDE;
-
-}
-
-static inline int width_to_agaw(int width)
-{
-       return (width - 30) / LEVEL_STRIDE;
-}
-
-static inline unsigned int level_to_offset_bits(int level)
-{
-       return (level - 1) * LEVEL_STRIDE;
-}
-
-static inline int pfn_level_offset(unsigned long pfn, int level)
-{
-       return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
-}
-
-static inline unsigned long level_mask(int level)
-{
-       return -1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long level_size(int level)
-{
-       return 1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long align_to_level(unsigned long pfn, int level)
-{
-       return (pfn + level_size(level) - 1) & level_mask(level);
-}
-
 static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
                                      unsigned long pfn)
 {
@@ -3761,6 +3757,33 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
 
+#define GGC 0x52
+#define GGC_MEMORY_SIZE_MASK   (0xf << 8)
+#define GGC_MEMORY_SIZE_NONE   (0x0 << 8)
+#define GGC_MEMORY_SIZE_1M     (0x1 << 8)
+#define GGC_MEMORY_SIZE_2M     (0x3 << 8)
+#define GGC_MEMORY_VT_ENABLED  (0x8 << 8)
+#define GGC_MEMORY_SIZE_2M_VT  (0x9 << 8)
+#define GGC_MEMORY_SIZE_3M_VT  (0xa << 8)
+#define GGC_MEMORY_SIZE_4M_VT  (0xb << 8)
+
+static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
+{
+       unsigned short ggc;
+
+       if (pci_read_config_word(dev, GGC, &ggc))
+               return;
+
+       if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
+               printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
+               dmar_map_gfx = 0;
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
+
 /* On Tylersburg chipsets, some BIOSes have been known to enable the
    ISOCH DMAR unit for the Azalia sound device, but not give it any
    TLB entries, which causes it to deadlock. Check for that.  We do
index fd1d2867cdcc518431032c4562681d53a79de5fe..ec87cd66f3eb21b792381b52c6d8f1656beadede 100644 (file)
@@ -46,109 +46,24 @@ static __init int setup_intremap(char *str)
 }
 early_param("intremap", setup_intremap);
 
-struct irq_2_iommu {
-       struct intel_iommu *iommu;
-       u16 irte_index;
-       u16 sub_handle;
-       u8  irte_mask;
-};
-
-#ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
-{
-       struct irq_2_iommu *iommu;
-
-       iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
-       printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
-
-       return iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-
-       if (WARN_ON_ONCE(!desc))
-               return NULL;
-
-       return desc->irq_2_iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
-       struct irq_desc *desc;
-       struct irq_2_iommu *irq_iommu;
-
-       desc = irq_to_desc(irq);
-       if (!desc) {
-               printk(KERN_INFO "can not get irq_desc for %d\n", irq);
-               return NULL;
-       }
-
-       irq_iommu = desc->irq_2_iommu;
-
-       if (!irq_iommu)
-               desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq));
-
-       return desc->irq_2_iommu;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
-       if (irq < nr_irqs)
-               return &irq_2_iommuX[irq];
-
-       return NULL;
-}
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
-       return irq_2_iommu(irq);
-}
-#endif
-
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
-static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
-{
-       struct irq_2_iommu *irq_iommu;
-
-       irq_iommu = irq_2_iommu(irq);
-
-       if (!irq_iommu)
-               return NULL;
-
-       if (!irq_iommu->iommu)
-               return NULL;
-
-       return irq_iommu;
-}
-
-int irq_remapped(int irq)
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
-       return valid_irq_2_iommu(irq) != NULL;
+       struct irq_cfg *cfg = get_irq_chip_data(irq);
+       return cfg ? &cfg->irq_2_iommu : NULL;
 }
 
 int get_irte(int irq, struct irte *entry)
 {
-       int index;
-       struct irq_2_iommu *irq_iommu;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        unsigned long flags;
+       int index;
 
-       if (!entry)
+       if (!entry || !irq_iommu)
                return -1;
 
        spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-               return -1;
-       }
 
        index = irq_iommu->irte_index + irq_iommu->sub_handle;
        *entry = *(irq_iommu->iommu->ir_table->base + index);
@@ -160,20 +75,14 @@ int get_irte(int irq, struct irte *entry)
 int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
 {
        struct ir_table *table = iommu->ir_table;
-       struct irq_2_iommu *irq_iommu;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        u16 index, start_index;
        unsigned int mask = 0;
        unsigned long flags;
        int i;
 
-       if (!count)
-               return -1;
-
-#ifndef CONFIG_SPARSE_IRQ
-       /* protect irq_2_iommu_alloc later */
-       if (irq >= nr_irqs)
+       if (!count || !irq_iommu)
                return -1;
-#endif
 
        /*
         * start the IRTE search from index 0.
@@ -214,13 +123,6 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
        for (i = index; i < index + count; i++)
                table->base[i].present = 1;
 
-       irq_iommu = irq_2_iommu_alloc(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-               printk(KERN_ERR "can't allocate irq_2_iommu\n");
-               return -1;
-       }
-
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index =  index;
        irq_iommu->sub_handle = 0;
@@ -244,17 +146,14 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 
 int map_irq_to_irte_handle(int irq, u16 *sub_handle)
 {
-       int index;
-       struct irq_2_iommu *irq_iommu;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        unsigned long flags;
+       int index;
 
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+       if (!irq_iommu)
                return -1;
-       }
 
+       spin_lock_irqsave(&irq_2_ir_lock, flags);
        *sub_handle = irq_iommu->sub_handle;
        index = irq_iommu->irte_index;
        spin_unlock_irqrestore(&irq_2_ir_lock, flags);
@@ -263,18 +162,13 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
 
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
-       struct irq_2_iommu *irq_iommu;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        unsigned long flags;
 
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-       irq_iommu = irq_2_iommu_alloc(irq);
-
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-               printk(KERN_ERR "can't allocate irq_2_iommu\n");
+       if (!irq_iommu)
                return -1;
-       }
+
+       spin_lock_irqsave(&irq_2_ir_lock, flags);
 
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index = index;
@@ -286,43 +180,18 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
        return 0;
 }
 
-int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
-{
-       struct irq_2_iommu *irq_iommu;
-       unsigned long flags;
-
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-               return -1;
-       }
-
-       irq_iommu->iommu = NULL;
-       irq_iommu->irte_index = 0;
-       irq_iommu->sub_handle = 0;
-       irq_2_iommu(irq)->irte_mask = 0;
-
-       spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-       return 0;
-}
-
 int modify_irte(int irq, struct irte *irte_modified)
 {
-       int rc;
-       int index;
-       struct irte *irte;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        struct intel_iommu *iommu;
-       struct irq_2_iommu *irq_iommu;
        unsigned long flags;
+       struct irte *irte;
+       int rc, index;
 
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+       if (!irq_iommu)
                return -1;
-       }
+
+       spin_lock_irqsave(&irq_2_ir_lock, flags);
 
        iommu = irq_iommu->iommu;
 
@@ -339,31 +208,6 @@ int modify_irte(int irq, struct irte *irte_modified)
        return rc;
 }
 
-int flush_irte(int irq)
-{
-       int rc;
-       int index;
-       struct intel_iommu *iommu;
-       struct irq_2_iommu *irq_iommu;
-       unsigned long flags;
-
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-               return -1;
-       }
-
-       iommu = irq_iommu->iommu;
-
-       index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
-       rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
-       spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-       return rc;
-}
-
 struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
 {
        int i;
@@ -420,16 +264,14 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
 
 int free_irte(int irq)
 {
-       int rc = 0;
-       struct irq_2_iommu *irq_iommu;
+       struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
        unsigned long flags;
+       int rc;
 
-       spin_lock_irqsave(&irq_2_ir_lock, flags);
-       irq_iommu = valid_irq_2_iommu(irq);
-       if (!irq_iommu) {
-               spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+       if (!irq_iommu)
                return -1;
-       }
+
+       spin_lock_irqsave(&irq_2_ir_lock, flags);
 
        rc = clear_entries(irq_iommu);
 
index ce6a3666b3d9878f70be6fb65f3e1272fdf6b6b2..553d8ee55c1c4aa3c9f6567867642d3505cf89df 100644 (file)
@@ -608,7 +608,7 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno,
  * the VF BAR size multiplied by the number of VFs.  The alignment
  * is just the VF BAR size.
  */
-int pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
+resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
 {
        struct resource tmp;
        enum pci_bar_type type;
index 69b7be33b3a24768a460843a13c17a88c96a8024..5fcf5aec680fc36a345dd08d0c6a54287a2dfb34 100644 (file)
@@ -170,33 +170,31 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
        desc->masked = __msix_mask_irq(desc, flag);
 }
 
-static void msi_set_mask_bit(unsigned irq, u32 flag)
+static void msi_set_mask_bit(struct irq_data *data, u32 flag)
 {
-       struct msi_desc *desc = get_irq_msi(irq);
+       struct msi_desc *desc = irq_data_get_msi(data);
 
        if (desc->msi_attrib.is_msix) {
                msix_mask_irq(desc, flag);
                readl(desc->mask_base);         /* Flush write to device */
        } else {
-               unsigned offset = irq - desc->dev->irq;
+               unsigned offset = data->irq - desc->dev->irq;
                msi_mask_irq(desc, 1 << offset, flag << offset);
        }
 }
 
-void mask_msi_irq(unsigned int irq)
+void mask_msi_irq(struct irq_data *data)
 {
-       msi_set_mask_bit(irq, 1);
+       msi_set_mask_bit(data, 1);
 }
 
-void unmask_msi_irq(unsigned int irq)
+void unmask_msi_irq(struct irq_data *data)
 {
-       msi_set_mask_bit(irq, 0);
+       msi_set_mask_bit(data, 0);
 }
 
-void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_desc_msi(desc);
-
        BUG_ON(entry->dev->current_state != PCI_D0);
 
        if (entry->msi_attrib.is_msix) {
@@ -227,15 +225,13 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 
 void read_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct msi_desc *entry = get_irq_msi(irq);
 
-       read_msi_msg_desc(desc, msg);
+       __read_msi_msg(entry, msg);
 }
 
-void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_desc_msi(desc);
-
        /* Assert that the cache is valid, assuming that
         * valid messages are not all-zeroes. */
        BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
@@ -246,15 +242,13 @@ void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 
 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct msi_desc *entry = get_irq_msi(irq);
 
-       get_cached_msi_msg_desc(desc, msg);
+       __get_cached_msi_msg(entry, msg);
 }
 
-void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-       struct msi_desc *entry = get_irq_desc_msi(desc);
-
        if (entry->dev->current_state != PCI_D0) {
                /* Don't touch the hardware now */
        } else if (entry->msi_attrib.is_msix) {
@@ -292,9 +286,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 
 void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct msi_desc *entry = get_irq_msi(irq);
 
-       write_msi_msg_desc(desc, msg);
+       __write_msi_msg(entry, msg);
 }
 
 static void free_msi_irqs(struct pci_dev *dev)
index 679c39de6a89124e96a36252f32e8ff45991b7aa..6beb11b617a92973f7a32cc47a7343a759218d6e 100644 (file)
@@ -140,8 +140,10 @@ static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 
 #ifdef CONFIG_PCIEAER
 void pci_no_aer(void);
+bool pci_aer_available(void);
 #else
 static inline void pci_no_aer(void) { }
+static inline bool pci_aer_available(void) { return false; }
 #endif
 
 static inline int pci_no_d1d2(struct pci_dev *dev)
@@ -262,7 +264,8 @@ extern int pci_iov_init(struct pci_dev *dev);
 extern void pci_iov_release(struct pci_dev *dev);
 extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
                                enum pci_bar_type *type);
-extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
+extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
+                                                   int resno);
 extern void pci_restore_iov_state(struct pci_dev *dev);
 extern int pci_iov_bus_range(struct pci_bus *bus);
 
@@ -318,7 +321,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
 }
 #endif /* CONFIG_PCI_IOV */
 
-static inline int pci_resource_alignment(struct pci_dev *dev,
+static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
                                         struct resource *res)
 {
 #ifdef CONFIG_PCI_IOV
index ea654545e7c468c876e7d7b2a7eb637d53c168b9..00c62df5a9fc4773405c74aca96d894f7515c108 100644 (file)
@@ -6,10 +6,11 @@
 obj-$(CONFIG_PCIEASPM)         += aspm.o
 
 pcieportdrv-y                  := portdrv_core.o portdrv_pci.o portdrv_bus.o
+pcieportdrv-$(CONFIG_ACPI)     += portdrv_acpi.o
 
 obj-$(CONFIG_PCIEPORTBUS)      += pcieportdrv.o
 
 # Build PCI Express AER if needed
 obj-$(CONFIG_PCIEAER)          += aer/
 
-obj-$(CONFIG_PCIE_PME) += pme/
+obj-$(CONFIG_PCIE_PME) += pme.o
index 909924692b8aeeb7a49c103cd31d2159e347eb9f..b3cf6223f63acdb80114cbaedf139800998ad3a9 100644 (file)
@@ -472,6 +472,7 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
 static const struct file_operations aer_inject_fops = {
        .write = aer_inject_write,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice aer_inject_device = {
index 484cc55194b8841809218cb15d5f2ccccdffd582..f409948e1a9bb614cfe5fedc1dc652285f8e0307 100644 (file)
@@ -72,6 +72,11 @@ void pci_no_aer(void)
        pcie_aer_disable = 1;   /* has priority over 'forceload' */
 }
 
+bool pci_aer_available(void)
+{
+       return !pcie_aer_disable && pci_msi_enabled();
+}
+
 static int set_device_error_reporting(struct pci_dev *dev, void *data)
 {
        bool enable = *((bool *)data);
@@ -411,9 +416,7 @@ static void aer_error_resume(struct pci_dev *dev)
  */
 static int __init aer_service_init(void)
 {
-       if (pcie_aer_disable)
-               return -ENXIO;
-       if (!pci_msi_enabled())
+       if (!pci_aer_available())
                return -ENXIO;
        return pcie_port_service_register(&aerdriver);
 }
index f278d7b0d95d32b636260cddbe763aa109fbfacf..2bb9b8972211073564b9d99b3cc85a148d79e583 100644 (file)
 #include <acpi/apei.h>
 #include "aerdrv.h"
 
-/**
- * aer_osc_setup - run ACPI _OSC method
- * @pciedev: pcie_device which AER is being enabled on
- *
- * @return: Zero on success. Nonzero otherwise.
- *
- * Invoked when PCIe bus loads AER service driver. To avoid conflict with
- * BIOS AER support requires BIOS to yield AER control to OS native driver.
- **/
-int aer_osc_setup(struct pcie_device *pciedev)
-{
-       acpi_status status = AE_NOT_FOUND;
-       struct pci_dev *pdev = pciedev->port;
-       acpi_handle handle = NULL;
-
-       if (acpi_pci_disabled)
-               return -1;
-
-       handle = acpi_find_root_bridge_handle(pdev);
-       if (handle) {
-               status = acpi_pci_osc_control_set(handle,
-                                       OSC_PCI_EXPRESS_AER_CONTROL |
-                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-       }
-
-       if (ACPI_FAILURE(status)) {
-               dev_printk(KERN_DEBUG, &pciedev->device, "AER service couldn't "
-                          "init device: %s\n",
-                          (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
-                          "no _OSC support" : "_OSC failed");
-               return -1;
-       }
-
-       return 0;
-}
-
 #ifdef CONFIG_ACPI_APEI
 static inline int hest_match_pci(struct acpi_hest_aer_common *p,
                                 struct pci_dev *pci)
index fc0b5a93e1deaf3895ef671ae1f30892980c9352..29e268fadf14cb44d18fac7570e118ce7ba489c9 100644 (file)
@@ -772,22 +772,10 @@ void aer_isr(struct work_struct *work)
  */
 int aer_init(struct pcie_device *dev)
 {
-       if (pcie_aer_get_firmware_first(dev->port)) {
-               dev_printk(KERN_DEBUG, &dev->device,
-                          "PCIe errors handled by platform firmware.\n");
-               goto out;
-       }
-
-       if (aer_osc_setup(dev))
-               goto out;
-
-       return 0;
-out:
        if (forceload) {
                dev_printk(KERN_DEBUG, &dev->device,
                           "aerdrv forceload requested.\n");
                pcie_aer_force_firmware_first(dev->port, 0);
-               return 0;
        }
-       return -ENXIO;
+       return 0;
 }
similarity index 83%
rename from drivers/pci/pcie/pme/pcie_pme.c
rename to drivers/pci/pcie/pme.c
index bbdea18693d94048fc2444dcb388c0a18817fc6e..2f3c904072273fcdaf5c5a660405281720dff7aa 100644 (file)
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
 
-#include "../../pci.h"
-#include "pcie_pme.h"
+#include "../pci.h"
+#include "portdrv.h"
 
 #define PCI_EXP_RTSTA_PME      0x10000 /* PME status */
 #define PCI_EXP_RTSTA_PENDING  0x20000 /* PME pending */
 
-/*
- * If set, this switch will prevent the PCIe root port PME service driver from
- * being registered.  Consequently, the interrupt-based PCIe PME signaling will
- * not be used by any PCIe root ports in that case.
- */
-static bool pcie_pme_disabled = true;
-
-/*
- * The PCI Express Base Specification 2.0, Section 6.1.8, states the following:
- * "In order to maintain compatibility with non-PCI Express-aware system
- * software, system power management logic must be configured by firmware to use
- * the legacy mechanism of signaling PME by default.  PCI Express-aware system
- * software must notify the firmware prior to enabling native, interrupt-based
- * PME signaling."  However, if the platform doesn't provide us with a suitable
- * notification mechanism or the notification fails, it is not clear whether or
- * not we are supposed to use the interrupt-based PCIe PME signaling.  The
- * switch below can be used to indicate the desired behaviour.  When set, it
- * will make the kernel use the interrupt-based PCIe PME signaling regardless of
- * the platform notification status, although the kernel will attempt to notify
- * the platform anyway.  When unset, it will prevent the kernel from using the
- * the interrupt-based PCIe PME signaling if the platform notification fails,
- * which is the default.
- */
-static bool pcie_pme_force_enable;
-
 /*
  * If this switch is set, MSI will not be used for PCIe PME signaling.  This
  * causes the PCIe port driver to use INTx interrupts only, but it turns out
@@ -64,38 +39,13 @@ bool pcie_pme_msi_disabled;
 
 static int __init pcie_pme_setup(char *str)
 {
-       if (!strncmp(str, "auto", 4))
-               pcie_pme_disabled = false;
-       else if (!strncmp(str, "force", 5))
-               pcie_pme_force_enable = true;
-
-       str = strchr(str, ',');
-       if (str) {
-               str++;
-               str += strspn(str, " \t");
-               if (*str && !strcmp(str, "nomsi"))
-                       pcie_pme_msi_disabled = true;
-       }
+       if (!strncmp(str, "nomsi", 5))
+               pcie_pme_msi_disabled = true;
 
        return 1;
 }
 __setup("pcie_pme=", pcie_pme_setup);
 
-/**
- * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME.
- * @srv: PCIe PME root port service to use for carrying out the check.
- *
- * Notify the platform that the native PCIe PME is going to be used and return
- * 'true' if the control of the PCIe PME registers has been acquired from the
- * platform.
- */
-static bool pcie_pme_platform_setup(struct pcie_device *srv)
-{
-       if (!pcie_pme_platform_notify(srv))
-               return true;
-       return pcie_pme_force_enable;
-}
-
 struct pcie_pme_service_data {
        spinlock_t lock;
        struct pcie_device *srv;
@@ -108,7 +58,7 @@ struct pcie_pme_service_data {
  * @dev: PCIe root port or event collector.
  * @enable: Enable or disable the interrupt.
  */
-static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
+void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
 {
        int rtctl_pos;
        u16 rtctl;
@@ -417,9 +367,6 @@ static int pcie_pme_probe(struct pcie_device *srv)
        struct pcie_pme_service_data *data;
        int ret;
 
-       if (!pcie_pme_platform_setup(srv))
-               return -EACCES;
-
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -509,8 +456,7 @@ static struct pcie_port_service_driver pcie_pme_driver = {
  */
 static int __init pcie_pme_service_init(void)
 {
-       return pcie_pme_disabled ?
-               -ENODEV : pcie_port_service_register(&pcie_pme_driver);
+       return pcie_port_service_register(&pcie_pme_driver);
 }
 
 module_init(pcie_pme_service_init);
diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile
deleted file mode 100644 (file)
index 8b92380..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for PCI-Express Root Port PME signaling driver
-#
-
-obj-$(CONFIG_PCIE_PME) += pmedriver.o
-
-pmedriver-objs := pcie_pme.o
-pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o
diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h
deleted file mode 100644 (file)
index b30d2b7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * drivers/pci/pcie/pme/pcie_pme.h
- *
- * PCI Express Root Port PME signaling support
- *
- * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
- */
-
-#ifndef _PCIE_PME_H_
-#define _PCIE_PME_H_
-
-struct pcie_device;
-
-#ifdef CONFIG_ACPI
-extern int pcie_pme_acpi_setup(struct pcie_device *srv);
-
-static inline int pcie_pme_platform_notify(struct pcie_device *srv)
-{
-       return pcie_pme_acpi_setup(srv);
-}
-#else /* !CONFIG_ACPI */
-static inline int pcie_pme_platform_notify(struct pcie_device *srv)
-{
-       return 0;
-}
-#endif /* !CONFIG_ACPI */
-
-#endif
diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c
deleted file mode 100644 (file)
index 83ab228..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * PCIe Native PME support, ACPI-related part
- *
- * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License V2.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-#include <linux/pcieport_if.h>
-
-/**
- * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME.
- * @srv - PCIe PME service for a root port or event collector.
- *
- * Invoked when the PCIe bus type loads PCIe PME service driver.  To avoid
- * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME
- * control to the kernel.
- */
-int pcie_pme_acpi_setup(struct pcie_device *srv)
-{
-       acpi_status status = AE_NOT_FOUND;
-       struct pci_dev *port = srv->port;
-       acpi_handle handle;
-       int error = 0;
-
-       if (acpi_pci_disabled)
-               return -ENOSYS;
-
-       dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n");
-
-       handle = acpi_find_root_bridge_handle(port);
-       if (!handle)
-               return -EINVAL;
-
-       status = acpi_pci_osc_control_set(handle,
-                       OSC_PCI_EXPRESS_PME_CONTROL |
-                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-       if (ACPI_FAILURE(status)) {
-               dev_info(&port->dev,
-                       "Failed to receive control of PCIe PME service: %s\n",
-                       (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
-                       "no _OSC support" : "ACPI _OSC failed");
-               error = -ENODEV;
-       }
-
-       return error;
-}
index 813a5c3427b69261d0d54d5c531ffc9f9973ce64..7b5aba0a3291107a231a8b6ee6a90cacf0c4557c 100644 (file)
@@ -20,6 +20,9 @@
 
 #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
 
+extern bool pcie_ports_disabled;
+extern bool pcie_ports_auto;
+
 extern struct bus_type pcie_port_bus_type;
 extern int pcie_port_device_register(struct pci_dev *dev);
 #ifdef CONFIG_PM
@@ -30,6 +33,8 @@ extern void pcie_port_device_remove(struct pci_dev *dev);
 extern int __must_check pcie_port_bus_register(void);
 extern void pcie_port_bus_unregister(void);
 
+struct pci_dev;
+
 #ifdef CONFIG_PCIE_PME
 extern bool pcie_pme_msi_disabled;
 
@@ -42,9 +47,26 @@ static inline bool pcie_pme_no_msi(void)
 {
        return pcie_pme_msi_disabled;
 }
+
+extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);
 #else /* !CONFIG_PCIE_PME */
 static inline void pcie_pme_disable_msi(void) {}
 static inline bool pcie_pme_no_msi(void) { return false; }
+static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
 #endif /* !CONFIG_PCIE_PME */
 
+#ifdef CONFIG_ACPI
+extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask);
+
+static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask)
+{
+       return pcie_port_acpi_setup(port, mask);
+}
+#else /* !CONFIG_ACPI */
+static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask)
+{
+       return 0;
+}
+#endif /* !CONFIG_ACPI */
+
 #endif /* _PORTDRV_H_ */
diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c
new file mode 100644 (file)
index 0000000..b7c4cb1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * PCIe Port Native Services Support, ACPI-Related Part
+ *
+ * Copyright (C) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License V2.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <linux/pcieport_if.h>
+
+#include "aer/aerdrv.h"
+#include "../pci.h"
+
+/**
+ * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services.
+ * @port: PCIe Port service for a root port or event collector.
+ * @srv_mask: Bit mask of services that can be enabled for @port.
+ *
+ * Invoked when @port is identified as a PCIe port device.  To avoid conflicts
+ * with the BIOS PCIe port native services support requires the BIOS to yield
+ * control of these services to the kernel.  The mask of services that the BIOS
+ * allows to be enabled for @port is written to @srv_mask.
+ *
+ * NOTE: It turns out that we cannot do that for individual port services
+ * separately, because that would make some systems work incorrectly.
+ */
+int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask)
+{
+       acpi_status status;
+       acpi_handle handle;
+       u32 flags;
+
+       if (acpi_pci_disabled)
+               return 0;
+
+       handle = acpi_find_root_bridge_handle(port);
+       if (!handle)
+               return -EINVAL;
+
+       flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
+               | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
+               | OSC_PCI_EXPRESS_PME_CONTROL;
+
+       if (pci_aer_available()) {
+               if (pcie_aer_get_firmware_first(port))
+                       dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n");
+               else
+                       flags |= OSC_PCI_EXPRESS_AER_CONTROL;
+       }
+
+       status = acpi_pci_osc_control_set(handle, &flags,
+                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+       if (ACPI_FAILURE(status)) {
+               dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n",
+                       status);
+               return -ENODEV;
+       }
+
+       dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags);
+
+       *srv_mask = PCIE_PORT_SERVICE_VC;
+       if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
+               *srv_mask |= PCIE_PORT_SERVICE_HP;
+       if (flags & OSC_PCI_EXPRESS_PME_CONTROL)
+               *srv_mask |= PCIE_PORT_SERVICE_PME;
+       if (flags & OSC_PCI_EXPRESS_AER_CONTROL)
+               *srv_mask |= PCIE_PORT_SERVICE_AER;
+
+       return 0;
+}
index e73effbe402c55e82be4d8a821b3d39e64f96bac..a9c222d79ebc5dc32cd6c4fad37f616ac291ff6a 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
+#include <linux/aer.h>
+#include <linux/pci-aspm.h>
 
 #include "../pci.h"
 #include "portdrv.h"
@@ -236,24 +238,64 @@ static int get_port_device_capability(struct pci_dev *dev)
        int services = 0, pos;
        u16 reg16;
        u32 reg32;
+       int cap_mask;
+       int err;
+
+       err = pcie_port_platform_notify(dev, &cap_mask);
+       if (pcie_ports_auto) {
+               if (err) {
+                       pcie_no_aspm();
+                       return 0;
+               }
+       } else {
+               cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
+                               | PCIE_PORT_SERVICE_VC;
+               if (pci_aer_available())
+                       cap_mask |= PCIE_PORT_SERVICE_AER;
+       }
 
        pos = pci_pcie_cap(dev);
        pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
        /* Hot-Plug Capable */
-       if (reg16 & PCI_EXP_FLAGS_SLOT) {
+       if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) {
                pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
-               if (reg32 & PCI_EXP_SLTCAP_HPC)
+               if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
+                       /*
+                        * Disable hot-plug interrupts in case they have been
+                        * enabled by the BIOS and the hot-plug service driver
+                        * is not loaded.
+                        */
+                       pos += PCI_EXP_SLTCTL;
+                       pci_read_config_word(dev, pos, &reg16);
+                       reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
+                       pci_write_config_word(dev, pos, reg16);
+               }
        }
        /* AER capable */
-       if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
+       if ((cap_mask & PCIE_PORT_SERVICE_AER)
+           && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) {
                services |= PCIE_PORT_SERVICE_AER;
+               /*
+                * Disable AER on this port in case it's been enabled by the
+                * BIOS (the AER service driver will enable it when necessary).
+                */
+               pci_disable_pcie_error_reporting(dev);
+       }
        /* VC support */
        if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
                services |= PCIE_PORT_SERVICE_VC;
        /* Root ports are capable of generating PME too */
-       if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+       if ((cap_mask & PCIE_PORT_SERVICE_PME)
+           && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
                services |= PCIE_PORT_SERVICE_PME;
+               /*
+                * Disable PME interrupt on this port in case it's been enabled
+                * by the BIOS (the PME service driver will enable it when
+                * necessary).
+                */
+               pcie_pme_interrupt_enable(dev, false);
+       }
 
        return services;
 }
@@ -494,6 +536,9 @@ static void pcie_port_shutdown_service(struct device *dev) {}
  */
 int pcie_port_service_register(struct pcie_port_service_driver *new)
 {
+       if (pcie_ports_disabled)
+               return -ENODEV;
+
        new->driver.name = (char *)new->name;
        new->driver.bus = &pcie_port_bus_type;
        new->driver.probe = pcie_port_probe_service;
index 3debed25e46bb63f4e70e4a58b0d9abff3fd33be..f9033e190fb62060e701ebf44b0eb1d3dfbefa90 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
 #include <linux/dmi.h>
+#include <linux/pci-aspm.h>
 
 #include "portdrv.h"
 #include "aer/aerdrv.h"
@@ -29,6 +30,31 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
+/* If this switch is set, PCIe port native services should not be enabled. */
+bool pcie_ports_disabled;
+
+/*
+ * If this switch is set, ACPI _OSC will be used to determine whether or not to
+ * enable PCIe port native services.
+ */
+bool pcie_ports_auto = true;
+
+static int __init pcie_port_setup(char *str)
+{
+       if (!strncmp(str, "compat", 6)) {
+               pcie_ports_disabled = true;
+       } else if (!strncmp(str, "native", 6)) {
+               pcie_ports_disabled = false;
+               pcie_ports_auto = false;
+       } else if (!strncmp(str, "auto", 4)) {
+               pcie_ports_disabled = false;
+               pcie_ports_auto = true;
+       }
+
+       return 1;
+}
+__setup("pcie_ports=", pcie_port_setup);
+
 /* global data */
 
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
@@ -301,6 +327,11 @@ static int __init pcie_portdrv_init(void)
 {
        int retval;
 
+       if (pcie_ports_disabled) {
+               pcie_no_aspm();
+               return -EACCES;
+       }
+
        dmi_check_system(pcie_portdrv_dmi_table);
 
        retval = pcie_port_bus_register();
@@ -315,11 +346,4 @@ static int __init pcie_portdrv_init(void)
        return retval;
 }
 
-static void __exit pcie_portdrv_exit(void)
-{
-       pci_unregister_driver(&pcie_portdriver);
-       pcie_port_bus_unregister();
-}
-
 module_init(pcie_portdrv_init);
-module_exit(pcie_portdrv_exit);
index 89ed181cd90cd9cd68506a212eb423ba60f9c8e2..857ae01734a66156c8abb92335be91cc674964a0 100644 (file)
@@ -162,6 +162,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1,       quirk_isa_d
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_2,       quirk_isa_dma_hangs);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_3,       quirk_isa_dma_hangs);
 
+/*
+ * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+ * for some HT machines to use C4 w/o hanging.
+ */
+static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+{
+       u32 pmbase;
+       u16 pm1a;
+
+       pci_read_config_dword(dev, 0x40, &pmbase);
+       pmbase = pmbase & 0xff80;
+       pm1a = inw(pmbase);
+
+       if (pm1a & 0x10) {
+               dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n");
+               outw(0x10, pmbase);
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts);
+
 /*
  *     Chipsets where PCI->PCI transfers vanish or hang
  */
index 659eaa0fc48facf81dad9c0b5c430498e01398e3..968cfea04f749ea76ffcb33bb62f114ecfd9a6ef 100644 (file)
@@ -49,7 +49,7 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)
 }
 
 /* these strings match up with the values in pci_bus_speed */
-static char *pci_bus_speed_strings[] = {
+static const char *pci_bus_speed_strings[] = {
        "33 MHz PCI",           /* 0x00 */
        "66 MHz PCI",           /* 0x01 */
        "66 MHz PCI-X",         /* 0x02 */
index 88c4c4098789e1e3e3b08dc3847412c570ebfc35..95dd7c62741ffb7a8014ade9885b072e1c15a4b9 100644 (file)
@@ -441,14 +441,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
 
 
 out_err:
-       flush_scheduled_work();
        ops->hw_shutdown(skt);
        while (i-- > 0) {
                skt = PCMCIA_SOCKET(i);
 
                del_timer_sync(&skt->poll_timer);
                pcmcia_unregister_socket(&skt->socket);
-               flush_scheduled_work();
                if (i == 0) {
                        iounmap(skt->virt_io + (u32)mips_io_port_base);
                        skt->virt_io = NULL;
@@ -480,7 +478,6 @@ int au1x00_drv_pcmcia_remove(struct platform_device *dev)
 
                del_timer_sync(&skt->poll_timer);
                pcmcia_unregister_socket(&skt->socket);
-               flush_scheduled_work();
                skt->ops->hw_shutdown(skt);
                au1x00_pcmcia_config_skt(skt, &dead_socket);
                iounmap(skt->virt_io + (u32)mips_io_port_base);
index 67530cefcf3c1bfd5d36ea1f93068a841e2d5642..5c36bda2963b3981a7e91fe2bb4ceb033fa9a2e9 100644 (file)
@@ -23,7 +23,6 @@
 
 /* include the world */
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
index 807f2d75dad3a84f7b98142af3e52e812cc601bd..b2396647a1656774a50b484031a7e41eede60de7 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/proc_fs.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
index 91414a0ddc442823faebfb1db8b5420ba407630a..884a984216febe247dee1bdcad69d47d1cd1adf2 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/unaligned.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
index 2ec8ac97445c1491d73102808de25dcf8e2c26bc..d9ea192c4001ed9e315d21bac96b2ab37361376f 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -845,7 +844,7 @@ static int pcmcia_socket_dev_resume_noirq(struct device *dev)
        return __pcmcia_pm_op(dev, socket_early_resume);
 }
 
-static int pcmcia_socket_dev_resume(struct device *dev)
+static int __used pcmcia_socket_dev_resume(struct device *dev)
 {
        return __pcmcia_pm_op(dev, socket_late_resume);
 }
index da055dc14d98a2933953e206d9544d33cc74cb17..7f1953f78b12b906421a4c8f130d4094e49c6d74 100644 (file)
 typedef struct config_t {
        struct kref     ref;
        unsigned int    state;
-       unsigned int    Attributes;
-       unsigned int    IntType;
-       unsigned int    ConfigBase;
-       unsigned char   Status, Pin, Copy, Option, ExtStatus;
-       unsigned int    CardValues;
 
        struct resource io[MAX_IO_WIN]; /* io ports */
        struct resource mem[MAX_WIN];   /* mem areas */
-
-       struct {
-               u_int   Attributes;
-       } irq;
 } config_t;
 
 
index 55570d9e1e4cc0246fe9c9add4583ccad5e3dae7..100c4412457de1357348c9e9eb5b3c29ae8bbdd8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
@@ -52,7 +51,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
 
        if (!p_drv->probe || !p_drv->remove)
                printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
-                      "function\n", p_drv->drv.name);
+                      "function\n", p_drv->name);
 
        while (did && did->match_flags) {
                for (i = 0; i < 4; i++) {
@@ -65,7 +64,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
 
                        printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
                               "product string \"%s\": is 0x%x, should "
-                              "be 0x%x\n", p_drv->drv.name, did->prod_id[i],
+                              "be 0x%x\n", p_drv->name, did->prod_id[i],
                               did->prod_id_hash[i], hash);
                        printk(KERN_DEBUG "pcmcia: see "
                                "Documentation/pcmcia/devicetable.txt for "
@@ -180,10 +179,11 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
        /* initialize common fields */
        driver->drv.bus = &pcmcia_bus_type;
        driver->drv.owner = driver->owner;
+       driver->drv.name = driver->name;
        mutex_init(&driver->dynids.lock);
        INIT_LIST_HEAD(&driver->dynids.list);
 
-       pr_debug("registering driver %s\n", driver->drv.name);
+       pr_debug("registering driver %s\n", driver->name);
 
        error = driver_register(&driver->drv);
        if (error < 0)
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);
  */
 void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
-       pr_debug("unregistering driver %s\n", driver->drv.name);
+       pr_debug("unregistering driver %s\n", driver->name);
        driver_unregister(&driver->drv);
        pcmcia_free_dynids(driver);
 }
@@ -264,7 +264,7 @@ static int pcmcia_device_probe(struct device *dev)
        p_drv = to_pcmcia_drv(dev->driver);
        s = p_dev->socket;
 
-       dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);
+       dev_dbg(dev, "trying to bind to %s\n", p_drv->name);
 
        if ((!p_drv->probe) || (!p_dev->function_config) ||
            (!try_module_get(p_drv->owner))) {
@@ -276,21 +276,28 @@ static int pcmcia_device_probe(struct device *dev)
        ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
                                &cis_config);
        if (!ret) {
-               p_dev->conf.ConfigBase = cis_config.base;
-               p_dev->conf.Present = cis_config.rmask[0];
+               p_dev->config_base = cis_config.base;
+               p_dev->config_regs = cis_config.rmask[0];
+               dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
+                       p_dev->config_regs);
        } else {
                dev_printk(KERN_INFO, dev,
                           "pcmcia: could not parse base and rmask0 of CIS\n");
-               p_dev->conf.ConfigBase = 0;
-               p_dev->conf.Present = 0;
+               p_dev->config_base = 0;
+               p_dev->config_regs = 0;
        }
 
        ret = p_drv->probe(p_dev);
        if (ret) {
                dev_dbg(dev, "binding to %s failed with %d\n",
-                          p_drv->drv.name, ret);
+                          p_drv->name, ret);
                goto put_module;
        }
+       dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
+               p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq);
+       dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR",
+               p_dev->resource[0], p_dev->resource[1], p_dev->resource[2],
+               p_dev->resource[3], p_dev->resource[4]);
 
        mutex_lock(&s->ops_mutex);
        if ((s->pcmcia_pfc) &&
@@ -374,13 +381,13 @@ static int pcmcia_device_remove(struct device *dev)
        if (p_dev->_irq || p_dev->_io || p_dev->_locked)
                dev_printk(KERN_INFO, dev,
                        "pcmcia: driver %s did not release config properly\n",
-                       p_drv->drv.name);
+                       p_drv->name);
 
        for (i = 0; i < MAX_WIN; i++)
                if (p_dev->_win & CLIENT_WIN_REQ(i))
                        dev_printk(KERN_INFO, dev,
                          "pcmcia: driver %s did not release window properly\n",
-                          p_drv->drv.name);
+                          p_drv->name);
 
        /* references from pcmcia_probe_device */
        pcmcia_put_dev(p_dev);
@@ -1136,7 +1143,7 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
                        dev_printk(KERN_ERR, dev,
                                   "pcmcia: device %s (driver %s) did "
                                   "not want to go to sleep (%d)\n",
-                                  p_dev->devname, p_drv->drv.name, ret);
+                                  p_dev->devname, p_drv->name, ret);
                        mutex_lock(&p_dev->socket->ops_mutex);
                        p_dev->suspended = 0;
                        mutex_unlock(&p_dev->socket->ops_mutex);
@@ -1178,7 +1185,7 @@ static int pcmcia_dev_resume(struct device *dev)
 
        if (p_dev->device_no == p_dev->func) {
                dev_dbg(dev, "requesting configuration\n");
-               ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+               ret = pcmcia_enable_device(p_dev);
                if (ret)
                        goto out;
        }
index 05d0879ce93568194f36f393cb951b43f3155bc8..fc7906eaf22877f16e0904219ec2544e6f3ebfa4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
index 61746bd598b36a58d1ee5c5c5a87e48b740532cc..72a033a2acdb262684cf02a164efb6ee89cea408 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <linux/isapnp.h>
 
index 24de499258630e2e6442ac0045134fa647fd0746..2adb0106a0397a3800b9c707493f871490d5636f 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #undef MAX_IO_WIN      /* FIXME */
 #define MAX_IO_WIN 1
index 8e4723844ad3a2bb447de65e70ea236e2d22e3ef..1511ff71c87b013914491e2695a97995253a694f 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/addrspace.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 /* XXX: should be moved into asm/irq.h */
 #define PCC0_IRQ 24
index f0ecad99ce819d0af8ac77467e2bce332bdc7bc8..99d4f23cb4353136dc73a7d0b7d6309f6f71f97e 100644 (file)
@@ -59,7 +59,6 @@
 #include <asm/irq.h>
 #include <asm/fs_pd.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
index e74bebac26950b2c9d5869c310f835ef99662b64..5096e92c7a4cfb39e1e300f5d8ac8016b5fe54d4 100644 (file)
@@ -153,14 +153,14 @@ static int o2micro_override(struct yenta_socket *socket)
 
                if (use_speedup) {
                        dev_info(&socket->dev->dev,
-                               "O2: enabling read prefetch/write burst\n");
+                               "O2: enabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=off'\n");
                        config_writeb(socket, O2_RESERVED1,
                                      a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
                        config_writeb(socket, O2_RESERVED2,
                                      b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
                } else {
                        dev_info(&socket->dev->dev,
-                               "O2: disabling read prefetch/write burst\n");
+                               "O2: disabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=on'\n");
                        config_writeb(socket, O2_RESERVED1,
                                      a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
                        config_writeb(socket, O2_RESERVED2,
index 0ac54da158850352c766cebd9c5a502b5b7e65e0..e2c92415b8924a89c27e6759652b4a7e5726139b 100644 (file)
@@ -6,7 +6,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Copyright (C) 1999       David A. Hinds
- * Copyright (C) 2004-2009   Dominik Brodowski
+ * Copyright (C) 2004-2010   Dominik Brodowski
  *
  * 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
@@ -22,7 +22,6 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ds.h>
 #include "cs_internal.h"
 
@@ -126,14 +125,24 @@ next_entry:
        return ret;
 }
 
+
+/**
+ * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
+ */
+static int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+       if (!(flags & CISTPL_IO_8BIT))
+               return IO_DATA_PATH_WIDTH_16;
+       if (!(flags & CISTPL_IO_16BIT))
+               return IO_DATA_PATH_WIDTH_8;
+       return IO_DATA_PATH_WIDTH_AUTO;
+}
+
+
 struct pcmcia_cfg_mem {
        struct pcmcia_device *p_dev;
+       int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
        void *priv_data;
-       int (*conf_check) (struct pcmcia_device *p_dev,
-                          cistpl_cftable_entry_t *cfg,
-                          cistpl_cftable_entry_t *dflt,
-                          unsigned int vcc,
-                          void *priv_data);
        cisparse_t parse;
        cistpl_cftable_entry_t dflt;
 };
@@ -147,25 +156,102 @@ struct pcmcia_cfg_mem {
  */
 static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 {
-       cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
        struct pcmcia_cfg_mem *cfg_mem = priv;
+       struct pcmcia_device *p_dev = cfg_mem->p_dev;
+       cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
+       cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
+       unsigned int flags = p_dev->config_flags;
+       unsigned int vcc = p_dev->socket->socket.Vcc;
+
+       dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
+               cfg->index, flags);
 
        /* default values */
-       cfg_mem->p_dev->conf.ConfigIndex = cfg->index;
+       cfg_mem->p_dev->config_index = cfg->index;
        if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
                cfg_mem->dflt = *cfg;
 
-       return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
-                                  cfg_mem->p_dev->socket->socket.Vcc,
-                                  cfg_mem->priv_data);
+       /* check for matching Vcc? */
+       if (flags & CONF_AUTO_CHECK_VCC) {
+               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               }
+       }
+
+       /* set Vpp? */
+       if (flags & CONF_AUTO_SET_VPP) {
+               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+                       p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+               else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+                       p_dev->vpp =
+                               dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       }
+
+       /* enable audio? */
+       if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
+               p_dev->config_flags |= CONF_ENABLE_SPKR;
+
+
+       /* IO window settings? */
+       if (flags & CONF_AUTO_SET_IO) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               int i = 0;
+
+               p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
+               p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+               if (io->nwin == 0)
+                       return -ENODEV;
+
+               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+               p_dev->resource[0]->flags |=
+                                       pcmcia_io_cfg_data_width(io->flags);
+               if (io->nwin > 1) {
+                       /* For multifunction cards, by convention, we
+                        * configure the network function with window 0,
+                        * and serial with window 1 */
+                       i = (io->win[1].len > io->win[0].len);
+                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+                       p_dev->resource[1]->start = io->win[1-i].base;
+                       p_dev->resource[1]->end = io->win[1-i].len;
+               }
+               p_dev->resource[0]->start = io->win[i].base;
+               p_dev->resource[0]->end = io->win[i].len;
+               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+       }
+
+       /* MEM window settings? */
+       if (flags & CONF_AUTO_SET_IOMEM) {
+               /* so far, we only set one memory window */
+               cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+
+               p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
+               if (mem->nwin == 0)
+                       return -ENODEV;
+
+               p_dev->resource[2]->start = mem->win[0].host_addr;
+               p_dev->resource[2]->end = mem->win[0].len;
+               if (p_dev->resource[2]->end < 0x1000)
+                       p_dev->resource[2]->end = 0x1000;
+               p_dev->card_addr = mem->win[0].card_addr;
+       }
+
+       dev_dbg(&p_dev->dev,
+               "checking configuration %x: %pr %pr %pr (%d lines)\n",
+               p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
+               p_dev->resource[2], p_dev->io_lines);
+
+       return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
 }
 
 /**
  * pcmcia_loop_config() - loop over configuration options
  * @p_dev:     the struct pcmcia_device which we need to loop for.
  * @conf_check:        function to call for each configuration option.
- *             It gets passed the struct pcmcia_device, the CIS data
- *             describing the configuration option, and private data
+ *             It gets passed the struct pcmcia_device and private data
  *             being passed to pcmcia_loop_config()
  * @priv_data: private data to be passed to the conf_check function.
  *
@@ -175,9 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
  */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
                       int      (*conf_check)   (struct pcmcia_device *p_dev,
-                                                cistpl_cftable_entry_t *cfg,
-                                                cistpl_cftable_entry_t *dflt,
-                                                unsigned int vcc,
                                                 void *priv_data),
                       void *priv_data)
 {
index 54aa1c238cb34a5966a1d8ff6621835846514d87..0bdda5b3ed550cc74504a7ceea539700b69cb9bd 100644 (file)
@@ -6,7 +6,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Copyright (C) 1999       David A. Hinds
- * Copyright (C) 2004-2005   Dominik Brodowski
+ * Copyright (C) 2004-2010   Dominik Brodowski
  *
  * 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
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -56,6 +55,12 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
 }
 
 
+/**
+ * release_io_space() - release IO ports allocated with alloc_io_space()
+ * @s: pcmcia socket
+ * @res: resource to release
+ *
+ */
 static void release_io_space(struct pcmcia_socket *s, struct resource *res)
 {
        resource_size_t num = resource_size(res);
@@ -81,9 +86,14 @@ static void release_io_space(struct pcmcia_socket *s, struct resource *res)
                        }
                }
        }
-} /* release_io_space */
+}
+
 
-/** alloc_io_space
+/**
+ * alloc_io_space() - allocate IO ports for use by a PCMCIA device
+ * @s: pcmcia socket
+ * @res: resource to allocate (begin: begin, end: size)
+ * @lines: number of IO lines decoded by the PCMCIA card
  *
  * Special stuff for managing IO windows, because they are scarce
  */
@@ -135,7 +145,7 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
        }
        dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
        return ret;
-} /* alloc_io_space */
+}
 
 
 /**
@@ -163,19 +173,19 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
        c = p_dev->function_config;
 
        if (!(c->state & CONFIG_LOCKED)) {
-               dev_dbg(&s->dev, "Configuration isnt't locked\n");
+               dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
                mutex_unlock(&s->ops_mutex);
                return -EACCES;
        }
 
-       addr = (c->ConfigBase + where) >> 1;
+       addr = (p_dev->config_base + where) >> 1;
 
        ret = accessf(s, 1, addr, 1, val);
 
        mutex_unlock(&s->ops_mutex);
 
        return ret;
-} /* pcmcia_access_config */
+}
 
 
 /**
@@ -204,11 +214,20 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
 EXPORT_SYMBOL(pcmcia_write_config_byte);
 
 
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
+/**
+ * pcmcia_map_mem_page() - modify iomem window to point to a different offset
+ * @p_dev: pcmcia device
+ * @res: iomem resource already enabled by pcmcia_request_window()
+ * @offset: card_offset to map
+ *
+ * pcmcia_map_mem_page() modifies what can be read and written by accessing
+ * an iomem range previously enabled by pcmcia_request_window(), by setting
+ * the card_offset value to @offset.
+ */
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
                        unsigned int offset)
 {
        struct pcmcia_socket *s = p_dev->socket;
-       struct resource *res = wh;
        unsigned int w;
        int ret;
 
@@ -220,99 +239,114 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
        s->win[w].card_start = offset;
        ret = s->ops->set_mem_map(s, &s->win[w]);
        if (ret)
-               dev_warn(&s->dev, "failed to set_mem_map\n");
+               dev_warn(&p_dev->dev, "failed to set_mem_map\n");
        mutex_unlock(&s->ops_mutex);
        return ret;
-} /* pcmcia_map_mem_page */
+}
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
 
-/** pcmcia_modify_configuration
+/**
+ * pcmcia_fixup_iowidth() - reduce io width to 8bit
+ * @p_dev: pcmcia device
  *
- * Modify a locked socket configuration
+ * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
+ * IO width to 8bit after having called pcmcia_enable_device()
+ * previously.
  */
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
-                               modconf_t *mod)
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
 {
-       struct pcmcia_socket *s;
-       config_t *c;
-       int ret;
-
-       s = p_dev->socket;
+       struct pcmcia_socket *s = p_dev->socket;
+       pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+       pccard_io_map io_on;
+       int i, ret = 0;
 
        mutex_lock(&s->ops_mutex);
-       c = p_dev->function_config;
 
-       if (!(s->state & SOCKET_PRESENT)) {
-               dev_dbg(&s->dev, "No card present\n");
-               ret = -ENODEV;
-               goto unlock;
-       }
-       if (!(c->state & CONFIG_LOCKED)) {
-               dev_dbg(&s->dev, "Configuration isnt't locked\n");
+       dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
+
+       if (!(s->state & SOCKET_PRESENT) ||
+               !(p_dev->function_config->state & CONFIG_LOCKED)) {
+               dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
                ret = -EACCES;
                goto unlock;
        }
 
-       if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
-               dev_dbg(&s->dev,
-                       "changing Vcc or IRQ is not allowed at this time\n");
-               ret = -EINVAL;
-               goto unlock;
-       }
+       io_on.speed = io_speed;
+       for (i = 0; i < MAX_IO_WIN; i++) {
+               if (!s->io[i].res)
+                       continue;
+               io_off.map = i;
+               io_on.map = i;
 
-       /* We only allow changing Vpp1 and Vpp2 to the same value */
-       if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
-           (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-               if (mod->Vpp1 != mod->Vpp2) {
-                       dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-               s->socket.Vpp = mod->Vpp1;
-               if (s->ops->set_socket(s, &s->socket)) {
-                       dev_printk(KERN_WARNING, &s->dev,
-                                  "Unable to set VPP\n");
-                       ret = -EIO;
-                       goto unlock;
-               }
-       } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
-                  (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-               dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
-               ret = -EINVAL;
-               goto unlock;
+               io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+               io_on.start = s->io[i].res->start;
+               io_on.stop = s->io[i].res->end;
+
+               s->ops->set_io_map(s, &io_off);
+               mdelay(40);
+               s->ops->set_io_map(s, &io_on);
        }
+unlock:
+       mutex_unlock(&s->ops_mutex);
 
-       if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
-               pccard_io_map io_off = { 0, 0, 0, 0, 1 };
-               pccard_io_map io_on;
-               int i;
+       return ret;
+}
+EXPORT_SYMBOL(pcmcia_fixup_iowidth);
 
-               io_on.speed = io_speed;
-               for (i = 0; i < MAX_IO_WIN; i++) {
-                       if (!s->io[i].res)
-                               continue;
-                       io_off.map = i;
-                       io_on.map = i;
 
-                       io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
-                       io_on.start = s->io[i].res->start;
-                       io_on.stop = s->io[i].res->end;
+/**
+ * pcmcia_fixup_vpp() - set Vpp to a new voltage level
+ * @p_dev: pcmcia device
+ * @new_vpp: new Vpp voltage
+ *
+ * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
+ * a new voltage level between calls to pcmcia_enable_device()
+ * and pcmcia_disable_device().
+ */
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
+{
+       struct pcmcia_socket *s = p_dev->socket;
+       int ret = 0;
 
-                       s->ops->set_io_map(s, &io_off);
-                       mdelay(40);
-                       s->ops->set_io_map(s, &io_on);
-               }
+       mutex_lock(&s->ops_mutex);
+
+       dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
+
+       if (!(s->state & SOCKET_PRESENT) ||
+               !(p_dev->function_config->state & CONFIG_LOCKED)) {
+               dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
+               ret = -EACCES;
+               goto unlock;
        }
-       ret = 0;
+
+       s->socket.Vpp = new_vpp;
+       if (s->ops->set_socket(s, &s->socket)) {
+               dev_warn(&p_dev->dev, "Unable to set VPP\n");
+               ret = -EIO;
+               goto unlock;
+       }
+       p_dev->vpp = new_vpp;
+
 unlock:
        mutex_unlock(&s->ops_mutex);
 
        return ret;
-} /* modify_configuration */
-EXPORT_SYMBOL(pcmcia_modify_configuration);
+}
+EXPORT_SYMBOL(pcmcia_fixup_vpp);
 
 
+/**
+ * pcmcia_release_configuration() - physically disable a PCMCIA device
+ * @p_dev: pcmcia device
+ *
+ * pcmcia_release_configuration() is the 1:1 counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used by any
+ * driver, the Vpp voltage is set to 0, IRQs will no longer be generated,
+ * and I/O ranges will be disabled. As pcmcia_release_io() and
+ * pcmcia_release_window() still need to be called, device drivers are
+ * expected to call pcmcia_disable_device() instead.
+ */
 int pcmcia_release_configuration(struct pcmcia_device *p_dev)
 {
        pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -325,7 +359,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
        if (p_dev->_locked) {
                p_dev->_locked = 0;
                if (--(s->lock_count) == 0) {
-                       s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
+                       s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
                        s->socket.Vpp = 0;
                        s->socket.io_irq = 0;
                        s->ops->set_socket(s, &s->socket);
@@ -347,16 +381,18 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
        mutex_unlock(&s->ops_mutex);
 
        return 0;
-} /* pcmcia_release_configuration */
+}
 
 
-/** pcmcia_release_io
+/**
+ * pcmcia_release_io() - release I/O allocated by a PCMCIA device
+ * @p_dev: pcmcia device
  *
- * Release_io() releases the I/O ranges allocated by a client.  This
- * may be invoked some time after a card ejection has already dumped
- * the actual socket configuration, so if the client is "stale", we
- * don't bother checking the port ranges against the current socket
- * values.
+ * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA
+ * device.  This may be invoked some time after a card ejection has
+ * already dumped the actual socket configuration, so if the client is
+ * "stale", we don't bother checking the port ranges against the
+ * current socket values.
  */
 static int pcmcia_release_io(struct pcmcia_device *p_dev)
 {
@@ -385,6 +421,14 @@ out:
 } /* pcmcia_release_io */
 
 
+/**
+ * pcmcia_release_window() - release reserved iomem for PCMCIA devices
+ * @p_dev: pcmcia device
+ * @res: iomem resource to release
+ *
+ * pcmcia_release_window() releases &struct resource *res which was
+ * previously reserved by calling pcmcia_request_window().
+ */
 int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 {
        struct pcmcia_socket *s = p_dev->socket;
@@ -401,7 +445,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
        win = &s->win[w];
 
        if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
-               dev_dbg(&s->dev, "not releasing unknown window\n");
+               dev_dbg(&p_dev->dev, "not releasing unknown window\n");
                mutex_unlock(&s->ops_mutex);
                return -EINVAL;
        }
@@ -418,6 +462,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
                kfree(win->res);
                win->res = NULL;
        }
+       res->start = res->end = 0;
+       res->flags = IORESOURCE_MEM;
        p_dev->_win &= ~CLIENT_WIN_REQ(w);
        mutex_unlock(&s->ops_mutex);
 
@@ -426,99 +472,116 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 EXPORT_SYMBOL(pcmcia_release_window);
 
 
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-                                config_req_t *req)
+/**
+ * pcmcia_enable_device() - set up and activate a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_enable_device() physically enables a PCMCIA device. It parses
+ * the flags passed to in @flags and stored in @p_dev->flags and sets up
+ * the Vpp voltage, enables the speaker line, I/O ports and store proper
+ * values to configuration registers.
+ */
+int pcmcia_enable_device(struct pcmcia_device *p_dev)
 {
        int i;
-       u_int base;
+       unsigned int base;
        struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
        pccard_io_map iomap;
+       unsigned char status = 0;
+       unsigned char ext_status = 0;
+       unsigned char option = 0;
+       unsigned int flags = p_dev->config_flags;
 
        if (!(s->state & SOCKET_PRESENT))
                return -ENODEV;
 
-       if (req->IntType & INT_CARDBUS) {
-               dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
-               return -EINVAL;
-       }
-
        mutex_lock(&s->ops_mutex);
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED) {
                mutex_unlock(&s->ops_mutex);
-               dev_dbg(&s->dev, "Configuration is locked\n");
+               dev_dbg(&p_dev->dev, "Configuration is locked\n");
                return -EACCES;
        }
 
        /* Do power control.  We don't allow changes in Vcc. */
-       s->socket.Vpp = req->Vpp;
+       s->socket.Vpp = p_dev->vpp;
        if (s->ops->set_socket(s, &s->socket)) {
                mutex_unlock(&s->ops_mutex);
-               dev_printk(KERN_WARNING, &s->dev,
+               dev_printk(KERN_WARNING, &p_dev->dev,
                           "Unable to set socket state\n");
                return -EINVAL;
        }
 
        /* Pick memory or I/O card, DMA mode, interrupt */
-       c->IntType = req->IntType;
-       c->Attributes = req->Attributes;
-       if (req->IntType & INT_MEMORY_AND_IO)
+       if (p_dev->_io || flags & CONF_ENABLE_IRQ)
+               flags |= CONF_ENABLE_IOCARD;
+       if (flags & CONF_ENABLE_IOCARD)
                s->socket.flags |= SS_IOCARD;
-       if (req->IntType & INT_ZOOMED_VIDEO)
-               s->socket.flags |= SS_ZVCARD | SS_IOCARD;
-       if (req->Attributes & CONF_ENABLE_DMA)
-               s->socket.flags |= SS_DMA_MODE;
-       if (req->Attributes & CONF_ENABLE_SPKR)
+       if (flags & CONF_ENABLE_SPKR) {
                s->socket.flags |= SS_SPKR_ENA;
-       if (req->Attributes & CONF_ENABLE_IRQ)
+               status = CCSR_AUDIO_ENA;
+               if (!(p_dev->config_regs & PRESENT_STATUS))
+                       dev_warn(&p_dev->dev, "speaker requested, but "
+                                             "PRESENT_STATUS not set!\n");
+       }
+       if (flags & CONF_ENABLE_IRQ)
                s->socket.io_irq = s->pcmcia_irq;
        else
                s->socket.io_irq = 0;
+       if (flags & CONF_ENABLE_ESR) {
+               p_dev->config_regs |= PRESENT_EXT_STATUS;
+               ext_status = ESR_REQ_ATTN_ENA;
+       }
        s->ops->set_socket(s, &s->socket);
        s->lock_count++;
 
+       dev_dbg(&p_dev->dev,
+               "enable_device: V %d, flags %x, base %x, regs %x, idx %x\n",
+               p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs,
+               p_dev->config_index);
+
        /* Set up CIS configuration registers */
-       base = c->ConfigBase = req->ConfigBase;
-       c->CardValues = req->Present;
-       if (req->Present & PRESENT_COPY) {
-               c->Copy = req->Copy;
-               pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
-       }
-       if (req->Present & PRESENT_OPTION) {
+       base = p_dev->config_base;
+       if (p_dev->config_regs & PRESENT_COPY) {
+               u16 tmp = 0;
+               dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n");
+               pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
+       }
+       if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
+               u16 tmp = 0;
+               dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n");
+               pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
+       }
+       if (p_dev->config_regs & PRESENT_OPTION) {
                if (s->functions == 1) {
-                       c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+                       option = p_dev->config_index & COR_CONFIG_MASK;
                } else {
-                       c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
-                       c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
-                       if (req->Present & PRESENT_IOBASE_0)
-                               c->Option |= COR_ADDR_DECODE;
+                       option = p_dev->config_index & COR_MFC_CONFIG_MASK;
+                       option |= COR_FUNC_ENA|COR_IREQ_ENA;
+                       if (p_dev->config_regs & PRESENT_IOBASE_0)
+                               option |= COR_ADDR_DECODE;
                }
-               if ((req->Attributes & CONF_ENABLE_IRQ) &&
-                       !(req->Attributes & CONF_ENABLE_PULSE_IRQ))
-                       c->Option |= COR_LEVEL_REQ;
-               pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+               if ((flags & CONF_ENABLE_IRQ) &&
+                       !(flags & CONF_ENABLE_PULSE_IRQ))
+                       option |= COR_LEVEL_REQ;
+               pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
                mdelay(40);
        }
-       if (req->Present & PRESENT_STATUS) {
-               c->Status = req->Status;
-               pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
-       }
-       if (req->Present & PRESENT_PIN_REPLACE) {
-               c->Pin = req->Pin;
-               pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
-       }
-       if (req->Present & PRESENT_EXT_STATUS) {
-               c->ExtStatus = req->ExtStatus;
-               pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
-       }
-       if (req->Present & PRESENT_IOBASE_0) {
+       if (p_dev->config_regs & PRESENT_STATUS)
+               pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
+
+       if (p_dev->config_regs & PRESENT_EXT_STATUS)
+               pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
+                                       &ext_status);
+
+       if (p_dev->config_regs & PRESENT_IOBASE_0) {
                u8 b = c->io[0].start & 0xff;
                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
                b = (c->io[0].start >> 8) & 0xff;
                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
        }
-       if (req->Present & PRESENT_IOSIZE) {
+       if (p_dev->config_regs & PRESENT_IOSIZE) {
                u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
                pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
        }
@@ -549,14 +612,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        p_dev->_locked = 1;
        mutex_unlock(&s->ops_mutex);
        return 0;
-} /* pcmcia_request_configuration */
-EXPORT_SYMBOL(pcmcia_request_configuration);
+} /* pcmcia_enable_device */
+EXPORT_SYMBOL(pcmcia_enable_device);
 
 
 /**
  * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
  *
- * pcmcia_request_io() attepts to reserve the IO port ranges specified in
+ * pcmcia_request_io() attempts to reserve the IO port ranges specified in
  * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
  * "start" value is the requested start of the IO port resource; "end"
  * reflects the number of ports requested. The number of IO lines requested
@@ -569,19 +633,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
        int ret = -EINVAL;
 
        mutex_lock(&s->ops_mutex);
-       dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
+       dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR",
+               &c->io[0], &c->io[1]);
 
        if (!(s->state & SOCKET_PRESENT)) {
-               dev_dbg(&s->dev, "pcmcia_request_io: No card present\n");
+               dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n");
                goto out;
        }
 
        if (c->state & CONFIG_LOCKED) {
-               dev_dbg(&s->dev, "Configuration is locked\n");
+               dev_dbg(&p_dev->dev, "Configuration is locked\n");
                goto out;
        }
        if (c->state & CONFIG_IO_REQ) {
-               dev_dbg(&s->dev, "IO already configured\n");
+               dev_dbg(&p_dev->dev, "IO already configured\n");
                goto out;
        }
 
@@ -592,7 +657,13 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
        if (c->io[1].end) {
                ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
                if (ret) {
+                       struct resource tmp = c->io[0];
+                       /* release the previously allocated resource */
                        release_io_space(s, &c->io[0]);
+                       /* but preserve the settings, for they worked... */
+                       c->io[0].end = resource_size(&tmp);
+                       c->io[0].start = tmp.start;
+                       c->io[0].flags = tmp.flags;
                        goto out;
                }
        } else
@@ -601,7 +672,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
        c->state |= CONFIG_IO_REQ;
        p_dev->_io = 1;
 
-       dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR",
+       dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR",
                &c->io[0], &c->io[1]);
 out:
        mutex_unlock(&s->ops_mutex);
@@ -613,11 +684,13 @@ EXPORT_SYMBOL(pcmcia_request_io);
 
 /**
  * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
  *
- * pcmcia_request_irq() is a wrapper around request_irq which will allow
+ * pcmcia_request_irq() is a wrapper around request_irq() which allows
  * the PCMCIA core to clean up the registration in pcmcia_disable_device().
  * Drivers are free to use request_irq() directly, but then they need to
- * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ
+ * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
  * handlers are allowed.
  */
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
@@ -640,12 +713,14 @@ EXPORT_SYMBOL(pcmcia_request_irq);
 
 /**
  * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
  *
- * pcmcia_request_exclusive_irq() is a wrapper around request_irq which
+ * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which
  * attempts first to request an exclusive IRQ. If it fails, it also accepts
  * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
  * IRQ sharing and either use request_irq directly (then they need to call
- * free_irq themselves, too), or the pcmcia_request_irq() function.
+ * free_irq() themselves, too), or the pcmcia_request_irq() function.
  */
 int __must_check
 __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
@@ -786,38 +861,47 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev)
 }
 
 
-/** pcmcia_request_window
+/**
+ * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
+ * @res: &struct resource pointing to p_dev->resource[2..5]
+ * @speed: access speed
  *
- * Request_window() establishes a mapping between card memory space
- * and system memory space.
+ * pcmcia_request_window() attepts to reserve an iomem ranges specified in
+ * &struct resource @res pointing to one of the entries in
+ * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the
+ * requested start of the IO mem resource; "end" reflects the size
+ * requested.
  */
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+                       unsigned int speed)
 {
        struct pcmcia_socket *s = p_dev->socket;
        pccard_mem_map *win;
        u_long align;
-       struct resource *res;
        int w;
 
+       dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed);
+
        if (!(s->state & SOCKET_PRESENT)) {
-               dev_dbg(&s->dev, "No card present\n");
+               dev_dbg(&p_dev->dev, "No card present\n");
                return -ENODEV;
        }
 
        /* Window size defaults to smallest available */
-       if (req->Size == 0)
-               req->Size = s->map_size;
-       align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
-       if (req->Size & (s->map_size-1)) {
-               dev_dbg(&s->dev, "invalid map size\n");
+       if (res->end == 0)
+               res->end = s->map_size;
+       align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
+       if (res->end & (s->map_size-1)) {
+               dev_dbg(&p_dev->dev, "invalid map size\n");
                return -EINVAL;
        }
-       if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
-           (req->Base & (align-1))) {
-               dev_dbg(&s->dev, "invalid base address\n");
+       if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
+           (res->start & (align-1))) {
+               dev_dbg(&p_dev->dev, "invalid base address\n");
                return -EINVAL;
        }
-       if (req->Base)
+       if (res->start)
                align = 0;
 
        /* Allocate system memory window */
@@ -826,7 +910,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
                if (!(s->state & SOCKET_WIN_REQ(w)))
                        break;
        if (w == MAX_WIN) {
-               dev_dbg(&s->dev, "all windows are used already\n");
+               dev_dbg(&p_dev->dev, "all windows are used already\n");
                mutex_unlock(&s->ops_mutex);
                return -EINVAL;
        }
@@ -834,10 +918,10 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
        win = &s->win[w];
 
        if (!(s->features & SS_CAP_STATIC_MAP)) {
-               win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
+               win->res = pcmcia_find_mem_region(res->start, res->end, align,
                                                0, s);
                if (!win->res) {
-                       dev_dbg(&s->dev, "allocating mem region failed\n");
+                       dev_dbg(&p_dev->dev, "allocating mem region failed\n");
                        mutex_unlock(&s->ops_mutex);
                        return -EINVAL;
                }
@@ -846,12 +930,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 
        /* Configure the socket controller */
        win->map = w+1;
-       win->flags = req->Attributes;
-       win->speed = req->AccessSpeed;
+       win->flags = res->flags & WIN_FLAGS_MAP;
+       win->speed = speed;
        win->card_start = 0;
 
        if (s->ops->set_mem_map(s, win) != 0) {
-               dev_dbg(&s->dev, "failed to set memory mapping\n");
+               dev_dbg(&p_dev->dev, "failed to set memory mapping\n");
                mutex_unlock(&s->ops_mutex);
                return -EIO;
        }
@@ -859,33 +943,45 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 
        /* Return window handle */
        if (s->features & SS_CAP_STATIC_MAP)
-               req->Base = win->static_start;
+               res->start = win->static_start;
        else
-               req->Base = win->res->start;
+               res->start = win->res->start;
 
        /* convert to new-style resources */
-       res = p_dev->resource[w + MAX_IO_WIN];
-       res->start = req->Base;
-       res->end = req->Base + req->Size - 1;
-       res->flags &= ~IORESOURCE_BITS;
-       res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
-       res->flags |= IORESOURCE_MEM;
+       res->end += res->start - 1;
+       res->flags &= ~WIN_FLAGS_REQ;
+       res->flags |= (win->map << 2) | IORESOURCE_MEM;
        res->parent = win->res;
        if (win->res)
                request_resource(&iomem_resource, res);
 
-       dev_dbg(&s->dev, "request_window results in %pR\n", res);
+       dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
 
        mutex_unlock(&s->ops_mutex);
-       *wh = res;
 
        return 0;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
 
+
+/**
+ * pcmcia_disable_device() - disable and clean up a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_disable_device() is the driver-callable counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used,
+ * drivers are expected to clean up and disable the device by calling
+ * this function. Any I/O ranges (iomem and ioports) will be released,
+ * the Vpp voltage will be set to 0, and IRQs will no longer be
+ * generated -- at least if there is no other card function (of
+ * multifunction devices) being used.
+ */
 void pcmcia_disable_device(struct pcmcia_device *p_dev)
 {
        int i;
+
+       dev_dbg(&p_dev->dev, "disabling device\n");
+
        for (i = 0; i < MAX_WIN; i++) {
                struct resource *res = p_dev->resource[MAX_IO_WIN + i];
                if (res->flags & WIN_FLAGS_REQ)
index b8a869af0f4410dd25a3cb0b4b5ace093ea5d6a5..8cbfa067171f8a1264dbc95b195928bd24833982 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 
@@ -646,7 +645,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
        if (!pci_resource_start(dev, 0)) {
                dev_warn(&dev->dev, "refusing to load the driver as the "
                        "io_base is NULL.\n");
-               goto err_out_free_mem;
+               goto err_out_disable;
        }
 
        dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
index 8510c35d2952e5a264877632f22954c0de85c77f..523eb691c30b954e3a14d05f4b4e91fc3d27675c 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
index 4e80421fd9084d02433aea7f1c0561edcd2c6192..aa628ed0e9f48178ca3ac9b1fbba39a370877228 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
index 96f348b35fdea356daabb8b1836d438b163ca117..b187555d4388d394345f06997ffaa39361ed1de3 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
index e09851480295dd22260cea8c7609acc9bf6d0b56..945857f8c2843d6d258769f54629562395fc088a 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #include <asm/hardware/scoop.h>
index 6f1a86b43c606ac5e21b9353363da911cc53c314..689e3c02edb819e7c41190787d30d55e06de1131 100644 (file)
@@ -627,8 +627,6 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
 
        pcmcia_unregister_socket(&skt->socket);
 
-       flush_scheduled_work();
-
        skt->ops->hw_shutdown(skt);
 
        soc_common_pcmcia_config_skt(skt, &dead_socket);
@@ -720,8 +718,6 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
        pcmcia_unregister_socket(&skt->socket);
 
  out_err_7:
-       flush_scheduled_work();
-
        skt->ops->hw_shutdown(skt);
  out_err_6:
        list_del(&skt->node);
index 3fba3a679128b10547714cd672461c0ba9e563b0..bbcd5385a221ae40d5dc0ffb0d21cbf1a09de602 100644 (file)
@@ -11,7 +11,6 @@
 
 /* include the world */
 #include <linux/cpufreq.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
index cb0d3ace18bd5b6113512e12a9c42c1142393468..71aeed93037c57485b330ee703efdc9b5bae4198 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
index be0d841c7ebd9d9e2bb1407a4165ee92623105ec..310160bffe382c46ac6cda7a3c848bbcb2646d0a 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include "tcic.h"
 
index 9b3c15827e5c763208a82b212eb7ab6cc2e9919f..c6d36b3a6ce89b04fb84540be5a32203fb5405b2 100644 (file)
@@ -461,7 +461,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
 {
        vrc4173_socket_t *socket;
        unsigned long start, len, flags;
-       int slot, err;
+       int slot, err, ret;
 
        slot = vrc4173_cardu_slots++;
        socket = &cardu_sockets[slot];
@@ -474,43 +474,63 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
                return err;
 
        start = pci_resource_start(dev, 0);
-       if (start == 0)
-               return -ENODEV;
+       if (start == 0) {
+               ret = -ENODEV;
+               goto disable;
+       }
 
        len = pci_resource_len(dev, 0);
-       if (len == 0)
-               return -ENODEV;
+       if (len == 0) {
+               ret = -ENODEV;
+               goto disable;
+       }
 
-       if (((flags = pci_resource_flags(dev, 0)) & IORESOURCE_MEM) == 0)
-               return -EBUSY;
+       flags = pci_resource_flags(dev, 0);
+       if ((flags & IORESOURCE_MEM) == 0) {
+               ret = -EBUSY;
+               goto disable;
+       }
 
-       if ((err = pci_request_regions(dev, socket->name)) < 0)
-               return err;
+       err = pci_request_regions(dev, socket->name);
+       if (err < 0) {
+               ret = err;
+               goto disable;
+       }
 
        socket->base = ioremap(start, len);
-       if (socket->base == NULL)
-               return -ENODEV;
+       if (socket->base == NULL) {
+               ret = -ENODEV;
+               goto release;
+       }
 
        socket->dev = dev;
 
        socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1);
        if (socket->pcmcia_socket == NULL) {
-               iounmap(socket->base);
-               socket->base = NULL;
-               return -ENOMEM;
+               ret =  -ENOMEM;
+               goto unmap;
        }
 
        if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) {
-               pcmcia_unregister_socket(socket->pcmcia_socket);
-               socket->pcmcia_socket = NULL;
-               iounmap(socket->base);
-               socket->base = NULL;
-               return -EBUSY;
+               ret = -EBUSY;
+               goto unregister;
        }
 
        printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq);
 
        return 0;
+
+unregister:
+       pcmcia_unregister_socket(socket->pcmcia_socket);
+       socket->pcmcia_socket = NULL;
+unmap:
+       iounmap(socket->base);
+       socket->base = NULL;
+release:
+       pci_release_regions(dev);
+disable:
+       pci_disable_device(dev);
+       return ret;
 }
 
 static int __devinit vrc4173_cardu_setup(char *options)
index fa88c360c37a21f1875ba05e3fea58c3194d95ab..3b67a1b6a1972670c5c305c94b64c8677a720fb8 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
index 414d9a6f9a32c04f3908373d93c6e361b34b4ed2..408dbaa080a17863e3e926cc2d6beba42ae05c2d 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include "yenta_socket.h"
 #include "i82365.h"
index 044f430f3b4324eb031f32b3e9aeaf1307309a7d..cff7cc2c1f025295746416e86e88a07859e29154 100644 (file)
@@ -486,10 +486,12 @@ config TOPSTAR_LAPTOP
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on ACPI
+       depends on LEDS_CLASS
+       depends on NEW_LEDS
+       depends on BACKLIGHT_CLASS_DEVICE
        depends on INPUT
        depends on RFKILL || RFKILL = n
        select INPUT_POLLDEV
-       select BACKLIGHT_CLASS_DEVICE
        ---help---
          This driver adds support for access to certain system settings
          on "legacy free" Toshiba laptops.  These laptops can be recognized by
index f15516374987cef2cf0bae21383259759c4095a0..c1741142a4cb64c3cf1c705bbd1385c03d89778c 100644 (file)
@@ -79,12 +79,13 @@ struct bios_args {
        u32 command;
        u32 commandtype;
        u32 datasize;
-       char *data;
+       u32 data;
 };
 
 struct bios_return {
        u32 sigpass;
        u32 return_code;
+       u32 value;
 };
 
 struct key_entry {
@@ -148,7 +149,7 @@ static struct platform_driver hp_wmi_driver = {
  *       buffer = kzalloc(128, GFP_KERNEL);
  *       ret = hp_wmi_perform_query(0x7, 0, buffer, 128)
  */
-static int hp_wmi_perform_query(int query, int write, char *buffer,
+static int hp_wmi_perform_query(int query, int write, u32 *buffer,
                                int buffersize)
 {
        struct bios_return bios_return;
@@ -159,7 +160,7 @@ static int hp_wmi_perform_query(int query, int write, char *buffer,
                .command = write ? 0x2 : 0x1,
                .commandtype = query,
                .datasize = buffersize,
-               .data = buffer,
+               .data = *buffer,
        };
        struct acpi_buffer input = { sizeof(struct bios_args), &args };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -177,29 +178,14 @@ static int hp_wmi_perform_query(int query, int write, char *buffer,
 
        bios_return = *((struct bios_return *)obj->buffer.pointer);
 
-       if (bios_return.return_code) {
-               printk(KERN_WARNING PREFIX "Query %d returned %d\n", query,
-                      bios_return.return_code);
-               kfree(obj);
-               return bios_return.return_code;
-       }
-       if (obj->buffer.length - sizeof(bios_return) > buffersize) {
-               kfree(obj);
-               return -EINVAL;
-       }
-
-       memset(buffer, 0, buffersize);
-       memcpy(buffer,
-              ((char *)obj->buffer.pointer) + sizeof(struct bios_return),
-              obj->buffer.length - sizeof(bios_return));
-       kfree(obj);
+       memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
        return 0;
 }
 
 static int hp_wmi_display_state(void)
 {
-       int state;
-       int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, (char *)&state,
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
                                       sizeof(state));
        if (ret)
                return -EINVAL;
@@ -208,8 +194,8 @@ static int hp_wmi_display_state(void)
 
 static int hp_wmi_hddtemp_state(void)
 {
-       int state;
-       int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, (char *)&state,
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
                                       sizeof(state));
        if (ret)
                return -EINVAL;
@@ -218,8 +204,8 @@ static int hp_wmi_hddtemp_state(void)
 
 static int hp_wmi_als_state(void)
 {
-       int state;
-       int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, (char *)&state,
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
                                       sizeof(state));
        if (ret)
                return -EINVAL;
@@ -228,8 +214,8 @@ static int hp_wmi_als_state(void)
 
 static int hp_wmi_dock_state(void)
 {
-       int state;
-       int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state,
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
                                       sizeof(state));
 
        if (ret)
@@ -240,8 +226,8 @@ static int hp_wmi_dock_state(void)
 
 static int hp_wmi_tablet_state(void)
 {
-       int state;
-       int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state,
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
                                       sizeof(state));
        if (ret)
                return ret;
@@ -256,7 +242,7 @@ static int hp_wmi_set_block(void *data, bool blocked)
        int ret;
 
        ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
-                                  (char *)&query, sizeof(query));
+                                  &query, sizeof(query));
        if (ret)
                return -EINVAL;
        return 0;
@@ -268,10 +254,10 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
 
 static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 {
-       int wireless;
+       int wireless = 0;
        int mask;
        hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-                            (char *)&wireless, sizeof(wireless));
+                            &wireless, sizeof(wireless));
        /* TBD: Pass error */
 
        mask = 0x200 << (r * 8);
@@ -284,10 +270,10 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 
 static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
 {
-       int wireless;
+       int wireless = 0;
        int mask;
        hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-                            (char *)&wireless, sizeof(wireless));
+                            &wireless, sizeof(wireless));
        /* TBD: Pass error */
 
        mask = 0x800 << (r * 8);
@@ -347,7 +333,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr,
                       const char *buf, size_t count)
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
-       int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, (char *)&tmp,
+       int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp,
                                       sizeof(tmp));
        if (ret)
                return -EINVAL;
@@ -421,7 +407,7 @@ static void hp_wmi_notify(u32 value, void *context)
        static struct key_entry *key;
        union acpi_object *obj;
        u32 event_id, event_data;
-       int key_code, ret;
+       int key_code = 0, ret;
        u32 *location;
        acpi_status status;
 
@@ -475,7 +461,7 @@ static void hp_wmi_notify(u32 value, void *context)
                break;
        case HPWMI_BEZEL_BUTTON:
                ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
-                                          (char *)&key_code,
+                                          &key_code,
                                           sizeof(key_code));
                if (ret)
                        break;
@@ -578,9 +564,9 @@ static void cleanup_sysfs(struct platform_device *device)
 static int __devinit hp_wmi_bios_setup(struct platform_device *device)
 {
        int err;
-       int wireless;
+       int wireless = 0;
 
-       err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, (char *)&wireless,
+       err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless,
                                   sizeof(wireless));
        if (err)
                return err;
index 9024480a82288ec071e26008f616fe2d9556c18b..c44a5e8b8b82da9d06706d9cd3a3ec0fcb2b883c 100644 (file)
@@ -51,7 +51,6 @@
  * TODO:
  *   - handle CPU hotplug
  *   - provide turbo enable/disable api
- *   - make sure we can write turbo enable/disable reg based on MISC_EN
  *
  * Related documents:
  *   - CDI 403777, 403778 - Auburndale EDS vol 1 & 2
 #define THM_TC2                0xac
 #define THM_DTV                0xb0
 #define THM_ITV                0xd8
-#define   ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */
+#define   ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */
 #define   ITV_ME_SEQNO_SHIFT (16)
 #define   ITV_MCH_TEMP_MASK 0x0000ff00
 #define   ITV_MCH_TEMP_SHIFT (8)
@@ -325,6 +324,7 @@ struct ips_driver {
        bool gpu_preferred;
        bool poll_turbo_status;
        bool second_cpu;
+       bool turbo_toggle_allowed;
        struct ips_mcp_limits *limits;
 
        /* Optional MCH interfaces for if i915 is in use */
@@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
        new_limit = cur_limit - 8; /* 1W decrease */
 
        /* Clamp to SKU TDP limit */
-       if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK))
+       if (new_limit  < (ips->orig_turbo_limit & TURBO_TDP_MASK))
                new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK;
 
        thm_writew(THM_MPCPC, (new_limit * 10) / 8);
@@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips)
        if (ips->__cpu_turbo_on)
                return;
 
-       on_each_cpu(do_enable_cpu_turbo, ips, 1);
+       if (ips->turbo_toggle_allowed)
+               on_each_cpu(do_enable_cpu_turbo, ips, 1);
 
        ips->__cpu_turbo_on = true;
 }
@@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
        if (!ips->__cpu_turbo_on)
                return;
 
-       on_each_cpu(do_disable_cpu_turbo, ips, 1);
+       if (ips->turbo_toggle_allowed)
+               on_each_cpu(do_disable_cpu_turbo, ips, 1);
 
        ips->__cpu_turbo_on = false;
 }
@@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips)
 {
        unsigned long flags;
        bool ret = false;
+       u32 temp_limit;
+       u32 avg_power;
+       const char *msg = "MCP limit exceeded: ";
 
        spin_lock_irqsave(&ips->turbo_status_lock, flags);
-       if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100))
-               ret = true;
-       if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit)
+
+       temp_limit = ips->mcp_temp_limit * 100;
+       if (ips->mcp_avg_temp > temp_limit) {
+               dev_info(&ips->dev->dev,
+                       "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp,
+                       temp_limit);
                ret = true;
-       spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
+       }
 
-       if (ret)
+       avg_power = ips->cpu_avg_power + ips->mch_avg_power;
+       if (avg_power > ips->mcp_power_limit) {
                dev_info(&ips->dev->dev,
-                        "MCP power or thermal limit exceeded\n");
+                       "%sAvg power %u, limit %u\n", msg, avg_power,
+                       ips->mcp_power_limit);
+               ret = true;
+       }
+
+       spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
 
        return ret;
 }
@@ -662,6 +676,27 @@ static bool mch_exceeded(struct ips_driver *ips)
        return ret;
 }
 
+/**
+ * verify_limits - verify BIOS provided limits
+ * @ips: IPS structure
+ *
+ * BIOS can optionally provide non-default limits for power and temp.  Check
+ * them here and use the defaults if the BIOS values are not provided or
+ * are otherwise unusable.
+ */
+static void verify_limits(struct ips_driver *ips)
+{
+       if (ips->mcp_power_limit < ips->limits->mcp_power_limit ||
+           ips->mcp_power_limit > 35000)
+               ips->mcp_power_limit = ips->limits->mcp_power_limit;
+
+       if (ips->mcp_temp_limit < ips->limits->core_temp_limit ||
+           ips->mcp_temp_limit < ips->limits->mch_temp_limit ||
+           ips->mcp_temp_limit > 150)
+               ips->mcp_temp_limit = min(ips->limits->core_temp_limit,
+                                         ips->limits->mch_temp_limit);
+}
+
 /**
  * update_turbo_limits - get various limits & settings from regs
  * @ips: IPS driver struct
@@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips)
        u32 hts = thm_readl(THM_HTS);
 
        ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS);
-       ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+       /* 
+        * Disable turbo for now, until we can figure out why the power figures
+        * are wrong
+        */
+       ips->cpu_turbo_enabled = false;
+
+       if (ips->gpu_busy)
+               ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+
        ips->core_power_limit = thm_readw(THM_MPCPC);
        ips->mch_power_limit = thm_readw(THM_MMGPC);
        ips->mcp_temp_limit = thm_readw(THM_PTL);
        ips->mcp_power_limit = thm_readw(THM_MPPC);
 
+       verify_limits(ips);
        /* Ignore BIOS CPU vs GPU pref */
 }
 
@@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period)
        ret = (ret * 1000) / 65535;
        *last = val;
 
-       return ret;
+       return 0;
 }
 
 static const u16 temp_decay_factor = 2;
@@ -940,7 +984,6 @@ static int ips_monitor(void *data)
                kfree(mch_samples);
                kfree(cpu_samples);
                kfree(mchp_samples);
-               kthread_stop(ips->adjust);
                return -ENOMEM;
        }
 
@@ -948,7 +991,7 @@ static int ips_monitor(void *data)
                ITV_ME_SEQNO_SHIFT;
        seqno_timestamp = get_jiffies_64();
 
-       old_cpu_power = thm_readl(THM_CEC) / 65535;
+       old_cpu_power = thm_readl(THM_CEC);
        schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
 
        /* Collect an initial average */
@@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg)
                                STS_GPL_SHIFT;
                        /* ignore EC CPU vs GPU pref */
                        ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS);
-                       ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
+                       /* 
+                        * Disable turbo for now, until we can figure
+                        * out why the power figures are wrong
+                        */
+                       ips->cpu_turbo_enabled = false;
+                       if (ips->gpu_busy)
+                               ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
                        ips->mcp_temp_limit = (sts & STS_PTL_MASK) >>
                                STS_PTL_SHIFT;
                        ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >>
                                STS_PPL_SHIFT;
+                       verify_limits(ips);
                        spin_unlock(&ips->turbo_status_lock);
 
                        thm_writeb(THM_SEC, SEC_ACK);
@@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
         * turbo manually or we'll get an illegal MSR access, even though
         * turbo will still be available.
         */
-       if (!(misc_en & IA32_MISC_TURBO_EN))
-               ; /* add turbo MSR write allowed flag if necessary */
+       if (misc_en & IA32_MISC_TURBO_EN)
+               ips->turbo_toggle_allowed = true;
+       else
+               ips->turbo_toggle_allowed = false;
 
        if (strstr(boot_cpu_data.x86_model_id, "CPU       M"))
                limits = &ips_sv_limits;
@@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
        tdp = turbo_power & TURBO_TDP_MASK;
 
        /* Sanity check TDP against CPU */
-       if (limits->mcp_power_limit != (tdp / 8) * 1000) {
-               dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n",
-                        tdp / 8, limits->mcp_power_limit / 1000);
+       if (limits->core_power_limit != (tdp / 8) * 1000) {
+               dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n",
+                        tdp / 8, limits->core_power_limit / 1000);
+               limits->core_power_limit = (tdp / 8) * 1000;
        }
 
 out:
@@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips)
        return true;
 
 out_put_busy:
-       symbol_put(i915_gpu_turbo_disable);
+       symbol_put(i915_gpu_busy);
 out_put_lower:
        symbol_put(i915_gpu_lower);
 out_put_raise:
@@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
        /* Save turbo limits & ratios */
        rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit);
 
-       ips_enable_cpu_turbo(ips);
-       ips->cpu_turbo_enabled = true;
+       ips_disable_cpu_turbo(ips);
+       ips->cpu_turbo_enabled = false;
 
-       /* Set up the work queue and monitor/adjust threads */
-       ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
-       if (IS_ERR(ips->monitor)) {
+       /* Create thermal adjust thread */
+       ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
+       if (IS_ERR(ips->adjust)) {
                dev_err(&dev->dev,
-                       "failed to create thermal monitor thread, aborting\n");
+                       "failed to create thermal adjust thread, aborting\n");
                ret = -ENOMEM;
                goto error_free_irq;
+
        }
 
-       ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
-       if (IS_ERR(ips->adjust)) {
+       /*
+        * Set up the work queue and monitor thread. The monitor thread
+        * will wake up ips_adjust thread.
+        */
+       ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
+       if (IS_ERR(ips->monitor)) {
                dev_err(&dev->dev,
-                       "failed to create thermal adjust thread, aborting\n");
+                       "failed to create thermal monitor thread, aborting\n");
                ret = -ENOMEM;
                goto error_thread_cleanup;
        }
@@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
        return ret;
 
 error_thread_cleanup:
-       kthread_stop(ips->monitor);
+       kthread_stop(ips->adjust);
 error_free_irq:
        free_irq(ips->dev->irq, ips);
 error_unmap:
index 73f8e6d726694ad918ba89fa6da7e5507885a2a7..2b11a33325e6a93bf872e67e7d1ab549b98ccc9c 100644 (file)
@@ -145,7 +145,7 @@ static void free_rar_device(struct rar_device *rar)
  */
 static struct rar_device *_rar_to_device(int rar, int *off)
 {
-       if (rar >= 0 && rar <= 3) {
+       if (rar >= 0 && rar < MRST_NUM_RAR) {
                *off = rar;
                return &my_rar_device;
        }
index 943f9084dcb11734e73064332f903320478c3c1e..6abe18e638e976f325ba92c9892bd2cc1501f4a8 100644 (file)
@@ -487,7 +487,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
                mdelay(1);
                *data = readl(ipcdev.i2c_base + I2C_DATA_ADDR);
        } else if (cmd == IPC_I2C_WRITE) {
-               writel(addr, ipcdev.i2c_base + I2C_DATA_ADDR);
+               writel(*data, ipcdev.i2c_base + I2C_DATA_ADDR);
                mdelay(1);
                writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
        } else {
index e3154ff7a39febe1c5021352f431f2d5fa243064..f200677851b8bcc508cdee1f350c3c829d31a12d 100644 (file)
@@ -2360,6 +2360,7 @@ static const struct file_operations sonypi_misc_fops = {
        .release        = sonypi_misc_release,
        .fasync         = sonypi_misc_fasync,
        .unlocked_ioctl = sonypi_misc_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice sonypi_misc_device = {
index e35ed128bdef439313a107106f36c47e03dc5b7e..2d61186ad5a2e96708fcec4beb0a8402eb2bc09f 100644 (file)
@@ -3093,7 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = {
        TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */
 };
 
-typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];
+typedef u16 tpacpi_keymap_entry_t;
+typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];
 
 static int __init hotkey_init(struct ibm_init_struct *iibm)
 {
@@ -3230,7 +3231,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        };
 
 #define TPACPI_HOTKEY_MAP_SIZE         sizeof(tpacpi_keymap_t)
-#define TPACPI_HOTKEY_MAP_TYPESIZE     sizeof(tpacpi_keymap_t[0])
+#define TPACPI_HOTKEY_MAP_TYPESIZE     sizeof(tpacpi_keymap_entry_t)
 
        int res, i;
        int status;
index 3f94edab25fa7f8551d456b2d8df34e1fc0d3ed4..e73ebefdf3e0930ba979b3a3a9b348dfe181d730 100644 (file)
@@ -31,8 +31,9 @@ static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
 static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 {
        loff_t new = -1;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
-       lock_kernel();
+       mutex_lock(&inode->i_mutex);
        switch (whence) {
        case 0:
                new = off;
@@ -44,12 +45,12 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
                new = 256 + off;
                break;
        }
-       if (new < 0 || new > 256) {
-               unlock_kernel();
-               return -EINVAL;
-       }
-       unlock_kernel();
-       return (file->f_pos = new);
+       if (new < 0 || new > 256)
+               new = -EINVAL;
+       else
+               file->f_pos = new;
+       mutex_unlock(&inode->i_mutex);
+       return new;
 }
 
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
index 936bae560fa1f730255bde8a94c9493c953efdfd..dc628cb2e762803b6f3374d33a99feae5b08640c 100644 (file)
@@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source)
                empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
                now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
                avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+               break;
        case SOURCE_VOLTAGE:
                full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
                empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
index c61ffec2ff106ca7aa153dac55cebf5a77b495b1..2a10cd361181292f9d6bbef7ef38cda9772c839b 100644 (file)
@@ -185,8 +185,8 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop)
 {
        u32 data[3];
        u8 *p = (u8 *)&data[1];
-       int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY,
-                               IPCMSG_BATTERY, NULL, 0, data, 3);
+       int err = intel_scu_ipc_command(IPCMSG_BATTERY,
+                               IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3);
 
        prop->capacity = data[0];
        prop->crnt = *p++;
@@ -207,7 +207,7 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop)
 
 static int pmic_scu_ipc_set_charger(int charger)
 {
-       return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY);
+       return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger);
 }
 
 /**
index 7d149a8d8d9b6cb7fe92f73b71536a723cbf6249..2ce2eb71d0f5be88e03495ea1de06e16902a461a 100644 (file)
@@ -215,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
        struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
        int ret = -EINVAL;
 
-       if (info->vol_table && (index < (2 << info->vol_nbits))) {
+       if (info->vol_table && (index < (1 << info->vol_nbits))) {
                ret = info->vol_table[index];
                if (info->slope_double)
                        ret <<= 1;
@@ -233,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
                max_uV = max_uV >> 1;
        }
        if (info->vol_table) {
-               for (i = 0; i < (2 << info->vol_nbits); i++) {
+               for (i = 0; i < (1 << info->vol_nbits); i++) {
                        if (!info->vol_table[i])
                                break;
                        if ((min_uV <= info->vol_table[i])
index 11790990277a3dbd9a96ca2ba398f505480f5e19..b349266a43de63c150b92ab36c8b49274958392b 100644 (file)
@@ -634,12 +634,9 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
                                "%s: failed to register regulator %s err %d\n",
                                __func__, ab3100_regulator_desc[i].name,
                                err);
-                       i--;
                        /* remove the already registered regulators */
-                       while (i > 0) {
+                       while (--i >= 0)
                                regulator_unregister(ab3100_regulators[i].rdev);
-                               i--;
-                       }
                        return err;
                }
 
index dc3f1a491675abe371a483f862b01b60d1489a47..28c7ae67cec9ea1d573c94b30d8732f7770340b0 100644 (file)
@@ -157,7 +157,7 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
        if (info->fixed_uV)
                return info->fixed_uV;
 
-       if (selector > info->voltages_len)
+       if (selector >= info->voltages_len)
                return -EINVAL;
 
        return info->supported_voltages[selector];
@@ -344,13 +344,14 @@ static inline struct ab8500_regulator_info *find_regulator_info(int id)
 static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
-       struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev);
+       struct ab8500_platform_data *pdata;
        int i, err;
 
        if (!ab8500) {
                dev_err(&pdev->dev, "null mfd parent\n");
                return -EINVAL;
        }
+       pdata = dev_get_platdata(ab8500->dev);
 
        /* register all regulators */
        for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
@@ -368,11 +369,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                        info->desc.name);
                        /* when we fail, un-register all earlier regulators */
-                       i--;
-                       while (i > 0) {
+                       while (--i >= 0) {
                                info = &ab8500_regulator_info[i];
                                regulator_unregister(info->regulator);
-                               i--;
                        }
                        return err;
                }
index d59d2f2314afc999b8c9b6b9b9eb1c68df02b08f..a4be41614eebd41fa5733c09a7e9645c64c72c59 100644 (file)
@@ -25,7 +25,7 @@ struct ad5398_chip_info {
        unsigned int current_level;
        unsigned int current_mask;
        unsigned int current_offset;
-       struct regulator_dev rdev;
+       struct regulator_dev *rdev;
 };
 
 static int ad5398_calc_current(struct ad5398_chip_info *chip,
@@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id);
 static int __devinit ad5398_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
-       struct regulator_dev *rdev;
        struct regulator_init_data *init_data = client->dev.platform_data;
        struct ad5398_chip_info *chip;
        const struct ad5398_current_data_format *df =
@@ -233,9 +232,10 @@ static int __devinit ad5398_probe(struct i2c_client *client,
        chip->current_offset = df->current_offset;
        chip->current_mask = (chip->current_level - 1) << chip->current_offset;
 
-       rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip);
-       if (IS_ERR(rdev)) {
-               ret = PTR_ERR(rdev);
+       chip->rdev = regulator_register(&ad5398_reg, &client->dev,
+                                       init_data, chip);
+       if (IS_ERR(chip->rdev)) {
+               ret = PTR_ERR(chip->rdev);
                dev_err(&client->dev, "failed to register %s %s\n",
                        id->name, ad5398_reg.name);
                goto err;
@@ -254,9 +254,8 @@ static int __devexit ad5398_remove(struct i2c_client *client)
 {
        struct ad5398_chip_info *chip = i2c_get_clientdata(client);
 
-       regulator_unregister(&chip->rdev);
+       regulator_unregister(chip->rdev);
        kfree(chip);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 422a709d271d51d593899db82b0b930cf93f2847..cc8b337b9119de5e955aabe1935ad931a895c71a 100644 (file)
@@ -700,7 +700,7 @@ static void print_constraints(struct regulator_dev *rdev)
            constraints->min_uA != constraints->max_uA) {
                ret = _regulator_get_current_limit(rdev);
                if (ret > 0)
-                       count += sprintf(buf + count, "at %d uA ", ret / 1000);
+                       count += sprintf(buf + count, "at %d mA ", ret / 1000);
        }
 
        if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
@@ -2302,8 +2302,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        dev_set_name(&rdev->dev, "regulator.%d",
                     atomic_inc_return(&regulator_no) - 1);
        ret = device_register(&rdev->dev);
-       if (ret != 0)
+       if (ret != 0) {
+               put_device(&rdev->dev);
                goto clean;
+       }
 
        dev_set_drvdata(&rdev->dev, rdev);
 
index e49d2bd393f27cdd105f0ba9a16e7a9c96b99c62..b8cc6389a541a0e3cbc0cc4a60231c166cd2e2e1 100644 (file)
@@ -165,7 +165,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
        mutex_init(&pmic->mtx);
 
        for (i = 0; i < 3; i++) {
-               pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev,
+               pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev,
                                                init_data, pmic);
                if (IS_ERR(pmic->rdev[i])) {
                        dev_err(&i2c->dev, "failed to register %s\n", id->name);
@@ -191,8 +191,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c)
        struct isl_pmic *pmic = i2c_get_clientdata(i2c);
        int i;
 
-       i2c_set_clientdata(i2c, NULL);
-
        for (i = 0; i < 3; i++)
                regulator_unregister(pmic->rdev[i]);
 
index 8867c2710a6d07319d9ad1b6d926922b280f30dc..559cfa271a4452389577be87543ce6116bfc0ebf 100644 (file)
@@ -121,14 +121,14 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV)
        if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV)
                return -EINVAL;
 
-       if (min_uV >= 3000000)
-               selector = 3;
-       if (min_uV < 3000000)
-               selector = 2;
-       if (min_uV < 2500000)
-               selector = 1;
        if (min_uV < 1800000)
                selector = 0;
+       else if (min_uV < 2500000)
+               selector = 1;
+       else if (min_uV < 3000000)
+               selector = 2;
+       else if (min_uV >= 3000000)
+               selector = 3;
 
        if (max1586_v6_calc_voltage(selector) > max_uV)
                return -EINVAL;
index 4520ace3f7e707f82ccbf0fb068df921dfc6c2df..6b60a9c0366b3c5236fa7019844274c8b1155b3e 100644 (file)
@@ -330,7 +330,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
                /* set external clock frequency */
                info->extclk_freq = pdata->extclk_freq;
                max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
-                                info->extclk_freq);
+                                info->extclk_freq << 6);
        }
 
        if (pdata->ramp_timing) {
index ab67298799f95a573f7a901199ac966cdc79847b..a1baf1fbe00472e71845591e2d427715a720a226 100644 (file)
@@ -549,7 +549,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
        if (!max8998)
                return -ENOMEM;
 
-       size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1);
+       size = sizeof(struct regulator_dev *) * pdata->num_regulators;
        max8998->rdev = kzalloc(size, GFP_KERNEL);
        if (!max8998->rdev) {
                kfree(max8998);
@@ -557,7 +557,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
        }
 
        rdev = max8998->rdev;
+       max8998->dev = &pdev->dev;
        max8998->iodev = iodev;
+       max8998->num_regulators = pdata->num_regulators;
        platform_set_drvdata(pdev, max8998);
 
        for (i = 0; i < pdata->num_regulators; i++) {
@@ -583,7 +585,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
 
        return 0;
 err:
-       for (i = 0; i <= max8998->num_regulators; i++)
+       for (i = 0; i < max8998->num_regulators; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
 
@@ -599,7 +601,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev)
        struct regulator_dev **rdev = max8998->rdev;
        int i;
 
-       for (i = 0; i <= max8998->num_regulators; i++)
+       for (i = 0; i < max8998->num_regulators; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
 
index c239f42aa4a3efa4ba47743f3d031c00f750a81a..020f5878d7fff19bb35f58b7cb2745d10beeb484 100644 (file)
@@ -626,12 +626,6 @@ fail:
        return error;
 }
 
-/**
- * tps6507x_remove - TPS6507x driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
 static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
index 8cff1413a147f1822336160602c57d253f3d1902..51237fbb1bbb7e15f952296a9ffcb9f668418fc9 100644 (file)
@@ -133,7 +133,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
        mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
        val = (val & mask) >> ri->volt_shift;
 
-       if (val > ri->desc.n_voltages)
+       if (val >= ri->desc.n_voltages)
                BUG();
 
        return ri->voltages[val] * 1000;
@@ -150,7 +150,7 @@ static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev,
        if (ret)
                return ret;
 
-       return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit);
+       return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
 }
 
 static int tps6586x_regulator_enable(struct regulator_dev *rdev)
index e686cdb61b97cd8a54ab7fbecb1312a41e333595..9edf8f692341d89ed3645459da80be221c94eeec 100644 (file)
@@ -215,8 +215,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,
 
        case REGULATOR_MODE_IDLE:
                ret = wm831x_set_bits(wm831x, ctrl_reg,
-                                     WM831X_LDO1_LP_MODE,
-                                     WM831X_LDO1_LP_MODE);
+                                     WM831X_LDO1_LP_MODE, 0);
                if (ret < 0)
                        return ret;
 
@@ -225,10 +224,12 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,
                                      WM831X_LDO1_ON_MODE);
                if (ret < 0)
                        return ret;
+               break;
 
        case REGULATOR_MODE_STANDBY:
                ret = wm831x_set_bits(wm831x, ctrl_reg,
-                                     WM831X_LDO1_LP_MODE, 0);
+                                     WM831X_LDO1_LP_MODE,
+                                     WM831X_LDO1_LP_MODE);
                if (ret < 0)
                        return ret;
 
index 0e6ed7db93643436eadaeee5fbc48b7fd8ed599f..fe4b8a8a9dfd43a88ba9df10a9496a1b732d4328 100644 (file)
@@ -1129,7 +1129,7 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
                        mode = REGULATOR_MODE_NORMAL;
        } else if (!active && !sleep)
                mode = REGULATOR_MODE_IDLE;
-       else if (!sleep)
+       else if (sleep)
                mode = REGULATOR_MODE_STANDBY;
 
        return mode;
index d26780ea254b5d9e9e296309dc23f2640418a7f5..261a07e0fb24c0dd7cd1d05d3d60c35d184b1e38 100644 (file)
@@ -235,6 +235,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
                err = PTR_ERR(rtc);
                return err;
        }
+       platform_set_drvdata(pdev, rtc);
 
        return 0;
 }
@@ -244,6 +245,7 @@ static int __exit ab3100_rtc_remove(struct platform_device *pdev)
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
        rtc_device_unregister(rtc);
+       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index 72b2bcc2c22413b1a63e465e355ea65084ec7b8e..d4fb82d85e9b36ab61e1626236cb98bf76364ea2 100644 (file)
@@ -426,7 +426,7 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state)
                enable_irq_wake(IRQ_RTC);
                bfin_rtc_sync_pending(&pdev->dev);
        } else
-               bfin_rtc_int_clear(-1);
+               bfin_rtc_int_clear(0);
 
        return 0;
 }
@@ -435,8 +435,17 @@ static int bfin_rtc_resume(struct platform_device *pdev)
 {
        if (device_may_wakeup(&pdev->dev))
                disable_irq_wake(IRQ_RTC);
-       else
-               bfin_write_RTC_ISTAT(-1);
+
+       /*
+        * Since only some of the RTC bits are maintained externally in the
+        * Vbat domain, we need to wait for the RTC MMRs to be synced into
+        * the core after waking up.  This happens every RTC 1HZ.  Once that
+        * has happened, we can go ahead and re-enable the important write
+        * complete interrupt event.
+        */
+       while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC))
+               continue;
+       bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE);
 
        return 0;
 }
index 9daed8db83d3e5400559ac3c51c86d0e6b45f00d..9de8516e3531e70bad818747f41de4b8052486bd 100644 (file)
@@ -268,7 +268,6 @@ out_irq:
                free_irq(client->irq, client);
 
 out_free:
-       i2c_set_clientdata(client, NULL);
        kfree(ds3232);
        return ret;
 }
@@ -287,7 +286,6 @@ static int __devexit ds3232_remove(struct i2c_client *client)
        }
 
        rtc_device_unregister(ds3232->rtc);
-       i2c_set_clientdata(client, NULL);
        kfree(ds3232);
        return 0;
 }
index 66377f3e28b851eaa908c6057a9646a639e9c229..5a8daa358066a5564f61276fb9e5bccf0a3bf640 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
 #include <linux/fs.h>
@@ -68,6 +68,7 @@
 
 #define DRV_VERSION "0.05"
 
+static DEFINE_MUTEX(m41t80_rtc_mutex);
 static const struct i2c_device_id m41t80_id[] = {
        { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
        { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@@ -364,7 +365,7 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        t->time.tm_isdst = -1;
        t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
        t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
-       return rtc_valid_tm(t);
+       return 0;
 }
 
 static struct rtc_class_ops m41t80_rtc_ops = {
@@ -677,9 +678,9 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&m41t80_rtc_mutex);
        ret = wdt_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&m41t80_rtc_mutex);
 
        return ret;
 }
@@ -693,16 +694,16 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
 static int wdt_open(struct inode *inode, struct file *file)
 {
        if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-               lock_kernel();
+               mutex_lock(&m41t80_rtc_mutex);
                if (test_and_set_bit(0, &wdt_is_open)) {
-                       unlock_kernel();
+                       mutex_unlock(&m41t80_rtc_mutex);
                        return -EBUSY;
                }
                /*
                 *      Activate
                 */
                wdt_is_open = 1;
-               unlock_kernel();
+               mutex_unlock(&m41t80_rtc_mutex);
                return nonseekable_open(inode, file);
        }
        return -ENODEV;
@@ -748,6 +749,7 @@ static const struct file_operations wdt_fops = {
        .write  = wdt_write,
        .open   = wdt_open,
        .release = wdt_release,
+       .llseek = no_llseek,
 };
 
 static struct miscdevice wdt_dev = {
index 6c418fe7f288ae2deaa9f44080a749a9eaafad88..b7a6690e5b35e8744295bf212a8e0d75e0d8dd6f 100644 (file)
@@ -403,7 +403,7 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id)
        }
 
        if (request_irq(adev->irq[0], pl031_interrupt,
-                       IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) {
+                       IRQF_DISABLED, "rtc-pl031", ldata)) {
                ret = -EIO;
                goto out_no_irq;
        }
index a0d3ec89d412ac57d683fa5a446720a375dfab22..f57a87f4ae96abb367a2e08d353378b31f2a19fa 100644 (file)
@@ -310,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        s3c_rtc_setaie(alrm->enabled);
 
-       if (alrm->enabled)
-               enable_irq_wake(s3c_rtc_alarmno);
-       else
-               disable_irq_wake(s3c_rtc_alarmno);
-
        return 0;
 }
 
@@ -587,6 +582,10 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
                ticnt_en_save &= S3C64XX_RTCCON_TICEN;
        }
        s3c_rtc_enable(pdev, 0);
+
+       if (device_may_wakeup(&pdev->dev))
+               enable_irq_wake(s3c_rtc_alarmno);
+
        return 0;
 }
 
@@ -600,6 +599,10 @@ static int s3c_rtc_resume(struct platform_device *pdev)
                tmp = readb(s3c_rtc_base + S3C2410_RTCCON);
                writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
        }
+
+       if (device_may_wakeup(&pdev->dev))
+               disable_irq_wake(s3c_rtc_alarmno);
+
        return 0;
 }
 #else
index 8373ca0de8e0b00484f40d48c5813e600da920c2..38e6fa9a2012fc40cdb25ab3a0089e916d9e5c8d 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -2236,7 +2235,6 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
        if (!block)
                return -ENODEV;
 
-       lock_kernel();
        base = block->base;
        atomic_inc(&block->open_count);
        if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
@@ -2271,14 +2269,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
                goto out;
        }
 
-       unlock_kernel();
        return 0;
 
 out:
        module_put(base->discipline->owner);
 unlock:
        atomic_dec(&block->open_count);
-       unlock_kernel();
        return rc;
 }
 
@@ -2286,10 +2282,8 @@ static int dasd_release(struct gendisk *disk, fmode_t mode)
 {
        struct dasd_block *block = disk->private_data;
 
-       lock_kernel();
        atomic_dec(&block->open_count);
        module_put(block->base->discipline->owner);
-       unlock_kernel();
        return 0;
 }
 
index 7158f9528eccd74a238b85b783a094240d4de6af..c71d89dba302cd1024ec3c167e5a168c390224c9 100644 (file)
@@ -670,6 +670,7 @@ static const struct file_operations dasd_eer_fops = {
        .read           = &dasd_eer_read,
        .poll           = &dasd_eer_poll,
        .owner          = THIS_MODULE,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice *dasd_eer_dev = NULL;
index 1557214944f718fda7b239a88de50b10e97973fd..26075e95b1bad786db8ff7b0e8504521fe8f3d68 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/compat.h>
 #include <asm/ccwdev.h>
@@ -370,9 +369,8 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
        return ret;
 }
 
-static int
-dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
-             unsigned int cmd, unsigned long arg)
+int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+              unsigned int cmd, unsigned long arg)
 {
        struct dasd_block *block = bdev->bd_disk->private_data;
        void __user *argp;
@@ -430,14 +428,3 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
                return -EINVAL;
        }
 }
-
-int dasd_ioctl(struct block_device *bdev, fmode_t mode,
-              unsigned int cmd, unsigned long arg)
-{
-       int rc;
-
-       lock_kernel();
-       rc = dasd_do_ioctl(bdev, mode, cmd, arg);
-       unlock_kernel();
-       return rc;
-}
index 2bd72aa34c59c2e6d62b418a06fe8fb8747d27bc..9b43ae94beba1dea263e1687d38060e9a1f243d6 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -776,7 +775,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode)
        struct dcssblk_dev_info *dev_info;
        int rc;
 
-       lock_kernel();
        dev_info = bdev->bd_disk->private_data;
        if (NULL == dev_info) {
                rc = -ENODEV;
@@ -786,7 +784,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode)
        bdev->bd_block_size = 4096;
        rc = 0;
 out:
-       unlock_kernel();
        return rc;
 }
 
@@ -797,7 +794,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode)
        struct segment_info *entry;
        int rc;
 
-       lock_kernel();
        if (!dev_info) {
                rc = -ENODEV;
                goto out;
@@ -815,7 +811,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode)
        up_write(&dcssblk_devices_sem);
        rc = 0;
 out:
-       unlock_kernel();
        return rc;
 }
 
index c6cbcb3f925e094445d1935a6e44df791ea61f10..0e9a309b96691d6ec1c2209bb01a6f351a3a04d6 100644 (file)
 
 #ifdef CONFIG_MAGIC_SYSRQ
 static int ctrlchar_sysrq_key;
-static struct tty_struct *sysrq_tty;
 
 static void
 ctrlchar_handle_sysrq(struct work_struct *work)
 {
-       handle_sysrq(ctrlchar_sysrq_key, sysrq_tty);
+       handle_sysrq(ctrlchar_sysrq_key);
 }
 
 static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
@@ -54,7 +53,6 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
        /* racy */
        if (len == 3 && buf[1] == '-') {
                ctrlchar_sysrq_key = buf[2];
-               sysrq_tty = tty;
                schedule_work(&ctrlchar_work);
                return CTRLCHAR_SYSRQ;
        }
index 857dfcb7b35999c694bcd740d51bbb51e4bf7ecb..eb28fb01a38ad86e23580b53acf81f6a7d719745 100644 (file)
@@ -520,6 +520,7 @@ static const struct file_operations fs3270_fops = {
        .compat_ioctl    = fs3270_ioctl,        /* ioctl */
        .open            = fs3270_open,         /* open */
        .release         = fs3270_close,        /* release */
+       .llseek         = no_llseek,
 };
 
 /*
index 18d9a497863bd5c2cdc3b4ba2160bdd450a19e4e..8cd58e412b5eae2cfe3188a03f616190146f8db0 100644 (file)
@@ -305,7 +305,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
                if (kbd->sysrq) {
                        if (kbd->sysrq == K(KT_LATIN, '-')) {
                                kbd->sysrq = 0;
-                               handle_sysrq(value, kbd->tty);
+                               handle_sysrq(value);
                                return;
                        }
                        if (value == '-') {
index e021ec663ef9bf140283ebe5a7b698f01438bfb6..5b8b8592d311b4a0c3e7df7ecdb0842821907640 100644 (file)
@@ -447,6 +447,7 @@ static const struct file_operations mon_fops = {
        .release = &mon_close,
        .read    = &mon_read,
        .poll    = &mon_poll,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
index 572a1e7fd099f5da539f070a1ba3475f26ad338d..e0702d3ea33ba669223b5237f3a60acba8cfa35e 100644 (file)
@@ -274,6 +274,7 @@ static const struct file_operations monwrite_fops = {
        .open    = &monwrite_open,
        .release = &monwrite_close,
        .write   = &monwrite_write,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
index f6d72e1f2a3897a324398f70767324bafb7056e0..5707a80b96b669d055ed26572051de637ccd7ae2 100644 (file)
@@ -468,7 +468,7 @@ sclp_sync_wait(void)
        cr0_sync &= 0xffff00a0;
        cr0_sync |= 0x00000200;
        __ctl_load(cr0_sync, 0, 0);
-       __raw_local_irq_stosm(0x01);
+       __arch_local_irq_stosm(0x01);
        /* Loop until driver state indicates finished request */
        while (sclp_running_state != sclp_running_state_idle) {
                /* Check for expired request timer */
index b7de02525ec901ebbee390b2798043eb1938f4bd..f0fa9ca5cb2cfe09fda7c4e31179e7b1b7a1d083 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
@@ -45,6 +45,7 @@
 /*
  * file operation structure for tape block frontend
  */
+static DEFINE_MUTEX(tape_block_mutex);
 static int tapeblock_open(struct block_device *, fmode_t);
 static int tapeblock_release(struct gendisk *, fmode_t);
 static int tapeblock_medium_changed(struct gendisk *);
@@ -217,8 +218,7 @@ tapeblock_setup_device(struct tape_device * device)
        if (!blkdat->request_queue)
                return -ENOMEM;
 
-       elevator_exit(blkdat->request_queue->elevator);
-       rc = elevator_init(blkdat->request_queue, "noop");
+       rc = elevator_change(blkdat->request_queue, "noop");
        if (rc)
                goto cleanup_queue;
 
@@ -362,7 +362,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
        struct tape_device *    device;
        int                     rc;
 
-       lock_kernel();
+       mutex_lock(&tape_block_mutex);
        device = tape_get_device(disk->private_data);
 
        if (device->required_tapemarks) {
@@ -386,14 +386,14 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
         *       is called.
         */
        tape_state_set(device, TS_BLKUSE);
-       unlock_kernel();
+       mutex_unlock(&tape_block_mutex);
        return 0;
 
 release:
        tape_release(device);
  put_device:
        tape_put_device(device);
-       unlock_kernel();
+       mutex_unlock(&tape_block_mutex);
        return rc;
 }
 
@@ -408,11 +408,11 @@ tapeblock_release(struct gendisk *disk, fmode_t mode)
 {
        struct tape_device *device = disk->private_data;
  
-       lock_kernel();
+       mutex_lock(&tape_block_mutex);
        tape_state_set(device, TS_IN_USE);
        tape_release(device);
        tape_put_device(device);
-       unlock_kernel();
+       mutex_unlock(&tape_block_mutex);
 
        return 0;
 }
index 539045acaad42875e03f7225f0249b55251c8e30..883e2db02bd3c8351e8195b5b45b12e84dd44fbf 100644 (file)
@@ -53,6 +53,7 @@ static const struct file_operations tape_fops =
 #endif
        .open = tapechar_open,
        .release = tapechar_release,
+       .llseek = no_llseek,
 };
 
 static int tapechar_major = TAPECHAR_MAJOR;
index 04e532eec032083912e05784f7c29d71f2244104..0e7cb1a841519cdeacedcb40a2eae43d36e71b62 100644 (file)
@@ -177,6 +177,7 @@ static const struct file_operations vmcp_fops = {
        .write          = vmcp_write,
        .unlocked_ioctl = vmcp_ioctl,
        .compat_ioctl   = vmcp_ioctl,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice vmcp_dev = {
index e40a1b89286667d02329800f64c03d2fa35cfdda..0d6dc4b92cc2daacc90a2a8e5210d84b560e7a72 100644 (file)
@@ -97,6 +97,7 @@ static const struct file_operations vmlogrdr_fops = {
        .open    = vmlogrdr_open,
        .release = vmlogrdr_release,
        .read    = vmlogrdr_read,
+       .llseek  = no_llseek,
 };
 
 
index e13508c98b1a754c38509f5cb89ce06eb2044e44..12ef9121d4f0fb9027118943ac177e3585a50cc7 100644 (file)
@@ -297,6 +297,7 @@ static const struct file_operations vmwdt_fops = {
        .unlocked_ioctl = &vmwdt_ioctl,
        .write   = &vmwdt_write,
        .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice vmwdt_dev = {
index f5ea3384a4b977ca6646fbd0e37bfd168928892b..3b94044027c2c0229df51a7c6e05f4519eb00df6 100644 (file)
@@ -459,6 +459,7 @@ static const struct file_operations zcore_memmap_fops = {
        .read           = zcore_memmap_read,
        .open           = zcore_memmap_open,
        .release        = zcore_memmap_release,
+       .llseek         = no_llseek,
 };
 
 static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
@@ -486,6 +487,7 @@ static const struct file_operations zcore_reipl_fops = {
        .write          = zcore_reipl_write,
        .open           = zcore_reipl_open,
        .release        = zcore_reipl_release,
+       .llseek         = no_llseek,
 };
 
 #ifdef CONFIG_32BIT
index a83877c664a654108791d785526f22f7de4e7043..f2b77e7bfc6f389aa11061a2c9986edfd98ff735 100644 (file)
@@ -806,6 +806,7 @@ static const struct file_operations chsc_fops = {
        .open = nonseekable_open,
        .unlocked_ioctl = chsc_ioctl,
        .compat_ioctl = chsc_ioctl,
+       .llseek = no_llseek,
 };
 
 static struct miscdevice chsc_misc_device = {
index ac94ac7514590ea1f15c4ff560f61ddcbbf8df17..ca8e1c240c3c29b9dd7be4cda58be76cbaa49c63 100644 (file)
@@ -1067,6 +1067,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf,
 static const struct file_operations cio_settle_proc_fops = {
        .open = nonseekable_open,
        .write = cio_settle_write,
+       .llseek = no_llseek,
 };
 
 static int __init cio_settle_init(void)
index 41e0aaefafd5bfce4fb13422eadadec736732386..f5221749d18069dcbb7f917b0bbd09ccadba8dcc 100644 (file)
@@ -897,7 +897,8 @@ static const struct file_operations zcrypt_fops = {
        .compat_ioctl   = zcrypt_compat_ioctl,
 #endif
        .open           = zcrypt_open,
-       .release        = zcrypt_release
+       .release        = zcrypt_release,
+       .llseek         = no_llseek,
 };
 
 /*
index 6edf20b62de5bae28214275931f0db9fd1fcd1f2..2c7d2d9be4d0cd3099f63d2b2690242cc12eed50 100644 (file)
@@ -1154,7 +1154,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
                                dev_fsm, dev_fsm_len, GFP_KERNEL);
        if (priv->fsm == NULL) {
                CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
-               kfree(dev);
+               free_netdev(dev);
                return NULL;
        }
        fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
@@ -1165,7 +1165,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
                grp = ctcmpc_init_mpc_group(priv);
                if (grp == NULL) {
                        MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
-                       kfree(dev);
+                       free_netdev(dev);
                        return NULL;
                }
                tasklet_init(&grp->mpc_tasklet2,
index fcbd2b756da4caf97f32c72348281110c1716d8b..1838cda68ba8ac3258129646081a6f1cdb62b724 100644 (file)
@@ -251,8 +251,9 @@ static const struct file_operations zfcp_cfdc_fops = {
        .open = nonseekable_open,
        .unlocked_ioctl = zfcp_cfdc_dev_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl = zfcp_cfdc_dev_ioctl
+       .compat_ioctl = zfcp_cfdc_dev_ioctl,
 #endif
+       .llseek = no_llseek,
 };
 
 struct miscdevice zfcp_cfdc_misc = {
index 1690e53fb84a80e220f32a1cfb0f066b2f47282e..55f71ea9c4180c853148314c13e31df8cd608cea 100644 (file)
@@ -162,6 +162,7 @@ static const struct file_operations d7s_fops = {
        .compat_ioctl =         d7s_ioctl,
        .open =                 d7s_open,
        .release =              d7s_release,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice d7s_miscdev = {
index 078e5f4520effe3a9e75c3249495574c1de0dff8..8ce414e39489495f9da40f84fa08630ac2beb215 100644 (file)
@@ -720,6 +720,7 @@ static const struct file_operations envctrl_fops = {
 #endif
        .open =                 envctrl_open,
        .release =              envctrl_release,
+       .llseek =               noop_llseek,
 };     
 
 static struct miscdevice envctrl_dev = {
index 4942050dc5b6f0ea795d62e992368669ab1f6f6a..13f48e28a1e1f3b8e4c80c73d9cfecb9eb50c077 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
@@ -68,6 +68,8 @@
 #define JSF_PART_BITS   2      /* 2 bits of minors to cover JSF_NPART */
 #define JSF_PART_MASK   0x3    /* 2 bits mask */
 
+static DEFINE_MUTEX(jsf_mutex);
+
 /*
  * Access functions.
  * We could ioremap(), but it's easier this way.
@@ -225,7 +227,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
 {
        loff_t ret;
 
-       lock_kernel();
+       mutex_lock(&jsf_mutex);
        switch (orig) {
                case 0:
                        file->f_pos = offset;
@@ -238,7 +240,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
                default:
                        ret = -EINVAL;
        }
-       unlock_kernel();
+       mutex_unlock(&jsf_mutex);
        return ret;
 }
 
@@ -384,18 +386,18 @@ static int jsf_ioctl_program(void __user *arg)
 
 static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
-       lock_kernel();
+       mutex_lock(&jsf_mutex);
        int error = -ENOTTY;
        void __user *argp = (void __user *)arg;
 
        if (!capable(CAP_SYS_ADMIN)) {
-               unlock_kernel();
+               mutex_unlock(&jsf_mutex);
                return -EPERM;
        }
        switch (cmd) {
        case JSFLASH_IDENT:
                if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
-                       unlock_kernel();
+                       mutex_unlock(&jsf_mutex);
                        return -EFAULT;
                }
                break;
@@ -407,7 +409,7 @@ static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                break;
        }
 
-       unlock_kernel();
+       mutex_unlock(&jsf_mutex);
        return error;
 }
 
@@ -418,17 +420,17 @@ static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
 
 static int jsf_open(struct inode * inode, struct file * filp)
 {
-       lock_kernel();
+       mutex_lock(&jsf_mutex);
        if (jsf0.base == 0) {
-               unlock_kernel();
+               mutex_unlock(&jsf_mutex);
                return -ENXIO;
        }
        if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) {
-               unlock_kernel();
+               mutex_unlock(&jsf_mutex);
                return -EBUSY;
        }
 
-       unlock_kernel();
+       mutex_unlock(&jsf_mutex);
        return 0;       /* XXX What security? */
 }
 
index e20b7bdd4c78e2409fc2783ad38e3fbb10e62e55..fcf08b3f52c1f2ee6b514c0b88ad2985c4f814da 100644 (file)
@@ -92,7 +92,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
 /* Globals */
 #define TW_DRIVER_VERSION "2.26.02.014"
+static DEFINE_MUTEX(twa_chrdev_mutex);
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -222,7 +222,8 @@ static const struct file_operations twa_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = twa_chrdev_ioctl,
        .open           = twa_chrdev_open,
-       .release        = NULL
+       .release        = NULL,
+       .llseek         = noop_llseek,
 };
 
 /* This function will complete an aen request from the isr */
@@ -658,7 +659,7 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
        int retval = TW_IOCTL_ERROR_OS_EFAULT;
        void __user *argp = (void __user *)arg;
 
-       lock_kernel();
+       mutex_lock(&twa_chrdev_mutex);
 
        /* Only let one of these through at a time */
        if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -879,7 +880,7 @@ out3:
 out2:
        mutex_unlock(&tw_dev->ioctl_lock);
 out:
-       unlock_kernel();
+       mutex_unlock(&twa_chrdev_mutex);
        return retval;
 } /* End twa_chrdev_ioctl() */
 
@@ -890,7 +891,6 @@ static int twa_chrdev_open(struct inode *inode, struct file *file)
        unsigned int minor_number;
        int retval = TW_IOCTL_ERROR_OS_ENODEV;
 
-       cycle_kernel_lock();
        minor_number = iminor(inode);
        if (minor_number >= twa_device_extension_count)
                goto out;
index f481e734aad488f762bf16e3289f72ec42105508..6a95d111d207269a920fc57c8ceee220ac5d42d8 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -77,6 +76,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "3.26.02.000"
+static DEFINE_MUTEX(twl_chrdev_mutex);
 static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
 static unsigned int twl_device_extension_count;
 static int twl_major = -1;
@@ -764,7 +764,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
        int retval = -EFAULT;
        void __user *argp = (void __user *)arg;
 
-       lock_kernel();
+       mutex_lock(&twl_chrdev_mutex);
 
        /* Only let one of these through at a time */
        if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -861,7 +861,7 @@ out3:
 out2:
        mutex_unlock(&tw_dev->ioctl_lock);
 out:
-       unlock_kernel();
+       mutex_unlock(&twl_chrdev_mutex);
        return retval;
 } /* End twl_chrdev_ioctl() */
 
@@ -876,7 +876,6 @@ static int twl_chrdev_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       cycle_kernel_lock();
        minor_number = iminor(inode);
        if (minor_number >= twl_device_extension_count)
                goto out;
@@ -890,7 +889,8 @@ static const struct file_operations twl_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = twl_chrdev_ioctl,
        .open           = twl_chrdev_open,
-       .release        = NULL
+       .release        = NULL,
+       .llseek         = noop_llseek,
 };
 
 /* This function passes sense data from firmware to scsi layer */
index 30d735ad35b5ee9a4909c686be1b6b7d0172a559..b1125341f4c89431521f978ca850135603f2c779 100644 (file)
 
 #include <linux/module.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 
 /* Globals */
 #define TW_DRIVER_VERSION "1.26.02.003"
+static DEFINE_MUTEX(tw_mutex);
 static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 static int tw_device_extension_count = 0;
 static int twe_major = -1;
@@ -900,10 +900,10 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
 
        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
-       lock_kernel();
+       mutex_lock(&tw_mutex);
        /* Only let one of these through at a time */
        if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
-               unlock_kernel();
+               mutex_unlock(&tw_mutex);
                return -EINTR;
        }
 
@@ -1034,7 +1034,7 @@ out2:
        dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
 out:
        mutex_unlock(&tw_dev->ioctl_lock);
-       unlock_kernel();
+       mutex_unlock(&tw_mutex);
        return retval;
 } /* End tw_chrdev_ioctl() */
 
@@ -1044,7 +1044,6 @@ static int tw_chrdev_open(struct inode *inode, struct file *file)
 {
        unsigned int minor_number;
 
-       cycle_kernel_lock();
        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
 
        minor_number = iminor(inode);
@@ -1059,7 +1058,8 @@ static const struct file_operations tw_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = tw_chrdev_ioctl,
        .open           = tw_chrdev_open,
-       .release        = NULL
+       .release        = NULL,
+       .llseek         = noop_llseek,
 };
 
 /* This function will free up device extension resources */
index cad6f9abaeb9cc274ae61ce006788ca236eae4cc..dae46d779c7b1c03421af3fa665c6d11979ef76e 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
@@ -76,6 +76,7 @@ MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
 MODULE_LICENSE("GPL");
 MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
+static DEFINE_MUTEX(aac_mutex);
 static LIST_HEAD(aac_devices);
 static int aac_cfg_major = -1;
 char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
@@ -678,7 +679,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
        unsigned minor_number = iminor(inode);
        int err = -ENODEV;
 
-       lock_kernel();  /* BKL pushdown: nothing else protects this list */
+       mutex_lock(&aac_mutex);  /* BKL pushdown: nothing else protects this list */
        list_for_each_entry(aac, &aac_devices, entry) {
                if (aac->id == minor_number) {
                        file->private_data = aac;
@@ -686,7 +687,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
                        break;
                }
        }
-       unlock_kernel();
+       mutex_unlock(&aac_mutex);
 
        return err;
 }
@@ -711,9 +712,9 @@ static long aac_cfg_ioctl(struct file *file,
        int ret;
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
-       lock_kernel();
+       mutex_lock(&aac_mutex);
        ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
-       unlock_kernel();
+       mutex_unlock(&aac_mutex);
 
        return ret;
 }
@@ -722,7 +723,7 @@ static long aac_cfg_ioctl(struct file *file,
 static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&aac_mutex);
        switch (cmd) {
        case FSACTL_MINIPORT_REV_CHECK:
        case FSACTL_SENDFIB:
@@ -756,7 +757,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
                ret = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&aac_mutex);
        return ret;
 }
 
@@ -1039,6 +1040,7 @@ static const struct file_operations aac_cfg_fops = {
        .compat_ioctl   = aac_compat_cfg_ioctl,
 #endif
        .open           = aac_cfg_open,
+       .llseek         = noop_llseek,
 };
 
 static struct scsi_host_template aac_driver_template = {
index 7d4d2275573c138d9e1c5223e41928defd4649aa..7f11f3e48e120ec82f1d7e26a0f1055fca771f97 100644 (file)
@@ -300,8 +300,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
                           enum iscsi_host_param param, char *buf)
 {
        struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
-       int len = 0;
-       int status;
+       int status = 0;
 
        SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);
        switch (param) {
@@ -315,7 +314,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
        default:
                return iscsi_host_get_param(shost, param, buf);
        }
-       return len;
+       return status;
 }
 
 int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
index 26350e470bccf71ea47b8dd99f387a31aff21670..877324fc594c28b606db82a12ab9b3559615ecbd 100644 (file)
@@ -368,7 +368,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
        memset(req, 0, sizeof(*req));
        wrb->tag0 |= tag;
 
-       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1);
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
                           OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
                           sizeof(*req));
index d6532187f616fefe0095ae11e071abaaddbb79b4..a15474eef5f7896fdb6cd5505fb7bf506be75f67 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/chio.h>                        /* here are all the ioctls */
 #include <linux/mutex.h>
 #include <linux/idr.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -44,6 +43,7 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
 
+static DEFINE_MUTEX(ch_mutex);
 static int init = 1;
 module_param(init, int, 0444);
 MODULE_PARM_DESC(init, \
@@ -581,19 +581,19 @@ ch_open(struct inode *inode, struct file *file)
        scsi_changer *ch;
        int minor = iminor(inode);
 
-       lock_kernel();
+       mutex_lock(&ch_mutex);
        spin_lock(&ch_index_lock);
        ch = idr_find(&ch_index_idr, minor);
 
        if (NULL == ch || scsi_device_get(ch->device)) {
                spin_unlock(&ch_index_lock);
-               unlock_kernel();
+               mutex_unlock(&ch_mutex);
                return -ENXIO;
        }
        spin_unlock(&ch_index_lock);
 
        file->private_data = ch;
-       unlock_kernel();
+       mutex_unlock(&ch_mutex);
        return 0;
 }
 
@@ -981,6 +981,7 @@ static const struct file_operations changer_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ch_ioctl_compat,
 #endif
+       .llseek         = noop_llseek,
 };
 
 static int __init init_ch_module(void)
index cd05e049d5f6ad7164c6485ee336db00933c63b0..d0c82340f0e25198d0c56101c76d0d1a00b17254 100644 (file)
@@ -1404,13 +1404,13 @@ void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
 {
        struct scsi_sense_hdr sshdr;
 
-       scmd_printk(KERN_INFO, cmd, "");
+       scmd_printk(KERN_INFO, cmd, " ");
        scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
                                 &sshdr);
        scsi_show_sense_hdr(&sshdr);
        scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
                                 &sshdr);
-       scmd_printk(KERN_INFO, cmd, "");
+       scmd_printk(KERN_INFO, cmd, " ");
        scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
 }
 EXPORT_SYMBOL(scsi_print_sense);
@@ -1453,7 +1453,7 @@ EXPORT_SYMBOL(scsi_show_result);
 
 void scsi_print_result(struct scsi_cmnd *cmd)
 {
-       scmd_printk(KERN_INFO, cmd, "");
+       scmd_printk(KERN_INFO, cmd, " ");
        scsi_show_result(cmd->result);
 }
 EXPORT_SYMBOL(scsi_print_result);
index ffc1edf5e80da4bb9158caa312a395029539a29c..23dec006338512a479e60b5e9d0c5281dde2beca 100644 (file)
@@ -49,7 +49,6 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
 #include <linux/kernel.h>      /* for printk */
 #include <linux/sched.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 
@@ -76,6 +75,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
  * Needed for our management apps
  *============================================================================
  */
+static DEFINE_MUTEX(adpt_mutex);
 static dpt_sig_S DPTI_sig = {
        {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
 #ifdef __i386__
@@ -126,6 +126,7 @@ static const struct file_operations adpt_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_adpt_ioctl,
 #endif
+       .llseek         = noop_llseek,
 };
 
 /* Structures and definitions for synchronous message posting.
@@ -1732,12 +1733,12 @@ static int adpt_open(struct inode *inode, struct file *file)
        int minor;
        adpt_hba* pHba;
 
-       lock_kernel();
+       mutex_lock(&adpt_mutex);
        //TODO check for root access
        //
        minor = iminor(inode);
        if (minor >= hba_count) {
-               unlock_kernel();
+               mutex_unlock(&adpt_mutex);
                return -ENXIO;
        }
        mutex_lock(&adpt_configuration_lock);
@@ -1748,7 +1749,7 @@ static int adpt_open(struct inode *inode, struct file *file)
        }
        if (pHba == NULL) {
                mutex_unlock(&adpt_configuration_lock);
-               unlock_kernel();
+               mutex_unlock(&adpt_mutex);
                return -ENXIO;
        }
 
@@ -1759,7 +1760,7 @@ static int adpt_open(struct inode *inode, struct file *file)
 
        pHba->in_use = 1;
        mutex_unlock(&adpt_configuration_lock);
-       unlock_kernel();
+       mutex_unlock(&adpt_mutex);
 
        return 0;
 }
@@ -2160,9 +2161,9 @@ static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
  
        inode = file->f_dentry->d_inode;
  
-       lock_kernel();
+       mutex_lock(&adpt_mutex);
        ret = adpt_ioctl(inode, file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&adpt_mutex);
 
        return ret;
 }
@@ -2176,7 +2177,7 @@ static long compat_adpt_ioctl(struct file *file,
  
        inode = file->f_dentry->d_inode;
  
-       lock_kernel();
+       mutex_lock(&adpt_mutex);
  
        switch(cmd) {
                case DPT_SIGNATURE:
@@ -2194,7 +2195,7 @@ static long compat_adpt_ioctl(struct file *file,
                        ret =  -ENOIOCTLCMD;
        }
  
-       unlock_kernel();
+       mutex_unlock(&adpt_mutex);
  
        return ret;
 }
index b860d650a563dfd6689815bce2e908c474181610..5a3f93101017b601fe98b2bbf12d9b55fd27152b 100644 (file)
 #include <linux/timer.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #ifdef GDTH_RTC
 #include <scsi/scsi_host.h>
 #include "gdth.h"
 
+static DEFINE_MUTEX(gdth_mutex);
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs);
 static irqreturn_t gdth_interrupt(int irq, void *dev_id);
@@ -372,6 +373,7 @@ static const struct file_operations gdth_fops = {
     .unlocked_ioctl   = gdth_unlocked_ioctl,
     .open    = gdth_open,
     .release = gdth_close,
+    .llseek = noop_llseek,
 };
 
 #include "gdth_proc.h"
@@ -4042,12 +4044,12 @@ static int gdth_open(struct inode *inode, struct file *filep)
 {
     gdth_ha_str *ha;
 
-    lock_kernel();
+    mutex_lock(&gdth_mutex);
     list_for_each_entry(ha, &gdth_instances, list) {
         if (!ha->sdev)
             ha->sdev = scsi_get_host_dev(ha->shost);
     }
-    unlock_kernel();
+    mutex_unlock(&gdth_mutex);
 
     TRACE(("gdth_open()\n"));
     return 0;
@@ -4615,9 +4617,9 @@ static long gdth_unlocked_ioctl(struct file *file, unsigned int cmd,
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&gdth_mutex);
        ret = gdth_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gdth_mutex);
 
        return ret;
 }
index 4f5551b5fe53d29a1a0473d3d5d799dabb46e0d5..c5d0606ad0974edab8c0326f4fadff905413c171 100644 (file)
@@ -3231,6 +3231,12 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
        misc_fw_support = readl(&cfgtable->misc_fw_support);
        use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 
+       /* The doorbell reset seems to cause lockups on some Smart
+        * Arrays (e.g. P410, P410i, maybe others).  Until this is
+        * fixed or at least isolated, avoid the doorbell reset.
+        */
+       use_doorbell = 0;
+
        rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
                goto unmap_cfgtable;
index 0b6e3228610ae08371ec9189ae95511b20e186d4..7ceb5cf12c6be3be77ccba93e4a1d550a9d80800 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsicam.h>
 
@@ -62,6 +62,7 @@ MODULE_DESCRIPTION ("LSI Logic MegaRAID legacy driver");
 MODULE_LICENSE ("GPL");
 MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
+static DEFINE_MUTEX(megadev_mutex);
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 module_param(max_cmd_per_lun, uint, 0);
 MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)");
@@ -101,6 +102,7 @@ static const struct file_operations megadev_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = megadev_unlocked_ioctl,
        .open           = megadev_open,
+       .llseek         = noop_llseek,
 };
 
 /*
@@ -3282,7 +3284,6 @@ mega_init_scb(adapter_t *adapter)
 static int
 megadev_open (struct inode *inode, struct file *filep)
 {
-       cycle_kernel_lock();
        /*
         * Only allow superuser to access private ioctl interface
         */
@@ -3701,9 +3702,9 @@ megadev_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&megadev_mutex);
        ret = megadev_ioctl(filep, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&megadev_mutex);
 
        return ret;
 }
index 41f82f76d8845ad92b7bfa765936ca513f325dee..a7008c0c24f9f44ffc5fcb663a2f83ce514b55e4 100644 (file)
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "megaraid_mm.h"
 
 
 // Entry points for char node driver
+static DEFINE_MUTEX(mraid_mm_mutex);
 static int mraid_mm_open(struct inode *, struct file *);
 static long mraid_mm_unlocked_ioctl(struct file *, uint, unsigned long);
 
@@ -75,6 +76,7 @@ static const struct file_operations lsi_fops = {
        .compat_ioctl = mraid_mm_compat_ioctl,
 #endif
        .owner  = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice megaraid_mm_dev = {
@@ -98,7 +100,6 @@ mraid_mm_open(struct inode *inode, struct file *filep)
         */
        if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
 
-       cycle_kernel_lock();
        return 0;
 }
 
@@ -224,9 +225,9 @@ mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd,
        int err;
 
        /* inconsistant: mraid_mm_compat_ioctl doesn't take the BKL */
-       lock_kernel();
+       mutex_lock(&mraid_mm_mutex);
        err = mraid_mm_ioctl(filep, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&mraid_mm_mutex);
 
        return err;
 }
index 99e4478c3f3ed4efc8d018ee2cc5f3b98d941514..51e2579a743a8c0f249577e64e520a014061e1f5 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -3557,7 +3556,6 @@ static void megasas_shutdown(struct pci_dev *pdev)
  */
 static int megasas_mgmt_open(struct inode *inode, struct file *filep)
 {
-       cycle_kernel_lock();
        /*
         * Allow only those users with admin rights
         */
@@ -3957,6 +3955,7 @@ static const struct file_operations megasas_mgmt_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = megasas_mgmt_compat_ioctl,
 #endif
+       .llseek = noop_llseek,
 };
 
 /*
index b774973f07658a3346fa10239846ee74fc3783cf..40cb8aeb21b104303246667ab137d0d4670cada5 100644 (file)
@@ -51,7 +51,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/poll.h>
 
@@ -61,6 +61,7 @@
 #include "mpt2sas_base.h"
 #include "mpt2sas_ctl.h"
 
+static DEFINE_MUTEX(_ctl_mutex);
 static struct fasync_struct *async_queue;
 static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
 
@@ -2238,9 +2239,9 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&_ctl_mutex);
        ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-       unlock_kernel();
+       mutex_unlock(&_ctl_mutex);
        return ret;
 }
 
@@ -2309,12 +2310,12 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&_ctl_mutex);
        if (cmd == MPT2COMMAND32)
                ret = _ctl_compat_mpt_command(file, cmd, arg);
        else
                ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-       unlock_kernel();
+       mutex_unlock(&_ctl_mutex);
        return ret;
 }
 #endif
@@ -2952,6 +2953,7 @@ static const struct file_operations ctl_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = _ctl_ioctl_compat,
 #endif
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice ctl_dev = {
index fda4de3440c4640f6754a1a66d143aeb5da8936c..e88bbdde49c5066b4bfb9fa2d8b5822115777cd8 100644 (file)
@@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or,
 {
        _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len);
        WARN_ON(or->in.bio || or->in.total_bytes);
-       WARN_ON(1 == (bio->bi_rw & REQ_WRITE));
+       WARN_ON(bio->bi_rw & REQ_WRITE);
        or->in.bio = bio;
        or->in.total_bytes = len;
 }
index ffdd9fdb9995bcd158ae293e353fbaf99a19171f..b31a8e3841d795154672cad902ec628bafb59c6f 100644 (file)
@@ -182,6 +182,7 @@ static const struct file_operations osd_fops = {
        .open           = osd_uld_open,
        .release        = osd_uld_release,
        .unlocked_ioctl = osd_uld_ioctl,
+       .llseek         = noop_llseek,
 };
 
 struct osd_dev *osduld_path_lookup(const char *name)
index 278b352ae78d0bdc6d5609f7d62bfc9893111a00..54de1d1af1a7377d9b0fba6e20753f0fd6854908 100644 (file)
@@ -51,7 +51,7 @@ static const char * osst_version = "0.99.4";
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -80,6 +80,7 @@ static const char * osst_version = "0.99.4";
 #include "osst_options.h"
 #include "osst_detect.h"
 
+static DEFINE_MUTEX(osst_int_mutex);
 static int max_dev = 0;
 static int write_threshold_kbs = 0;
 static int max_sg_segs = 0;
@@ -4807,9 +4808,9 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&osst_int_mutex);
        ret = __os_scsi_tape_open(inode, filp);
-       unlock_kernel();
+       mutex_unlock(&osst_int_mutex);
        return ret;
 }
 
@@ -4943,9 +4944,9 @@ static long osst_ioctl(struct file * file,
        char                * name  = tape_name(STp);
        void        __user  * p     = (void __user *)arg;
 
-       lock_kernel();
+       mutex_lock(&osst_int_mutex);
        if (mutex_lock_interruptible(&STp->lock)) {
-               unlock_kernel();
+               mutex_unlock(&osst_int_mutex);
                return -ERESTARTSYS;
        }
 
@@ -5260,14 +5261,14 @@ static long osst_ioctl(struct file * file,
        mutex_unlock(&STp->lock);
 
        retval = scsi_ioctl(STp->device, cmd_in, p);
-       unlock_kernel();
+       mutex_unlock(&osst_int_mutex);
        return retval;
 
 out:
        if (SRpnt) osst_release_request(SRpnt);
 
        mutex_unlock(&STp->lock);
-       unlock_kernel();
+       mutex_unlock(&osst_int_mutex);
 
        return retval;
 }
index 61f49bdcc0c2815cc3b28f805c711cc3e4163ff8..e77dd02eccddcba823d2f7faec9f13a97237689d 100644 (file)
@@ -49,7 +49,6 @@
 #include <scsi/scsi_host.h>
 #include "aha152x.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -86,8 +85,6 @@ static void aha152x_release_cs(struct pcmcia_device *link);
 static void aha152x_detach(struct pcmcia_device *p_dev);
 static int aha152x_config_cs(struct pcmcia_device *link);
 
-static struct pcmcia_device *dev_list;
-
 static int aha152x_probe(struct pcmcia_device *link)
 {
     scsi_info_t *info;
@@ -100,11 +97,8 @@ static int aha152x_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->end = 0x20;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    link->config_regs = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
 } /* aha152x_attach */
@@ -123,25 +117,24 @@ static void aha152x_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int aha152x_config_check(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        p_dev->io_lines = 10;
+
        /* For New Media T&J, look for a SCSI window */
-       if (cfg->io.win[0].len >= 0x20)
-               p_dev->resource[0]->start = cfg->io.win[0].base;
-       else if ((cfg->io.nwin > 1) &&
-                (cfg->io.win[1].len >= 0x20))
-               p_dev->resource[0]->start = cfg->io.win[1].base;
-       if ((cfg->io.nwin > 0) &&
-           (p_dev->resource[0]->start < 0xffff)) {
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -EINVAL;
+       if ((p_dev->resource[0]->end < 0x20) &&
+               (p_dev->resource[1]->end >= 0x20))
+               p_dev->resource[0]->start = p_dev->resource[1]->start;
+
+       if (p_dev->resource[0]->start >= 0xffff)
+               return -EINVAL;
+
+       p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+       p_dev->resource[0]->end = 0x20;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int aha152x_config_cs(struct pcmcia_device *link)
@@ -160,7 +153,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
     if (!link->irq)
            goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
     
@@ -221,9 +214,7 @@ MODULE_DEVICE_TABLE(pcmcia, aha152x_ids);
 
 static struct pcmcia_driver aha152x_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "aha152x_cs",
-       },
+       .name           = "aha152x_cs",
        .probe          = aha152x_probe,
        .remove         = aha152x_detach,
        .id_table       = aha152x_ids,
@@ -238,7 +229,6 @@ static int __init init_aha152x_cs(void)
 static void __exit exit_aha152x_cs(void)
 {
        pcmcia_unregister_driver(&aha152x_cs_driver);
-       BUG_ON(dev_list != NULL);
 }
 
 module_init(init_aha152x_cs);
index 13dbe5c48492e720c2691e24ad17930d3ee41f36..cd69c2670f810dd7ca7a738a5a75ef0ba4b28a52 100644 (file)
@@ -46,7 +46,6 @@
 #include <scsi/scsi_host.h>
 #include "fdomain.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -83,11 +82,8 @@ static int fdomain_probe(struct pcmcia_device *link)
 
        info->p_dev = link;
        link->priv = info;
-       link->resource[0]->end = 0x10;
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->conf.Present = PRESENT_OPTION;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+       link->config_regs = PRESENT_OPTION;
 
        return fdomain_config(link);
 } /* fdomain_attach */
@@ -105,14 +101,12 @@ static void fdomain_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int fdomain_config_check(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        p_dev->io_lines = 10;
-       p_dev->resource[0]->start = cfg->io.win[0].base;
+       p_dev->resource[0]->end = 0x10;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
        return pcmcia_request_io(p_dev);
 }
 
@@ -132,7 +126,7 @@ static int fdomain_config(struct pcmcia_device *link)
 
     if (!link->irq)
            goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
            goto failed;
 
@@ -194,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, fdomain_ids);
 
 static struct pcmcia_driver fdomain_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "fdomain_cs",
-       },
+       .name           = "fdomain_cs",
        .probe          = fdomain_probe,
        .remove         = fdomain_detach,
        .id_table       = fdomain_ids,
index dd9b40306f3d28f0d355a2ed72903b5fa148530f..9326c2c148803a6d1933faa0d183b6fad26be460 100644 (file)
@@ -47,7 +47,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -1531,15 +1530,6 @@ static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt)
   PCMCIA functions
 **********************************************************************/
 
-/*======================================================================
-    nsp_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-======================================================================*/
 static int nsp_cs_probe(struct pcmcia_device *link)
 {
        scsi_info_t  *info;
@@ -1557,14 +1547,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 
        nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
 
-       /* The io structure describes IO port mapping */
-       link->resource[0]->end   = 0x10;
-       link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
-
-       /* General socket configuration */
-       link->conf.Attributes    = CONF_ENABLE_IRQ;
-       link->conf.IntType       = INT_MEMORY_AND_IO;
-
        ret = nsp_cs_config(link);
 
        nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
@@ -1572,12 +1554,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 } /* nsp_cs_attach */
 
 
-/*======================================================================
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.         If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-======================================================================*/
 static void nsp_cs_detach(struct pcmcia_device *link)
 {
        nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
@@ -1590,98 +1566,36 @@ static void nsp_cs_detach(struct pcmcia_device *link)
 } /* nsp_cs_detach */
 
 
-/*======================================================================
-    nsp_cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-======================================================================*/
-
-struct nsp_cs_configdata {
-       nsp_hw_data             *data;
-       win_req_t               req;
-};
-
-static int nsp_cs_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cfg,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       struct nsp_cs_configdata *cfg_mem = priv_data;
+       nsp_hw_data             *data = priv_data;
 
-       if (cfg->index == 0)
+       if (p_dev->config_index == 0)
                return -ENODEV;
 
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-                       return -ENODEV;
-               else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-                               return -ENODEV;
-               }
-
-               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       p_dev->conf.Vpp =
-                               cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       p_dev->conf.Vpp =
-                               dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               }
-
-               /* Do we need to allocate an interrupt? */
-               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-               /* IO window settings */
-               p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-               if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-                       p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-                       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-                       p_dev->resource[0]->flags |=
-                               pcmcia_io_cfg_data_width(io->flags);
-                       p_dev->resource[0]->start = io->win[0].base;
-                       p_dev->resource[0]->end = io->win[0].len;
-                       if (io->nwin > 1) {
-                               p_dev->resource[1]->flags =
-                                       p_dev->resource[0]->flags;
-                               p_dev->resource[1]->start = io->win[1].base;
-                               p_dev->resource[1]->end = io->win[1].len;
-                       }
-                       /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(p_dev) != 0)
-                               goto next_entry;
-               }
-
-               if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-                       cistpl_mem_t    *mem =
-                               (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-                       cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-                       cfg_mem->req.Attributes |= WIN_ENABLE;
-                       cfg_mem->req.Base = mem->win[0].host_addr;
-                       cfg_mem->req.Size = mem->win[0].len;
-                       if (cfg_mem->req.Size < 0x1000)
-                               cfg_mem->req.Size = 0x1000;
-                       cfg_mem->req.AccessSpeed = 0;
-                       if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)
-                               goto next_entry;
-                       if (pcmcia_map_mem_page(p_dev, p_dev->win,
-                                       mem->win[0].card_addr) != 0)
-                               goto next_entry;
-
-                       cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
-                       cfg_mem->data->MmioLength  = cfg_mem->req.Size;
-               }
-               /* If we got this far, we're cool! */
-               return 0;
+       /* This reserves IO space but doesn't actually enable it */
+       if (pcmcia_request_io(p_dev) != 0)
+               goto next_entry;
+
+       if (resource_size(p_dev->resource[2])) {
+               p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
+                                       WIN_MEMORY_TYPE_CM |
+                                       WIN_ENABLE);
+               if (p_dev->resource[2]->end < 0x1000)
+                       p_dev->resource[2]->end = 0x1000;
+               if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
+                       goto next_entry;
+               if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
+                                               p_dev->card_addr) != 0)
+                       goto next_entry;
+
+               data->MmioAddress = (unsigned long)
+                       ioremap_nocache(p_dev->resource[2]->start,
+                                       resource_size(p_dev->resource[2]));
+               data->MmioLength  = resource_size(p_dev->resource[2]);
        }
+       /* If we got this far, we're cool! */
+       return 0;
 
 next_entry:
        nsp_dbg(NSP_DEBUG_INIT, "next");
@@ -1693,25 +1607,23 @@ static int nsp_cs_config(struct pcmcia_device *link)
 {
        int               ret;
        scsi_info_t      *info   = link->priv;
-       struct nsp_cs_configdata *cfg_mem;
        struct Scsi_Host *host;
        nsp_hw_data      *data = &nsp_data_base;
 
        nsp_dbg(NSP_DEBUG_INIT, "in");
 
-       cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL);
-       if (!cfg_mem)
-               return -ENOMEM;
-       cfg_mem->data = data;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+               CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |
+               CONF_AUTO_SET_IO;
 
-       ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+       ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
        if (ret)
                goto cs_failed;
 
        if (pcmcia_request_irq(link, nspintr))
                goto cs_failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto cs_failed;
 
@@ -1754,41 +1666,16 @@ static int nsp_cs_config(struct pcmcia_device *link)
 
        info->host = host;
 
-       /* Finally, report what we've done */
-       printk(KERN_INFO "nsp_cs: index 0x%02x: ",
-              link->conf.ConfigIndex);
-       if (link->conf.Vpp) {
-               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-       }
-       if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-               printk(", irq %d", link->irq);
-       }
-       if (link->resource[0])
-               printk(", io %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       if (link->win)
-               printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
-                      cfg_mem->req.Base+cfg_mem->req.Size-1);
-       printk("\n");
-
-       kfree(cfg_mem);
        return 0;
 
  cs_failed:
        nsp_dbg(NSP_DEBUG_INIT, "config fail");
        nsp_cs_release(link);
-       kfree(cfg_mem);
 
        return -ENODEV;
 } /* nsp_cs_config */
 
 
-/*======================================================================
-    After a card is removed, nsp_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-======================================================================*/
 static void nsp_cs_release(struct pcmcia_device *link)
 {
        scsi_info_t *info = link->priv;
@@ -1807,7 +1694,7 @@ static void nsp_cs_release(struct pcmcia_device *link)
                scsi_remove_host(info->host);
        }
 
-       if (link->win) {
+       if (resource_size(link->resource[2])) {
                if (data != NULL) {
                        iounmap((void *)(data->MmioAddress));
                }
@@ -1877,9 +1764,7 @@ MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids);
 
 static struct pcmcia_driver nsp_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "nsp_cs",
-       },
+       .name           = "nsp_cs",
        .probe          = nsp_cs_probe,
        .remove         = nsp_cs_detach,
        .id_table       = nsp_cs_ids,
@@ -1889,14 +1774,11 @@ static struct pcmcia_driver nsp_driver = {
 
 static int __init nsp_cs_init(void)
 {
-       nsp_msg(KERN_INFO, "loading...");
-
        return pcmcia_register_driver(&nsp_driver);
 }
 
 static void __exit nsp_cs_exit(void)
 {
-       nsp_msg(KERN_INFO, "unloading...");
        pcmcia_unregister_driver(&nsp_driver);
 }
 
index eb775f1a523cef364b0666db7baa01609a9d833d..9c96ca889ec97ac03d9bdaec0329b3e967c2250e 100644 (file)
@@ -48,7 +48,6 @@
 #include <scsi/scsi_host.h>
 #include "../qlogicfas408.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -156,11 +155,8 @@ static int qlogic_probe(struct pcmcia_device *link)
                return -ENOMEM;
        info->p_dev = link;
        link->priv = info;
-       link->resource[0]->end = 16;
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->conf.Present = PRESENT_OPTION;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+       link->config_regs = PRESENT_OPTION;
 
        return qlogic_config(link);
 }                              /* qlogic_attach */
@@ -178,15 +174,11 @@ static void qlogic_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int qlogic_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cfg,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        p_dev->io_lines = 10;
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
        if (p_dev->resource[0]->start == 0)
                return -ENODEV;
@@ -209,7 +201,7 @@ static int qlogic_config(struct pcmcia_device * link)
        if (!link->irq)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -264,7 +256,7 @@ static int qlogic_resume(struct pcmcia_device *link)
 {
        scsi_info_t *info = link->priv;
 
-       pcmcia_request_configuration(link, &link->conf);
+       pcmcia_enable_device(link);
        if ((info->manf_id == MANFID_MACNICA) ||
            (info->manf_id == MANFID_PIONEER) ||
            (info->manf_id == 0x0098)) {
@@ -302,9 +294,7 @@ MODULE_DEVICE_TABLE(pcmcia, qlogic_ids);
 
 static struct pcmcia_driver qlogic_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
        .name           = "qlogic_cs",
-       },
        .probe          = qlogic_probe,
        .remove         = qlogic_detach,
        .id_table       = qlogic_ids,
index 321e390c9120631f07b81434e2dfe853bf78f05c..0ae27cb5cd6f30334d6e2dd19bae9c187729733d 100644 (file)
@@ -71,7 +71,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -684,15 +683,11 @@ static struct scsi_host_template sym53c500_driver_template = {
      .shost_attrs              = SYM53C500_shost_attrs
 };
 
-static int SYM53C500_config_check(struct pcmcia_device *p_dev,
-                                 cistpl_cftable_entry_t *cfg,
-                                 cistpl_cftable_entry_t *dflt,
-                                 unsigned int vcc,
-                                 void *priv_data)
+static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        p_dev->io_lines = 10;
-       p_dev->resource[0]->start = cfg->io.win[0].base;
-       p_dev->resource[0]->end = cfg->io.win[0].len;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
        if (p_dev->resource[0]->start == 0)
                return -ENODEV;
@@ -721,7 +716,7 @@ SYM53C500_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -859,10 +854,7 @@ SYM53C500_probe(struct pcmcia_device *link)
                return -ENOMEM;
        info->p_dev = link;
        link->priv = info;
-       link->resource[0]->end = 16;
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
        return SYM53C500_config(link);
 } /* SYM53C500_attach */
@@ -881,9 +873,7 @@ MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids);
 
 static struct pcmcia_driver sym53c500_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "sym53c500_cs",
-       },
+       .name           = "sym53c500_cs",
        .probe          = SYM53C500_probe,
        .remove         = SYM53C500_detach,
        .id_table       = sym53c500_ids,
index ecc45c8b4e6bd47d851c79f82c69af9447861b25..4b8765785aeb0cb3020acdb51b1b0218e42bac34 100644 (file)
@@ -4165,6 +4165,7 @@ static const struct file_operations pmcraid_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = pmcraid_chr_ioctl,
 #endif
+       .llseek = noop_llseek,
 };
 
 
index 420238cc794eb7dd69dbe132bdf6be29752ed644..114bc5a81171993ac91c27ba600cee72adb9aed9 100644 (file)
@@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 
        qla24xx_disable_vp(vha);
 
+       vha->flags.delete_progress = 1;
+
        fc_remove_host(vha->host);
 
        scsi_remove_host(vha->host);
 
-       qla2x00_free_fcports(vha);
+       if (vha->timer_active) {
+               qla2x00_vp_stop_timer(vha);
+               DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
+               " = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
+       }
 
        qla24xx_deallocate_vp_id(vha);
 
+       /* No pending activities shall be there on the vha now */
+       DEBUG(msleep(random32()%10));  /* Just to see if something falls on
+                                       * the net we have placed below */
+
+       BUG_ON(atomic_read(&vha->vref_count));
+
+       qla2x00_free_fcports(vha);
+
        mutex_lock(&ha->vport_lock);
        ha->cur_vport_count--;
        clear_bit(vha->vp_idx, ha->vp_idx_map);
        mutex_unlock(&ha->vport_lock);
 
-       if (vha->timer_active) {
-               qla2x00_vp_stop_timer(vha);
-               DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
-                   "has stopped\n",
-                   vha->host_no, vha->vp_idx, vha));
-        }
-
        if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
                if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
                        qla_printk(KERN_WARNING, ha,
index 6cfc28a25eb3c41cca4f24b91ba575fd8d12c48d..b74e6b5743dc2931cfefa730beb351f1fa60ea57 100644 (file)
@@ -29,8 +29,6 @@
 /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
 /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
 
-/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */
-
 /*
 * Macros use for debugging the driver.
 */
index 3a432ea0c7a3548844dd4013fd06798396135a70..d2a4e1530708add3659525948aec20ce13629f91 100644 (file)
@@ -2641,6 +2641,7 @@ struct qla_hw_data {
 #define MBX_UPDATE_FLASH_ACTIVE        3
 
        struct mutex vport_lock;        /* Virtual port synchronization */
+       spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */
        struct completion mbx_cmd_comp; /* Serialize mbx access */
        struct completion mbx_intr_comp;  /* Used for completion notification */
        struct completion dcbx_comp;    /* For set port config notification */
@@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host {
                uint32_t        management_server_logged_in :1;
                uint32_t        process_response_queue  :1;
                uint32_t        difdix_supported:1;
+               uint32_t        delete_progress:1;
        } flags;
 
        atomic_t        loop_state;
@@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host {
        struct req_que *req;
        int             fw_heartbeat_counter;
        int             seconds_since_last_heartbeat;
+
+       atomic_t        vref_count;
 } scsi_qla_host_t;
 
 /*
@@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host {
         test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
         atomic_read(&ha->loop_state) == LOOP_DOWN)
 
+#define QLA_VHA_MARK_BUSY(__vha, __bail) do {               \
+       atomic_inc(&__vha->vref_count);                      \
+       mb();                                                \
+       if (__vha->flags.delete_progress) {                  \
+               atomic_dec(&__vha->vref_count);              \
+               __bail = 1;                                  \
+       } else {                                             \
+               __bail = 0;                                  \
+       }                                                    \
+} while (0)
+
+#define QLA_VHA_MARK_NOT_BUSY(__vha) do {                   \
+       atomic_dec(&__vha->vref_count);                      \
+} while (0)
+
+
 #define qla_printk(level, ha, format, arg...) \
        dev_printk(level , &((ha)->pdev->dev) , format , ## arg)
 
index d863ed2619b56853f7d29250dfd17b876fb0ee5c..9c383baebe279d0c27bb3027dc1bd337ab52603e 100644 (file)
@@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp)
 {
        struct srb_ctx *ctx = sp->ctx;
        struct srb_iocb *iocb = ctx->u.iocb_cmd;
+       struct scsi_qla_host *vha = sp->fcport->vha;
 
        del_timer_sync(&iocb->timer);
        kfree(iocb);
        kfree(ctx);
        mempool_free(sp, sp->fcport->vha->hw->srb_mempool);
+
+       QLA_VHA_MARK_NOT_BUSY(vha);
 }
 
 inline srb_t *
 qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
     unsigned long tmo)
 {
-       srb_t *sp;
+       srb_t *sp = NULL;
        struct qla_hw_data *ha = vha->hw;
        struct srb_ctx *ctx;
        struct srb_iocb *iocb;
+       uint8_t bail;
+
+       QLA_VHA_MARK_BUSY(vha, bail);
+       if (bail)
+               return NULL;
 
        sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
        if (!sp)
@@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
        iocb->timer.function = qla2x00_ctx_sp_timeout;
        add_timer(&iocb->timer);
 done:
+       if (!sp)
+               QLA_VHA_MARK_NOT_BUSY(vha);
        return sp;
 }
 
@@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
                qla2x00_init_response_q_entries(rsp);
        }
 
+       spin_lock_irqsave(&ha->vport_slock, flags);
        /* Clear RSCN queue. */
        list_for_each_entry(vp, &ha->vp_list, list) {
                vp->rscn_in_ptr = 0;
                vp->rscn_out_ptr = 0;
        }
+
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        ha->isp_ops->config_rings(vha);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                /* Bypass virtual ports of the same host. */
                found = 0;
                if (ha->num_vhosts) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&ha->vport_slock, flags);
                        list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
                                if (new_fcport->d_id.b24 == vp->d_id.b24) {
                                        found = 1;
                                        break;
                                }
                        }
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                        if (found)
                                continue;
                }
@@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *vp;
        struct scsi_qla_host *tvp;
+       unsigned long flags = 0;
 
        rval = QLA_SUCCESS;
 
@@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
                /* Check for loop ID being already in use. */
                found = 0;
                fcport = NULL;
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
                list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
                        list_for_each_entry(fcport, &vp->vp_fcports, list) {
                                if (fcport->loop_id == dev->loop_id &&
@@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
                        if (found)
                                break;
                }
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
 
                /* If not in use then it is free to use. */
                if (!found) {
@@ -3791,14 +3814,27 @@ void
 qla2x00_update_fcports(scsi_qla_host_t *base_vha)
 {
        fc_port_t *fcport;
-       struct scsi_qla_host *tvp, *vha;
+       struct scsi_qla_host *vha;
+       struct qla_hw_data *ha = base_vha->hw;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ha->vport_slock, flags);
        /* Go with deferred removal of rport references. */
-       list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list)
-               list_for_each_entry(fcport, &vha->vp_fcports, list)
+       list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
+               atomic_inc(&vha->vref_count);
+               list_for_each_entry(fcport, &vha->vp_fcports, list) {
                        if (fcport && fcport->drport &&
-                           atomic_read(&fcport->state) != FCS_UNCONFIGURED)
+                           atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
+                               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                                qla2x00_rport_del(fcport);
+
+                               spin_lock_irqsave(&ha->vport_slock, flags);
+                       }
+               }
+               atomic_dec(&vha->vref_count);
+       }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
 void
@@ -3806,7 +3842,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
-       struct scsi_qla_host *tvp;
+       unsigned long flags;
 
        vha->flags.online = 0;
        ha->flags.chip_reset_done = 0;
@@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
                qla2x00_mark_all_devices_lost(vha, 0);
-               list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list)
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
+                       atomic_inc(&vp->vref_count);
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                        qla2x00_mark_all_devices_lost(vp, 0);
+
+                       spin_lock_irqsave(&ha->vport_slock, flags);
+                       atomic_dec(&vp->vref_count);
+               }
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
        } else {
                if (!atomic_read(&vha->loop_down_timer))
                        atomic_set(&vha->loop_down_timer,
@@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
        uint8_t        status = 0;
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *vp;
-       struct scsi_qla_host *tvp;
        struct req_que *req = ha->req_q_map[0];
+       unsigned long flags;
 
        if (vha->flags.online) {
                qla2x00_abort_isp_cleanup(vha);
@@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                DEBUG(printk(KERN_INFO
                                "qla2x00_abort_isp(%ld): succeeded.\n",
                                vha->host_no));
-               list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
-                       if (vp->vp_idx)
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               list_for_each_entry(vp, &ha->vp_list, list) {
+                       if (vp->vp_idx) {
+                               atomic_inc(&vp->vref_count);
+                               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                                qla2x00_vp_abort_isp(vp);
+
+                               spin_lock_irqsave(&ha->vport_slock, flags);
+                               atomic_dec(&vp->vref_count);
+                       }
                }
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        } else {
                qla_printk(KERN_INFO, ha,
                        "qla2x00_abort_isp: **** FAILED ****\n");
@@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
        struct req_que *req = ha->req_q_map[0];
        struct rsp_que *rsp = ha->rsp_q_map[0];
        struct scsi_qla_host *vp;
-       struct scsi_qla_host *tvp;
+       unsigned long flags;
 
        status = qla2x00_init_rings(vha);
        if (!status) {
@@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
                DEBUG(printk(KERN_INFO
                        "qla82xx_restart_isp(%ld): succeeded.\n",
                        vha->host_no));
-               list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
-                       if (vp->vp_idx)
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               list_for_each_entry(vp, &ha->vp_list, list) {
+                       if (vp->vp_idx) {
+                               atomic_inc(&vp->vref_count);
+                               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                                qla2x00_vp_abort_isp(vp);
+
+                               spin_lock_irqsave(&ha->vport_slock, flags);
+                               atomic_dec(&vp->vref_count);
+                       }
                }
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        } else {
                qla_printk(KERN_INFO, ha,
                        "qla82xx_restart_isp: **** FAILED ****\n");
index 6982ba70e12af12235d8d6502c78f81c06e732aa..28f65be19dad9878f19981a18ebc60ef13bed356 100644 (file)
@@ -1706,19 +1706,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                                cp->result = DID_ERROR << 16;
                                break;
                        }
-               } else if (!lscsi_status) {
+               } else {
                        DEBUG2(qla_printk(KERN_INFO, ha,
                            "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x "
                            "of 0x%x bytes).\n", vha->host_no, cp->device->id,
                            cp->device->lun, resid, scsi_bufflen(cp)));
 
-                       cp->result = DID_ERROR << 16;
-                       break;
+                       cp->result = DID_ERROR << 16 | lscsi_status;
+                       goto check_scsi_status;
                }
 
                cp->result = DID_OK << 16 | lscsi_status;
                logit = 0;
 
+check_scsi_status:
                /*
                 * Check to see if SCSI Status is non zero. If so report SCSI
                 * Status.
index 6009b0c69488144bf21715a2a8b03192fbac56ef..a595ec8264f8d7f73823a11d0616591a7957bd63 100644 (file)
@@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
        uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
        struct qla_hw_data *ha = vha->hw;
        scsi_qla_host_t *vp;
-       scsi_qla_host_t *tvp;
+       unsigned long   flags;
 
        if (rptid_entry->entry_status != 0)
                return;
@@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                        return;
                }
 
-               list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               list_for_each_entry(vp, &ha->vp_list, list)
                        if (vp_idx == vp->vp_idx)
                                break;
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                if (!vp)
                        return;
 
index 987c5b0ca78ea22d67d074ee7d170ef1f14b52a4..2b69392a71a1fac76b50ab389a0c3e1054dce59f 100644 (file)
@@ -30,6 +30,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
 {
        uint32_t vp_id;
        struct qla_hw_data *ha = vha->hw;
+       unsigned long flags;
 
        /* Find an empty slot and assign an vp_id */
        mutex_lock(&ha->vport_lock);
@@ -44,7 +45,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
        set_bit(vp_id, ha->vp_idx_map);
        ha->num_vhosts++;
        vha->vp_idx = vp_id;
+
+       spin_lock_irqsave(&ha->vport_slock, flags);
        list_add_tail(&vha->list, &ha->vp_list);
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        mutex_unlock(&ha->vport_lock);
        return vp_id;
 }
@@ -54,12 +59,31 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
 {
        uint16_t vp_id;
        struct qla_hw_data *ha = vha->hw;
+       unsigned long flags = 0;
 
        mutex_lock(&ha->vport_lock);
+       /*
+        * Wait for all pending activities to finish before removing vport from
+        * the list.
+        * Lock needs to be held for safe removal from the list (it
+        * ensures no active vp_list traversal while the vport is removed
+        * from the queue)
+        */
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       while (atomic_read(&vha->vref_count)) {
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+               msleep(500);
+
+               spin_lock_irqsave(&ha->vport_slock, flags);
+       }
+       list_del(&vha->list);
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
        vp_id = vha->vp_idx;
        ha->num_vhosts--;
        clear_bit(vp_id, ha->vp_idx_map);
-       list_del(&vha->list);
+
        mutex_unlock(&ha->vport_lock);
 }
 
@@ -68,12 +92,17 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name)
 {
        scsi_qla_host_t *vha;
        struct scsi_qla_host *tvha;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ha->vport_slock, flags);
        /* Locate matching device in database. */
        list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
-               if (!memcmp(port_name, vha->port_name, WWN_SIZE))
+               if (!memcmp(port_name, vha->port_name, WWN_SIZE)) {
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
                        return vha;
+               }
        }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
        return NULL;
 }
 
@@ -93,6 +122,12 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name)
 static void
 qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 {
+       /*
+        * !!! NOTE !!!
+        * This function, if called in contexts other than vp create, disable
+        * or delete, please make sure this is synchronized with the
+        * delete thread.
+        */
        fc_port_t *fcport;
 
        list_for_each_entry(fcport, &vha->vp_fcports, list) {
@@ -100,7 +135,6 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
                    "loop_id=0x%04x :%x\n",
                    vha->host_no, fcport->loop_id, fcport->vp_idx));
 
-               atomic_set(&fcport->state, FCS_DEVICE_DEAD);
                qla2x00_mark_device_lost(vha, fcport, 0, 0);
                atomic_set(&fcport->state, FCS_UNCONFIGURED);
        }
@@ -194,12 +228,17 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
 void
 qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 {
-       scsi_qla_host_t *vha, *tvha;
+       scsi_qla_host_t *vha;
        struct qla_hw_data *ha = rsp->hw;
        int i = 0;
+       unsigned long flags;
 
-       list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       list_for_each_entry(vha, &ha->vp_list, list) {
                if (vha->vp_idx) {
+                       atomic_inc(&vha->vref_count);
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                        switch (mb[0]) {
                        case MBA_LIP_OCCURRED:
                        case MBA_LOOP_UP:
@@ -215,9 +254,13 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
                                qla2x00_async_event(vha, rsp, mb);
                                break;
                        }
+
+                       spin_lock_irqsave(&ha->vport_slock, flags);
+                       atomic_dec(&vha->vref_count);
                }
                i++;
        }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
 int
@@ -297,7 +340,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
        int ret;
        struct qla_hw_data *ha = vha->hw;
        scsi_qla_host_t *vp;
-       struct scsi_qla_host *tvp;
+       unsigned long flags = 0;
 
        if (vha->vp_idx)
                return;
@@ -309,10 +352,19 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
        if (!(ha->current_topology & ISP_CFG_F))
                return;
 
-       list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
-               if (vp->vp_idx)
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       list_for_each_entry(vp, &ha->vp_list, list) {
+               if (vp->vp_idx) {
+                       atomic_inc(&vp->vref_count);
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                        ret = qla2x00_do_dpc_vp(vp);
+
+                       spin_lock_irqsave(&ha->vport_slock, flags);
+                       atomic_dec(&vp->vref_count);
+               }
        }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
 int
index 915b77a6e19390026134ff697cceaa89e9dd8c99..0a71cc71eab23922e9c6aee451962f60a1e3cfb3 100644 (file)
@@ -2672,6 +2672,19 @@ qla82xx_start_scsi(srb_t *sp)
 sufficient_dsds:
                req_cnt = 1;
 
+               if (req->cnt < (req_cnt + 2)) {
+                       cnt = (uint16_t)RD_REG_DWORD_RELAXED(
+                               &reg->req_q_out[0]);
+                       if (req->ring_index < cnt)
+                               req->cnt = cnt - req->ring_index;
+                       else
+                               req->cnt = req->length -
+                                       (req->ring_index - cnt);
+               }
+
+               if (req->cnt < (req_cnt + 2))
+                       goto queuing_error;
+
                ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
                if (!sp->ctx) {
                        DEBUG(printk(KERN_INFO
@@ -3307,16 +3320,19 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        }
                        qla2xxx_wake_dpc(vha);
+                       ha->flags.fw_hung = 1;
                        if (ha->flags.mbox_busy) {
-                               ha->flags.fw_hung = 1;
                                ha->flags.mbox_int = 1;
                                DEBUG2(qla_printk(KERN_ERR, ha,
-                                   "Due to fw hung, doing premature "
-                                   "completion of mbx command\n"));
-                               complete(&ha->mbx_intr_comp);
+                                       "Due to fw hung, doing premature "
+                                       "completion of mbx command\n"));
+                               if (test_bit(MBX_INTR_WAIT,
+                                       &ha->mbx_cmd_flags))
+                                       complete(&ha->mbx_intr_comp);
                        }
                }
-       }
+       } else
+               vha->seconds_since_last_heartbeat = 0;
        vha->fw_heartbeat_counter = fw_heartbeat_counter;
 }
 
@@ -3418,13 +3434,15 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
                                "%s(): Adapter reset needed!\n", __func__);
                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        qla2xxx_wake_dpc(vha);
+                       ha->flags.fw_hung = 1;
                        if (ha->flags.mbox_busy) {
-                               ha->flags.fw_hung = 1;
                                ha->flags.mbox_int = 1;
                                DEBUG2(qla_printk(KERN_ERR, ha,
-                                   "Need reset, doing premature "
-                                   "completion of mbx command\n"));
-                               complete(&ha->mbx_intr_comp);
+                                       "Need reset, doing premature "
+                                       "completion of mbx command\n"));
+                               if (test_bit(MBX_INTR_WAIT,
+                                       &ha->mbx_cmd_flags))
+                                       complete(&ha->mbx_intr_comp);
                        }
                } else {
                        qla82xx_check_fw_alive(vha);
index 8c80b49ac1c44d875f7c033fbb1c8962723307cb..9946fac542556567bea18e0c8f3ae252267fc81b 100644 (file)
@@ -2341,16 +2341,28 @@ probe_out:
 static void
 qla2x00_remove_one(struct pci_dev *pdev)
 {
-       scsi_qla_host_t *base_vha, *vha, *temp;
+       scsi_qla_host_t *base_vha, *vha;
        struct qla_hw_data  *ha;
+       unsigned long flags;
 
        base_vha = pci_get_drvdata(pdev);
        ha = base_vha->hw;
 
-       list_for_each_entry_safe(vha, temp, &ha->vp_list, list) {
-               if (vha && vha->fc_vport)
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       list_for_each_entry(vha, &ha->vp_list, list) {
+               atomic_inc(&vha->vref_count);
+
+               if (vha && vha->fc_vport) {
+                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+
                        fc_vport_terminate(vha->fc_vport);
+
+                       spin_lock_irqsave(&ha->vport_slock, flags);
+               }
+
+               atomic_dec(&vha->vref_count);
        }
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 
        set_bit(UNLOADING, &base_vha->dpc_flags);
 
@@ -2975,10 +2987,17 @@ static struct qla_work_evt *
 qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
 {
        struct qla_work_evt *e;
+       uint8_t bail;
+
+       QLA_VHA_MARK_BUSY(vha, bail);
+       if (bail)
+               return NULL;
 
        e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
-       if (!e)
+       if (!e) {
+               QLA_VHA_MARK_NOT_BUSY(vha);
                return NULL;
+       }
 
        INIT_LIST_HEAD(&e->list);
        e->type = type;
@@ -3135,6 +3154,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                }
                if (e->flags & QLA_EVT_FLAG_FREE)
                        kfree(e);
+
+               /* For each work completed decrement vha ref count */
+               QLA_VHA_MARK_NOT_BUSY(vha);
        }
 }
 
@@ -3926,6 +3948,7 @@ static struct pci_driver qla2xxx_pci_driver = {
 
 static struct file_operations apidev_fops = {
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 /**
index e75ccb91317dcd27b030efb04f59a3f5ea4fcf16..8edbccb3232d3b68cb16d0054a444e657a452975 100644 (file)
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.03-k0"
+#define QLA2XXX_VERSION      "8.03.04-k0"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
-#define QLA_DRIVER_PATCH_VER   3
+#define QLA_DRIVER_PATCH_VER   4
 #define QLA_DRIVER_BETA_VER    0
index ad0ed212db4ad094441f7a5656639e989c980738..348fba0a8976467fa9724411699b918a9cd8b0ea 100644 (file)
@@ -1046,13 +1046,13 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 
        /* If the user actually wanted this page, we can skip the rest */
        if (page == 0)
-               return -EINVAL;
+               return 0;
 
        for (i = 0; i < min((int)buf[3], buf_len - 4); i++)
                if (buf[i + 4] == page)
                        goto found;
 
-       if (i < buf[3] && i > buf_len)
+       if (i < buf[3] && i >= buf_len - 4)
                /* ran off the end of the buffer, give us benefit of doubt */
                goto found;
        /* The device claims it doesn't support the requested page */
index 861c0b937ac988151e62429c25f0772c03b26d2e..8041fe1ab179c2c2e77386726b8082c05643b187 100644 (file)
@@ -1013,8 +1013,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 
 err_exit:
        scsi_release_buffers(cmd);
-       scsi_put_command(cmd);
        cmd->request->special = NULL;
+       scsi_put_command(cmd);
        return error;
 }
 EXPORT_SYMBOL(scsi_init_io);
index a87e21c35ef269ecae82f68e49ee235dd3d0eced..0172de19700874280447d563520feea7d901125d 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/gfp.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <net/tcp.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -323,7 +322,6 @@ static int tgt_open(struct inode *inode, struct file *file)
 {
        tx_ring.tr_idx = rx_ring.tr_idx = 0;
 
-       cycle_kernel_lock();
        return 0;
 }
 
@@ -333,6 +331,7 @@ static const struct file_operations tgt_fops = {
        .poll           = tgt_poll,
        .write          = tgt_write,
        .mmap           = tgt_mmap,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice tgt_miscdev = {
index 2714becc2eaf72fc4cb4452232b3fc67ab320586..ffa0689ee84050c13b8d347b9429e5bf64a88ee6 100644 (file)
@@ -870,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
 
        SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
 
-       if (atomic_dec_return(&sdkp->openers) && sdev->removable) {
+       if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) {
                if (scsi_block_when_processing_errors(sdev))
                        scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
        }
@@ -2625,15 +2625,15 @@ module_exit(exit_sd);
 static void sd_print_sense_hdr(struct scsi_disk *sdkp,
                               struct scsi_sense_hdr *sshdr)
 {
-       sd_printk(KERN_INFO, sdkp, "");
+       sd_printk(KERN_INFO, sdkp, " ");
        scsi_show_sense_hdr(sshdr);
-       sd_printk(KERN_INFO, sdkp, "");
+       sd_printk(KERN_INFO, sdkp, " ");
        scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
 }
 
 static void sd_print_result(struct scsi_disk *sdkp, int result)
 {
-       sd_printk(KERN_INFO, sdkp, "");
+       sd_printk(KERN_INFO, sdkp, " ");
        scsi_show_result(result);
 }
 
index 655ab920cff4cdbb6b6a3a1505dee088d5dba47c..5428d53f5a133992bef0114b785e2d54ebec1c0c 100644 (file)
@@ -49,7 +49,7 @@ static int sg_version_num = 30534;    /* 2 digits for each component */
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -103,6 +103,8 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 static int sg_add(struct device *, struct class_interface *);
 static void sg_remove(struct device *, struct class_interface *);
 
+static DEFINE_MUTEX(sg_mutex);
+
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
                                                           file descriptor list for device */
@@ -229,7 +231,7 @@ sg_open(struct inode *inode, struct file *filp)
        int res;
        int retval;
 
-       lock_kernel();
+       mutex_lock(&sg_mutex);
        nonseekable_open(inode, filp);
        SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
        sdp = sg_get_dev(dev);
@@ -314,7 +316,7 @@ sdp_put:
 sg_put:
        if (sdp)
                sg_put_dev(sdp);
-       unlock_kernel();
+       mutex_unlock(&sg_mutex);
        return retval;
 }
 
@@ -1092,9 +1094,9 @@ sg_unlocked_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&sg_mutex);
        ret = sg_ioctl(filp, cmd_in, arg);
-       unlock_kernel();
+       mutex_unlock(&sg_mutex);
 
        return ret;
 }
@@ -1351,6 +1353,7 @@ static const struct file_operations sg_fops = {
        .mmap = sg_mmap,
        .release = sg_release,
        .fasync = sg_fasync,
+       .llseek = no_llseek,
 };
 
 static struct class *sg_sysfs_class;
index ba9c3e0387ce313fc9ee588552c42101418e9f13..e148341079b5108f873a4f26d86344984a488292 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 
@@ -76,6 +75,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
         CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
         CDC_MRW|CDC_MRW_W|CDC_RAM)
 
+static DEFINE_MUTEX(sr_mutex);
 static int sr_probe(struct device *);
 static int sr_remove(struct device *);
 static int sr_done(struct scsi_cmnd *);
@@ -470,24 +470,24 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode)
        struct scsi_cd *cd;
        int ret = -ENXIO;
 
-       lock_kernel();
+       mutex_lock(&sr_mutex);
        cd = scsi_cd_get(bdev->bd_disk);
        if (cd) {
                ret = cdrom_open(&cd->cdi, bdev, mode);
                if (ret)
                        scsi_cd_put(cd);
        }
-       unlock_kernel();
+       mutex_unlock(&sr_mutex);
        return ret;
 }
 
 static int sr_block_release(struct gendisk *disk, fmode_t mode)
 {
        struct scsi_cd *cd = scsi_cd(disk);
-       lock_kernel();
+       mutex_lock(&sr_mutex);
        cdrom_release(&cd->cdi, mode);
        scsi_cd_put(cd);
-       unlock_kernel();
+       mutex_unlock(&sr_mutex);
        return 0;
 }
 
@@ -499,7 +499,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
        void __user *argp = (void __user *)arg;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&sr_mutex);
 
        /*
         * Send SCSI addressing ioctls directly to mid level, send other
@@ -529,7 +529,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
        ret = scsi_ioctl(sdev, cmd, argp);
 
 out:
-       unlock_kernel();
+       mutex_unlock(&sr_mutex);
        return ret;
 }
 
index 24211d0efa6d5d82557dac4e6047c3b9efc25c3f..afdc3f5d915cf7fc278d980147e632a68e727d32 100644 (file)
@@ -39,7 +39,6 @@ static const char *verstr = "20081215";
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
@@ -76,6 +75,7 @@ static const char *verstr = "20081215";
 #include "st_options.h"
 #include "st.h"
 
+static DEFINE_MUTEX(st_mutex);
 static int buffer_kbs;
 static int max_sg_segs;
 static int try_direct_io = TRY_DIRECT_IO;
@@ -1180,7 +1180,7 @@ static int st_open(struct inode *inode, struct file *filp)
        int dev = TAPE_NR(inode);
        char *name;
 
-       lock_kernel();
+       mutex_lock(&st_mutex);
        /*
         * We really want to do nonseekable_open(inode, filp); here, but some
         * versions of tar incorrectly call lseek on tapes and bail out if that
@@ -1189,7 +1189,7 @@ static int st_open(struct inode *inode, struct file *filp)
        filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 
        if (!(STp = scsi_tape_get(dev))) {
-               unlock_kernel();
+               mutex_unlock(&st_mutex);
                return -ENXIO;
        }
 
@@ -1200,7 +1200,7 @@ static int st_open(struct inode *inode, struct file *filp)
        if (STp->in_use) {
                write_unlock(&st_dev_arr_lock);
                scsi_tape_put(STp);
-               unlock_kernel();
+               mutex_unlock(&st_mutex);
                DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
                return (-EBUSY);
        }
@@ -1249,14 +1249,14 @@ static int st_open(struct inode *inode, struct file *filp)
                        retval = (-EIO);
                goto err_out;
        }
-       unlock_kernel();
+       mutex_unlock(&st_mutex);
        return 0;
 
  err_out:
        normalize_buffer(STp->buffer);
        STp->in_use = 0;
        scsi_tape_put(STp);
-       unlock_kernel();
+       mutex_unlock(&st_mutex);
        return retval;
 
 }
index a7bc8b7b09ac3f26f7a17f0a992d9806b1e4ce40..2c3e89ddf069fb66fad54c46912216c97daa1ff8 100644 (file)
@@ -72,10 +72,7 @@ static void sym_printl_hex(u_char *p, int n)
 
 static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
 {
-       if (label)
-               sym_print_addr(cp->cmd, "%s: ", label);
-       else
-               sym_print_addr(cp->cmd, "");
+       sym_print_addr(cp->cmd, "%s: ", label);
 
        spi_print_msg(msg);
        printf("\n");
@@ -4558,7 +4555,8 @@ static void sym_int_sir(struct sym_hcb *np)
                        switch (np->msgin [2]) {
                        case M_X_MODIFY_DP:
                                if (DEBUG_FLAGS & DEBUG_POINTER)
-                                       sym_print_msg(cp, NULL, np->msgin);
+                                       sym_print_msg(cp, "extended msg ",
+                                                     np->msgin);
                                tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + 
                                      (np->msgin[5]<<8)  + (np->msgin[6]);
                                sym_modify_dp(np, tp, cp, tmp);
@@ -4585,7 +4583,7 @@ static void sym_int_sir(struct sym_hcb *np)
                 */
                case M_IGN_RESIDUE:
                        if (DEBUG_FLAGS & DEBUG_POINTER)
-                               sym_print_msg(cp, NULL, np->msgin);
+                               sym_print_msg(cp, "1 or 2 byte ", np->msgin);
                        if (cp->host_flags & HF_SENSE)
                                OUTL_DSP(np, SCRIPTA_BA(np, clrack));
                        else
index 7356a56ac458f697c54bdd8d1335b763a47f000b..be0ebce36e54906fce49dd9c1993d184ebaddbb9 100644 (file)
@@ -869,7 +869,9 @@ static int get_serial_info(struct m68k_serial * info,
        tmp.close_delay = info->close_delay;
        tmp.closing_wait = info->closing_wait;
        tmp.custom_divisor = info->custom_divisor;
-       copy_to_user(retinfo,&tmp,sizeof(*retinfo));
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+
        return 0;
 }
 
@@ -882,7 +884,8 @@ static int set_serial_info(struct m68k_serial * info,
 
        if (!new_info)
                return -EFAULT;
-       copy_from_user(&new_serial,new_info,sizeof(new_serial));
+       if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+               return -EFAULT;
        old_info = *info;
 
        if (!capable(CAP_SYS_ADMIN)) {
@@ -943,8 +946,7 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
        status = 0;
 #endif
        local_irq_restore(flags);
-       put_user(status,value);
-       return 0;
+       return put_user(status, value);
 }
 
 /*
@@ -999,27 +1001,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        send_break(info, arg ? arg*(100) : 250);
                        return 0;
                case TIOCGSERIAL:
-                       if (access_ok(VERIFY_WRITE, (void *) arg,
-                                               sizeof(struct serial_struct)))
-                               return get_serial_info(info,
-                                              (struct serial_struct *) arg);
-                       return -EFAULT;
+                       return get_serial_info(info,
+                                      (struct serial_struct *) arg);
                case TIOCSSERIAL:
                        return set_serial_info(info,
                                               (struct serial_struct *) arg);
                case TIOCSERGETLSR: /* Get line status register */
-                       if (access_ok(VERIFY_WRITE, (void *) arg,
-                                               sizeof(unsigned int)))
-                               return get_lsr_info(info, (unsigned int *) arg);
-                       return -EFAULT;
+                       return get_lsr_info(info, (unsigned int *) arg);
                case TIOCSERGSTRUCT:
-                       if (!access_ok(VERIFY_WRITE, (void *) arg,
-                                               sizeof(struct m68k_serial)))
+                       if (copy_to_user((struct m68k_serial *) arg,
+                                   info, sizeof(struct m68k_serial)))
                                return -EFAULT;
-                       copy_to_user((struct m68k_serial *) arg,
-                                   info, sizeof(struct m68k_serial));
                        return 0;
-                       
                default:
                        return -ENOIOCTLCMD;
                }
index b745792ec25a08e9981d22bbdd2897c99b6f738e..eaafb98debed89e2f1b2e5e83ac33cd79301792e 100644 (file)
@@ -203,13 +203,13 @@ static int __init parse_options(struct early_serial8250_device *device,
 
        if (mmio || mmio32)
                printk(KERN_INFO
-                      "Early serial console at MMIO%s 0x%llu (options '%s')\n",
+                      "Early serial console at MMIO%s 0x%llx (options '%s')\n",
                        mmio32 ? "32" : "",
                        (unsigned long long)port->mapbase,
                        device->options);
        else
                printk(KERN_INFO
-                     "Early serial console at I/O port 0x%lu (options '%s')\n",
+                     "Early serial console at I/O port 0x%lx (options '%s')\n",
                        port->iobase,
                        device->options);
 
index 12900f7083b08819fdf31b3ab626d560bbfa01f8..3198c5335f0bcfae8f08680592164a0f1953281a 100644 (file)
@@ -458,6 +458,7 @@ config SERIAL_SAMSUNG_UARTS
        int
        depends on ARM && PLAT_SAMSUNG
        default 2 if ARCH_S3C2400
+       default 6 if ARCH_S5P6450
        default 4 if SERIAL_SAMSUNG_UARTS_4
        default 3
        help
@@ -526,12 +527,12 @@ config SERIAL_S3C24A0
          Serial port support for the Samsung S3C24A0 SoC
 
 config SERIAL_S3C6400
-       tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support"
-       depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100)
+       tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
+       depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
        select SERIAL_SAMSUNG_UARTS_4
        default y
        help
-         Serial port support for the Samsung S3C6400, S3C6410, S5P6440
+         Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450
          and S5PC100 SoCs
 
 config SERIAL_S5PV210
index 50441ffe8e3856592dbfdae368e9891b64078d50..2904aa044126dbc49729caacbcb3d236da900bc6 100644 (file)
@@ -472,14 +472,9 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
-static void pl010_set_ldisc(struct uart_port *port)
+static void pl010_set_ldisc(struct uart_port *port, int new)
 {
-       int line = port->line;
-
-       if (line >= port->state->port.tty->driver->num)
-               return;
-
-       if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+       if (new == N_PPS) {
                port->flags |= UPF_HARDPPS_CD;
                pl010_enable_ms(port);
        } else
index e57fb3d228e2dd0881ab10f3410a457b46e0e405..5318dd3774ae156dc17f482a73e80f8c8a3ec77b 100644 (file)
@@ -121,7 +121,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
        unsigned int sclk = get_sclk();
 
        /* Set TCR1 and TCR2, TFSR is not enabled for uart */
-       SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK));
+       SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
        SPORT_PUT_TCR2(up, size + 1);
        pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
 
index 93de907b12088a54ab5809cf79c46ba5ec2757f2..ee43efc7bdcc5b1dcc406f69845f7bbcca0582e5 100644 (file)
@@ -2017,6 +2017,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
        struct ioc3_port *port;
        struct ioc3_port *ports[PORTS_PER_CARD];
        int phys_port;
+       int cnt;
 
        DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
 
@@ -2044,6 +2045,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
                if (!port) {
                        printk(KERN_WARNING
                               "IOC3 serial memory not available for port\n");
+                       ret = -ENOMEM;
                        goto out4;
                }
                spin_lock_init(&port->ip_lock);
@@ -2146,6 +2148,9 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
        /* error exits that give back resources */
 out4:
+       for (cnt = 0; cnt < phys_port; cnt++)
+               kfree(ports[cnt]);
+
        kfree(card_ptr);
        return ret;
 }
index bc9af503907f4b24ac0845068701b2de1474a105..dc0967fb9ea64aadbf36a06f2d253131fb47cb3c 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/slab.h>
 #include <linux/serial_reg.h>
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
@@ -227,12 +228,14 @@ static const struct file_operations port_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = port_show_regs,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations dma_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = dma_show_regs,
+       .llseek         = default_llseek,
 };
 
 static int hsu_debugfs_init(struct hsu_port *hsu)
@@ -1423,7 +1426,6 @@ static void hsu_global_init(void)
        }
 
        phsu = hsu;
-
        hsu_debugfs_init(hsu);
        return;
 
@@ -1435,18 +1437,20 @@ err_free_region:
 
 static void serial_hsu_remove(struct pci_dev *pdev)
 {
-       struct hsu_port *hsu;
-       int i;
+       void *priv = pci_get_drvdata(pdev);
+       struct uart_hsu_port *up;
 
-       hsu = pci_get_drvdata(pdev);
-       if (!hsu)
+       if (!priv)
                return;
 
-       for (i = 0; i < 3; i++)
-               uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port);
+       /* For port 0/1/2, priv is the address of uart_hsu_port */
+       if (pdev->device != 0x081E) {
+               up = priv;
+               uart_remove_one_port(&serial_hsu_reg, &up->port);
+       }
 
        pci_set_drvdata(pdev, NULL);
-       free_irq(hsu->irq, hsu);
+       free_irq(pdev->irq, priv);
        pci_disable_device(pdev);
 }
 
index 8dedb266f143f1cf801d84f34892a999b2dc9934..c4399e23565aca0c986fdecc56fc424dee2c1ee3 100644 (file)
@@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void)
        psc_fifoc = of_iomap(np, 0);
        if (!psc_fifoc) {
                pr_err("%s: Can't map FIFOC\n", __func__);
+               of_node_put(np);
                return -ENODEV;
        }
 
index f6ad1ecbff79ec9688fbc024a2036f351efff26e..51c15f58e01ef84a8ce43ba8b62472f0e4d7bec0 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
index b1156ba8ad1452c113fff20740a1d01596ab3cb2..7ac2bf5167cd8052f7f82b1361258f93643a03bd 100644 (file)
@@ -1101,7 +1101,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
        dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
 
        port->mapbase = res->start;
-       port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000);
+       port->membase = S3C_VA_UART + (res->start & 0xfffff);
        ret = platform_get_irq(platdev, 0);
        if (ret < 0)
                port->irq = 0;
index 141c69554bd481d27863b852bbd79b364417643e..93760b2ea1727a908ca862dfc9922e4b13a3db63 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -183,10 +182,8 @@ static void quirk_config_socket(struct pcmcia_device *link)
 {
        struct serial_info *info = link->priv;
 
-       if (info->multi) {
-               link->conf.Present |= PRESENT_EXT_STATUS;
-               link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
-       }
+       if (info->multi)
+               link->config_flags |= CONF_ENABLE_ESR;
 }
 
 static const struct serial_quirk quirks[] = {
@@ -265,13 +262,6 @@ static const struct serial_quirk quirks[] = {
 static int serial_config(struct pcmcia_device * link);
 
 
-/*======================================================================
-
-    After a card is removed, serial_remove() will unregister
-    the serial device(s), and release the PCMCIA configuration.
-    
-======================================================================*/
-
 static void serial_remove(struct pcmcia_device *link)
 {
        struct serial_info *info = link->priv;
@@ -314,14 +304,6 @@ static int serial_resume(struct pcmcia_device *link)
        return 0;
 }
 
-/*======================================================================
-
-    serial_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int serial_probe(struct pcmcia_device *link)
 {
        struct serial_info *info;
@@ -335,38 +317,19 @@ static int serial_probe(struct pcmcia_device *link)
        info->p_dev = link;
        link->priv = info;
 
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[0]->end = 8;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       if (do_sound) {
-               link->conf.Attributes |= CONF_ENABLE_SPKR;
-               link->conf.Status = CCSR_AUDIO_ENA;
-       }
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->config_flags |= CONF_ENABLE_IRQ;
+       if (do_sound)
+               link->config_flags |= CONF_ENABLE_SPKR;
 
        return serial_config(link);
 }
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void serial_detach(struct pcmcia_device *link)
 {
        struct serial_info *info = link->priv;
 
        dev_dbg(&link->dev, "serial_detach\n");
 
-       /*
-        * Ensure any outstanding scheduled tasks are completed.
-        */
-       flush_scheduled_work();
-
        /*
         * Ensure that the ports have been released.
         */
@@ -411,47 +374,66 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
 
 /*====================================================================*/
 
-static int simple_config_check(struct pcmcia_device *p_dev,
-                              cistpl_cftable_entry_t *cf,
-                              cistpl_cftable_entry_t *dflt,
-                              unsigned int vcc,
-                              void *priv_data)
+static int pfc_config(struct pcmcia_device *p_dev)
+{
+       unsigned int port = 0;
+       struct serial_info *info = p_dev->priv;
+
+       if ((p_dev->resource[1]->end != 0) &&
+               (resource_size(p_dev->resource[1]) == 8)) {
+               port = p_dev->resource[1]->start;
+               info->slave = 1;
+       } else if ((info->manfid == MANFID_OSITECH) &&
+               (resource_size(p_dev->resource[0]) == 0x40)) {
+               port = p_dev->resource[0]->start + 0x28;
+               info->slave = 1;
+       }
+       if (info->slave)
+               return setup_serial(p_dev, info, port, p_dev->irq);
+
+       dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
+       return -ENODEV;
+}
+
+static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
        static const int size_table[2] = { 8, 16 };
        int *try = priv_data;
 
-       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       if (p_dev->resource[0]->start == 0)
+               return -ENODEV;
 
-       p_dev->io_lines = ((*try & 0x1) == 0) ?
-                       16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+       if ((*try & 0x1) == 0)
+               p_dev->io_lines = 16;
 
-       if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
-           && (cf->io.win[0].base != 0)) {
-               p_dev->resource[0]->start = cf->io.win[0].base;
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -EINVAL;
+       if (p_dev->resource[0]->end != size_table[(*try >> 1)])
+               return -ENODEV;
+
+       p_dev->resource[0]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
-                                       cistpl_cftable_entry_t *cf,
-                                       cistpl_cftable_entry_t *dflt,
-                                       unsigned int vcc,
                                        void *priv_data)
 {
        static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        int j;
 
-       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-               for (j = 0; j < 5; j++) {
-                       p_dev->resource[0]->start = base[j];
-                       p_dev->io_lines = base[j] ? 16 : 3;
-                       if (!pcmcia_request_io(p_dev))
-                               return 0;
-               }
+       if (p_dev->io_lines > 3)
+               return -ENODEV;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = 8;
+
+       for (j = 0; j < 5; j++) {
+               p_dev->resource[0]->start = base[j];
+               p_dev->io_lines = base[j] ? 16 : 3;
+               if (!pcmcia_request_io(p_dev))
+                       return 0;
        }
        return -ENODEV;
 }
@@ -461,26 +443,9 @@ static int simple_config(struct pcmcia_device *link)
        struct serial_info *info = link->priv;
        int i = -ENODEV, try;
 
-       /* If the card is already configured, look up the port and irq */
-       if (link->function_config) {
-               unsigned int port = 0;
-               if ((link->resource[1]->end != 0) &&
-                       (resource_size(link->resource[1]) == 8)) {
-                       port = link->resource[1]->end;
-                       info->slave = 1;
-               } else if ((info->manfid == MANFID_OSITECH) &&
-                       (resource_size(link->resource[0]) == 0x40)) {
-                       port = link->resource[0]->start + 0x28;
-                       info->slave = 1;
-               }
-               if (info->slave) {
-                       return setup_serial(link, info, port,
-                                           link->irq);
-               }
-       }
-
        /* First pass: look for a config entry that looks normal.
         * Two tries: without IO aliases, then with aliases */
+       link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO;
        for (try = 0; try < 4; try++)
                if (!pcmcia_loop_config(link, simple_config_check, &try))
                        goto found_port;
@@ -491,13 +456,12 @@ static int simple_config(struct pcmcia_device *link)
        if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
                goto found_port;
 
-       printk(KERN_NOTICE
-              "serial_cs: no usable port range found, giving up\n");
+       dev_warn(&link->dev, "no usable port range found, giving up\n");
        return -1;
 
 found_port:
        if (info->multi && (info->manfid == MANFID_3COM))
-               link->conf.ConfigIndex &= ~(0x08);
+               link->config_index &= ~(0x08);
 
        /*
         * Apply any configuration quirks.
@@ -505,51 +469,50 @@ found_port:
        if (info->quirk && info->quirk->config)
                info->quirk->config(link);
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                return -1;
        return setup_serial(link, info, link->resource[0]->start, link->irq);
 }
 
-static int multi_config_check(struct pcmcia_device *p_dev,
-                             cistpl_cftable_entry_t *cf,
-                             cistpl_cftable_entry_t *dflt,
-                             unsigned int vcc,
-                             void *priv_data)
+static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       int *base2 = priv_data;
+       int *multi = priv_data;
+
+       if (p_dev->resource[1]->end)
+               return -EINVAL;
 
        /* The quad port cards have bad CIS's, so just look for a
           window larger than 8 ports and assume it will be right */
-       if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-               p_dev->resource[0]->start = cf->io.win[0].base;
-               p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-               if (!pcmcia_request_io(p_dev)) {
-                       *base2 = p_dev->resource[0]->start + 8;
-                       return 0;
-               }
-       }
-       return -ENODEV;
+       if (p_dev->resource[0]->end <= 8)
+               return -EINVAL;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = *multi * 8;
+
+       if (pcmcia_request_io(p_dev))
+               return -ENODEV;
+       return 0;
 }
 
 static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
-                                      cistpl_cftable_entry_t *cf,
-                                      cistpl_cftable_entry_t *dflt,
-                                      unsigned int vcc,
                                       void *priv_data)
 {
        int *base2 = priv_data;
 
-       if (cf->io.nwin == 2) {
-               p_dev->resource[0]->start = cf->io.win[0].base;
-               p_dev->resource[1]->start = cf->io.win[1].base;
-               p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-               if (!pcmcia_request_io(p_dev)) {
-                       *base2 = p_dev->resource[1]->start;
-                       return 0;
-               }
-       }
-       return -ENODEV;
+       if (!p_dev->resource[0]->end || !p_dev->resource[1]->end)
+               return -ENODEV;
+
+       p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       if (pcmcia_request_io(p_dev))
+               return -ENODEV;
+
+       *base2 = p_dev->resource[0]->start + 8;
+       return 0;
 }
 
 static int multi_config(struct pcmcia_device *link)
@@ -557,23 +520,23 @@ static int multi_config(struct pcmcia_device *link)
        struct serial_info *info = link->priv;
        int i, base2 = 0;
 
+       link->config_flags |= CONF_AUTO_SET_IO;
        /* First, look for a generic full-sized window */
-       link->resource[0]->end = info->multi * 8;
-       if (pcmcia_loop_config(link, multi_config_check, &base2)) {
+       if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
+               base2 = link->resource[0]->start + 8;
+       else {
                /* If that didn't work, look for two windows */
-               link->resource[0]->end = link->resource[1]->end = 8;
                info->multi = 2;
                if (pcmcia_loop_config(link, multi_config_check_notpicky,
                                       &base2)) {
-                       printk(KERN_NOTICE "serial_cs: no usable port range"
+                       dev_warn(&link->dev, "no usable port range "
                               "found, giving up\n");
                        return -ENODEV;
                }
        }
 
        if (!link->irq)
-               dev_warn(&link->dev,
-                       "serial_cs: no usable IRQ found, continuing...\n");
+               dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
 
        /*
         * Apply any configuration quirks.
@@ -581,7 +544,7 @@ static int multi_config(struct pcmcia_device *link)
        if (info->quirk && info->quirk->config)
                info->quirk->config(link);
 
-       i = pcmcia_request_configuration(link, &link->conf);
+       i = pcmcia_enable_device(link);
        if (i != 0)
                return -ENODEV;
 
@@ -593,11 +556,11 @@ static int multi_config(struct pcmcia_device *link)
                                info->prodid == PRODID_POSSIO_GCC)) {
                int err;
 
-               if (link->conf.ConfigIndex == 1 ||
-                   link->conf.ConfigIndex == 3) {
+               if (link->config_index == 1 ||
+                   link->config_index == 3) {
                        err = setup_serial(link, info, base2,
                                        link->irq);
-                       base2 = link->resource[0]->start;;
+                       base2 = link->resource[0]->start;
                } else {
                        err = setup_serial(link, info, link->resource[0]->start,
                                        link->irq);
@@ -621,33 +584,24 @@ static int multi_config(struct pcmcia_device *link)
        return 0;
 }
 
-static int serial_check_for_multi(struct pcmcia_device *p_dev,
-                                 cistpl_cftable_entry_t *cf,
-                                 cistpl_cftable_entry_t *dflt,
-                                 unsigned int vcc,
-                                 void *priv_data)
+static int serial_check_for_multi(struct pcmcia_device *p_dev,  void *priv_data)
 {
        struct serial_info *info = p_dev->priv;
 
-       if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
-               info->multi = cf->io.win[0].len >> 3;
+       if (!p_dev->resource[0]->end)
+               return -EINVAL;
+
+       if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
+               info->multi = p_dev->resource[0]->end >> 3;
 
-       if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
-               (cf->io.win[1].len == 8))
+       if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
+               && (p_dev->resource[1]->end == 8))
                info->multi = 2;
 
        return 0; /* break */
 }
 
 
-/*======================================================================
-
-    serial_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    serial device available to the system.
-
-======================================================================*/
-
 static int serial_config(struct pcmcia_device * link)
 {
        struct serial_info *info = link->priv;
@@ -675,6 +629,7 @@ static int serial_config(struct pcmcia_device * link)
           multifunction cards that ask for appropriate IO port ranges */
        if ((info->multi == 0) &&
            (link->has_func_id) &&
+           (link->socket->pcmcia_pfc == 0) &&
            ((link->func_id == CISTPL_FUNCID_MULTI) ||
             (link->func_id == CISTPL_FUNCID_SERIAL)))
                pcmcia_loop_config(link, serial_check_for_multi, info);
@@ -685,7 +640,13 @@ static int serial_config(struct pcmcia_device * link)
        if (info->quirk && info->quirk->multi != -1)
                info->multi = info->quirk->multi;
 
-       if (info->multi > 1)
+       dev_info(&link->dev,
+               "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
+               link->manf_id, link->card_id,
+               link->socket->pcmcia_pfc, info->multi, info->quirk);
+       if (link->socket->pcmcia_pfc)
+               i = pfc_config(link);
+       else if (info->multi > 1)
                i = multi_config(link);
        else
                i = simple_config(link);
@@ -704,7 +665,7 @@ static int serial_config(struct pcmcia_device * link)
        return 0;
 
 failed:
-       dev_warn(&link->dev, "serial_cs: failed to initialize\n");
+       dev_warn(&link->dev, "failed to initialize\n");
        serial_remove(link);
        return -ENODEV;
 }
@@ -884,9 +845,7 @@ MODULE_FIRMWARE("cis/RS-COM-2P.cis");
 
 static struct pcmcia_driver serial_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "serial_cs",
-       },
+       .name           = "serial_cs",
        .probe          = serial_probe,
        .remove         = serial_detach,
        .id_table       = serial_ids,
index 7e5e5efea4e27659ef564f28652e07377fcf19db..cff9a306660faede7827d705b5cf5d98fdef9067 100644 (file)
@@ -492,7 +492,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags)
                         sysrq_requested = 0;
                         if (ch && time_before(jiffies, sysrq_timeout)) {
                                 spin_unlock_irqrestore(&port->sc_port.lock, flags);
-                                handle_sysrq(ch, NULL);
+                                handle_sysrq(ch);
                                 spin_lock_irqsave(&port->sc_port.lock, flags);
                                 /* ignore actual sysrq command char */
                                 continue;
index 91c2f4f3af10ecfc33a6a101a19b0f1762c79aea..4b9eec68fad6b84bca9c2f5f6f397f0e9be79c45 100644 (file)
@@ -143,10 +143,26 @@ config SPI_GPIO
          GPIO operations, you should be able to leverage that for better
          speed with a custom version of this driver; see the source code.
 
+config SPI_IMX_VER_IMX1
+       def_bool y if SOC_IMX1
+
+config SPI_IMX_VER_0_0
+       def_bool y if SOC_IMX21 || SOC_IMX27
+
+config SPI_IMX_VER_0_4
+       def_bool y if ARCH_MX31
+
+config SPI_IMX_VER_0_7
+       def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51
+
+config SPI_IMX_VER_2_3
+       def_bool y if ARCH_MX51
+
 config SPI_IMX
        tristate "Freescale i.MX SPI controllers"
        depends on ARCH_MXC
        select SPI_BITBANG
+       default m if IMX_HAVE_PLATFORM_SPI_IMX
        help
          This enables using the Freescale i.MX SPI controllers in master
          mode.
@@ -182,12 +198,27 @@ config SPI_MPC512x_PSC
          This enables using the Freescale MPC5121 Programmable Serial
          Controller in SPI master mode.
 
-config SPI_MPC8xxx
-       tristate "Freescale MPC8xxx SPI controller"
+config SPI_FSL_LIB
+       tristate
+       depends on FSL_SOC
+
+config SPI_FSL_SPI
+       tristate "Freescale SPI controller"
        depends on FSL_SOC
+       select SPI_FSL_LIB
        help
-         This enables using the Freescale MPC8xxx SPI controllers in master
-         mode.
+         This enables using the Freescale SPI controllers in master mode.
+         MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
+         MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
+
+config SPI_FSL_ESPI
+       tristate "Freescale eSPI controller"
+       depends on FSL_SOC
+       select SPI_FSL_LIB
+       help
+         This enables using the Freescale eSPI controllers in master mode.
+         From MPC8536, 85xx platform uses the controller, and all P10xx,
+         P20xx, P30xx,P40xx, P50xx uses this controller.
 
 config SPI_OMAP_UWIRE
        tristate "OMAP1 MicroWire"
@@ -298,6 +329,13 @@ config SPI_STMP3XXX
        help
          SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
+config SPI_TOPCLIFF_PCH
+       tristate "Topcliff PCH SPI Controller"
+       depends on PCI
+       help
+         SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
+         used in some x86 embedded processors.
+
 config SPI_TXX9
        tristate "Toshiba TXx9 SPI controller"
        depends on GENERIC_GPIO && CPU_TX49XX
index e9cbd18217a0559248698075141b6dd3f9d1277f..557aaadf56b2df40620a3b02073b44b78f09fb66 100644 (file)
@@ -2,9 +2,7 @@
 # Makefile for kernel SPI drivers.
 #
 
-ifeq ($(CONFIG_SPI_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 
 # small core, mostly translating board-specific
 # config declarations into driver model code
@@ -34,11 +32,14 @@ obj-$(CONFIG_SPI_PL022)                     += amba-pl022.o
 obj-$(CONFIG_SPI_MPC512x_PSC)          += mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)          += mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)              += mpc52xx_spi.o
-obj-$(CONFIG_SPI_MPC8xxx)              += spi_mpc8xxx.o
+obj-$(CONFIG_SPI_FSL_LIB)              += spi_fsl_lib.o
+obj-$(CONFIG_SPI_FSL_ESPI)             += spi_fsl_espi.o
+obj-$(CONFIG_SPI_FSL_SPI)              += spi_fsl_spi.o
 obj-$(CONFIG_SPI_PPC4xx)               += spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)              += spi_s3c64xx.o
+obj-$(CONFIG_SPI_TOPCLIFF_PCH)         += spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
 obj-$(CONFIG_SPI_XILINX_OF)            += xilinx_spi_of.o
index acd35d1ebd12621e35a05324daa450992b081f17..fb3d1b31772d223e24840ae2ac2c1e18b224ef76 100644 (file)
@@ -27,7 +27,6 @@
 /*
  * TODO:
  * - add timeout on polled transfers
- * - add generic DMA framework support
  */
 
 #include <linux/init.h>
@@ -45,6 +44,9 @@
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
 
 /*
  * This macro is used to define some register default values.
@@ -381,6 +383,14 @@ struct pl022 {
        enum ssp_reading                read;
        enum ssp_writing                write;
        u32                             exp_fifo_level;
+       /* DMA settings */
+#ifdef CONFIG_DMA_ENGINE
+       struct dma_chan                 *dma_rx_channel;
+       struct dma_chan                 *dma_tx_channel;
+       struct sg_table                 sgt_rx;
+       struct sg_table                 sgt_tx;
+       char                            *dummypage;
+#endif
 };
 
 /**
@@ -406,7 +416,7 @@ struct chip_data {
        u16 dmacr;
        u16 cpsr;
        u8 n_bytes;
-       u8 enable_dma:1;
+       bool enable_dma;
        enum ssp_reading read;
        enum ssp_writing write;
        void (*cs_control) (u32 command);
@@ -503,8 +513,9 @@ static void giveback(struct pl022 *pl022)
        msg->state = NULL;
        if (msg->complete)
                msg->complete(msg->context);
-       /* This message is completed, so let's turn off the clock! */
+       /* This message is completed, so let's turn off the clocks! */
        clk_disable(pl022->clk);
+       amba_pclk_disable(pl022->adev);
 }
 
 /**
@@ -762,6 +773,371 @@ static void *next_transfer(struct pl022 *pl022)
        }
        return STATE_DONE;
 }
+
+/*
+ * This DMA functionality is only compiled in if we have
+ * access to the generic DMA devices/DMA engine.
+ */
+#ifdef CONFIG_DMA_ENGINE
+static void unmap_free_dma_scatter(struct pl022 *pl022)
+{
+       /* Unmap and free the SG tables */
+       dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+                    pl022->sgt_tx.nents, DMA_TO_DEVICE);
+       dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+                    pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+       sg_free_table(&pl022->sgt_rx);
+       sg_free_table(&pl022->sgt_tx);
+}
+
+static void dma_callback(void *data)
+{
+       struct pl022 *pl022 = data;
+       struct spi_message *msg = pl022->cur_msg;
+
+       BUG_ON(!pl022->sgt_rx.sgl);
+
+#ifdef VERBOSE_DEBUG
+       /*
+        * Optionally dump out buffers to inspect contents, this is
+        * good if you want to convince yourself that the loopback
+        * read/write contents are the same, when adopting to a new
+        * DMA engine.
+        */
+       {
+               struct scatterlist *sg;
+               unsigned int i;
+
+               dma_sync_sg_for_cpu(&pl022->adev->dev,
+                                   pl022->sgt_rx.sgl,
+                                   pl022->sgt_rx.nents,
+                                   DMA_FROM_DEVICE);
+
+               for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
+                       dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
+                       print_hex_dump(KERN_ERR, "SPI RX: ",
+                                      DUMP_PREFIX_OFFSET,
+                                      16,
+                                      1,
+                                      sg_virt(sg),
+                                      sg_dma_len(sg),
+                                      1);
+               }
+               for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
+                       dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
+                       print_hex_dump(KERN_ERR, "SPI TX: ",
+                                      DUMP_PREFIX_OFFSET,
+                                      16,
+                                      1,
+                                      sg_virt(sg),
+                                      sg_dma_len(sg),
+                                      1);
+               }
+       }
+#endif
+
+       unmap_free_dma_scatter(pl022);
+
+       /* Update total bytes transfered */
+       msg->actual_length += pl022->cur_transfer->len;
+       if (pl022->cur_transfer->cs_change)
+               pl022->cur_chip->
+                       cs_control(SSP_CHIP_DESELECT);
+
+       /* Move to next transfer */
+       msg->state = next_transfer(pl022);
+       tasklet_schedule(&pl022->pump_transfers);
+}
+
+static void setup_dma_scatter(struct pl022 *pl022,
+                             void *buffer,
+                             unsigned int length,
+                             struct sg_table *sgtab)
+{
+       struct scatterlist *sg;
+       int bytesleft = length;
+       void *bufp = buffer;
+       int mapbytes;
+       int i;
+
+       if (buffer) {
+               for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+                       /*
+                        * If there are less bytes left than what fits
+                        * in the current page (plus page alignment offset)
+                        * we just feed in this, else we stuff in as much
+                        * as we can.
+                        */
+                       if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
+                               mapbytes = bytesleft;
+                       else
+                               mapbytes = PAGE_SIZE - offset_in_page(bufp);
+                       sg_set_page(sg, virt_to_page(bufp),
+                                   mapbytes, offset_in_page(bufp));
+                       bufp += mapbytes;
+                       bytesleft -= mapbytes;
+                       dev_dbg(&pl022->adev->dev,
+                               "set RX/TX target page @ %p, %d bytes, %d left\n",
+                               bufp, mapbytes, bytesleft);
+               }
+       } else {
+               /* Map the dummy buffer on every page */
+               for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+                       if (bytesleft < PAGE_SIZE)
+                               mapbytes = bytesleft;
+                       else
+                               mapbytes = PAGE_SIZE;
+                       sg_set_page(sg, virt_to_page(pl022->dummypage),
+                                   mapbytes, 0);
+                       bytesleft -= mapbytes;
+                       dev_dbg(&pl022->adev->dev,
+                               "set RX/TX to dummy page %d bytes, %d left\n",
+                               mapbytes, bytesleft);
+
+               }
+       }
+       BUG_ON(bytesleft);
+}
+
+/**
+ * configure_dma - configures the channels for the next transfer
+ * @pl022: SSP driver's private data structure
+ */
+static int configure_dma(struct pl022 *pl022)
+{
+       struct dma_slave_config rx_conf = {
+               .src_addr = SSP_DR(pl022->phybase),
+               .direction = DMA_FROM_DEVICE,
+               .src_maxburst = pl022->vendor->fifodepth >> 1,
+       };
+       struct dma_slave_config tx_conf = {
+               .dst_addr = SSP_DR(pl022->phybase),
+               .direction = DMA_TO_DEVICE,
+               .dst_maxburst = pl022->vendor->fifodepth >> 1,
+       };
+       unsigned int pages;
+       int ret;
+       int sglen;
+       struct dma_chan *rxchan = pl022->dma_rx_channel;
+       struct dma_chan *txchan = pl022->dma_tx_channel;
+       struct dma_async_tx_descriptor *rxdesc;
+       struct dma_async_tx_descriptor *txdesc;
+       dma_cookie_t cookie;
+
+       /* Check that the channels are available */
+       if (!rxchan || !txchan)
+               return -ENODEV;
+
+       switch (pl022->read) {
+       case READING_NULL:
+               /* Use the same as for writing */
+               rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+               break;
+       case READING_U8:
+               rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+               break;
+       case READING_U16:
+               rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+               break;
+       case READING_U32:
+               rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               break;
+       }
+
+       switch (pl022->write) {
+       case WRITING_NULL:
+               /* Use the same as for reading */
+               tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+               break;
+       case WRITING_U8:
+               tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+               break;
+       case WRITING_U16:
+               tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+               break;
+       case WRITING_U32:
+               tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;;
+               break;
+       }
+
+       /* SPI pecularity: we need to read and write the same width */
+       if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+               rx_conf.src_addr_width = tx_conf.dst_addr_width;
+       if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+               tx_conf.dst_addr_width = rx_conf.src_addr_width;
+       BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
+
+       rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
+                                      (unsigned long) &rx_conf);
+       txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
+                                      (unsigned long) &tx_conf);
+
+       /* Create sglists for the transfers */
+       pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
+       dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
+
+       ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
+       if (ret)
+               goto err_alloc_rx_sg;
+
+       ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
+       if (ret)
+               goto err_alloc_tx_sg;
+
+       /* Fill in the scatterlists for the RX+TX buffers */
+       setup_dma_scatter(pl022, pl022->rx,
+                         pl022->cur_transfer->len, &pl022->sgt_rx);
+       setup_dma_scatter(pl022, pl022->tx,
+                         pl022->cur_transfer->len, &pl022->sgt_tx);
+
+       /* Map DMA buffers */
+       sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+                          pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+       if (!sglen)
+               goto err_rx_sgmap;
+
+       sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+                          pl022->sgt_tx.nents, DMA_TO_DEVICE);
+       if (!sglen)
+               goto err_tx_sgmap;
+
+       /* Send both scatterlists */
+       rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+                                     pl022->sgt_rx.sgl,
+                                     pl022->sgt_rx.nents,
+                                     DMA_FROM_DEVICE,
+                                     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!rxdesc)
+               goto err_rxdesc;
+
+       txdesc = txchan->device->device_prep_slave_sg(txchan,
+                                     pl022->sgt_tx.sgl,
+                                     pl022->sgt_tx.nents,
+                                     DMA_TO_DEVICE,
+                                     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!txdesc)
+               goto err_txdesc;
+
+       /* Put the callback on the RX transfer only, that should finish last */
+       rxdesc->callback = dma_callback;
+       rxdesc->callback_param = pl022;
+
+       /* Submit and fire RX and TX with TX last so we're ready to read! */
+       cookie = rxdesc->tx_submit(rxdesc);
+       if (dma_submit_error(cookie))
+               goto err_submit_rx;
+       cookie = txdesc->tx_submit(txdesc);
+       if (dma_submit_error(cookie))
+               goto err_submit_tx;
+       rxchan->device->device_issue_pending(rxchan);
+       txchan->device->device_issue_pending(txchan);
+
+       return 0;
+
+err_submit_tx:
+err_submit_rx:
+err_txdesc:
+       txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+err_rxdesc:
+       rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+       dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+                    pl022->sgt_tx.nents, DMA_TO_DEVICE);
+err_tx_sgmap:
+       dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+                    pl022->sgt_tx.nents, DMA_FROM_DEVICE);
+err_rx_sgmap:
+       sg_free_table(&pl022->sgt_tx);
+err_alloc_tx_sg:
+       sg_free_table(&pl022->sgt_rx);
+err_alloc_rx_sg:
+       return -ENOMEM;
+}
+
+static int __init pl022_dma_probe(struct pl022 *pl022)
+{
+       dma_cap_mask_t mask;
+
+       /* Try to acquire a generic DMA engine slave channel */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       /*
+        * We need both RX and TX channels to do DMA, else do none
+        * of them.
+        */
+       pl022->dma_rx_channel = dma_request_channel(mask,
+                                           pl022->master_info->dma_filter,
+                                           pl022->master_info->dma_rx_param);
+       if (!pl022->dma_rx_channel) {
+               dev_err(&pl022->adev->dev, "no RX DMA channel!\n");
+               goto err_no_rxchan;
+       }
+
+       pl022->dma_tx_channel = dma_request_channel(mask,
+                                           pl022->master_info->dma_filter,
+                                           pl022->master_info->dma_tx_param);
+       if (!pl022->dma_tx_channel) {
+               dev_err(&pl022->adev->dev, "no TX DMA channel!\n");
+               goto err_no_txchan;
+       }
+
+       pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!pl022->dummypage) {
+               dev_err(&pl022->adev->dev, "no DMA dummypage!\n");
+               goto err_no_dummypage;
+       }
+
+       dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
+                dma_chan_name(pl022->dma_rx_channel),
+                dma_chan_name(pl022->dma_tx_channel));
+
+       return 0;
+
+err_no_dummypage:
+       dma_release_channel(pl022->dma_tx_channel);
+err_no_txchan:
+       dma_release_channel(pl022->dma_rx_channel);
+       pl022->dma_rx_channel = NULL;
+err_no_rxchan:
+       return -ENODEV;
+}
+
+static void terminate_dma(struct pl022 *pl022)
+{
+       struct dma_chan *rxchan = pl022->dma_rx_channel;
+       struct dma_chan *txchan = pl022->dma_tx_channel;
+
+       rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+       txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+       unmap_free_dma_scatter(pl022);
+}
+
+static void pl022_dma_remove(struct pl022 *pl022)
+{
+       if (pl022->busy)
+               terminate_dma(pl022);
+       if (pl022->dma_tx_channel)
+               dma_release_channel(pl022->dma_tx_channel);
+       if (pl022->dma_rx_channel)
+               dma_release_channel(pl022->dma_rx_channel);
+       kfree(pl022->dummypage);
+}
+
+#else
+static inline int configure_dma(struct pl022 *pl022)
+{
+       return -ENODEV;
+}
+
+static inline int pl022_dma_probe(struct pl022 *pl022)
+{
+       return 0;
+}
+
+static inline void pl022_dma_remove(struct pl022 *pl022)
+{
+}
+#endif
+
 /**
  * pl022_interrupt_handler - Interrupt handler for SSP controller
  *
@@ -793,14 +1169,17 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
        if (unlikely(!irq_status))
                return IRQ_NONE;
 
-       /* This handles the error code interrupts */
+       /*
+        * This handles the FIFO interrupts, the timeout
+        * interrupts are flatly ignored, they cannot be
+        * trusted.
+        */
        if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) {
                /*
                 * Overrun interrupt - bail out since our Data has been
                 * corrupted
                 */
-               dev_err(&pl022->adev->dev,
-                       "FIFO overrun\n");
+               dev_err(&pl022->adev->dev, "FIFO overrun\n");
                if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
                        dev_err(&pl022->adev->dev,
                                "RXFIFO is full\n");
@@ -895,8 +1274,8 @@ static int set_up_next_transfer(struct pl022 *pl022,
 }
 
 /**
- * pump_transfers - Tasklet function which schedules next interrupt transfer
- * when running in interrupt transfer mode.
+ * pump_transfers - Tasklet function which schedules next transfer
+ * when running in interrupt or DMA transfer mode.
  * @data: SSP driver private data structure
  *
  */
@@ -953,65 +1332,23 @@ static void pump_transfers(unsigned long data)
        }
        /* Flush the FIFOs and let's go! */
        flush(pl022);
-       writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
-}
 
-/**
- * NOT IMPLEMENTED
- * configure_dma - It configures the DMA pipes for DMA transfers
- * @data: SSP driver's private data structure
- *
- */
-static int configure_dma(void *data)
-{
-       struct pl022 *pl022 = data;
-       dev_dbg(&pl022->adev->dev, "configure DMA\n");
-       return -ENOTSUPP;
-}
-
-/**
- * do_dma_transfer - It handles transfers of the current message
- * if it is DMA xfer.
- * NOT FULLY IMPLEMENTED
- * @data: SSP driver's private data structure
- */
-static void do_dma_transfer(void *data)
-{
-       struct pl022 *pl022 = data;
-
-       if (configure_dma(data)) {
-               dev_dbg(&pl022->adev->dev, "configuration of DMA Failed!\n");
-               goto err_config_dma;
-       }
-
-       /* TODO: Implememt DMA setup of pipes here */
-
-       /* Enable target chip, set up transfer */
-       pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-       if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
-               /* Error path */
-               pl022->cur_msg->state = STATE_ERROR;
-               pl022->cur_msg->status = -EIO;
-               giveback(pl022);
+       if (pl022->cur_chip->enable_dma) {
+               if (configure_dma(pl022)) {
+                       dev_dbg(&pl022->adev->dev,
+                               "configuration of DMA failed, fall back to interrupt mode\n");
+                       goto err_config_dma;
+               }
                return;
        }
-       /* Enable SSP */
-       writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
-              SSP_CR1(pl022->virtbase));
-
-       /* TODO: Enable the DMA transfer here */
-       return;
 
- err_config_dma:
-       pl022->cur_msg->state = STATE_ERROR;
-       pl022->cur_msg->status = -EIO;
-       giveback(pl022);
-       return;
+err_config_dma:
+       writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
 }
 
-static void do_interrupt_transfer(void *data)
+static void do_interrupt_dma_transfer(struct pl022 *pl022)
 {
-       struct pl022 *pl022 = data;
+       u32 irqflags = ENABLE_ALL_INTERRUPTS;
 
        /* Enable target chip */
        pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
@@ -1022,15 +1359,26 @@ static void do_interrupt_transfer(void *data)
                giveback(pl022);
                return;
        }
+       /* If we're using DMA, set up DMA here */
+       if (pl022->cur_chip->enable_dma) {
+               /* Configure DMA transfer */
+               if (configure_dma(pl022)) {
+                       dev_dbg(&pl022->adev->dev,
+                               "configuration of DMA failed, fall back to interrupt mode\n");
+                       goto err_config_dma;
+               }
+               /* Disable interrupts in DMA mode, IRQ from DMA controller */
+               irqflags = DISABLE_ALL_INTERRUPTS;
+       }
+err_config_dma:
        /* Enable SSP, turn on interrupts */
        writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
               SSP_CR1(pl022->virtbase));
-       writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
+       writew(irqflags, SSP_IMSC(pl022->virtbase));
 }
 
-static void do_polling_transfer(void *data)
+static void do_polling_transfer(struct pl022 *pl022)
 {
-       struct pl022 *pl022 = data;
        struct spi_message *message = NULL;
        struct spi_transfer *transfer = NULL;
        struct spi_transfer *previous = NULL;
@@ -1100,7 +1448,7 @@ static void do_polling_transfer(void *data)
  *
  * This function checks if there is any spi message in the queue that
  * needs processing and delegate control to appropriate function
- * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer()
+ * do_polling_transfer()/do_interrupt_dma_transfer()
  * based on the kind of the transfer
  *
  */
@@ -1139,19 +1487,18 @@ static void pump_messages(struct work_struct *work)
        /* Setup the SPI using the per chip configuration */
        pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
        /*
-        * We enable the clock here, then the clock will be disabled when
+        * We enable the clocks here, then the clocks will be disabled when
         * giveback() is called in each method (poll/interrupt/DMA)
         */
+       amba_pclk_enable(pl022->adev);
        clk_enable(pl022->clk);
        restore_state(pl022);
        flush(pl022);
 
        if (pl022->cur_chip->xfer_type == POLLING_TRANSFER)
                do_polling_transfer(pl022);
-       else if (pl022->cur_chip->xfer_type == INTERRUPT_TRANSFER)
-               do_interrupt_transfer(pl022);
        else
-               do_dma_transfer(pl022);
+               do_interrupt_dma_transfer(pl022);
 }
 
 
@@ -1246,100 +1593,56 @@ static int destroy_queue(struct pl022 *pl022)
 }
 
 static int verify_controller_parameters(struct pl022 *pl022,
-                                       struct pl022_config_chip *chip_info)
+                               struct pl022_config_chip const *chip_info)
 {
-       if ((chip_info->lbm != LOOPBACK_ENABLED)
-           && (chip_info->lbm != LOOPBACK_DISABLED)) {
-               dev_err(chip_info->dev,
-                       "loopback Mode is configured incorrectly\n");
-               return -EINVAL;
-       }
        if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
            || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "interface is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
            (!pl022->vendor->unidir)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "unidirectional mode not supported in this "
                        "hardware version\n");
                return -EINVAL;
        }
        if ((chip_info->hierarchy != SSP_MASTER)
            && (chip_info->hierarchy != SSP_SLAVE)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "hierarchy is configured incorrectly\n");
                return -EINVAL;
        }
-       if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN)
-           || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) {
-               dev_err(chip_info->dev,
-                       "cpsdvsr is configured incorrectly\n");
-               return -EINVAL;
-       }
-       if ((chip_info->endian_rx != SSP_RX_MSB)
-           && (chip_info->endian_rx != SSP_RX_LSB)) {
-               dev_err(chip_info->dev,
-                       "RX FIFO endianess is configured incorrectly\n");
-               return -EINVAL;
-       }
-       if ((chip_info->endian_tx != SSP_TX_MSB)
-           && (chip_info->endian_tx != SSP_TX_LSB)) {
-               dev_err(chip_info->dev,
-                       "TX FIFO endianess is configured incorrectly\n");
-               return -EINVAL;
-       }
-       if ((chip_info->data_size < SSP_DATA_BITS_4)
-           || (chip_info->data_size > SSP_DATA_BITS_32)) {
-               dev_err(chip_info->dev,
-                       "DATA Size is configured incorrectly\n");
-               return -EINVAL;
-       }
        if ((chip_info->com_mode != INTERRUPT_TRANSFER)
            && (chip_info->com_mode != DMA_TRANSFER)
            && (chip_info->com_mode != POLLING_TRANSFER)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "Communication mode is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
            || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "RX FIFO Trigger Level is configured incorrectly\n");
                return -EINVAL;
        }
        if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
            || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
-               dev_err(chip_info->dev,
+               dev_err(&pl022->adev->dev,
                        "TX FIFO Trigger Level is configured incorrectly\n");
                return -EINVAL;
        }
-       if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) {
-               if ((chip_info->clk_phase != SSP_CLK_FIRST_EDGE)
-                   && (chip_info->clk_phase != SSP_CLK_SECOND_EDGE)) {
-                       dev_err(chip_info->dev,
-                               "Clock Phase is configured incorrectly\n");
-                       return -EINVAL;
-               }
-               if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW)
-                   && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) {
-                       dev_err(chip_info->dev,
-                               "Clock Polarity is configured incorrectly\n");
-                       return -EINVAL;
-               }
-       }
        if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
                if ((chip_info->ctrl_len < SSP_BITS_4)
                    || (chip_info->ctrl_len > SSP_BITS_32)) {
-                       dev_err(chip_info->dev,
+                       dev_err(&pl022->adev->dev,
                                "CTRL LEN is configured incorrectly\n");
                        return -EINVAL;
                }
                if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
                    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
-                       dev_err(chip_info->dev,
+                       dev_err(&pl022->adev->dev,
                                "Wait State is configured incorrectly\n");
                        return -EINVAL;
                }
@@ -1348,24 +1651,20 @@ static int verify_controller_parameters(struct pl022 *pl022,
                        if ((chip_info->duplex !=
                             SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
                            && (chip_info->duplex !=
-                               SSP_MICROWIRE_CHANNEL_HALF_DUPLEX))
-                               dev_err(chip_info->dev,
+                               SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
+                               dev_err(&pl022->adev->dev,
                                        "Microwire duplex mode is configured incorrectly\n");
                                return -EINVAL;
+                       }
                } else {
                        if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-                               dev_err(chip_info->dev,
+                               dev_err(&pl022->adev->dev,
                                        "Microwire half duplex mode requested,"
                                        " but this is only available in the"
                                        " ST version of PL022\n");
                        return -EINVAL;
                }
        }
-       if (chip_info->cs_control == NULL) {
-               dev_warn(chip_info->dev,
-                       "Chip Select Function is NULL for this chip\n");
-               chip_info->cs_control = null_cs_control;
-       }
        return 0;
 }
 
@@ -1465,22 +1764,24 @@ static int calculate_effective_freq(struct pl022 *pl022,
        return 0;
 }
 
-/**
- * NOT IMPLEMENTED
- * process_dma_info - Processes the DMA info provided by client drivers
- * @chip_info: chip info provided by client device
- * @chip: Runtime state maintained by the SSP controller for each spi device
- *
- * This function processes and stores DMA config provided by client driver
- * into the runtime state maintained by the SSP controller driver
+
+/*
+ * A piece of default chip info unless the platform
+ * supplies it.
  */
-static int process_dma_info(struct pl022_config_chip *chip_info,
-                           struct chip_data *chip)
-{
-       dev_err(chip_info->dev,
-               "cannot process DMA info, DMA not implemented!\n");
-       return -ENOTSUPP;
-}
+static const struct pl022_config_chip pl022_default_chip_info = {
+       .com_mode = POLLING_TRANSFER,
+       .iface = SSP_INTERFACE_MOTOROLA_SPI,
+       .hierarchy = SSP_SLAVE,
+       .slave_tx_disable = DO_NOT_DRIVE_TX,
+       .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
+       .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+       .ctrl_len = SSP_BITS_8,
+       .wait_state = SSP_MWIRE_WAIT_ZERO,
+       .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+       .cs_control = null_cs_control,
+};
+
 
 /**
  * pl022_setup - setup function registered to SPI master framework
@@ -1494,23 +1795,15 @@ static int process_dma_info(struct pl022_config_chip *chip_info,
  * controller hardware here, that is not done until the actual transfer
  * commence.
  */
-
-/* FIXME: JUST GUESSING the spi->mode bits understood by this driver */
-#define MODEBITS       (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
-                       | SPI_LSB_FIRST | SPI_LOOP)
-
 static int pl022_setup(struct spi_device *spi)
 {
-       struct pl022_config_chip *chip_info;
+       struct pl022_config_chip const *chip_info;
        struct chip_data *chip;
+       struct ssp_clock_params clk_freq;
        int status = 0;
        struct pl022 *pl022 = spi_master_get_devdata(spi->master);
-
-       if (spi->mode & ~MODEBITS) {
-               dev_dbg(&spi->dev, "unsupported mode bits %x\n",
-                       spi->mode & ~MODEBITS);
-               return -EINVAL;
-       }
+       unsigned int bits = spi->bits_per_word;
+       u32 tmp;
 
        if (!spi->max_speed_hz)
                return -EINVAL;
@@ -1533,48 +1826,13 @@ static int pl022_setup(struct spi_device *spi)
        chip_info = spi->controller_data;
 
        if (chip_info == NULL) {
+               chip_info = &pl022_default_chip_info;
                /* spi_board_info.controller_data not is supplied */
                dev_dbg(&spi->dev,
                        "using default controller_data settings\n");
-
-               chip_info =
-                       kzalloc(sizeof(struct pl022_config_chip), GFP_KERNEL);
-
-               if (!chip_info) {
-                       dev_err(&spi->dev,
-                               "cannot allocate controller data\n");
-                       status = -ENOMEM;
-                       goto err_first_setup;
-               }
-
-               dev_dbg(&spi->dev, "allocated memory for controller data\n");
-
-               /* Pointer back to the SPI device */
-               chip_info->dev = &spi->dev;
-               /*
-                * Set controller data default values:
-                * Polling is supported by default
-                */
-               chip_info->lbm = LOOPBACK_DISABLED;
-               chip_info->com_mode = POLLING_TRANSFER;
-               chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI;
-               chip_info->hierarchy = SSP_SLAVE;
-               chip_info->slave_tx_disable = DO_NOT_DRIVE_TX;
-               chip_info->endian_tx = SSP_TX_LSB;
-               chip_info->endian_rx = SSP_RX_LSB;
-               chip_info->data_size = SSP_DATA_BITS_12;
-               chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM;
-               chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC;
-               chip_info->clk_phase = SSP_CLK_SECOND_EDGE;
-               chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW;
-               chip_info->ctrl_len = SSP_BITS_8;
-               chip_info->wait_state = SSP_MWIRE_WAIT_ZERO;
-               chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX;
-               chip_info->cs_control = null_cs_control;
-       } else {
+       } else
                dev_dbg(&spi->dev,
                        "using user supplied controller_data settings\n");
-       }
 
        /*
         * We can override with custom divisors, else we use the board
@@ -1584,29 +1842,48 @@ static int pl022_setup(struct spi_device *spi)
            && (0 == chip_info->clk_freq.scr)) {
                status = calculate_effective_freq(pl022,
                                                  spi->max_speed_hz,
-                                                 &chip_info->clk_freq);
+                                                 &clk_freq);
                if (status < 0)
                        goto err_config_params;
        } else {
-               if ((chip_info->clk_freq.cpsdvsr % 2) != 0)
-                       chip_info->clk_freq.cpsdvsr =
-                               chip_info->clk_freq.cpsdvsr - 1;
+               memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq));
+               if ((clk_freq.cpsdvsr % 2) != 0)
+                       clk_freq.cpsdvsr =
+                               clk_freq.cpsdvsr - 1;
        }
+       if ((clk_freq.cpsdvsr < CPSDVR_MIN)
+           || (clk_freq.cpsdvsr > CPSDVR_MAX)) {
+               dev_err(&spi->dev,
+                       "cpsdvsr is configured incorrectly\n");
+               goto err_config_params;
+       }
+
+
        status = verify_controller_parameters(pl022, chip_info);
        if (status) {
                dev_err(&spi->dev, "controller data is incorrect");
                goto err_config_params;
        }
+
        /* Now set controller state based on controller data */
        chip->xfer_type = chip_info->com_mode;
-       chip->cs_control = chip_info->cs_control;
-
-       if (chip_info->data_size <= 8) {
-               dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n");
+       if (!chip_info->cs_control) {
+               chip->cs_control = null_cs_control;
+               dev_warn(&spi->dev,
+                        "chip select function is NULL for this chip\n");
+       } else
+               chip->cs_control = chip_info->cs_control;
+
+       if (bits <= 3) {
+               /* PL022 doesn't support less than 4-bits */
+               status = -ENOTSUPP;
+               goto err_config_params;
+       } else if (bits <= 8) {
+               dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
                chip->n_bytes = 1;
                chip->read = READING_U8;
                chip->write = WRITING_U8;
-       } else if (chip_info->data_size <= 16) {
+       } else if (bits <= 16) {
                dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
                chip->n_bytes = 2;
                chip->read = READING_U16;
@@ -1623,6 +1900,7 @@ static int pl022_setup(struct spi_device *spi)
                        dev_err(&spi->dev,
                                "a standard pl022 can only handle "
                                "1 <= n <= 16 bit words\n");
+                       status = -ENOTSUPP;
                        goto err_config_params;
                }
        }
@@ -1634,9 +1912,8 @@ static int pl022_setup(struct spi_device *spi)
        chip->cpsr = 0;
        if ((chip_info->com_mode == DMA_TRANSFER)
            && ((pl022->master_info)->enable_dma)) {
-               chip->enable_dma = 1;
+               chip->enable_dma = true;
                dev_dbg(&spi->dev, "DMA mode set in controller state\n");
-               status = process_dma_info(chip_info, chip);
                if (status < 0)
                        goto err_config_params;
                SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
@@ -1644,7 +1921,7 @@ static int pl022_setup(struct spi_device *spi)
                SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
                               SSP_DMACR_MASK_TXDMAE, 1);
        } else {
-               chip->enable_dma = 0;
+               chip->enable_dma = false;
                dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
                SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
                               SSP_DMACR_MASK_RXDMAE, 0);
@@ -1652,10 +1929,12 @@ static int pl022_setup(struct spi_device *spi)
                               SSP_DMACR_MASK_TXDMAE, 1);
        }
 
-       chip->cpsr = chip_info->clk_freq.cpsdvsr;
+       chip->cpsr = clk_freq.cpsdvsr;
 
        /* Special setup for the ST micro extended control registers */
        if (pl022->vendor->extended_cr) {
+               u32 etx;
+
                if (pl022->vendor->pl023) {
                        /* These bits are only in the PL023 */
                        SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
@@ -1671,29 +1950,51 @@ static int pl022_setup(struct spi_device *spi)
                        SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
                                       SSP_CR1_MASK_MWAIT_ST, 6);
                }
-               SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
+               SSP_WRITE_BITS(chip->cr0, bits - 1,
                               SSP_CR0_MASK_DSS_ST, 0);
-               SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx,
-                              SSP_CR1_MASK_RENDN_ST, 4);
-               SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx,
-                              SSP_CR1_MASK_TENDN_ST, 5);
+
+               if (spi->mode & SPI_LSB_FIRST) {
+                       tmp = SSP_RX_LSB;
+                       etx = SSP_TX_LSB;
+               } else {
+                       tmp = SSP_RX_MSB;
+                       etx = SSP_TX_MSB;
+               }
+               SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
+               SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
                SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
                               SSP_CR1_MASK_RXIFLSEL_ST, 7);
                SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
                               SSP_CR1_MASK_TXIFLSEL_ST, 10);
        } else {
-               SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
+               SSP_WRITE_BITS(chip->cr0, bits - 1,
                               SSP_CR0_MASK_DSS, 0);
                SSP_WRITE_BITS(chip->cr0, chip_info->iface,
                               SSP_CR0_MASK_FRF, 4);
        }
+
        /* Stuff that is common for all versions */
-       SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6);
-       SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7);
-       SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8);
+       if (spi->mode & SPI_CPOL)
+               tmp = SSP_CLK_POL_IDLE_HIGH;
+       else
+               tmp = SSP_CLK_POL_IDLE_LOW;
+       SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
+
+       if (spi->mode & SPI_CPHA)
+               tmp = SSP_CLK_SECOND_EDGE;
+       else
+               tmp = SSP_CLK_FIRST_EDGE;
+       SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
+
+       SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
        /* Loopback is available on all versions except PL023 */
-       if (!pl022->vendor->pl023)
-               SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
+       if (!pl022->vendor->pl023) {
+               if (spi->mode & SPI_LOOP)
+                       tmp = LOOPBACK_ENABLED;
+               else
+                       tmp = LOOPBACK_DISABLED;
+               SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
+       }
        SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
        SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
        SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
@@ -1702,7 +2003,7 @@ static int pl022_setup(struct spi_device *spi)
        spi_set_ctldata(spi, chip);
        return status;
  err_config_params:
- err_first_setup:
+       spi_set_ctldata(spi, NULL);
        kfree(chip);
        return status;
 }
@@ -1764,12 +2065,21 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
        master->setup = pl022_setup;
        master->transfer = pl022_transfer;
 
+       /*
+        * Supports mode 0-3, loopback, and active low CS. Transfers are
+        * always MS bit first on the original pl022.
+        */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+       if (pl022->vendor->extended_cr)
+               master->mode_bits |= SPI_LSB_FIRST;
+
        dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
 
        status = amba_request_regions(adev, NULL);
        if (status)
                goto err_no_ioregion;
 
+       pl022->phybase = adev->res.start;
        pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
        if (pl022->virtbase == NULL) {
                status = -ENOMEM;
@@ -1786,11 +2096,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
        }
 
        /* Disable SSP */
-       clk_enable(pl022->clk);
        writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
               SSP_CR1(pl022->virtbase));
        load_ssp_default_config(pl022);
-       clk_disable(pl022->clk);
 
        status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
                             pl022);
@@ -1798,6 +2106,14 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
                dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
                goto err_no_irq;
        }
+
+       /* Get DMA channels */
+       if (platform_info->enable_dma) {
+               status = pl022_dma_probe(pl022);
+               if (status != 0)
+                       goto err_no_dma;
+       }
+
        /* Initialize and start queue */
        status = init_queue(pl022);
        if (status != 0) {
@@ -1818,12 +2134,16 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
                goto err_spi_register;
        }
        dev_dbg(dev, "probe succeded\n");
+       /* Disable the silicon block pclk and clock it when needed */
+       amba_pclk_disable(adev);
        return 0;
 
  err_spi_register:
  err_start_queue:
  err_init_queue:
        destroy_queue(pl022);
+       pl022_dma_remove(pl022);
+ err_no_dma:
        free_irq(adev->irq[0], pl022);
  err_no_irq:
        clk_put(pl022->clk);
@@ -1854,6 +2174,7 @@ pl022_remove(struct amba_device *adev)
                return status;
        }
        load_ssp_default_config(pl022);
+       pl022_dma_remove(pl022);
        free_irq(adev->irq[0], pl022);
        clk_disable(pl022->clk);
        clk_put(pl022->clk);
@@ -1879,9 +2200,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state)
                return status;
        }
 
-       clk_enable(pl022->clk);
+       amba_pclk_enable(adev);
        load_ssp_default_config(pl022);
-       clk_disable(pl022->clk);
+       amba_pclk_disable(adev);
        dev_dbg(&adev->dev, "suspended\n");
        return 0;
 }
@@ -1981,7 +2302,7 @@ static int __init pl022_init(void)
        return amba_driver_register(&pl022_driver);
 }
 
-module_init(pl022_init);
+subsys_initcall(pl022_init);
 
 static void __exit pl022_exit(void)
 {
index c4e04428992de8302b3b3e2a512927bdb159643b..154529aacc037e332b005c418659089d80d5c9c5 100644 (file)
@@ -654,6 +654,8 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
        struct spi_transfer     *xfer;
        unsigned long           flags;
        struct device           *controller = spi->master->dev.parent;
+       u8                      bits;
+       struct atmel_spi_device *asd;
 
        as = spi_master_get_devdata(spi->master);
 
@@ -672,8 +674,18 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
                        return -EINVAL;
                }
 
+               if (xfer->bits_per_word) {
+                       asd = spi->controller_state;
+                       bits = (asd->csr >> 4) & 0xf;
+                       if (bits != xfer->bits_per_word - 8) {
+                               dev_dbg(&spi->dev, "you can't yet change "
+                                        "bits_per_word in transfers\n");
+                               return -ENOPROTOOPT;
+                       }
+               }
+
                /* FIXME implement these protocol options!! */
-               if (xfer->bits_per_word || xfer->speed_hz) {
+               if (xfer->speed_hz) {
                        dev_dbg(&spi->dev, "no protocol options yet\n");
                        return -ENOPROTOOPT;
                }
index d256cb00604c55db5cc2ce25233b8d8e189c69be..90439314cf673ce19c33747ab4f283f0f3f0bc01 100644 (file)
@@ -131,6 +131,7 @@ static const struct file_operations mrst_spi_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = spi_show_regs_open,
        .read           = spi_show_regs,
+       .llseek         = default_llseek,
 };
 
 static int mrst_spi_debugfs_init(struct dw_spi *dws)
@@ -181,10 +182,6 @@ static void flush(struct dw_spi *dws)
        wait_till_not_busy(dws);
 }
 
-static void null_cs_control(u32 command)
-{
-}
-
 static int null_writer(struct dw_spi *dws)
 {
        u8 n_bytes = dws->n_bytes;
@@ -322,7 +319,7 @@ static void giveback(struct dw_spi *dws)
                                        struct spi_transfer,
                                        transfer_list);
 
-       if (!last_transfer->cs_change)
+       if (!last_transfer->cs_change && dws->cs_control)
                dws->cs_control(MRST_SPI_DEASSERT);
 
        msg->state = NULL;
@@ -396,6 +393,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
        struct dw_spi *dws = dev_id;
+       u16 irq_status, irq_mask = 0x3f;
+
+       irq_status = dw_readw(dws, isr) & irq_mask;
+       if (!irq_status)
+               return IRQ_NONE;
 
        if (!dws->cur_msg) {
                spi_mask_intr(dws, SPI_INT_TXEI);
@@ -544,13 +546,13 @@ static void pump_transfers(unsigned long data)
         */
        if (dws->cs_control) {
                if (dws->rx && dws->tx)
-                       chip->tmode = 0x00;
+                       chip->tmode = SPI_TMOD_TR;
                else if (dws->rx)
-                       chip->tmode = 0x02;
+                       chip->tmode = SPI_TMOD_RO;
                else
-                       chip->tmode = 0x01;
+                       chip->tmode = SPI_TMOD_TO;
 
-               cr0 &= ~(0x3 << SPI_MODE_OFFSET);
+               cr0 &= ~SPI_TMOD_MASK;
                cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
        }
 
@@ -699,9 +701,6 @@ static int dw_spi_setup(struct spi_device *spi)
                chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
                if (!chip)
                        return -ENOMEM;
-
-               chip->cs_control = null_cs_control;
-               chip->enable_dma = 0;
        }
 
        /*
@@ -883,7 +882,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
        dws->dma_inited = 0;
        dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
 
-       ret = request_irq(dws->irq, dw_spi_irq, 0,
+       ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
                        "dw_spi", dws);
        if (ret < 0) {
                dev_err(&master->dev, "can not get IRQ\n");
index b3a94ca0a75a01abc643f96fb3209b6a359d1dc6..2a651e61bfbff30f23e8e44dddfcb70ab8a05173 100644 (file)
@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
        return 0;
 }
 
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(1000);
+       while (!(__raw_readl(reg) & bit)) {
+               if (time_after(jiffies, timeout))
+                       return -1;
+               cpu_relax();
+       }
+       return 0;
+}
+
 static unsigned
 omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        u32                     l;
        u8                      * rx;
        const u8                * tx;
+       void __iomem            *chstat_reg;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
        l = mcspi_cached_chconf0(spi);
 
+       chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+
        count = xfer->len;
        c = count;
        word_len = cs->word_len;
@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        if (tx != NULL) {
                wait_for_completion(&mcspi_dma->dma_tx_completion);
                dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+
+               /* for TX_ONLY mode, be sure all words have shifted out */
+               if (rx == NULL) {
+                       if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_TXS) < 0)
+                               dev_err(&spi->dev, "TXS timed out\n");
+                       else if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_EOT) < 0)
+                               dev_err(&spi->dev, "EOT timed out\n");
+               }
        }
 
        if (rx != NULL) {
@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        return count;
 }
 
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(1000);
-       while (!(__raw_readl(reg) & bit)) {
-               if (time_after(jiffies, timeout))
-                       return -1;
-               cpu_relax();
-       }
-       return 0;
-}
-
 static unsigned
 omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -489,10 +502,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %02x\n",
+                               dev_vdbg(&spi->dev, "write-%d %02x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -506,10 +517,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %02x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -522,10 +531,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %02x\n",
+                               dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        } else if (word_len <= 16) {
@@ -542,10 +549,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %04x\n",
+                               dev_vdbg(&spi->dev, "write-%d %04x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -559,10 +564,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %04x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -575,10 +578,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %04x\n",
+                               dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        } else if (word_len <= 32) {
@@ -595,10 +596,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %08x\n",
+                               dev_vdbg(&spi->dev, "write-%d %08x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -612,10 +611,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %08x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -628,10 +625,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %08x\n",
+                               dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        }
@@ -644,6 +639,12 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                } else if (mcspi_wait_for_reg_bit(chstat_reg,
                                OMAP2_MCSPI_CHSTAT_EOT) < 0)
                        dev_err(&spi->dev, "EOT timed out\n");
+
+               /* disable chan to purge rx datas received in TX_ONLY transfer,
+                * otherwise these rx datas will affect the direct following
+                * RX_ONLY transfer.
+                */
+               omap2_mcspi_set_enable(spi, 0);
        }
 out:
        omap2_mcspi_set_enable(spi, 1);
index 3aea50da7b29f22211d7dc93410208b7dc876e87..0b677dc041ad1a6b07cf92c9a3e9444275cec4e8 100644 (file)
@@ -404,7 +404,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
                        goto msg_rejected;
                }
 
-               if ((t != NULL) && t->bits_per_word)
+               if (t->bits_per_word)
                        bits_per_word = t->bits_per_word;
 
                if ((bits_per_word != 8) && (bits_per_word != 16)) {
@@ -415,7 +415,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
                        goto msg_rejected;
                }
                /*make sure buffer length is even when working in 16 bit mode*/
-               if ((t != NULL) && (t->bits_per_word == 16) && (t->len & 1)) {
+               if ((t->bits_per_word == 16) && (t->len & 1)) {
                        dev_err(&spi->dev,
                                "message rejected : "
                                "odd data length (%d) while in 16 bit mode\n",
index a9e5c79ae52a04a43aebabeacfc2d3cc29e03e77..b5a78a1f4421a0c19aa8735bd49f076fd8f91b46 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/cache.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
@@ -86,6 +87,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
        const struct spi_device *spi = to_spi_device(dev);
        const struct spi_driver *sdrv = to_spi_driver(drv);
 
+       /* Attempt an OF style match */
+       if (of_driver_match_device(dev, drv))
+               return 1;
+
        if (sdrv->id_table)
                return !!spi_match_id(sdrv->id_table, spi);
 
@@ -554,11 +559,9 @@ done:
 EXPORT_SYMBOL_GPL(spi_register_master);
 
 
-static int __unregister(struct device *dev, void *master_dev)
+static int __unregister(struct device *dev, void *null)
 {
-       /* note: before about 2.6.14-rc1 this would corrupt memory: */
-       if (dev != master_dev)
-               spi_unregister_device(to_spi_device(dev));
+       spi_unregister_device(to_spi_device(dev));
        return 0;
 }
 
@@ -576,8 +579,7 @@ void spi_unregister_master(struct spi_master *master)
 {
        int dummy;
 
-       dummy = device_for_each_child(master->dev.parent, &master->dev,
-                                       __unregister);
+       dummy = device_for_each_child(&master->dev, NULL, __unregister);
        device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
index 10a6dc3d37ac835568083698b1165ea027893739..ab483a0ec6d05b7738ab85aed075ee0a293598bf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip SPI Driver
  *
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -41,13 +41,16 @@ MODULE_LICENSE("GPL");
 #define RUNNING_STATE  ((void *)1)
 #define DONE_STATE     ((void *)2)
 #define ERROR_STATE    ((void *)-1)
-#define QUEUE_RUNNING  0
-#define QUEUE_STOPPED  1
 
-/* Value to send if no TX value is supplied */
-#define SPI_IDLE_TXVAL 0x0000
+struct bfin_spi_master_data;
 
-struct driver_data {
+struct bfin_spi_transfer_ops {
+       void (*write) (struct bfin_spi_master_data *);
+       void (*read) (struct bfin_spi_master_data *);
+       void (*duplex) (struct bfin_spi_master_data *);
+};
+
+struct bfin_spi_master_data {
        /* Driver model hookup */
        struct platform_device *pdev;
 
@@ -69,7 +72,7 @@ struct driver_data {
        spinlock_t lock;
        struct list_head queue;
        int busy;
-       int run;
+       bool running;
 
        /* Message Transfer pump */
        struct tasklet_struct pump_transfers;
@@ -77,7 +80,7 @@ struct driver_data {
        /* Current message transfer state info */
        struct spi_message *cur_msg;
        struct spi_transfer *cur_transfer;
-       struct chip_data *cur_chip;
+       struct bfin_spi_slave_data *cur_chip;
        size_t len_in_bytes;
        size_t len;
        void *tx;
@@ -92,38 +95,37 @@ struct driver_data {
        dma_addr_t rx_dma;
        dma_addr_t tx_dma;
 
+       int irq_requested;
+       int spi_irq;
+
        size_t rx_map_len;
        size_t tx_map_len;
        u8 n_bytes;
+       u16 ctrl_reg;
+       u16 flag_reg;
+
        int cs_change;
-       void (*write) (struct driver_data *);
-       void (*read) (struct driver_data *);
-       void (*duplex) (struct driver_data *);
+       const struct bfin_spi_transfer_ops *ops;
 };
 
-struct chip_data {
+struct bfin_spi_slave_data {
        u16 ctl_reg;
        u16 baud;
        u16 flag;
 
        u8 chip_select_num;
-       u8 n_bytes;
-       u8 width;               /* 0 or 1 */
        u8 enable_dma;
-       u8 bits_per_word;       /* 8 or 16 */
-       u8 cs_change_per_word;
        u16 cs_chg_udelay;      /* Some devices require > 255usec delay */
        u32 cs_gpio;
        u16 idle_tx_val;
-       void (*write) (struct driver_data *);
-       void (*read) (struct driver_data *);
-       void (*duplex) (struct driver_data *);
+       u8 pio_interrupt;       /* use spi data irq */
+       const struct bfin_spi_transfer_ops *ops;
 };
 
 #define DEFINE_SPI_REG(reg, off) \
-static inline u16 read_##reg(struct driver_data *drv_data) \
+static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
        { return bfin_read16(drv_data->regs_base + off); } \
-static inline void write_##reg(struct driver_data *drv_data, u16 v) \
+static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \
        { bfin_write16(drv_data->regs_base + off, v); }
 
 DEFINE_SPI_REG(CTRL, 0x00)
@@ -134,7 +136,7 @@ DEFINE_SPI_REG(RDBR, 0x10)
 DEFINE_SPI_REG(BAUD, 0x14)
 DEFINE_SPI_REG(SHAW, 0x18)
 
-static void bfin_spi_enable(struct driver_data *drv_data)
+static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
 {
        u16 cr;
 
@@ -142,7 +144,7 @@ static void bfin_spi_enable(struct driver_data *drv_data)
        write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
 }
 
-static void bfin_spi_disable(struct driver_data *drv_data)
+static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
 {
        u16 cr;
 
@@ -165,7 +167,7 @@ static u16 hz_to_spi_baud(u32 speed_hz)
        return spi_baud;
 }
 
-static int bfin_spi_flush(struct driver_data *drv_data)
+static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
 {
        unsigned long limit = loops_per_jiffy << 1;
 
@@ -179,13 +181,12 @@ static int bfin_spi_flush(struct driver_data *drv_data)
 }
 
 /* Chip select operation functions for cs_change flag */
-static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
 {
-       if (likely(chip->chip_select_num)) {
+       if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
                u16 flag = read_FLAG(drv_data);
 
-               flag |= chip->flag;
-               flag &= ~(chip->flag << 8);
+               flag &= ~chip->flag;
 
                write_FLAG(drv_data, flag);
        } else {
@@ -193,13 +194,13 @@ static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *c
        }
 }
 
-static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
+                                 struct bfin_spi_slave_data *chip)
 {
-       if (likely(chip->chip_select_num)) {
+       if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
                u16 flag = read_FLAG(drv_data);
 
-               flag &= ~chip->flag;
-               flag |= (chip->flag << 8);
+               flag |= chip->flag;
 
                write_FLAG(drv_data, flag);
        } else {
@@ -211,16 +212,43 @@ static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data
                udelay(chip->cs_chg_udelay);
 }
 
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
+                                      struct bfin_spi_slave_data *chip)
+{
+       if (chip->chip_select_num < MAX_CTRL_CS) {
+               u16 flag = read_FLAG(drv_data);
+
+               flag |= (chip->flag >> 8);
+
+               write_FLAG(drv_data, flag);
+       }
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
+                                       struct bfin_spi_slave_data *chip)
+{
+       if (chip->chip_select_num < MAX_CTRL_CS) {
+               u16 flag = read_FLAG(drv_data);
+
+               flag &= ~(chip->flag >> 8);
+
+               write_FLAG(drv_data, flag);
+       }
+}
+
 /* stop controller and re-config current chip*/
-static void bfin_spi_restore_state(struct driver_data *drv_data)
+static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
 {
-       struct chip_data *chip = drv_data->cur_chip;
+       struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 
        /* Clear status and disable clock */
        write_STAT(drv_data, BIT_STAT_CLR);
        bfin_spi_disable(drv_data);
        dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
 
+       SSYNC();
+
        /* Load the registers */
        write_CTRL(drv_data, chip->ctl_reg);
        write_BAUD(drv_data, chip->baud);
@@ -230,49 +258,12 @@ static void bfin_spi_restore_state(struct driver_data *drv_data)
 }
 
 /* used to kick off transfer in rx mode and read unwanted RX data */
-static inline void bfin_spi_dummy_read(struct driver_data *drv_data)
+static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
 {
        (void) read_RDBR(drv_data);
 }
 
-static void bfin_spi_null_writer(struct driver_data *drv_data)
-{
-       u8 n_bytes = drv_data->n_bytes;
-       u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-       /* clear RXS (we check for RXS inside the loop) */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->tx < drv_data->tx_end) {
-               write_TDBR(drv_data, tx_val);
-               drv_data->tx += n_bytes;
-               /* wait until transfer finished.
-                  checking SPIF or TXS may not guarantee transfer completion */
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               /* discard RX data and clear RXS */
-               bfin_spi_dummy_read(drv_data);
-       }
-}
-
-static void bfin_spi_null_reader(struct driver_data *drv_data)
-{
-       u8 n_bytes = drv_data->n_bytes;
-       u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-       /* discard old RX data and clear RXS */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->rx < drv_data->rx_end) {
-               write_TDBR(drv_data, tx_val);
-               drv_data->rx += n_bytes;
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               bfin_spi_dummy_read(drv_data);
-       }
-}
-
-static void bfin_spi_u8_writer(struct driver_data *drv_data)
+static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
 {
        /* clear RXS (we check for RXS inside the loop) */
        bfin_spi_dummy_read(drv_data);
@@ -288,25 +279,7 @@ static void bfin_spi_u8_writer(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u8_cs_chg_writer(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-
-       /* clear RXS (we check for RXS inside the loop) */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->tx < drv_data->tx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-               /* make sure transfer finished before deactiving CS */
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               bfin_spi_dummy_read(drv_data);
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
-
-static void bfin_spi_u8_reader(struct driver_data *drv_data)
+static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
 {
        u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
@@ -321,25 +294,7 @@ static void bfin_spi_u8_reader(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u8_cs_chg_reader(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-       u16 tx_val = chip->idle_tx_val;
-
-       /* discard old RX data and clear RXS */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->rx < drv_data->rx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, tx_val);
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               *(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
-
-static void bfin_spi_u8_duplex(struct driver_data *drv_data)
+static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
 {
        /* discard old RX data and clear RXS */
        bfin_spi_dummy_read(drv_data);
@@ -352,24 +307,13 @@ static void bfin_spi_u8_duplex(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u8_cs_chg_duplex(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-
-       /* discard old RX data and clear RXS */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->rx < drv_data->rx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               *(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+       .write  = bfin_spi_u8_writer,
+       .read   = bfin_spi_u8_reader,
+       .duplex = bfin_spi_u8_duplex,
+};
 
-static void bfin_spi_u16_writer(struct driver_data *drv_data)
+static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
 {
        /* clear RXS (we check for RXS inside the loop) */
        bfin_spi_dummy_read(drv_data);
@@ -386,26 +330,7 @@ static void bfin_spi_u16_writer(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u16_cs_chg_writer(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-
-       /* clear RXS (we check for RXS inside the loop) */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->tx < drv_data->tx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-               drv_data->tx += 2;
-               /* make sure transfer finished before deactiving CS */
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               bfin_spi_dummy_read(drv_data);
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
-
-static void bfin_spi_u16_reader(struct driver_data *drv_data)
+static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
 {
        u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
@@ -421,26 +346,7 @@ static void bfin_spi_u16_reader(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u16_cs_chg_reader(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-       u16 tx_val = chip->idle_tx_val;
-
-       /* discard old RX data and clear RXS */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->rx < drv_data->rx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, tx_val);
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-               drv_data->rx += 2;
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
-
-static void bfin_spi_u16_duplex(struct driver_data *drv_data)
+static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
 {
        /* discard old RX data and clear RXS */
        bfin_spi_dummy_read(drv_data);
@@ -455,27 +361,14 @@ static void bfin_spi_u16_duplex(struct driver_data *drv_data)
        }
 }
 
-static void bfin_spi_u16_cs_chg_duplex(struct driver_data *drv_data)
-{
-       struct chip_data *chip = drv_data->cur_chip;
-
-       /* discard old RX data and clear RXS */
-       bfin_spi_dummy_read(drv_data);
-
-       while (drv_data->rx < drv_data->rx_end) {
-               bfin_spi_cs_active(drv_data, chip);
-               write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-               drv_data->tx += 2;
-               while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-                       cpu_relax();
-               *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-               drv_data->rx += 2;
-               bfin_spi_cs_deactive(drv_data, chip);
-       }
-}
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+       .write  = bfin_spi_u16_writer,
+       .read   = bfin_spi_u16_reader,
+       .duplex = bfin_spi_u16_duplex,
+};
 
-/* test if ther is more transfer to be done */
-static void *bfin_spi_next_transfer(struct driver_data *drv_data)
+/* test if there is more transfer to be done */
+static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
 {
        struct spi_message *msg = drv_data->cur_msg;
        struct spi_transfer *trans = drv_data->cur_transfer;
@@ -494,9 +387,9 @@ static void *bfin_spi_next_transfer(struct driver_data *drv_data)
  * caller already set message->status;
  * dma and pio irqs are blocked give finished message back
  */
-static void bfin_spi_giveback(struct driver_data *drv_data)
+static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
 {
-       struct chip_data *chip = drv_data->cur_chip;
+       struct bfin_spi_slave_data *chip = drv_data->cur_chip;
        struct spi_transfer *last_transfer;
        unsigned long flags;
        struct spi_message *msg;
@@ -525,10 +418,83 @@ static void bfin_spi_giveback(struct driver_data *drv_data)
                msg->complete(msg->context);
 }
 
+/* spi data irq handler */
+static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
+{
+       struct bfin_spi_master_data *drv_data = dev_id;
+       struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+       struct spi_message *msg = drv_data->cur_msg;
+       int n_bytes = drv_data->n_bytes;
+
+       /* wait until transfer finished. */
+       while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+               cpu_relax();
+
+       if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
+               (drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
+               /* last read */
+               if (drv_data->rx) {
+                       dev_dbg(&drv_data->pdev->dev, "last read\n");
+                       if (n_bytes == 2)
+                               *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+                       else if (n_bytes == 1)
+                               *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+                       drv_data->rx += n_bytes;
+               }
+
+               msg->actual_length += drv_data->len_in_bytes;
+               if (drv_data->cs_change)
+                       bfin_spi_cs_deactive(drv_data, chip);
+               /* Move to next transfer */
+               msg->state = bfin_spi_next_transfer(drv_data);
+
+               disable_irq_nosync(drv_data->spi_irq);
+
+               /* Schedule transfer tasklet */
+               tasklet_schedule(&drv_data->pump_transfers);
+               return IRQ_HANDLED;
+       }
+
+       if (drv_data->rx && drv_data->tx) {
+               /* duplex */
+               dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
+               if (drv_data->n_bytes == 2) {
+                       *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+                       write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+               } else if (drv_data->n_bytes == 1) {
+                       *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+                       write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+               }
+       } else if (drv_data->rx) {
+               /* read */
+               dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
+               if (drv_data->n_bytes == 2)
+                       *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+               else if (drv_data->n_bytes == 1)
+                       *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+               write_TDBR(drv_data, chip->idle_tx_val);
+       } else if (drv_data->tx) {
+               /* write */
+               dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
+               bfin_spi_dummy_read(drv_data);
+               if (drv_data->n_bytes == 2)
+                       write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+               else if (drv_data->n_bytes == 1)
+                       write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+       }
+
+       if (drv_data->tx)
+               drv_data->tx += n_bytes;
+       if (drv_data->rx)
+               drv_data->rx += n_bytes;
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 {
-       struct driver_data *drv_data = dev_id;
-       struct chip_data *chip = drv_data->cur_chip;
+       struct bfin_spi_master_data *drv_data = dev_id;
+       struct bfin_spi_slave_data *chip = drv_data->cur_chip;
        struct spi_message *msg = drv_data->cur_msg;
        unsigned long timeout;
        unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
@@ -540,10 +506,6 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 
        clear_dma_irqstat(drv_data->dma_channel);
 
-       /* Wait for DMA to complete */
-       while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN)
-               cpu_relax();
-
        /*
         * wait for the last transaction shifted out.  HRM states:
         * at this point there may still be data in the SPI DMA FIFO waiting
@@ -551,8 +513,8 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
         * register until it goes low for 2 successive reads
         */
        if (drv_data->tx != NULL) {
-               while ((read_STAT(drv_data) & TXS) ||
-                      (read_STAT(drv_data) & TXS))
+               while ((read_STAT(drv_data) & BIT_STAT_TXS) ||
+                      (read_STAT(drv_data) & BIT_STAT_TXS))
                        cpu_relax();
        }
 
@@ -561,14 +523,14 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
                dmastat, read_STAT(drv_data));
 
        timeout = jiffies + HZ;
-       while (!(read_STAT(drv_data) & SPIF))
+       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
                if (!time_before(jiffies, timeout)) {
                        dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
                        break;
                } else
                        cpu_relax();
 
-       if ((dmastat & DMA_ERR) && (spistat & RBSY)) {
+       if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) {
                msg->state = ERROR_STATE;
                dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
        } else {
@@ -588,20 +550,20 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
        dev_dbg(&drv_data->pdev->dev,
                "disable dma channel irq%d\n",
                drv_data->dma_channel);
-       dma_disable_irq(drv_data->dma_channel);
+       dma_disable_irq_nosync(drv_data->dma_channel);
 
        return IRQ_HANDLED;
 }
 
 static void bfin_spi_pump_transfers(unsigned long data)
 {
-       struct driver_data *drv_data = (struct driver_data *)data;
+       struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data;
        struct spi_message *message = NULL;
        struct spi_transfer *transfer = NULL;
        struct spi_transfer *previous = NULL;
-       struct chip_data *chip = NULL;
-       u8 width;
-       u16 cr, dma_width, dma_config;
+       struct bfin_spi_slave_data *chip = NULL;
+       unsigned int bits_per_word;
+       u16 cr, cr_width, dma_width, dma_config;
        u32 tranf_success = 1;
        u8 full_duplex = 0;
 
@@ -639,7 +601,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
                        udelay(previous->delay_usecs);
        }
 
-       /* Setup the transfer state based on the type of transfer */
+       /* Flush any existing transfers that may be sitting in the hardware */
        if (bfin_spi_flush(drv_data) == 0) {
                dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
                message->status = -EIO;
@@ -679,52 +641,31 @@ static void bfin_spi_pump_transfers(unsigned long data)
        drv_data->cs_change = transfer->cs_change;
 
        /* Bits per word setup */
-       switch (transfer->bits_per_word) {
-       case 8:
+       bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
+       if (bits_per_word == 8) {
                drv_data->n_bytes = 1;
-               width = CFG_SPI_WORDSIZE8;
-               drv_data->read = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
-               drv_data->write = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
-               drv_data->duplex = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
-               break;
-
-       case 16:
+               drv_data->len = transfer->len;
+               cr_width = 0;
+               drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
+       } else if (bits_per_word == 16) {
                drv_data->n_bytes = 2;
-               width = CFG_SPI_WORDSIZE16;
-               drv_data->read = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
-               drv_data->write = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
-               drv_data->duplex = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
-               break;
-
-       default:
-               /* No change, the same as default setting */
-               drv_data->n_bytes = chip->n_bytes;
-               width = chip->width;
-               drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer;
-               drv_data->read = drv_data->rx ? chip->read : bfin_spi_null_reader;
-               drv_data->duplex = chip->duplex ? chip->duplex : bfin_spi_null_writer;
-               break;
-       }
-       cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
-       cr |= (width << 8);
-       write_CTRL(drv_data, cr);
-
-       if (width == CFG_SPI_WORDSIZE16) {
                drv_data->len = (transfer->len) >> 1;
+               cr_width = BIT_CTL_WORDSIZE;
+               drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
        } else {
-               drv_data->len = transfer->len;
+               dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
+               message->status = -EINVAL;
+               bfin_spi_giveback(drv_data);
+               return;
        }
+       cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+       cr |= cr_width;
+       write_CTRL(drv_data, cr);
+
        dev_dbg(&drv_data->pdev->dev,
-               "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
-               drv_data->write, chip->write, bfin_spi_null_writer);
+               "transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
+               drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8);
 
-       /* speed and width has been set on per message */
        message->state = RUNNING_STATE;
        dma_config = 0;
 
@@ -735,13 +676,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
                write_BAUD(drv_data, chip->baud);
 
        write_STAT(drv_data, BIT_STAT_CLR);
-       cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
-       if (drv_data->cs_change)
-               bfin_spi_cs_active(drv_data, chip);
+       bfin_spi_cs_active(drv_data, chip);
 
        dev_dbg(&drv_data->pdev->dev,
                "now pumping a transfer: width is %d, len is %d\n",
-               width, transfer->len);
+               cr_width, transfer->len);
 
        /*
         * Try to map dma buffer and do a dma transfer.  If successful use,
@@ -760,7 +699,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
                /* config dma channel */
                dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
                set_dma_x_count(drv_data->dma_channel, drv_data->len);
-               if (width == CFG_SPI_WORDSIZE16) {
+               if (cr_width == BIT_CTL_WORDSIZE) {
                        set_dma_x_modify(drv_data->dma_channel, 2);
                        dma_width = WDSIZE_16;
                } else {
@@ -846,73 +785,100 @@ static void bfin_spi_pump_transfers(unsigned long data)
                dma_enable_irq(drv_data->dma_channel);
                local_irq_restore(flags);
 
-       } else {
-               /* IO mode write then read */
-               dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
-
-               /* we always use SPI_WRITE mode. SPI_READ mode
-                  seems to have problems with setting up the
-                  output value in TDBR prior to the transfer. */
-               write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
-
-               if (full_duplex) {
-                       /* full duplex mode */
-                       BUG_ON((drv_data->tx_end - drv_data->tx) !=
-                              (drv_data->rx_end - drv_data->rx));
-                       dev_dbg(&drv_data->pdev->dev,
-                               "IO duplex: cr is 0x%x\n", cr);
-
-                       drv_data->duplex(drv_data);
+               return;
+       }
 
-                       if (drv_data->tx != drv_data->tx_end)
-                               tranf_success = 0;
-               } else if (drv_data->tx != NULL) {
-                       /* write only half duplex */
-                       dev_dbg(&drv_data->pdev->dev,
-                               "IO write: cr is 0x%x\n", cr);
+       /*
+        * We always use SPI_WRITE mode (transfer starts with TDBR write).
+        * SPI_READ mode (transfer starts with RDBR read) seems to have
+        * problems with setting up the output value in TDBR prior to the
+        * start of the transfer.
+        */
+       write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
 
-                       drv_data->write(drv_data);
+       if (chip->pio_interrupt) {
+               /* SPI irq should have been disabled by now */
 
-                       if (drv_data->tx != drv_data->tx_end)
-                               tranf_success = 0;
-               } else if (drv_data->rx != NULL) {
-                       /* read only half duplex */
-                       dev_dbg(&drv_data->pdev->dev,
-                               "IO read: cr is 0x%x\n", cr);
+               /* discard old RX data and clear RXS */
+               bfin_spi_dummy_read(drv_data);
 
-                       drv_data->read(drv_data);
-                       if (drv_data->rx != drv_data->rx_end)
-                               tranf_success = 0;
+               /* start transfer */
+               if (drv_data->tx == NULL)
+                       write_TDBR(drv_data, chip->idle_tx_val);
+               else {
+                       if (bits_per_word == 8)
+                               write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+                       else
+                               write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+                       drv_data->tx += drv_data->n_bytes;
                }
 
-               if (!tranf_success) {
-                       dev_dbg(&drv_data->pdev->dev,
-                               "IO write error!\n");
-                       message->state = ERROR_STATE;
-               } else {
-                       /* Update total byte transfered */
-                       message->actual_length += drv_data->len_in_bytes;
-                       /* Move to next transfer of this msg */
-                       message->state = bfin_spi_next_transfer(drv_data);
-                       if (drv_data->cs_change)
-                               bfin_spi_cs_deactive(drv_data, chip);
-               }
-               /* Schedule next transfer tasklet */
-               tasklet_schedule(&drv_data->pump_transfers);
+               /* once TDBR is empty, interrupt is triggered */
+               enable_irq(drv_data->spi_irq);
+               return;
+       }
+
+       /* IO mode */
+       dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
+
+       if (full_duplex) {
+               /* full duplex mode */
+               BUG_ON((drv_data->tx_end - drv_data->tx) !=
+                      (drv_data->rx_end - drv_data->rx));
+               dev_dbg(&drv_data->pdev->dev,
+                       "IO duplex: cr is 0x%x\n", cr);
+
+               drv_data->ops->duplex(drv_data);
+
+               if (drv_data->tx != drv_data->tx_end)
+                       tranf_success = 0;
+       } else if (drv_data->tx != NULL) {
+               /* write only half duplex */
+               dev_dbg(&drv_data->pdev->dev,
+                       "IO write: cr is 0x%x\n", cr);
+
+               drv_data->ops->write(drv_data);
+
+               if (drv_data->tx != drv_data->tx_end)
+                       tranf_success = 0;
+       } else if (drv_data->rx != NULL) {
+               /* read only half duplex */
+               dev_dbg(&drv_data->pdev->dev,
+                       "IO read: cr is 0x%x\n", cr);
+
+               drv_data->ops->read(drv_data);
+               if (drv_data->rx != drv_data->rx_end)
+                       tranf_success = 0;
+       }
+
+       if (!tranf_success) {
+               dev_dbg(&drv_data->pdev->dev,
+                       "IO write error!\n");
+               message->state = ERROR_STATE;
+       } else {
+               /* Update total byte transfered */
+               message->actual_length += drv_data->len_in_bytes;
+               /* Move to next transfer of this msg */
+               message->state = bfin_spi_next_transfer(drv_data);
+               if (drv_data->cs_change)
+                       bfin_spi_cs_deactive(drv_data, chip);
        }
+
+       /* Schedule next transfer tasklet */
+       tasklet_schedule(&drv_data->pump_transfers);
 }
 
 /* pop a msg from queue and kick off real transfer */
 static void bfin_spi_pump_messages(struct work_struct *work)
 {
-       struct driver_data *drv_data;
+       struct bfin_spi_master_data *drv_data;
        unsigned long flags;
 
-       drv_data = container_of(work, struct driver_data, pump_messages);
+       drv_data = container_of(work, struct bfin_spi_master_data, pump_messages);
 
        /* Lock queue and check for queue work */
        spin_lock_irqsave(&drv_data->lock, flags);
-       if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+       if (list_empty(&drv_data->queue) || !drv_data->running) {
                /* pumper kicked off but no work to do */
                drv_data->busy = 0;
                spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -962,12 +928,12 @@ static void bfin_spi_pump_messages(struct work_struct *work)
  */
 static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 {
-       struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+       struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
        unsigned long flags;
 
        spin_lock_irqsave(&drv_data->lock, flags);
 
-       if (drv_data->run == QUEUE_STOPPED) {
+       if (!drv_data->running) {
                spin_unlock_irqrestore(&drv_data->lock, flags);
                return -ESHUTDOWN;
        }
@@ -979,7 +945,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
        dev_dbg(&spi->dev, "adding an msg in transfer() \n");
        list_add_tail(&msg->queue, &drv_data->queue);
 
-       if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+       if (drv_data->running && !drv_data->busy)
                queue_work(drv_data->workqueue, &drv_data->pump_messages);
 
        spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -1003,147 +969,184 @@ static u16 ssel[][MAX_SPI_SSEL] = {
        P_SPI2_SSEL6, P_SPI2_SSEL7},
 };
 
-/* first setup for new devices */
+/* setup for devices (may be called multiple times -- not just first setup) */
 static int bfin_spi_setup(struct spi_device *spi)
 {
-       struct bfin5xx_spi_chip *chip_info = NULL;
-       struct chip_data *chip;
-       struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-       int ret;
-
-       if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
-               return -EINVAL;
+       struct bfin5xx_spi_chip *chip_info;
+       struct bfin_spi_slave_data *chip = NULL;
+       struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+       u16 bfin_ctl_reg;
+       int ret = -EINVAL;
 
        /* Only alloc (or use chip_info) on first setup */
+       chip_info = NULL;
        chip = spi_get_ctldata(spi);
        if (chip == NULL) {
-               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-               if (!chip)
-                       return -ENOMEM;
+               chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+               if (!chip) {
+                       dev_err(&spi->dev, "cannot allocate chip data\n");
+                       ret = -ENOMEM;
+                       goto error;
+               }
 
                chip->enable_dma = 0;
                chip_info = spi->controller_data;
        }
 
+       /* Let people set non-standard bits directly */
+       bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO |
+               BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ;
+
        /* chip_info isn't always needed */
        if (chip_info) {
                /* Make sure people stop trying to set fields via ctl_reg
                 * when they should actually be using common SPI framework.
-                * Currently we let through: WOM EMISO PSSE GM SZ TIMOD.
+                * Currently we let through: WOM EMISO PSSE GM SZ.
                 * Not sure if a user actually needs/uses any of these,
                 * but let's assume (for now) they do.
                 */
-               if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) {
+               if (chip_info->ctl_reg & ~bfin_ctl_reg) {
                        dev_err(&spi->dev, "do not set bits in ctl_reg "
                                "that the SPI framework manages\n");
-                       return -EINVAL;
+                       goto error;
                }
-
                chip->enable_dma = chip_info->enable_dma != 0
                    && drv_data->master_info->enable_dma;
                chip->ctl_reg = chip_info->ctl_reg;
-               chip->bits_per_word = chip_info->bits_per_word;
-               chip->cs_change_per_word = chip_info->cs_change_per_word;
                chip->cs_chg_udelay = chip_info->cs_chg_udelay;
-               chip->cs_gpio = chip_info->cs_gpio;
                chip->idle_tx_val = chip_info->idle_tx_val;
+               chip->pio_interrupt = chip_info->pio_interrupt;
+               spi->bits_per_word = chip_info->bits_per_word;
+       } else {
+               /* force a default base state */
+               chip->ctl_reg &= bfin_ctl_reg;
+       }
+
+       if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+               dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+                               spi->bits_per_word);
+               goto error;
        }
 
        /* translate common spi framework into our register */
+       if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
+               dev_err(&spi->dev, "unsupported spi modes detected\n");
+               goto error;
+       }
        if (spi->mode & SPI_CPOL)
-               chip->ctl_reg |= CPOL;
+               chip->ctl_reg |= BIT_CTL_CPOL;
        if (spi->mode & SPI_CPHA)
-               chip->ctl_reg |= CPHA;
+               chip->ctl_reg |= BIT_CTL_CPHA;
        if (spi->mode & SPI_LSB_FIRST)
-               chip->ctl_reg |= LSBF;
+               chip->ctl_reg |= BIT_CTL_LSBF;
        /* we dont support running in slave mode (yet?) */
-       chip->ctl_reg |= MSTR;
+       chip->ctl_reg |= BIT_CTL_MASTER;
 
+       /*
+        * Notice: for blackfin, the speed_hz is the value of register
+        * SPI_BAUD, not the real baudrate
+        */
+       chip->baud = hz_to_spi_baud(spi->max_speed_hz);
+       chip->chip_select_num = spi->chip_select;
+       if (chip->chip_select_num < MAX_CTRL_CS) {
+               if (!(spi->mode & SPI_CPHA))
+                       dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
+                               " Slave Select not under software control!\n"
+                               " See Documentation/blackfin/bfin-spi-notes.txt");
+
+               chip->flag = (1 << spi->chip_select) << 8;
+       } else
+               chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
+
+       if (chip->enable_dma && chip->pio_interrupt) {
+               dev_err(&spi->dev, "enable_dma is set, "
+                               "do not set pio_interrupt\n");
+               goto error;
+       }
        /*
         * if any one SPI chip is registered and wants DMA, request the
         * DMA channel for it
         */
        if (chip->enable_dma && !drv_data->dma_requested) {
                /* register dma irq handler */
-               if (request_dma(drv_data->dma_channel, "BFIN_SPI_DMA") < 0) {
-                       dev_dbg(&spi->dev,
+               ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA");
+               if (ret) {
+                       dev_err(&spi->dev,
                                "Unable to request BlackFin SPI DMA channel\n");
-                       return -ENODEV;
+                       goto error;
                }
-               if (set_dma_callback(drv_data->dma_channel,
-                   bfin_spi_dma_irq_handler, drv_data) < 0) {
-                       dev_dbg(&spi->dev, "Unable to set dma callback\n");
-                       return -EPERM;
+               drv_data->dma_requested = 1;
+
+               ret = set_dma_callback(drv_data->dma_channel,
+                       bfin_spi_dma_irq_handler, drv_data);
+               if (ret) {
+                       dev_err(&spi->dev, "Unable to set dma callback\n");
+                       goto error;
                }
                dma_disable_irq(drv_data->dma_channel);
-               drv_data->dma_requested = 1;
        }
 
-       /*
-        * Notice: for blackfin, the speed_hz is the value of register
-        * SPI_BAUD, not the real baudrate
-        */
-       chip->baud = hz_to_spi_baud(spi->max_speed_hz);
-       chip->flag = 1 << (spi->chip_select);
-       chip->chip_select_num = spi->chip_select;
+       if (chip->pio_interrupt && !drv_data->irq_requested) {
+               ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
+                       IRQF_DISABLED, "BFIN_SPI", drv_data);
+               if (ret) {
+                       dev_err(&spi->dev, "Unable to register spi IRQ\n");
+                       goto error;
+               }
+               drv_data->irq_requested = 1;
+               /* we use write mode, spi irq has to be disabled here */
+               disable_irq(drv_data->spi_irq);
+       }
 
-       if (chip->chip_select_num == 0) {
+       if (chip->chip_select_num >= MAX_CTRL_CS) {
                ret = gpio_request(chip->cs_gpio, spi->modalias);
                if (ret) {
-                       if (drv_data->dma_requested)
-                               free_dma(drv_data->dma_channel);
-                       return ret;
+                       dev_err(&spi->dev, "gpio_request() error\n");
+                       goto pin_error;
                }
                gpio_direction_output(chip->cs_gpio, 1);
        }
 
-       switch (chip->bits_per_word) {
-       case 8:
-               chip->n_bytes = 1;
-               chip->width = CFG_SPI_WORDSIZE8;
-               chip->read = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
-               chip->write = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
-               chip->duplex = chip->cs_change_per_word ?
-                       bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
-               break;
-
-       case 16:
-               chip->n_bytes = 2;
-               chip->width = CFG_SPI_WORDSIZE16;
-               chip->read = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
-               chip->write = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
-               chip->duplex = chip->cs_change_per_word ?
-                       bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
-               break;
-
-       default:
-               dev_err(&spi->dev, "%d bits_per_word is not supported\n",
-                               chip->bits_per_word);
-               if (chip_info)
-                       kfree(chip);
-               return -ENODEV;
-       }
-
        dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
-                       spi->modalias, chip->width, chip->enable_dma);
+                       spi->modalias, spi->bits_per_word, chip->enable_dma);
        dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
                        chip->ctl_reg, chip->flag);
 
        spi_set_ctldata(spi, chip);
 
        dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
-       if ((chip->chip_select_num > 0)
-               && (chip->chip_select_num <= spi->master->num_chipselect))
-               peripheral_request(ssel[spi->master->bus_num]
-                       [chip->chip_select_num-1], spi->modalias);
+       if (chip->chip_select_num < MAX_CTRL_CS) {
+               ret = peripheral_request(ssel[spi->master->bus_num]
+                                        [chip->chip_select_num-1], spi->modalias);
+               if (ret) {
+                       dev_err(&spi->dev, "peripheral_request() error\n");
+                       goto pin_error;
+               }
+       }
 
+       bfin_spi_cs_enable(drv_data, chip);
        bfin_spi_cs_deactive(drv_data, chip);
 
        return 0;
+
+ pin_error:
+       if (chip->chip_select_num >= MAX_CTRL_CS)
+               gpio_free(chip->cs_gpio);
+       else
+               peripheral_free(ssel[spi->master->bus_num]
+                       [chip->chip_select_num - 1]);
+ error:
+       if (chip) {
+               if (drv_data->dma_requested)
+                       free_dma(drv_data->dma_channel);
+               drv_data->dma_requested = 0;
+
+               kfree(chip);
+               /* prevent free 'chip' twice */
+               spi_set_ctldata(spi, NULL);
+       }
+
+       return ret;
 }
 
 /*
@@ -1152,28 +1155,30 @@ static int bfin_spi_setup(struct spi_device *spi)
  */
 static void bfin_spi_cleanup(struct spi_device *spi)
 {
-       struct chip_data *chip = spi_get_ctldata(spi);
+       struct bfin_spi_slave_data *chip = spi_get_ctldata(spi);
+       struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
 
        if (!chip)
                return;
 
-       if ((chip->chip_select_num > 0)
-               && (chip->chip_select_num <= spi->master->num_chipselect))
+       if (chip->chip_select_num < MAX_CTRL_CS) {
                peripheral_free(ssel[spi->master->bus_num]
                                        [chip->chip_select_num-1]);
-
-       if (chip->chip_select_num == 0)
+               bfin_spi_cs_disable(drv_data, chip);
+       } else
                gpio_free(chip->cs_gpio);
 
        kfree(chip);
+       /* prevent free 'chip' twice */
+       spi_set_ctldata(spi, NULL);
 }
 
-static inline int bfin_spi_init_queue(struct driver_data *drv_data)
+static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
 {
        INIT_LIST_HEAD(&drv_data->queue);
        spin_lock_init(&drv_data->lock);
 
-       drv_data->run = QUEUE_STOPPED;
+       drv_data->running = false;
        drv_data->busy = 0;
 
        /* init transfer tasklet */
@@ -1190,18 +1195,18 @@ static inline int bfin_spi_init_queue(struct driver_data *drv_data)
        return 0;
 }
 
-static inline int bfin_spi_start_queue(struct driver_data *drv_data)
+static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&drv_data->lock, flags);
 
-       if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+       if (drv_data->running || drv_data->busy) {
                spin_unlock_irqrestore(&drv_data->lock, flags);
                return -EBUSY;
        }
 
-       drv_data->run = QUEUE_RUNNING;
+       drv_data->running = true;
        drv_data->cur_msg = NULL;
        drv_data->cur_transfer = NULL;
        drv_data->cur_chip = NULL;
@@ -1212,7 +1217,7 @@ static inline int bfin_spi_start_queue(struct driver_data *drv_data)
        return 0;
 }
 
-static inline int bfin_spi_stop_queue(struct driver_data *drv_data)
+static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
 {
        unsigned long flags;
        unsigned limit = 500;
@@ -1226,7 +1231,7 @@ static inline int bfin_spi_stop_queue(struct driver_data *drv_data)
         * execution path (pump_messages) would be required to call wake_up or
         * friends on every SPI message. Do this instead
         */
-       drv_data->run = QUEUE_STOPPED;
+       drv_data->running = false;
        while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
                spin_unlock_irqrestore(&drv_data->lock, flags);
                msleep(10);
@@ -1241,7 +1246,7 @@ static inline int bfin_spi_stop_queue(struct driver_data *drv_data)
        return status;
 }
 
-static inline int bfin_spi_destroy_queue(struct driver_data *drv_data)
+static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
 {
        int status;
 
@@ -1259,14 +1264,14 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct bfin5xx_spi_master *platform_info;
        struct spi_master *master;
-       struct driver_data *drv_data = 0;
+       struct bfin_spi_master_data *drv_data;
        struct resource *res;
        int status = 0;
 
        platform_info = dev->platform_data;
 
        /* Allocate master with space for drv_data */
-       master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+       master = spi_alloc_master(dev, sizeof(*drv_data));
        if (!master) {
                dev_err(&pdev->dev, "can not alloc spi_master\n");
                return -ENOMEM;
@@ -1302,11 +1307,19 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
                goto out_error_ioremap;
        }
 
-       drv_data->dma_channel = platform_get_irq(pdev, 0);
-       if (drv_data->dma_channel < 0) {
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (res == NULL) {
                dev_err(dev, "No DMA channel specified\n");
                status = -ENOENT;
-               goto out_error_no_dma_ch;
+               goto out_error_free_io;
+       }
+       drv_data->dma_channel = res->start;
+
+       drv_data->spi_irq = platform_get_irq(pdev, 0);
+       if (drv_data->spi_irq < 0) {
+               dev_err(dev, "No spi pio irq specified\n");
+               status = -ENOENT;
+               goto out_error_free_io;
        }
 
        /* Initial and start queue */
@@ -1328,6 +1341,12 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
                goto out_error_queue_alloc;
        }
 
+       /* Reset SPI registers. If these registers were used by the boot loader,
+        * the sky may fall on your head if you enable the dma controller.
+        */
+       write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
+       write_FLAG(drv_data, 0xFF00);
+
        /* Register with the SPI framework */
        platform_set_drvdata(pdev, drv_data);
        status = spi_register_master(master);
@@ -1343,7 +1362,7 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
 
 out_error_queue_alloc:
        bfin_spi_destroy_queue(drv_data);
-out_error_no_dma_ch:
+out_error_free_io:
        iounmap((void *) drv_data->regs_base);
 out_error_ioremap:
 out_error_get_res:
@@ -1355,7 +1374,7 @@ out_error_get_res:
 /* stop hardware and remove the driver */
 static int __devexit bfin_spi_remove(struct platform_device *pdev)
 {
-       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
        int status = 0;
 
        if (!drv_data)
@@ -1375,6 +1394,11 @@ static int __devexit bfin_spi_remove(struct platform_device *pdev)
                        free_dma(drv_data->dma_channel);
        }
 
+       if (drv_data->irq_requested) {
+               free_irq(drv_data->spi_irq, drv_data);
+               drv_data->irq_requested = 0;
+       }
+
        /* Disconnect from the SPI framework */
        spi_unregister_master(drv_data->master);
 
@@ -1389,26 +1413,32 @@ static int __devexit bfin_spi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
        int status = 0;
 
        status = bfin_spi_stop_queue(drv_data);
        if (status != 0)
                return status;
 
-       /* stop hardware */
-       bfin_spi_disable(drv_data);
+       drv_data->ctrl_reg = read_CTRL(drv_data);
+       drv_data->flag_reg = read_FLAG(drv_data);
+
+       /*
+        * reset SPI_CTL and SPI_FLG registers
+        */
+       write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
+       write_FLAG(drv_data, 0xFF00);
 
        return 0;
 }
 
 static int bfin_spi_resume(struct platform_device *pdev)
 {
-       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
        int status = 0;
 
-       /* Enable the SPI interface */
-       bfin_spi_enable(drv_data);
+       write_CTRL(drv_data, drv_data->ctrl_reg);
+       write_FLAG(drv_data, drv_data->flag_reg);
 
        /* Start the queue running */
        status = bfin_spi_start_queue(drv_data);
@@ -1439,7 +1469,7 @@ static int __init bfin_spi_init(void)
 {
        return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
 }
-module_init(bfin_spi_init);
+subsys_initcall(bfin_spi_init);
 
 static void __exit bfin_spi_exit(void)
 {
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
new file mode 100644 (file)
index 0000000..e3b4f64
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ * Freescale eSPI controller driver.
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+/* eSPI Controller registers */
+struct fsl_espi_reg {
+       __be32 mode;            /* 0x000 - eSPI mode register */
+       __be32 event;           /* 0x004 - eSPI event register */
+       __be32 mask;            /* 0x008 - eSPI mask register */
+       __be32 command;         /* 0x00c - eSPI command register */
+       __be32 transmit;        /* 0x010 - eSPI transmit FIFO access register*/
+       __be32 receive;         /* 0x014 - eSPI receive FIFO access register*/
+       u8 res[8];              /* 0x018 - 0x01c reserved */
+       __be32 csmode[4];       /* 0x020 - 0x02c eSPI cs mode register */
+};
+
+struct fsl_espi_transfer {
+       const void *tx_buf;
+       void *rx_buf;
+       unsigned len;
+       unsigned n_tx;
+       unsigned n_rx;
+       unsigned actual_length;
+       int status;
+};
+
+/* eSPI Controller mode register definitions */
+#define SPMODE_ENABLE          (1 << 31)
+#define SPMODE_LOOP            (1 << 30)
+#define SPMODE_TXTHR(x)                ((x) << 8)
+#define SPMODE_RXTHR(x)                ((x) << 0)
+
+/* eSPI Controller CS mode register definitions */
+#define CSMODE_CI_INACTIVEHIGH (1 << 31)
+#define CSMODE_CP_BEGIN_EDGECLK        (1 << 30)
+#define CSMODE_REV             (1 << 29)
+#define CSMODE_DIV16           (1 << 28)
+#define CSMODE_PM(x)           ((x) << 24)
+#define CSMODE_POL_1           (1 << 20)
+#define CSMODE_LEN(x)          ((x) << 16)
+#define CSMODE_BEF(x)          ((x) << 12)
+#define CSMODE_AFT(x)          ((x) << 8)
+#define CSMODE_CG(x)           ((x) << 3)
+
+/* Default mode/csmode for eSPI controller */
+#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
+#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
+               | CSMODE_AFT(0) | CSMODE_CG(1))
+
+/* SPIE register values */
+#define        SPIE_NE         0x00000200      /* Not empty */
+#define        SPIE_NF         0x00000100      /* Not full */
+
+/* SPIM register values */
+#define        SPIM_NE         0x00000200      /* Not empty */
+#define        SPIM_NF         0x00000100      /* Not full */
+#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
+#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
+
+/* SPCOM register values */
+#define SPCOM_CS(x)            ((x) << 30)
+#define SPCOM_TRANLEN(x)       ((x) << 0)
+#define        SPCOM_TRANLEN_MAX       0xFFFF  /* Max transaction length */
+
+static void fsl_espi_change_mode(struct spi_device *spi)
+{
+       struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+       struct spi_mpc8xxx_cs *cs = spi->controller_state;
+       struct fsl_espi_reg *reg_base = mspi->reg_base;
+       __be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
+       __be32 __iomem *espi_mode = &reg_base->mode;
+       u32 tmp;
+       unsigned long flags;
+
+       /* Turn off IRQs locally to minimize time that SPI is disabled. */
+       local_irq_save(flags);
+
+       /* Turn off SPI unit prior changing mode */
+       tmp = mpc8xxx_spi_read_reg(espi_mode);
+       mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
+       mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+       mpc8xxx_spi_write_reg(espi_mode, tmp);
+
+       local_irq_restore(flags);
+}
+
+static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
+{
+       u32 data;
+       u16 data_h;
+       u16 data_l;
+       const u32 *tx = mpc8xxx_spi->tx;
+
+       if (!tx)
+               return 0;
+
+       data = *tx++ << mpc8xxx_spi->tx_shift;
+       data_l = data & 0xffff;
+       data_h = (data >> 16) & 0xffff;
+       swab16s(&data_l);
+       swab16s(&data_h);
+       data = data_h | data_l;
+
+       mpc8xxx_spi->tx = tx;
+       return data;
+}
+
+static int fsl_espi_setup_transfer(struct spi_device *spi,
+                                       struct spi_transfer *t)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+       int bits_per_word = 0;
+       u8 pm;
+       u32 hz = 0;
+       struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+       if (t) {
+               bits_per_word = t->bits_per_word;
+               hz = t->speed_hz;
+       }
+
+       /* spi_transfer level calls that work per-word */
+       if (!bits_per_word)
+               bits_per_word = spi->bits_per_word;
+
+       /* Make sure its a bit width we support [4..16] */
+       if ((bits_per_word < 4) || (bits_per_word > 16))
+               return -EINVAL;
+
+       if (!hz)
+               hz = spi->max_speed_hz;
+
+       cs->rx_shift = 0;
+       cs->tx_shift = 0;
+       cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+       cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+       if (bits_per_word <= 8) {
+               cs->rx_shift = 8 - bits_per_word;
+       } else if (bits_per_word <= 16) {
+               cs->rx_shift = 16 - bits_per_word;
+               if (spi->mode & SPI_LSB_FIRST)
+                       cs->get_tx = fsl_espi_tx_buf_lsb;
+       } else {
+               return -EINVAL;
+       }
+
+       mpc8xxx_spi->rx_shift = cs->rx_shift;
+       mpc8xxx_spi->tx_shift = cs->tx_shift;
+       mpc8xxx_spi->get_rx = cs->get_rx;
+       mpc8xxx_spi->get_tx = cs->get_tx;
+
+       bits_per_word = bits_per_word - 1;
+
+       /* mask out bits we are going to set */
+       cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
+
+       cs->hw_mode |= CSMODE_LEN(bits_per_word);
+
+       if ((mpc8xxx_spi->spibrg / hz) > 64) {
+               cs->hw_mode |= CSMODE_DIV16;
+               pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+               WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+                         "Will use %d Hz instead.\n", dev_name(&spi->dev),
+                         hz, mpc8xxx_spi->spibrg / 1024);
+               if (pm > 16)
+                       pm = 16;
+       } else {
+               pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+       }
+       if (pm)
+               pm--;
+
+       cs->hw_mode |= CSMODE_PM(pm);
+
+       fsl_espi_change_mode(spi);
+       return 0;
+}
+
+static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
+               unsigned int len)
+{
+       u32 word;
+       struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+       mspi->count = len;
+
+       /* enable rx ints */
+       mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+       /* transmit word */
+       word = mspi->get_tx(mspi);
+       mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+       return 0;
+}
+
+static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+       struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
+       unsigned int len = t->len;
+       u8 bits_per_word;
+       int ret;
+
+       bits_per_word = spi->bits_per_word;
+       if (t->bits_per_word)
+               bits_per_word = t->bits_per_word;
+
+       mpc8xxx_spi->len = t->len;
+       len = roundup(len, 4) / 4;
+
+       mpc8xxx_spi->tx = t->tx_buf;
+       mpc8xxx_spi->rx = t->rx_buf;
+
+       INIT_COMPLETION(mpc8xxx_spi->done);
+
+       /* Set SPCOM[CS] and SPCOM[TRANLEN] field */
+       if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
+               dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
+                               " beyond the SPCOM[TRANLEN] field\n", t->len);
+               return -EINVAL;
+       }
+       mpc8xxx_spi_write_reg(&reg_base->command,
+               (SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
+
+       ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
+       if (ret)
+               return ret;
+
+       wait_for_completion(&mpc8xxx_spi->done);
+
+       /* disable rx ints */
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+       return mpc8xxx_spi->count;
+}
+
+static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
+{
+       if (cmd[1] && cmd[2] && cmd[3]) {
+               cmd[1] = (u8)(addr >> 16);
+               cmd[2] = (u8)(addr >> 8);
+               cmd[3] = (u8)(addr >> 0);
+       }
+}
+
+static unsigned int fsl_espi_cmd2addr(u8 *cmd)
+{
+       if (cmd[1] && cmd[2] && cmd[3])
+               return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
+
+       return 0;
+}
+
+static void fsl_espi_do_trans(struct spi_message *m,
+                               struct fsl_espi_transfer *tr)
+{
+       struct spi_device *spi = m->spi;
+       struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+       struct fsl_espi_transfer *espi_trans = tr;
+       struct spi_message message;
+       struct spi_transfer *t, *first, trans;
+       int status = 0;
+
+       spi_message_init(&message);
+       memset(&trans, 0, sizeof(trans));
+
+       first = list_first_entry(&m->transfers, struct spi_transfer,
+                       transfer_list);
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if ((first->bits_per_word != t->bits_per_word) ||
+                       (first->speed_hz != t->speed_hz)) {
+                       espi_trans->status = -EINVAL;
+                       dev_err(mspi->dev, "bits_per_word/speed_hz should be"
+                                       " same for the same SPI transfer\n");
+                       return;
+               }
+
+               trans.speed_hz = t->speed_hz;
+               trans.bits_per_word = t->bits_per_word;
+               trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
+       }
+
+       trans.len = espi_trans->len;
+       trans.tx_buf = espi_trans->tx_buf;
+       trans.rx_buf = espi_trans->rx_buf;
+       spi_message_add_tail(&trans, &message);
+
+       list_for_each_entry(t, &message.transfers, transfer_list) {
+               if (t->bits_per_word || t->speed_hz) {
+                       status = -EINVAL;
+
+                       status = fsl_espi_setup_transfer(spi, t);
+                       if (status < 0)
+                               break;
+               }
+
+               if (t->len)
+                       status = fsl_espi_bufs(spi, t);
+
+               if (status) {
+                       status = -EMSGSIZE;
+                       break;
+               }
+
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+       }
+
+       espi_trans->status = status;
+       fsl_espi_setup_transfer(spi, NULL);
+}
+
+static void fsl_espi_cmd_trans(struct spi_message *m,
+                               struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+       struct spi_transfer *t;
+       u8 *local_buf;
+       int i = 0;
+       struct fsl_espi_transfer *espi_trans = trans;
+
+       local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+       if (!local_buf) {
+               espi_trans->status = -ENOMEM;
+               return;
+       }
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->tx_buf) {
+                       memcpy(local_buf + i, t->tx_buf, t->len);
+                       i += t->len;
+               }
+       }
+
+       espi_trans->tx_buf = local_buf;
+       espi_trans->rx_buf = local_buf + espi_trans->n_tx;
+       fsl_espi_do_trans(m, espi_trans);
+
+       espi_trans->actual_length = espi_trans->len;
+       kfree(local_buf);
+}
+
+static void fsl_espi_rw_trans(struct spi_message *m,
+                               struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+       struct fsl_espi_transfer *espi_trans = trans;
+       unsigned int n_tx = espi_trans->n_tx;
+       unsigned int n_rx = espi_trans->n_rx;
+       struct spi_transfer *t;
+       u8 *local_buf;
+       u8 *rx_buf = rx_buff;
+       unsigned int trans_len;
+       unsigned int addr;
+       int i, pos, loop;
+
+       local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+       if (!local_buf) {
+               espi_trans->status = -ENOMEM;
+               return;
+       }
+
+       for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
+               trans_len = n_rx - pos;
+               if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
+                       trans_len = SPCOM_TRANLEN_MAX - n_tx;
+
+               i = 0;
+               list_for_each_entry(t, &m->transfers, transfer_list) {
+                       if (t->tx_buf) {
+                               memcpy(local_buf + i, t->tx_buf, t->len);
+                               i += t->len;
+                       }
+               }
+
+               addr = fsl_espi_cmd2addr(local_buf);
+               addr += pos;
+               fsl_espi_addr2cmd(addr, local_buf);
+
+               espi_trans->n_tx = n_tx;
+               espi_trans->n_rx = trans_len;
+               espi_trans->len = trans_len + n_tx;
+               espi_trans->tx_buf = local_buf;
+               espi_trans->rx_buf = local_buf + n_tx;
+               fsl_espi_do_trans(m, espi_trans);
+
+               memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
+
+               if (loop > 0)
+                       espi_trans->actual_length += espi_trans->len - n_tx;
+               else
+                       espi_trans->actual_length += espi_trans->len;
+       }
+
+       kfree(local_buf);
+}
+
+static void fsl_espi_do_one_msg(struct spi_message *m)
+{
+       struct spi_transfer *t;
+       u8 *rx_buf = NULL;
+       unsigned int n_tx = 0;
+       unsigned int n_rx = 0;
+       struct fsl_espi_transfer espi_trans;
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->tx_buf)
+                       n_tx += t->len;
+               if (t->rx_buf) {
+                       n_rx += t->len;
+                       rx_buf = t->rx_buf;
+               }
+       }
+
+       espi_trans.n_tx = n_tx;
+       espi_trans.n_rx = n_rx;
+       espi_trans.len = n_tx + n_rx;
+       espi_trans.actual_length = 0;
+       espi_trans.status = 0;
+
+       if (!rx_buf)
+               fsl_espi_cmd_trans(m, &espi_trans, NULL);
+       else
+               fsl_espi_rw_trans(m, &espi_trans, rx_buf);
+
+       m->actual_length = espi_trans.actual_length;
+       m->status = espi_trans.status;
+       m->complete(m->context);
+}
+
+static int fsl_espi_setup(struct spi_device *spi)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       int retval;
+       u32 hw_mode;
+       u32 loop_mode;
+       struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+       if (!spi->max_speed_hz)
+               return -EINVAL;
+
+       if (!cs) {
+               cs = kzalloc(sizeof *cs, GFP_KERNEL);
+               if (!cs)
+                       return -ENOMEM;
+               spi->controller_state = cs;
+       }
+
+       mpc8xxx_spi = spi_master_get_devdata(spi->master);
+       reg_base = mpc8xxx_spi->reg_base;
+
+       hw_mode = cs->hw_mode; /* Save orginal settings */
+       cs->hw_mode = mpc8xxx_spi_read_reg(
+                       &reg_base->csmode[spi->chip_select]);
+       /* mask out bits we are going to set */
+       cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
+                        | CSMODE_REV);
+
+       if (spi->mode & SPI_CPHA)
+               cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
+       if (spi->mode & SPI_CPOL)
+               cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
+       if (!(spi->mode & SPI_LSB_FIRST))
+               cs->hw_mode |= CSMODE_REV;
+
+       /* Handle the loop mode */
+       loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+       loop_mode &= ~SPMODE_LOOP;
+       if (spi->mode & SPI_LOOP)
+               loop_mode |= SPMODE_LOOP;
+       mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
+
+       retval = fsl_espi_setup_transfer(spi, NULL);
+       if (retval < 0) {
+               cs->hw_mode = hw_mode; /* Restore settings */
+               return retval;
+       }
+       return 0;
+}
+
+void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+       struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+       /* We need handle RX first */
+       if (events & SPIE_NE) {
+               u32 rx_data;
+
+               /* Spin until RX is done */
+               while (SPIE_RXCNT(events) < min(4, mspi->len)) {
+                       cpu_relax();
+                       events = mpc8xxx_spi_read_reg(&reg_base->event);
+               }
+               mspi->len -= 4;
+
+               rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+
+               if (mspi->rx)
+                       mspi->get_rx(rx_data, mspi);
+       }
+
+       if (!(events & SPIE_NF)) {
+               int ret;
+
+               /* spin until TX is done */
+               ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
+                               &reg_base->event)) & SPIE_NF) == 0, 1000, 0);
+               if (!ret) {
+                       dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
+                       return;
+               }
+       }
+
+       /* Clear the events */
+       mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+       mspi->count -= 1;
+       if (mspi->count) {
+               u32 word = mspi->get_tx(mspi);
+
+               mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+       } else {
+               complete(&mspi->done);
+       }
+}
+
+static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
+{
+       struct mpc8xxx_spi *mspi = context_data;
+       struct fsl_espi_reg *reg_base = mspi->reg_base;
+       irqreturn_t ret = IRQ_NONE;
+       u32 events;
+
+       /* Get interrupt events(tx/rx) */
+       events = mpc8xxx_spi_read_reg(&reg_base->event);
+       if (events)
+               ret = IRQ_HANDLED;
+
+       dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+       fsl_espi_cpu_irq(mspi, events);
+
+       return ret;
+}
+
+static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+{
+       iounmap(mspi->reg_base);
+}
+
+static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
+               struct resource *mem, unsigned int irq)
+{
+       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct spi_master *master;
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       u32 regval;
+       int i, ret = 0;
+
+       master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+       if (!master) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       dev_set_drvdata(dev, master);
+
+       ret = mpc8xxx_spi_probe(dev, mem, irq);
+       if (ret)
+               goto err_probe;
+
+       master->setup = fsl_espi_setup;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
+       mpc8xxx_spi->spi_remove = fsl_espi_remove;
+
+       mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+       if (!mpc8xxx_spi->reg_base) {
+               ret = -ENOMEM;
+               goto err_probe;
+       }
+
+       reg_base = mpc8xxx_spi->reg_base;
+
+       /* Register for SPI Interrupt */
+       ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+                         0, "fsl_espi", mpc8xxx_spi);
+       if (ret)
+               goto free_irq;
+
+       if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+               mpc8xxx_spi->rx_shift = 16;
+               mpc8xxx_spi->tx_shift = 24;
+       }
+
+       /* SPI controller initializations */
+       mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+       mpc8xxx_spi_write_reg(&reg_base->command, 0);
+       mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+       /* Init eSPI CS mode register */
+       for (i = 0; i < pdata->max_chipselect; i++)
+               mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+       /* Enable SPI interface */
+       regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+       ret = spi_register_master(master);
+       if (ret < 0)
+               goto unreg_master;
+
+       dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+
+       return master;
+
+unreg_master:
+       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+       iounmap(mpc8xxx_spi->reg_base);
+err_probe:
+       spi_master_put(master);
+err:
+       return ERR_PTR(ret);
+}
+
+static int of_fsl_espi_get_chipselects(struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       const u32 *prop;
+       int len;
+
+       prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
+       if (!prop || len < sizeof(*prop)) {
+               dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
+               return -EINVAL;
+       }
+
+       pdata->max_chipselect = *prop;
+       pdata->cs_control = NULL;
+
+       return 0;
+}
+
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
+                                       const struct of_device_id *ofid)
+{
+       struct device *dev = &ofdev->dev;
+       struct device_node *np = ofdev->dev.of_node;
+       struct spi_master *master;
+       struct resource mem;
+       struct resource irq;
+       int ret = -ENOMEM;
+
+       ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+       if (ret)
+               return ret;
+
+       ret = of_fsl_espi_get_chipselects(dev);
+       if (ret)
+               goto err;
+
+       ret = of_address_to_resource(np, 0, &mem);
+       if (ret)
+               goto err;
+
+       ret = of_irq_to_resource(np, 0, &irq);
+       if (!ret) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       master = fsl_espi_probe(dev, &mem, irq.start);
+       if (IS_ERR(master)) {
+               ret = PTR_ERR(master);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       return ret;
+}
+
+static int __devexit of_fsl_espi_remove(struct platform_device *dev)
+{
+       return mpc8xxx_spi_remove(&dev->dev);
+}
+
+static const struct of_device_id of_fsl_espi_match[] = {
+       { .compatible = "fsl,mpc8536-espi" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
+
+static struct of_platform_driver fsl_espi_driver = {
+       .driver = {
+               .name = "fsl_espi",
+               .owner = THIS_MODULE,
+               .of_match_table = of_fsl_espi_match,
+       },
+       .probe          = of_fsl_espi_probe,
+       .remove         = __devexit_p(of_fsl_espi_remove),
+};
+
+static int __init fsl_espi_init(void)
+{
+       return of_register_platform_driver(&fsl_espi_driver);
+}
+module_init(fsl_espi_init);
+
+static void __exit fsl_espi_exit(void)
+{
+       of_unregister_platform_driver(&fsl_espi_driver);
+}
+module_exit(fsl_espi_exit);
+
+MODULE_AUTHOR("Mingkai Hu");
+MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
new file mode 100644 (file)
index 0000000..5cd741f
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+#define MPC8XXX_SPI_RX_BUF(type)                                         \
+void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
+{                                                                        \
+       type *rx = mpc8xxx_spi->rx;                                       \
+       *rx++ = (type)(data >> mpc8xxx_spi->rx_shift);                    \
+       mpc8xxx_spi->rx = rx;                                             \
+}
+
+#define MPC8XXX_SPI_TX_BUF(type)                               \
+u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \
+{                                                              \
+       u32 data;                                               \
+       const type *tx = mpc8xxx_spi->tx;                       \
+       if (!tx)                                                \
+               return 0;                                       \
+       data = *tx++ << mpc8xxx_spi->tx_shift;                  \
+       mpc8xxx_spi->tx = tx;                                   \
+       return data;                                            \
+}
+
+MPC8XXX_SPI_RX_BUF(u8)
+MPC8XXX_SPI_RX_BUF(u16)
+MPC8XXX_SPI_RX_BUF(u32)
+MPC8XXX_SPI_TX_BUF(u8)
+MPC8XXX_SPI_TX_BUF(u16)
+MPC8XXX_SPI_TX_BUF(u32)
+
+struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
+{
+       return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
+}
+
+void mpc8xxx_spi_work(struct work_struct *work)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
+                                                      work);
+
+       spin_lock_irq(&mpc8xxx_spi->lock);
+       while (!list_empty(&mpc8xxx_spi->queue)) {
+               struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
+                                                  struct spi_message, queue);
+
+               list_del_init(&m->queue);
+               spin_unlock_irq(&mpc8xxx_spi->lock);
+
+               if (mpc8xxx_spi->spi_do_one_msg)
+                       mpc8xxx_spi->spi_do_one_msg(m);
+
+               spin_lock_irq(&mpc8xxx_spi->lock);
+       }
+       spin_unlock_irq(&mpc8xxx_spi->lock);
+}
+
+int mpc8xxx_spi_transfer(struct spi_device *spi,
+                               struct spi_message *m)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+       unsigned long flags;
+
+       m->actual_length = 0;
+       m->status = -EINPROGRESS;
+
+       spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
+       list_add_tail(&m->queue, &mpc8xxx_spi->queue);
+       queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
+       spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+
+       return 0;
+}
+
+void mpc8xxx_spi_cleanup(struct spi_device *spi)
+{
+       kfree(spi->controller_state);
+}
+
+const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+       if (flags & SPI_QE_CPU_MODE) {
+               return "QE CPU";
+       } else if (flags & SPI_CPM_MODE) {
+               if (flags & SPI_QE)
+                       return "QE";
+               else if (flags & SPI_CPM2)
+                       return "CPM2";
+               else
+                       return "CPM1";
+       }
+       return "CPU";
+}
+
+int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+                       unsigned int irq)
+{
+       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct spi_master *master;
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       int ret = 0;
+
+       master = dev_get_drvdata(dev);
+
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
+                       | SPI_LSB_FIRST | SPI_LOOP;
+
+       master->transfer = mpc8xxx_spi_transfer;
+       master->cleanup = mpc8xxx_spi_cleanup;
+       master->dev.of_node = dev->of_node;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       mpc8xxx_spi->dev = dev;
+       mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
+       mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+       mpc8xxx_spi->flags = pdata->flags;
+       mpc8xxx_spi->spibrg = pdata->sysclk;
+       mpc8xxx_spi->irq = irq;
+
+       mpc8xxx_spi->rx_shift = 0;
+       mpc8xxx_spi->tx_shift = 0;
+
+       init_completion(&mpc8xxx_spi->done);
+
+       master->bus_num = pdata->bus_num;
+       master->num_chipselect = pdata->max_chipselect;
+
+       spin_lock_init(&mpc8xxx_spi->lock);
+       init_completion(&mpc8xxx_spi->done);
+       INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
+       INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+       mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+               dev_name(master->dev.parent));
+       if (mpc8xxx_spi->workqueue == NULL) {
+               ret = -EBUSY;
+               goto err;
+       }
+
+       return 0;
+
+err:
+       return ret;
+}
+
+int __devexit mpc8xxx_spi_remove(struct device *dev)
+{
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct spi_master *master;
+
+       master = dev_get_drvdata(dev);
+       mpc8xxx_spi = spi_master_get_devdata(master);
+
+       flush_workqueue(mpc8xxx_spi->workqueue);
+       destroy_workqueue(mpc8xxx_spi->workqueue);
+       spi_unregister_master(master);
+
+       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+
+       if (mpc8xxx_spi->spi_remove)
+               mpc8xxx_spi->spi_remove(mpc8xxx_spi);
+
+       return 0;
+}
+
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+                                       const struct of_device_id *ofid)
+{
+       struct device *dev = &ofdev->dev;
+       struct device_node *np = ofdev->dev.of_node;
+       struct mpc8xxx_spi_probe_info *pinfo;
+       struct fsl_spi_platform_data *pdata;
+       const void *prop;
+       int ret = -ENOMEM;
+
+       pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+       if (!pinfo)
+               return -ENOMEM;
+
+       pdata = &pinfo->pdata;
+       dev->platform_data = pdata;
+
+       /* Allocate bus num dynamically. */
+       pdata->bus_num = -1;
+
+       /* SPI controller is either clocked from QE or SoC clock. */
+       pdata->sysclk = get_brgfreq();
+       if (pdata->sysclk == -1) {
+               pdata->sysclk = fsl_get_sys_freq();
+               if (pdata->sysclk == -1) {
+                       ret = -ENODEV;
+                       goto err;
+               }
+       }
+
+       prop = of_get_property(np, "mode", NULL);
+       if (prop && !strcmp(prop, "cpu-qe"))
+               pdata->flags = SPI_QE_CPU_MODE;
+       else if (prop && !strcmp(prop, "qe"))
+               pdata->flags = SPI_CPM_MODE | SPI_QE;
+       else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+               pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+       else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+               pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+
+       return 0;
+
+err:
+       kfree(pinfo);
+       return ret;
+}
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
new file mode 100644 (file)
index 0000000..281e060
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.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 __SPI_FSL_LIB_H__
+#define __SPI_FSL_LIB_H__
+
+#include <asm/io.h>
+
+/* SPI/eSPI Controller driver's private data. */
+struct mpc8xxx_spi {
+       struct device *dev;
+       void *reg_base;
+
+       /* rx & tx bufs from the spi_transfer */
+       const void *tx;
+       void *rx;
+#ifdef CONFIG_SPI_FSL_ESPI
+       int len;
+#endif
+
+       int subblock;
+       struct spi_pram __iomem *pram;
+       struct cpm_buf_desc __iomem *tx_bd;
+       struct cpm_buf_desc __iomem *rx_bd;
+
+       struct spi_transfer *xfer_in_progress;
+
+       /* dma addresses for CPM transfers */
+       dma_addr_t tx_dma;
+       dma_addr_t rx_dma;
+       bool map_tx_dma;
+       bool map_rx_dma;
+
+       dma_addr_t dma_dummy_tx;
+       dma_addr_t dma_dummy_rx;
+
+       /* functions to deal with different sized buffers */
+       void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+       u32(*get_tx) (struct mpc8xxx_spi *);
+
+       /* hooks for different controller driver */
+       void (*spi_do_one_msg) (struct spi_message *m);
+       void (*spi_remove) (struct mpc8xxx_spi *mspi);
+
+       unsigned int count;
+       unsigned int irq;
+
+       unsigned nsecs;         /* (clock cycle time)/2 */
+
+       u32 spibrg;             /* SPIBRG input clock */
+       u32 rx_shift;           /* RX data reg shift when in qe mode */
+       u32 tx_shift;           /* TX data reg shift when in qe mode */
+
+       unsigned int flags;
+
+       struct workqueue_struct *workqueue;
+       struct work_struct work;
+
+       struct list_head queue;
+       spinlock_t lock;
+
+       struct completion done;
+};
+
+struct spi_mpc8xxx_cs {
+       /* functions to deal with different sized buffers */
+       void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+       u32 (*get_tx) (struct mpc8xxx_spi *);
+       u32 rx_shift;           /* RX data reg shift when in qe mode */
+       u32 tx_shift;           /* TX data reg shift when in qe mode */
+       u32 hw_mode;            /* Holds HW mode register settings */
+};
+
+static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
+{
+       out_be32(reg, val);
+}
+
+static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
+{
+       return in_be32(reg);
+}
+
+struct mpc8xxx_spi_probe_info {
+       struct fsl_spi_platform_data pdata;
+       int *gpios;
+       bool *alow_flags;
+};
+
+extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+
+extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
+               struct fsl_spi_platform_data *pdata);
+extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
+               struct spi_transfer *t, unsigned int len);
+extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
+extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
+extern const char *mpc8xxx_spi_strmode(unsigned int flags);
+extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+               unsigned int irq);
+extern int mpc8xxx_spi_remove(struct device *dev);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+                               const struct of_device_id *ofid);
+
+#endif /* __SPI_FSL_LIB_H__ */
similarity index 63%
rename from drivers/spi/spi_mpc8xxx.c
rename to drivers/spi/spi_fsl_spi.c
index d31b57f7baaf3c3bf970294afd13a1396cecf46c..7ca52d3ae8f8bc3d322ec273042960fbdc6a9e9c 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * MPC8xxx SPI controller driver.
+ * Freescale SPI controller driver.
  *
  * Maintainer: Kumar Gala
  *
  * Copyright (C) 2006 Polycom, Inc.
+ * Copyright 2010 Freescale Semiconductor, Inc.
  *
  * CPM SPI and QE buffer descriptors mode support:
  * Copyright (c) 2009  MontaVista Software, Inc.
  * option) any later version.
  */
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
-#include <linux/slab.h>
 
 #include <sysdev/fsl_soc.h>
 #include <asm/cpm.h>
 #include <asm/qe.h>
-#include <asm/irq.h>
+
+#include "spi_fsl_lib.h"
 
 /* CPM1 and CPM2 are mutually exclusive. */
 #ifdef CONFIG_CPM1
@@ -55,7 +49,7 @@
 #endif
 
 /* SPI Controller registers */
-struct mpc8xxx_spi_reg {
+struct fsl_spi_reg {
        u8 res1[0x20];
        __be32 mode;
        __be32 event;
@@ -80,7 +74,7 @@ struct mpc8xxx_spi_reg {
 
 /*
  * Default for SPI Mode:
- *     SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ *     SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
  */
 #define        SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
                         SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
@@ -102,112 +96,16 @@ struct mpc8xxx_spi_reg {
 #define        SPI_PRAM_SIZE   0x100
 #define        SPI_MRBLR       ((unsigned int)PAGE_SIZE)
 
-/* SPI Controller driver's private data. */
-struct mpc8xxx_spi {
-       struct device *dev;
-       struct mpc8xxx_spi_reg __iomem *base;
-
-       /* rx & tx bufs from the spi_transfer */
-       const void *tx;
-       void *rx;
-
-       int subblock;
-       struct spi_pram __iomem *pram;
-       struct cpm_buf_desc __iomem *tx_bd;
-       struct cpm_buf_desc __iomem *rx_bd;
-
-       struct spi_transfer *xfer_in_progress;
-
-       /* dma addresses for CPM transfers */
-       dma_addr_t tx_dma;
-       dma_addr_t rx_dma;
-       bool map_tx_dma;
-       bool map_rx_dma;
-
-       dma_addr_t dma_dummy_tx;
-       dma_addr_t dma_dummy_rx;
-
-       /* functions to deal with different sized buffers */
-       void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-       u32(*get_tx) (struct mpc8xxx_spi *);
-
-       unsigned int count;
-       unsigned int irq;
-
-       unsigned nsecs;         /* (clock cycle time)/2 */
-
-       u32 spibrg;             /* SPIBRG input clock */
-       u32 rx_shift;           /* RX data reg shift when in qe mode */
-       u32 tx_shift;           /* TX data reg shift when in qe mode */
-
-       unsigned int flags;
-
-       struct workqueue_struct *workqueue;
-       struct work_struct work;
-
-       struct list_head queue;
-       spinlock_t lock;
+static void *fsl_dummy_rx;
+static DEFINE_MUTEX(fsl_dummy_rx_lock);
+static int fsl_dummy_rx_refcnt;
 
-       struct completion done;
-};
-
-static void *mpc8xxx_dummy_rx;
-static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
-static int mpc8xxx_dummy_rx_refcnt;
-
-struct spi_mpc8xxx_cs {
-       /* functions to deal with different sized buffers */
-       void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-       u32 (*get_tx) (struct mpc8xxx_spi *);
-       u32 rx_shift;           /* RX data reg shift when in qe mode */
-       u32 tx_shift;           /* TX data reg shift when in qe mode */
-       u32 hw_mode;            /* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
-       out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
-       return in_be32(reg);
-}
-
-#define MPC83XX_SPI_RX_BUF(type)                                         \
-static                                                                   \
-void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
-{                                                                        \
-       type *rx = mpc8xxx_spi->rx;                                       \
-       *rx++ = (type)(data >> mpc8xxx_spi->rx_shift);                    \
-       mpc8xxx_spi->rx = rx;                                             \
-}
-
-#define MPC83XX_SPI_TX_BUF(type)                               \
-static                                                         \
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \
-{                                                              \
-       u32 data;                                               \
-       const type *tx = mpc8xxx_spi->tx;                       \
-       if (!tx)                                                \
-               return 0;                                       \
-       data = *tx++ << mpc8xxx_spi->tx_shift;                  \
-       mpc8xxx_spi->tx = tx;                                   \
-       return data;                                            \
-}
-
-MPC83XX_SPI_RX_BUF(u8)
-MPC83XX_SPI_RX_BUF(u16)
-MPC83XX_SPI_RX_BUF(u32)
-MPC83XX_SPI_TX_BUF(u8)
-MPC83XX_SPI_TX_BUF(u16)
-MPC83XX_SPI_TX_BUF(u32)
-
-static void mpc8xxx_spi_change_mode(struct spi_device *spi)
+static void fsl_spi_change_mode(struct spi_device *spi)
 {
        struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
        struct spi_mpc8xxx_cs *cs = spi->controller_state;
-       __be32 __iomem *mode = &mspi->base->mode;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
+       __be32 __iomem *mode = &reg_base->mode;
        unsigned long flags;
 
        if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
@@ -238,7 +136,7 @@ static void mpc8xxx_spi_change_mode(struct spi_device *spi)
        local_irq_restore(flags);
 }
 
-static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
+static void fsl_spi_chipselect(struct spi_device *spi, int value)
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
        struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
@@ -256,18 +154,17 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
                mpc8xxx_spi->get_rx = cs->get_rx;
                mpc8xxx_spi->get_tx = cs->get_tx;
 
-               mpc8xxx_spi_change_mode(spi);
+               fsl_spi_change_mode(spi);
 
                if (pdata->cs_control)
                        pdata->cs_control(spi, pol);
        }
 }
 
-static int
-mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-                          struct spi_device *spi,
-                          struct mpc8xxx_spi *mpc8xxx_spi,
-                          int bits_per_word)
+static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+                               struct spi_device *spi,
+                               struct mpc8xxx_spi *mpc8xxx_spi,
+                               int bits_per_word)
 {
        cs->rx_shift = 0;
        cs->tx_shift = 0;
@@ -307,10 +204,9 @@ mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
        return bits_per_word;
 }
 
-static int
-mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-                         struct spi_device *spi,
-                         int bits_per_word)
+static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+                               struct spi_device *spi,
+                               int bits_per_word)
 {
        /* QE uses Little Endian for words > 8
         * so transform all words > 8 into 8 bits
@@ -326,13 +222,13 @@ mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
        return bits_per_word;
 }
 
-static
-int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+static int fsl_spi_setup_transfer(struct spi_device *spi,
+                                       struct spi_transfer *t)
 {
        struct mpc8xxx_spi *mpc8xxx_spi;
-       int bits_per_word;
+       int bits_per_word = 0;
        u8 pm;
-       u32 hz;
+       u32 hz = 0;
        struct spi_mpc8xxx_cs   *cs = spi->controller_state;
 
        mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -340,9 +236,6 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        if (t) {
                bits_per_word = t->bits_per_word;
                hz = t->speed_hz;
-       } else {
-               bits_per_word = 0;
-               hz = 0;
        }
 
        /* spi_transfer level calls that work per-word */
@@ -388,43 +281,52 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                          hz, mpc8xxx_spi->spibrg / 1024);
                if (pm > 16)
                        pm = 16;
-       } else
+       } else {
                pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+       }
        if (pm)
                pm--;
 
        cs->hw_mode |= SPMODE_PM(pm);
 
-       mpc8xxx_spi_change_mode(spi);
+       fsl_spi_change_mode(spi);
        return 0;
 }
 
-static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
 {
        struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
        struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
        unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
        unsigned int xfer_ofs;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
 
        xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
 
-       out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+       if (mspi->rx_dma == mspi->dma_dummy_rx)
+               out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
+       else
+               out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
        out_be16(&rx_bd->cbd_datlen, 0);
        out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
 
-       out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+       if (mspi->tx_dma == mspi->dma_dummy_tx)
+               out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
+       else
+               out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
        out_be16(&tx_bd->cbd_datlen, xfer_len);
        out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
                                 BD_SC_LAST);
 
        /* start transfer */
-       mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
+       mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
 }
 
-static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
                                struct spi_transfer *t, bool is_dma_mapped)
 {
        struct device *dev = mspi->dev;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
 
        if (is_dma_mapped) {
                mspi->map_tx_dma = 0;
@@ -469,13 +371,13 @@ static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
        }
 
        /* enable rx ints */
-       mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
+       mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
 
        mspi->xfer_in_progress = t;
        mspi->count = t->len;
 
        /* start CPM transfers */
-       mpc8xxx_spi_cpm_bufs_start(mspi);
+       fsl_spi_cpm_bufs_start(mspi);
 
        return 0;
 
@@ -485,7 +387,7 @@ err_rx_dma:
        return -ENOMEM;
 }
 
-static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
 {
        struct device *dev = mspi->dev;
        struct spi_transfer *t = mspi->xfer_in_progress;
@@ -497,31 +399,34 @@ static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
        mspi->xfer_in_progress = NULL;
 }
 
-static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
                                struct spi_transfer *t, unsigned int len)
 {
        u32 word;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
 
        mspi->count = len;
 
        /* enable rx ints */
-       mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
+       mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
 
        /* transmit word */
        word = mspi->get_tx(mspi);
-       mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+       mpc8xxx_spi_write_reg(&reg_base->transmit, word);
 
        return 0;
 }
 
-static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
                            bool is_dma_mapped)
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+       struct fsl_spi_reg *reg_base;
        unsigned int len = t->len;
        u8 bits_per_word;
        int ret;
 
+       reg_base = mpc8xxx_spi->reg_base;
        bits_per_word = spi->bits_per_word;
        if (t->bits_per_word)
                bits_per_word = t->bits_per_word;
@@ -545,24 +450,24 @@ static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
        INIT_COMPLETION(mpc8xxx_spi->done);
 
        if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-               ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+               ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
        else
-               ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
+               ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
        if (ret)
                return ret;
 
        wait_for_completion(&mpc8xxx_spi->done);
 
        /* disable rx ints */
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
 
        if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-               mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
+               fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
 
        return mpc8xxx_spi->count;
 }
 
-static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
+static void fsl_spi_do_one_msg(struct spi_message *m)
 {
        struct spi_device *spi = m->spi;
        struct spi_transfer *t;
@@ -578,18 +483,18 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
                        status = -EINVAL;
 
                        if (cs_change)
-                               status = mpc8xxx_spi_setup_transfer(spi, t);
+                               status = fsl_spi_setup_transfer(spi, t);
                        if (status < 0)
                                break;
                }
 
                if (cs_change) {
-                       mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
+                       fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
                        ndelay(nsecs);
                }
                cs_change = t->cs_change;
                if (t->len)
-                       status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
+                       status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
                if (status) {
                        status = -EMSGSIZE;
                        break;
@@ -601,7 +506,7 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
 
                if (cs_change) {
                        ndelay(nsecs);
-                       mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+                       fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
                        ndelay(nsecs);
                }
        }
@@ -611,35 +516,16 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
 
        if (status || !cs_change) {
                ndelay(nsecs);
-               mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+               fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
        }
 
-       mpc8xxx_spi_setup_transfer(spi, NULL);
-}
-
-static void mpc8xxx_spi_work(struct work_struct *work)
-{
-       struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
-                                                      work);
-
-       spin_lock_irq(&mpc8xxx_spi->lock);
-       while (!list_empty(&mpc8xxx_spi->queue)) {
-               struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
-                                                  struct spi_message, queue);
-
-               list_del_init(&m->queue);
-               spin_unlock_irq(&mpc8xxx_spi->lock);
-
-               mpc8xxx_spi_do_one_msg(m);
-
-               spin_lock_irq(&mpc8xxx_spi->lock);
-       }
-       spin_unlock_irq(&mpc8xxx_spi->lock);
+       fsl_spi_setup_transfer(spi, NULL);
 }
 
-static int mpc8xxx_spi_setup(struct spi_device *spi)
+static int fsl_spi_setup(struct spi_device *spi)
 {
        struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_spi_reg *reg_base;
        int retval;
        u32 hw_mode;
        struct spi_mpc8xxx_cs   *cs = spi->controller_state;
@@ -655,8 +541,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
        }
        mpc8xxx_spi = spi_master_get_devdata(spi->master);
 
+       reg_base = mpc8xxx_spi->reg_base;
+
        hw_mode = cs->hw_mode; /* Save original settings */
-       cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
+       cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
        /* mask out bits we are going to set */
        cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
                         | SPMODE_REV | SPMODE_LOOP);
@@ -670,7 +558,7 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
        if (spi->mode & SPI_LOOP)
                cs->hw_mode |= SPMODE_LOOP;
 
-       retval = mpc8xxx_spi_setup_transfer(spi, NULL);
+       retval = fsl_spi_setup_transfer(spi, NULL);
        if (retval < 0) {
                cs->hw_mode = hw_mode; /* Restore settings */
                return retval;
@@ -678,9 +566,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
        return 0;
 }
 
-static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
+static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
        u16 len;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
 
        dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
                in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
@@ -692,20 +581,22 @@ static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
        }
 
        /* Clear the events */
-       mpc8xxx_spi_write_reg(&mspi->base->event, events);
+       mpc8xxx_spi_write_reg(&reg_base->event, events);
 
        mspi->count -= len;
        if (mspi->count)
-               mpc8xxx_spi_cpm_bufs_start(mspi);
+               fsl_spi_cpm_bufs_start(mspi);
        else
                complete(&mspi->done);
 }
 
-static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
+
        /* We need handle RX first */
        if (events & SPIE_NE) {
-               u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
+               u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
 
                if (mspi->rx)
                        mspi->get_rx(rx_data, mspi);
@@ -714,102 +605,80 @@ static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
        if ((events & SPIE_NF) == 0)
                /* spin until TX is done */
                while (((events =
-                       mpc8xxx_spi_read_reg(&mspi->base->event)) &
+                       mpc8xxx_spi_read_reg(&reg_base->event)) &
                                                SPIE_NF) == 0)
                        cpu_relax();
 
        /* Clear the events */
-       mpc8xxx_spi_write_reg(&mspi->base->event, events);
+       mpc8xxx_spi_write_reg(&reg_base->event, events);
 
        mspi->count -= 1;
        if (mspi->count) {
                u32 word = mspi->get_tx(mspi);
 
-               mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+               mpc8xxx_spi_write_reg(&reg_base->transmit, word);
        } else {
                complete(&mspi->done);
        }
 }
 
-static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
+static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
 {
        struct mpc8xxx_spi *mspi = context_data;
        irqreturn_t ret = IRQ_NONE;
        u32 events;
+       struct fsl_spi_reg *reg_base = mspi->reg_base;
 
        /* Get interrupt events(tx/rx) */
-       events = mpc8xxx_spi_read_reg(&mspi->base->event);
+       events = mpc8xxx_spi_read_reg(&reg_base->event);
        if (events)
                ret = IRQ_HANDLED;
 
        dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
 
        if (mspi->flags & SPI_CPM_MODE)
-               mpc8xxx_spi_cpm_irq(mspi, events);
+               fsl_spi_cpm_irq(mspi, events);
        else
-               mpc8xxx_spi_cpu_irq(mspi, events);
+               fsl_spi_cpu_irq(mspi, events);
 
        return ret;
 }
 
-static int mpc8xxx_spi_transfer(struct spi_device *spi,
-                               struct spi_message *m)
+static void *fsl_spi_alloc_dummy_rx(void)
 {
-       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-       unsigned long flags;
+       mutex_lock(&fsl_dummy_rx_lock);
 
-       m->actual_length = 0;
-       m->status = -EINPROGRESS;
+       if (!fsl_dummy_rx)
+               fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+       if (fsl_dummy_rx)
+               fsl_dummy_rx_refcnt++;
 
-       spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
-       list_add_tail(&m->queue, &mpc8xxx_spi->queue);
-       queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
-       spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+       mutex_unlock(&fsl_dummy_rx_lock);
 
-       return 0;
+       return fsl_dummy_rx;
 }
 
-
-static void mpc8xxx_spi_cleanup(struct spi_device *spi)
+static void fsl_spi_free_dummy_rx(void)
 {
-       kfree(spi->controller_state);
-}
-
-static void *mpc8xxx_spi_alloc_dummy_rx(void)
-{
-       mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-       if (!mpc8xxx_dummy_rx)
-               mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
-       if (mpc8xxx_dummy_rx)
-               mpc8xxx_dummy_rx_refcnt++;
-
-       mutex_unlock(&mpc8xxx_dummy_rx_lock);
-
-       return mpc8xxx_dummy_rx;
-}
-
-static void mpc8xxx_spi_free_dummy_rx(void)
-{
-       mutex_lock(&mpc8xxx_dummy_rx_lock);
+       mutex_lock(&fsl_dummy_rx_lock);
 
-       switch (mpc8xxx_dummy_rx_refcnt) {
+       switch (fsl_dummy_rx_refcnt) {
        case 0:
                WARN_ON(1);
                break;
        case 1:
-               kfree(mpc8xxx_dummy_rx);
-               mpc8xxx_dummy_rx = NULL;
+               kfree(fsl_dummy_rx);
+               fsl_dummy_rx = NULL;
                /* fall through */
        default:
-               mpc8xxx_dummy_rx_refcnt--;
+               fsl_dummy_rx_refcnt--;
                break;
        }
 
-       mutex_unlock(&mpc8xxx_dummy_rx_lock);
+       mutex_unlock(&fsl_dummy_rx_lock);
 }
 
-static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 {
        struct device *dev = mspi->dev;
        struct device_node *np = dev->of_node;
@@ -863,7 +732,7 @@ static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
        return pram_ofs;
 }
 
-static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
+static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
 {
        struct device *dev = mspi->dev;
        struct device_node *np = dev->of_node;
@@ -875,7 +744,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
        if (!(mspi->flags & SPI_CPM_MODE))
                return 0;
 
-       if (!mpc8xxx_spi_alloc_dummy_rx())
+       if (!fsl_spi_alloc_dummy_rx())
                return -ENOMEM;
 
        if (mspi->flags & SPI_QE) {
@@ -896,7 +765,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
                }
        }
 
-       pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
+       pram_ofs = fsl_spi_cpm_get_pram(mspi);
        if (IS_ERR_VALUE(pram_ofs)) {
                dev_err(dev, "can't allocate spi parameter ram\n");
                goto err_pram;
@@ -916,7 +785,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
                goto err_dummy_tx;
        }
 
-       mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
+       mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
                                            DMA_FROM_DEVICE);
        if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
                dev_err(dev, "unable to map dummy rx buffer\n");
@@ -954,11 +823,11 @@ err_dummy_tx:
 err_bds:
        cpm_muram_free(pram_ofs);
 err_pram:
-       mpc8xxx_spi_free_dummy_rx();
+       fsl_spi_free_dummy_rx();
        return -ENOMEM;
 }
 
-static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
 {
        struct device *dev = mspi->dev;
 
@@ -966,30 +835,22 @@ static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
        dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
        cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
        cpm_muram_free(cpm_muram_offset(mspi->pram));
-       mpc8xxx_spi_free_dummy_rx();
+       fsl_spi_free_dummy_rx();
 }
 
-static const char *mpc8xxx_spi_strmode(unsigned int flags)
+static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
 {
-       if (flags & SPI_QE_CPU_MODE) {
-               return "QE CPU";
-       } else if (flags & SPI_CPM_MODE) {
-               if (flags & SPI_QE)
-                       return "QE";
-               else if (flags & SPI_CPM2)
-                       return "CPM2";
-               else
-                       return "CPM1";
-       }
-       return "CPU";
+       iounmap(mspi->reg_base);
+       fsl_spi_cpm_free(mspi);
 }
 
-static struct spi_master * __devinit
-mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
+static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
+               struct resource *mem, unsigned int irq)
 {
        struct fsl_spi_platform_data *pdata = dev->platform_data;
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_spi_reg *reg_base;
        u32 regval;
        int ret = 0;
 
@@ -1001,132 +862,77 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
 
        dev_set_drvdata(dev, master);
 
-       /* the spi->mode bits understood by this driver: */
-       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
-                       | SPI_LSB_FIRST | SPI_LOOP;
+       ret = mpc8xxx_spi_probe(dev, mem, irq);
+       if (ret)
+               goto err_probe;
 
-       master->setup = mpc8xxx_spi_setup;
-       master->transfer = mpc8xxx_spi_transfer;
-       master->cleanup = mpc8xxx_spi_cleanup;
-       master->dev.of_node = dev->of_node;
+       master->setup = fsl_spi_setup;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
-       mpc8xxx_spi->dev = dev;
-       mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
-       mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
-       mpc8xxx_spi->flags = pdata->flags;
-       mpc8xxx_spi->spibrg = pdata->sysclk;
+       mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
+       mpc8xxx_spi->spi_remove = fsl_spi_remove;
 
-       ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
+
+       ret = fsl_spi_cpm_init(mpc8xxx_spi);
        if (ret)
                goto err_cpm_init;
 
-       mpc8xxx_spi->rx_shift = 0;
-       mpc8xxx_spi->tx_shift = 0;
        if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
                mpc8xxx_spi->rx_shift = 16;
                mpc8xxx_spi->tx_shift = 24;
        }
 
-       init_completion(&mpc8xxx_spi->done);
-
-       mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
-       if (mpc8xxx_spi->base == NULL) {
+       mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+       if (mpc8xxx_spi->reg_base == NULL) {
                ret = -ENOMEM;
                goto err_ioremap;
        }
 
-       mpc8xxx_spi->irq = irq;
-
        /* Register for SPI Interrupt */
-       ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
-                         0, "mpc8xxx_spi", mpc8xxx_spi);
+       ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
+                         0, "fsl_spi", mpc8xxx_spi);
 
        if (ret != 0)
-               goto unmap_io;
+               goto free_irq;
 
-       master->bus_num = pdata->bus_num;
-       master->num_chipselect = pdata->max_chipselect;
+       reg_base = mpc8xxx_spi->reg_base;
 
        /* SPI controller initializations */
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
+       mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+       mpc8xxx_spi_write_reg(&reg_base->command, 0);
+       mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
 
        /* Enable SPI interface */
        regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
        if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
                regval |= SPMODE_OP;
 
-       mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
-       spin_lock_init(&mpc8xxx_spi->lock);
-       init_completion(&mpc8xxx_spi->done);
-       INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
-       INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
-       mpc8xxx_spi->workqueue = create_singlethread_workqueue(
-               dev_name(master->dev.parent));
-       if (mpc8xxx_spi->workqueue == NULL) {
-               ret = -EBUSY;
-               goto free_irq;
-       }
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
        ret = spi_register_master(master);
        if (ret < 0)
                goto unreg_master;
 
-       dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
+       dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
                 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
 
        return master;
 
 unreg_master:
-       destroy_workqueue(mpc8xxx_spi->workqueue);
-free_irq:
        free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-unmap_io:
-       iounmap(mpc8xxx_spi->base);
+free_irq:
+       iounmap(mpc8xxx_spi->reg_base);
 err_ioremap:
-       mpc8xxx_spi_cpm_free(mpc8xxx_spi);
+       fsl_spi_cpm_free(mpc8xxx_spi);
 err_cpm_init:
+err_probe:
        spi_master_put(master);
 err:
        return ERR_PTR(ret);
 }
 
-static int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
-       struct mpc8xxx_spi *mpc8xxx_spi;
-       struct spi_master *master;
-
-       master = dev_get_drvdata(dev);
-       mpc8xxx_spi = spi_master_get_devdata(master);
-
-       flush_workqueue(mpc8xxx_spi->workqueue);
-       destroy_workqueue(mpc8xxx_spi->workqueue);
-       spi_unregister_master(master);
-
-       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-       iounmap(mpc8xxx_spi->base);
-       mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-
-       return 0;
-}
-
-struct mpc8xxx_spi_probe_info {
-       struct fsl_spi_platform_data pdata;
-       int *gpios;
-       bool *alow_flags;
-};
-
-static struct mpc8xxx_spi_probe_info *
-to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
-       return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
+static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 {
        struct device *dev = spi->dev.parent;
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
@@ -1137,7 +943,7 @@ static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
        gpio_set_value(gpio, on ^ alow);
 }
 
-static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
+static int of_fsl_spi_get_chipselects(struct device *dev)
 {
        struct device_node *np = dev->of_node;
        struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -1198,7 +1004,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
        }
 
        pdata->max_chipselect = ngpios;
-       pdata->cs_control = mpc8xxx_spi_cs_control;
+       pdata->cs_control = fsl_spi_cs_control;
 
        return 0;
 
@@ -1217,7 +1023,7 @@ err_alloc_flags:
        return ret;
 }
 
-static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
+static int of_fsl_spi_free_chipselects(struct device *dev)
 {
        struct fsl_spi_platform_data *pdata = dev->platform_data;
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
@@ -1236,50 +1042,21 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
        return 0;
 }
 
-static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-                                         const struct of_device_id *ofid)
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
+                                       const struct of_device_id *ofid)
 {
        struct device *dev = &ofdev->dev;
        struct device_node *np = ofdev->dev.of_node;
-       struct mpc8xxx_spi_probe_info *pinfo;
-       struct fsl_spi_platform_data *pdata;
        struct spi_master *master;
        struct resource mem;
        struct resource irq;
-       const void *prop;
        int ret = -ENOMEM;
 
-       pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-       if (!pinfo)
-               return -ENOMEM;
-
-       pdata = &pinfo->pdata;
-       dev->platform_data = pdata;
-
-       /* Allocate bus num dynamically. */
-       pdata->bus_num = -1;
-
-       /* SPI controller is either clocked from QE or SoC clock. */
-       pdata->sysclk = get_brgfreq();
-       if (pdata->sysclk == -1) {
-               pdata->sysclk = fsl_get_sys_freq();
-               if (pdata->sysclk == -1) {
-                       ret = -ENODEV;
-                       goto err_clk;
-               }
-       }
+       ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+       if (ret)
+               return ret;
 
-       prop = of_get_property(np, "mode", NULL);
-       if (prop && !strcmp(prop, "cpu-qe"))
-               pdata->flags = SPI_QE_CPU_MODE;
-       else if (prop && !strcmp(prop, "qe"))
-               pdata->flags = SPI_CPM_MODE | SPI_QE;
-       else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
-               pdata->flags = SPI_CPM_MODE | SPI_CPM2;
-       else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
-               pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
-       ret = of_mpc8xxx_spi_get_chipselects(dev);
+       ret = of_fsl_spi_get_chipselects(dev);
        if (ret)
                goto err;
 
@@ -1293,7 +1070,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
                goto err;
        }
 
-       master = mpc8xxx_spi_probe(dev, &mem, irq.start);
+       master = fsl_spi_probe(dev, &mem, irq.start);
        if (IS_ERR(master)) {
                ret = PTR_ERR(master);
                goto err;
@@ -1302,42 +1079,40 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
        return 0;
 
 err:
-       of_mpc8xxx_spi_free_chipselects(dev);
-err_clk:
-       kfree(pinfo);
+       of_fsl_spi_free_chipselects(dev);
        return ret;
 }
 
-static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
+static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
 {
        int ret;
 
        ret = mpc8xxx_spi_remove(&ofdev->dev);
        if (ret)
                return ret;
-       of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
+       of_fsl_spi_free_chipselects(&ofdev->dev);
        return 0;
 }
 
-static const struct of_device_id of_mpc8xxx_spi_match[] = {
+static const struct of_device_id of_fsl_spi_match[] = {
        { .compatible = "fsl,spi" },
-       {},
+       {}
 };
-MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
+MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
 
-static struct of_platform_driver of_mpc8xxx_spi_driver = {
+static struct of_platform_driver of_fsl_spi_driver = {
        .driver = {
-               .name = "mpc8xxx_spi",
+               .name = "fsl_spi",
                .owner = THIS_MODULE,
-               .of_match_table = of_mpc8xxx_spi_match,
+               .of_match_table = of_fsl_spi_match,
        },
-       .probe          = of_mpc8xxx_spi_probe,
-       .remove         = __devexit_p(of_mpc8xxx_spi_remove),
+       .probe          = of_fsl_spi_probe,
+       .remove         = __devexit_p(of_fsl_spi_remove),
 };
 
 #ifdef CONFIG_MPC832x_RDB
 /*
- *                             XXX XXX XXX
+ * XXX XXX XXX
  * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
  * only. The driver should go away soon, since newer MPC8323E-RDB's device
  * tree can work with OpenFirmware driver. But for now we support old trees
@@ -1360,7 +1135,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
        if (irq <= 0)
                return -EINVAL;
 
-       master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
+       master = fsl_spi_probe(&pdev->dev, mem, irq);
        if (IS_ERR(master))
                return PTR_ERR(master);
        return 0;
@@ -1399,21 +1174,20 @@ static void __init legacy_driver_register(void) {}
 static void __exit legacy_driver_unregister(void) {}
 #endif /* CONFIG_MPC832x_RDB */
 
-static int __init mpc8xxx_spi_init(void)
+static int __init fsl_spi_init(void)
 {
        legacy_driver_register();
-       return of_register_platform_driver(&of_mpc8xxx_spi_driver);
+       return of_register_platform_driver(&of_fsl_spi_driver);
 }
+module_init(fsl_spi_init);
 
-static void __exit mpc8xxx_spi_exit(void)
+static void __exit fsl_spi_exit(void)
 {
-       of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
+       of_unregister_platform_driver(&of_fsl_spi_driver);
        legacy_driver_unregister();
 }
-
-module_init(mpc8xxx_spi_init);
-module_exit(mpc8xxx_spi_exit);
+module_exit(fsl_spi_exit);
 
 MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
+MODULE_DESCRIPTION("Simple Freescale SPI Driver");
 MODULE_LICENSE("GPL");
index e24a63498acb84f7e4f9f83710aca3fadefcc177..63e51b011d508c8922bb047cfb94572049323493 100644 (file)
@@ -350,7 +350,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev)
        spi_gpio->bitbang.master = spi_master_get(master);
        spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
 
-       if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
+       if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
                spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
                spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
                spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
index 7972e90774738d87d75b835be0a8555d63b78c58..55a38e2c6c137a0530b107bdfe5bc0ac0dd94e7b 100644 (file)
@@ -56,7 +56,28 @@ struct spi_imx_config {
        unsigned int speed_hz;
        unsigned int bpw;
        unsigned int mode;
-       int cs;
+       u8 cs;
+};
+
+enum spi_imx_devtype {
+       SPI_IMX_VER_IMX1,
+       SPI_IMX_VER_0_0,
+       SPI_IMX_VER_0_4,
+       SPI_IMX_VER_0_5,
+       SPI_IMX_VER_0_7,
+       SPI_IMX_VER_2_3,
+       SPI_IMX_VER_AUTODETECT,
+};
+
+struct spi_imx_data;
+
+struct spi_imx_devtype_data {
+       void (*intctrl)(struct spi_imx_data *, int);
+       int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+       void (*trigger)(struct spi_imx_data *);
+       int (*rx_available)(struct spi_imx_data *);
+       void (*reset)(struct spi_imx_data *);
+       unsigned int fifosize;
 };
 
 struct spi_imx_data {
@@ -76,11 +97,7 @@ struct spi_imx_data {
        const void *tx_buf;
        unsigned int txfifo; /* number of words pushed in tx FIFO */
 
-       /* SoC specific functions */
-       void (*intctrl)(struct spi_imx_data *, int);
-       int (*config)(struct spi_imx_data *, struct spi_imx_config *);
-       void (*trigger)(struct spi_imx_data *);
-       int (*rx_available)(struct spi_imx_data *);
+       struct spi_imx_devtype_data devtype_data;
 };
 
 #define MXC_SPI_BUF_RX(type)                                           \
@@ -140,7 +157,7 @@ static unsigned int spi_imx_clkdiv_1(unsigned int fin,
        return max;
 }
 
-/* MX1, MX31, MX35 */
+/* MX1, MX31, MX35, MX51 CSPI */
 static unsigned int spi_imx_clkdiv_2(unsigned int fin,
                unsigned int fspi)
 {
@@ -155,6 +172,128 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
        return 7;
 }
 
+#define SPI_IMX2_3_CTRL                0x08
+#define SPI_IMX2_3_CTRL_ENABLE         (1 <<  0)
+#define SPI_IMX2_3_CTRL_XCH            (1 <<  2)
+#define SPI_IMX2_3_CTRL_MODE(cs)       (1 << ((cs) +  4))
+#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET 8
+#define SPI_IMX2_3_CTRL_PREDIV_OFFSET  12
+#define SPI_IMX2_3_CTRL_CS(cs)         ((cs) << 18)
+#define SPI_IMX2_3_CTRL_BL_OFFSET      20
+
+#define SPI_IMX2_3_CONFIG      0x0c
+#define SPI_IMX2_3_CONFIG_SCLKPHA(cs)  (1 << ((cs) +  0))
+#define SPI_IMX2_3_CONFIG_SCLKPOL(cs)  (1 << ((cs) +  4))
+#define SPI_IMX2_3_CONFIG_SBBCTRL(cs)  (1 << ((cs) +  8))
+#define SPI_IMX2_3_CONFIG_SSBPOL(cs)   (1 << ((cs) + 12))
+
+#define SPI_IMX2_3_INT         0x10
+#define SPI_IMX2_3_INT_TEEN            (1 <<  0)
+#define SPI_IMX2_3_INT_RREN            (1 <<  3)
+
+#define SPI_IMX2_3_STAT                0x18
+#define SPI_IMX2_3_STAT_RR             (1 <<  3)
+
+/* MX51 eCSPI */
+static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
+{
+       /*
+        * there are two 4-bit dividers, the pre-divider divides by
+        * $pre, the post-divider by 2^$post
+        */
+       unsigned int pre, post;
+
+       if (unlikely(fspi > fin))
+               return 0;
+
+       post = fls(fin) - fls(fspi);
+       if (fin > fspi << post)
+               post++;
+
+       /* now we have: (fin <= fspi << post) with post being minimal */
+
+       post = max(4U, post) - 4;
+       if (unlikely(post > 0xf)) {
+               pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
+                               __func__, fspi, fin);
+               return 0xff;
+       }
+
+       pre = DIV_ROUND_UP(fin, fspi << post) - 1;
+
+       pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
+                       __func__, fin, fspi, post, pre);
+       return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) |
+               (post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET);
+}
+
+static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+       unsigned val = 0;
+
+       if (enable & MXC_INT_TE)
+               val |= SPI_IMX2_3_INT_TEEN;
+
+       if (enable & MXC_INT_RR)
+               val |= SPI_IMX2_3_INT_RREN;
+
+       writel(val, spi_imx->base + SPI_IMX2_3_INT);
+}
+
+static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx)
+{
+       u32 reg;
+
+       reg = readl(spi_imx->base + SPI_IMX2_3_CTRL);
+       reg |= SPI_IMX2_3_CTRL_XCH;
+       writel(reg, spi_imx->base + SPI_IMX2_3_CTRL);
+}
+
+static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
+               struct spi_imx_config *config)
+{
+       u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
+
+       /* set master mode */
+       ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs);
+
+       /* set clock speed */
+       ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
+
+       /* set chip select to use */
+       ctrl |= SPI_IMX2_3_CTRL_CS(config->cs);
+
+       ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET;
+
+       cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs);
+
+       if (config->mode & SPI_CPHA)
+               cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs);
+
+       if (config->mode & SPI_CPOL)
+               cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs);
+
+       if (config->mode & SPI_CS_HIGH)
+               cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs);
+
+       writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL);
+       writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG);
+
+       return 0;
+}
+
+static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx)
+{
+       return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR;
+}
+
+static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx)
+{
+       /* drain receive buffer */
+       while (spi_imx2_3_rx_available(spi_imx))
+               readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
 #define MX31_INTREG_TEEN       (1 << 0)
 #define MX31_INTREG_RREN       (1 << 3)
 
@@ -178,7 +317,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
  * the i.MX35 has a slightly different register layout for bits
  * we do not use here.
  */
-static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -190,7 +329,7 @@ static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx31_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -199,20 +338,16 @@ static void mx31_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx31_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
        unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
+       int cs = spi_imx->chipselect[config->cs];
 
        reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
                MX31_CSPICTRL_DR_SHIFT;
 
-       if (cpu_is_mx31())
-               reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-       else if (cpu_is_mx25() || cpu_is_mx35()) {
-               reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
-               reg |= MX31_CSPICTRL_SSCTL;
-       }
+       reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
 
        if (config->mode & SPI_CPHA)
                reg |= MX31_CSPICTRL_PHA;
@@ -220,23 +355,52 @@ static int mx31_config(struct spi_imx_data *spi_imx,
                reg |= MX31_CSPICTRL_POL;
        if (config->mode & SPI_CS_HIGH)
                reg |= MX31_CSPICTRL_SSPOL;
-       if (config->cs < 0) {
-               if (cpu_is_mx31())
-                       reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-               else if (cpu_is_mx25() || cpu_is_mx35())
-                       reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT;
-       }
+       if (cs < 0)
+               reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT;
+
+       writel(reg, spi_imx->base + MXC_CSPICTRL);
+
+       return 0;
+}
+
+static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
+               struct spi_imx_config *config)
+{
+       unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
+       int cs = spi_imx->chipselect[config->cs];
+
+       reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
+               MX31_CSPICTRL_DR_SHIFT;
+
+       reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
+       reg |= MX31_CSPICTRL_SSCTL;
+
+       if (config->mode & SPI_CPHA)
+               reg |= MX31_CSPICTRL_PHA;
+       if (config->mode & SPI_CPOL)
+               reg |= MX31_CSPICTRL_POL;
+       if (config->mode & SPI_CS_HIGH)
+               reg |= MX31_CSPICTRL_SSPOL;
+       if (cs < 0)
+               reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT;
 
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 
        return 0;
 }
 
-static int mx31_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
 }
 
+static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx)
+{
+       /* drain receive buffer */
+       while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
+               readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
 #define MX27_INTREG_RR         (1 << 4)
 #define MX27_INTREG_TEEN       (1 << 9)
 #define MX27_INTREG_RREN       (1 << 13)
@@ -250,7 +414,7 @@ static int mx31_rx_available(struct spi_imx_data *spi_imx)
 #define MX27_CSPICTRL_DR_SHIFT 14
 #define MX27_CSPICTRL_CS_SHIFT 19
 
-static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -262,7 +426,7 @@ static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx27_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -271,10 +435,11 @@ static void mx27_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx27_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
        unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
+       int cs = spi_imx->chipselect[config->cs];
 
        reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
                MX27_CSPICTRL_DR_SHIFT;
@@ -286,19 +451,24 @@ static int mx27_config(struct spi_imx_data *spi_imx,
                reg |= MX27_CSPICTRL_POL;
        if (config->mode & SPI_CS_HIGH)
                reg |= MX27_CSPICTRL_SSPOL;
-       if (config->cs < 0)
-               reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT;
+       if (cs < 0)
+               reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT;
 
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 
        return 0;
 }
 
-static int mx27_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
 }
 
+static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx)
+{
+       writel(1, spi_imx->base + MXC_RESET);
+}
+
 #define MX1_INTREG_RR          (1 << 3)
 #define MX1_INTREG_TEEN                (1 << 8)
 #define MX1_INTREG_RREN                (1 << 11)
@@ -310,7 +480,7 @@ static int mx27_rx_available(struct spi_imx_data *spi_imx)
 #define MX1_CSPICTRL_MASTER    (1 << 10)
 #define MX1_CSPICTRL_DR_SHIFT  13
 
-static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -322,7 +492,7 @@ static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx1_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -331,7 +501,7 @@ static void mx1_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx1_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
        unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
@@ -350,11 +520,73 @@ static int mx1_config(struct spi_imx_data *spi_imx,
        return 0;
 }
 
-static int mx1_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
 }
 
+static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
+{
+       writel(1, spi_imx->base + MXC_RESET);
+}
+
+/*
+ * These version numbers are taken from the Freescale driver.  Unfortunately it
+ * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
+ */
+static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
+#ifdef CONFIG_SPI_IMX_VER_IMX1
+       [SPI_IMX_VER_IMX1] = {
+               .intctrl = mx1_intctrl,
+               .config = mx1_config,
+               .trigger = mx1_trigger,
+               .rx_available = mx1_rx_available,
+               .reset = mx1_reset,
+               .fifosize = 8,
+       },
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_0
+       [SPI_IMX_VER_0_0] = {
+               .intctrl = mx27_intctrl,
+               .config = mx27_config,
+               .trigger = mx27_trigger,
+               .rx_available = mx27_rx_available,
+               .reset = spi_imx0_0_reset,
+               .fifosize = 8,
+       },
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_4
+       [SPI_IMX_VER_0_4] = {
+               .intctrl = mx31_intctrl,
+               .config = spi_imx0_4_config,
+               .trigger = mx31_trigger,
+               .rx_available = mx31_rx_available,
+               .reset = spi_imx0_4_reset,
+               .fifosize = 8,
+       },
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_7
+       [SPI_IMX_VER_0_7] = {
+               .intctrl = mx31_intctrl,
+               .config = spi_imx0_7_config,
+               .trigger = mx31_trigger,
+               .rx_available = mx31_rx_available,
+               .reset = spi_imx0_4_reset,
+               .fifosize = 8,
+       },
+#endif
+#ifdef CONFIG_SPI_IMX_VER_2_3
+       [SPI_IMX_VER_2_3] = {
+               .intctrl = spi_imx2_3_intctrl,
+               .config = spi_imx2_3_config,
+               .trigger = spi_imx2_3_trigger,
+               .rx_available = spi_imx2_3_rx_available,
+               .reset = spi_imx2_3_reset,
+               .fifosize = 64,
+       },
+#endif
+};
+
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
@@ -370,21 +602,21 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 
 static void spi_imx_push(struct spi_imx_data *spi_imx)
 {
-       while (spi_imx->txfifo < 8) {
+       while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) {
                if (!spi_imx->count)
                        break;
                spi_imx->tx(spi_imx);
                spi_imx->txfifo++;
        }
 
-       spi_imx->trigger(spi_imx);
+       spi_imx->devtype_data.trigger(spi_imx);
 }
 
 static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 {
        struct spi_imx_data *spi_imx = dev_id;
 
-       while (spi_imx->rx_available(spi_imx)) {
+       while (spi_imx->devtype_data.rx_available(spi_imx)) {
                spi_imx->rx(spi_imx);
                spi_imx->txfifo--;
        }
@@ -398,11 +630,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
                /* No data left to push, but still waiting for rx data,
                 * enable receive data available interrupt.
                 */
-               spi_imx->intctrl(spi_imx, MXC_INT_RR);
+               spi_imx->devtype_data.intctrl(
+                               spi_imx, MXC_INT_RR);
                return IRQ_HANDLED;
        }
 
-       spi_imx->intctrl(spi_imx, 0);
+       spi_imx->devtype_data.intctrl(spi_imx, 0);
        complete(&spi_imx->xfer_done);
 
        return IRQ_HANDLED;
@@ -417,7 +650,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
        config.bpw = t ? t->bits_per_word : spi->bits_per_word;
        config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
        config.mode = spi->mode;
-       config.cs = spi_imx->chipselect[spi->chip_select];
+       config.cs = spi->chip_select;
 
        if (!config.speed_hz)
                config.speed_hz = spi->max_speed_hz;
@@ -439,7 +672,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
        } else
                BUG();
 
-       spi_imx->config(spi_imx, &config);
+       spi_imx->devtype_data.config(spi_imx, &config);
 
        return 0;
 }
@@ -458,7 +691,7 @@ static int spi_imx_transfer(struct spi_device *spi,
 
        spi_imx_push(spi_imx);
 
-       spi_imx->intctrl(spi_imx, MXC_INT_TE);
+       spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
 
        wait_for_completion(&spi_imx->xfer_done);
 
@@ -485,6 +718,39 @@ static void spi_imx_cleanup(struct spi_device *spi)
 {
 }
 
+static struct platform_device_id spi_imx_devtype[] = {
+       {
+               .name = DRIVER_NAME,
+               .driver_data = SPI_IMX_VER_AUTODETECT,
+       }, {
+               .name = "imx1-cspi",
+               .driver_data = SPI_IMX_VER_IMX1,
+       }, {
+               .name = "imx21-cspi",
+               .driver_data = SPI_IMX_VER_0_0,
+       }, {
+               .name = "imx25-cspi",
+               .driver_data = SPI_IMX_VER_0_7,
+       }, {
+               .name = "imx27-cspi",
+               .driver_data = SPI_IMX_VER_0_0,
+       }, {
+               .name = "imx31-cspi",
+               .driver_data = SPI_IMX_VER_0_4,
+       }, {
+               .name = "imx35-cspi",
+               .driver_data = SPI_IMX_VER_0_7,
+       }, {
+               .name = "imx51-cspi",
+               .driver_data = SPI_IMX_VER_0_7,
+       }, {
+               .name = "imx51-ecspi",
+               .driver_data = SPI_IMX_VER_2_3,
+       }, {
+               /* sentinel */
+       }
+};
+
 static int __devinit spi_imx_probe(struct platform_device *pdev)
 {
        struct spi_imx_master *mxc_platform_info;
@@ -536,6 +802,31 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 
        init_completion(&spi_imx->xfer_done);
 
+       if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
+               if (cpu_is_mx25() || cpu_is_mx35())
+                       spi_imx->devtype_data =
+                               spi_imx_devtype_data[SPI_IMX_VER_0_7];
+               else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
+                       spi_imx->devtype_data =
+                               spi_imx_devtype_data[SPI_IMX_VER_0_4];
+               else if (cpu_is_mx27() || cpu_is_mx21())
+                       spi_imx->devtype_data =
+                               spi_imx_devtype_data[SPI_IMX_VER_0_0];
+               else if (cpu_is_mx1())
+                       spi_imx->devtype_data =
+                               spi_imx_devtype_data[SPI_IMX_VER_IMX1];
+               else
+                       BUG();
+       } else
+               spi_imx->devtype_data =
+                       spi_imx_devtype_data[pdev->id_entry->driver_data];
+
+       if (!spi_imx->devtype_data.intctrl) {
+               dev_err(&pdev->dev, "no support for this device compiled in\n");
+               ret = -ENODEV;
+               goto out_gpio_free;
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "can't get platform resource\n");
@@ -567,24 +858,6 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
                goto out_iounmap;
        }
 
-       if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) {
-               spi_imx->intctrl = mx31_intctrl;
-               spi_imx->config = mx31_config;
-               spi_imx->trigger = mx31_trigger;
-               spi_imx->rx_available = mx31_rx_available;
-       } else  if (cpu_is_mx27() || cpu_is_mx21()) {
-               spi_imx->intctrl = mx27_intctrl;
-               spi_imx->config = mx27_config;
-               spi_imx->trigger = mx27_trigger;
-               spi_imx->rx_available = mx27_rx_available;
-       } else if (cpu_is_mx1()) {
-               spi_imx->intctrl = mx1_intctrl;
-               spi_imx->config = mx1_config;
-               spi_imx->trigger = mx1_trigger;
-               spi_imx->rx_available = mx1_rx_available;
-       } else
-               BUG();
-
        spi_imx->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(spi_imx->clk)) {
                dev_err(&pdev->dev, "unable to get clock\n");
@@ -595,15 +868,9 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
        clk_enable(spi_imx->clk);
        spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
 
-       if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
-               writel(1, spi_imx->base + MXC_RESET);
-
-       /* drain receive buffer */
-       if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
-               while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
-                       readl(spi_imx->base + MXC_CSPIRXDATA);
+       spi_imx->devtype_data.reset(spi_imx);
 
-       spi_imx->intctrl(spi_imx, 0);
+       spi_imx->devtype_data.intctrl(spi_imx, 0);
 
        ret = spi_bitbang_start(&spi_imx->bitbang);
        if (ret) {
@@ -668,6 +935,7 @@ static struct platform_driver spi_imx_driver = {
                   .name = DRIVER_NAME,
                   .owner = THIS_MODULE,
                   },
+       .id_table = spi_imx_devtype,
        .probe = spi_imx_probe,
        .remove = __devexit_p(spi_imx_remove),
 };
index 97365815a729a2d3c17d47d3815ffa38ff6c6526..795828b90f45ebe4eef243d4abccfebee503f2f7 100644 (file)
@@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
                val = readl(regs + S3C64XX_SPI_STATUS);
        } while (TX_FIFO_LVL(val, sci) && loops--);
 
+       if (loops == 0)
+               dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
+
        /* Flush RxFIFO*/
        loops = msecs_to_loops(1);
        do {
@@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
                        break;
        } while (loops--);
 
+       if (loops == 0)
+               dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n");
+
        val = readl(regs + S3C64XX_SPI_CH_CFG);
        val &= ~S3C64XX_SPI_CH_SW_RST;
        writel(val, regs + S3C64XX_SPI_CH_CFG);
@@ -255,15 +261,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                chcfg |= S3C64XX_SPI_CH_TXCH_ON;
                if (dma_mode) {
                        modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-                       s3c2410_dma_config(sdd->tx_dmach, 1);
+                       s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
                        s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
                                                xfer->tx_dma, xfer->len);
                        s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
                } else {
-                       unsigned char *buf = (unsigned char *) xfer->tx_buf;
-                       int i = 0;
-                       while (i < xfer->len)
-                               writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
+                       switch (sdd->cur_bpw) {
+                       case 32:
+                               iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
+                                       xfer->tx_buf, xfer->len / 4);
+                               break;
+                       case 16:
+                               iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
+                                       xfer->tx_buf, xfer->len / 2);
+                               break;
+                       default:
+                               iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
+                                       xfer->tx_buf, xfer->len);
+                               break;
+                       }
                }
        }
 
@@ -280,7 +296,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                        writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
                                        | S3C64XX_SPI_PACKET_CNT_EN,
                                        regs + S3C64XX_SPI_PACKET_CNT);
-                       s3c2410_dma_config(sdd->rx_dmach, 1);
+                       s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
                        s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
                                                xfer->rx_dma, xfer->len);
                        s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
@@ -320,16 +336,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
 
        /* millisecs to xfer 'len' bytes @ 'cur_speed' */
        ms = xfer->len * 8 * 1000 / sdd->cur_speed;
-       ms += 5; /* some tolerance */
+       ms += 10; /* some tolerance */
 
        if (dma_mode) {
                val = msecs_to_jiffies(ms) + 10;
                val = wait_for_completion_timeout(&sdd->xfer_completion, val);
        } else {
+               u32 status;
                val = msecs_to_loops(ms);
                do {
-                       val = readl(regs + S3C64XX_SPI_STATUS);
-               } while (RX_FIFO_LVL(val, sci) < xfer->len && --val);
+                       status = readl(regs + S3C64XX_SPI_STATUS);
+               } while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
        }
 
        if (!val)
@@ -359,20 +376,26 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                                return -EIO;
                }
        } else {
-               unsigned char *buf;
-               int i;
-
                /* If it was only Tx */
                if (xfer->rx_buf == NULL) {
                        sdd->state &= ~TXBUSY;
                        return 0;
                }
 
-               i = 0;
-               buf = xfer->rx_buf;
-               while (i < xfer->len)
-                       buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
-
+               switch (sdd->cur_bpw) {
+               case 32:
+                       ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
+                               xfer->rx_buf, xfer->len / 4);
+                       break;
+               case 16:
+                       ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
+                               xfer->rx_buf, xfer->len / 2);
+                       break;
+               default:
+                       ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
+                               xfer->rx_buf, xfer->len);
+                       break;
+               }
                sdd->state &= ~RXBUSY;
        }
 
@@ -392,13 +415,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 {
+       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        u32 val;
 
        /* Disable Clock */
-       val = readl(regs + S3C64XX_SPI_CLK_CFG);
-       val &= ~S3C64XX_SPI_ENCLK_ENABLE;
-       writel(val, regs + S3C64XX_SPI_CLK_CFG);
+       if (sci->clk_from_cmu) {
+               clk_disable(sdd->src_clk);
+       } else {
+               val = readl(regs + S3C64XX_SPI_CLK_CFG);
+               val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+               writel(val, regs + S3C64XX_SPI_CLK_CFG);
+       }
 
        /* Set Polarity and Phase */
        val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -422,33 +450,43 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
        switch (sdd->cur_bpw) {
        case 32:
                val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
+               val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
                break;
        case 16:
                val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
+               val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
                break;
        default:
                val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
+               val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
                break;
        }
-       val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
 
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
-       /* Configure Clock */
-       val = readl(regs + S3C64XX_SPI_CLK_CFG);
-       val &= ~S3C64XX_SPI_PSR_MASK;
-       val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
-                       & S3C64XX_SPI_PSR_MASK);
-       writel(val, regs + S3C64XX_SPI_CLK_CFG);
-
-       /* Enable Clock */
-       val = readl(regs + S3C64XX_SPI_CLK_CFG);
-       val |= S3C64XX_SPI_ENCLK_ENABLE;
-       writel(val, regs + S3C64XX_SPI_CLK_CFG);
+       if (sci->clk_from_cmu) {
+               /* Configure Clock */
+               /* There is half-multiplier before the SPI */
+               clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
+               /* Enable Clock */
+               clk_enable(sdd->src_clk);
+       } else {
+               /* Configure Clock */
+               val = readl(regs + S3C64XX_SPI_CLK_CFG);
+               val &= ~S3C64XX_SPI_PSR_MASK;
+               val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
+                               & S3C64XX_SPI_PSR_MASK);
+               writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+               /* Enable Clock */
+               val = readl(regs + S3C64XX_SPI_CLK_CFG);
+               val |= S3C64XX_SPI_ENCLK_ENABLE;
+               writel(val, regs + S3C64XX_SPI_CLK_CFG);
+       }
 }
 
-void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                               int size, enum s3c2410_dma_buffresult res)
+static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
+                                int size, enum s3c2410_dma_buffresult res)
 {
        struct s3c64xx_spi_driver_data *sdd = buf_id;
        unsigned long flags;
@@ -467,8 +505,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
        spin_unlock_irqrestore(&sdd->lock, flags);
 }
 
-void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                               int size, enum s3c2410_dma_buffresult res)
+static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
+                                int size, enum s3c2410_dma_buffresult res)
 {
        struct s3c64xx_spi_driver_data *sdd = buf_id;
        unsigned long flags;
@@ -492,6 +530,7 @@ void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
+       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -507,9 +546,13 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
        /* Map until end or first fail */
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
+               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+                       continue;
+
                if (xfer->tx_buf != NULL) {
-                       xfer->tx_dma = dma_map_single(dev, xfer->tx_buf,
-                                               xfer->len, DMA_TO_DEVICE);
+                       xfer->tx_dma = dma_map_single(dev,
+                                       (void *)xfer->tx_buf, xfer->len,
+                                       DMA_TO_DEVICE);
                        if (dma_mapping_error(dev, xfer->tx_dma)) {
                                dev_err(dev, "dma_map_single Tx failed\n");
                                xfer->tx_dma = XFER_DMAADDR_INVALID;
@@ -537,6 +580,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
 static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
+       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -545,6 +589,9 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
+               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+                       continue;
+
                if (xfer->rx_buf != NULL
                                && xfer->rx_dma != XFER_DMAADDR_INVALID)
                        dma_unmap_single(dev, xfer->rx_dma,
@@ -600,6 +647,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
                bpw = xfer->bits_per_word ? : spi->bits_per_word;
                speed = xfer->speed_hz ? : spi->max_speed_hz;
 
+               if (xfer->len % (bpw / 8)) {
+                       dev_err(&spi->dev,
+                               "Xfer length(%u) not a multiple of word size(%u)\n",
+                               xfer->len, bpw / 8);
+                       status = -EIO;
+                       goto out;
+               }
+
                if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
                        sdd->cur_bpw = bpw;
                        sdd->cur_speed = speed;
@@ -790,7 +845,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        struct s3c64xx_spi_driver_data *sdd;
        struct s3c64xx_spi_info *sci;
        struct spi_message *msg;
-       u32 psr, speed;
        unsigned long flags;
        int err = 0;
 
@@ -833,32 +887,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        }
 
        /* Check if we can provide the requested rate */
-       speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */
-
-       if (spi->max_speed_hz > speed)
-               spi->max_speed_hz = speed;
-
-       psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
-       psr &= S3C64XX_SPI_PSR_MASK;
-       if (psr == S3C64XX_SPI_PSR_MASK)
-               psr--;
+       if (!sci->clk_from_cmu) {
+               u32 psr, speed;
+
+               /* Max possible */
+               speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
+
+               if (spi->max_speed_hz > speed)
+                       spi->max_speed_hz = speed;
+
+               psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
+               psr &= S3C64XX_SPI_PSR_MASK;
+               if (psr == S3C64XX_SPI_PSR_MASK)
+                       psr--;
+
+               speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+               if (spi->max_speed_hz < speed) {
+                       if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+                               psr++;
+                       } else {
+                               err = -EINVAL;
+                               goto setup_exit;
+                       }
+               }
 
-       speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-       if (spi->max_speed_hz < speed) {
-               if (psr+1 < S3C64XX_SPI_PSR_MASK) {
-                       psr++;
-               } else {
+               speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+               if (spi->max_speed_hz >= speed)
+                       spi->max_speed_hz = speed;
+               else
                        err = -EINVAL;
-                       goto setup_exit;
-               }
        }
 
-       speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-       if (spi->max_speed_hz >= speed)
-               spi->max_speed_hz = speed;
-       else
-               err = -EINVAL;
-
 setup_exit:
 
        /* setup() returns with device de-selected */
@@ -880,7 +939,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        /* Disable Interrupts - we use Polling if not DMA mode */
        writel(0, regs + S3C64XX_SPI_INT_EN);
 
-       writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+       if (!sci->clk_from_cmu)
+               writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
                                regs + S3C64XX_SPI_CLK_CFG);
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
        writel(0, regs + S3C64XX_SPI_PACKET_CNT);
@@ -919,6 +979,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       sci = pdev->dev.platform_data;
+       if (!sci->src_clk_name) {
+               dev_err(&pdev->dev,
+                       "Board init must call s3c64xx_spi_set_info()\n");
+               return -EINVAL;
+       }
+
        /* Check for availability of necessary resource */
 
        dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -946,8 +1013,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       sci = pdev->dev.platform_data;
-
        platform_set_drvdata(pdev, master);
 
        sdd = spi_master_get_devdata(master);
@@ -1170,7 +1235,7 @@ static int __init s3c64xx_spi_init(void)
 {
        return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
 }
-module_init(s3c64xx_spi_init);
+subsys_initcall(s3c64xx_spi_init);
 
 static void __exit s3c64xx_spi_exit(void)
 {
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi_topcliff_pch.c
new file mode 100644 (file)
index 0000000..58e187f
--- /dev/null
@@ -0,0 +1,1303 @@
+/*
+ * SPI bus driver for the Topcliff PCH used by Intel SoCs
+ *
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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/delay.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spi/spidev.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+/* Register offsets */
+#define PCH_SPCR               0x00    /* SPI control register */
+#define PCH_SPBRR              0x04    /* SPI baud rate register */
+#define PCH_SPSR               0x08    /* SPI status register */
+#define PCH_SPDWR              0x0C    /* SPI write data register */
+#define PCH_SPDRR              0x10    /* SPI read data register */
+#define PCH_SSNXCR             0x18    /* SSN Expand Control Register */
+#define PCH_SRST               0x1C    /* SPI reset register */
+
+#define PCH_SPSR_TFD           0x000007C0
+#define PCH_SPSR_RFD           0x0000F800
+
+#define PCH_READABLE(x)                (((x) & PCH_SPSR_RFD)>>11)
+#define PCH_WRITABLE(x)                (((x) & PCH_SPSR_TFD)>>6)
+
+#define PCH_RX_THOLD           7
+#define PCH_RX_THOLD_MAX       15
+
+#define PCH_MAX_BAUDRATE       5000000
+#define PCH_MAX_FIFO_DEPTH     16
+
+#define STATUS_RUNNING         1
+#define STATUS_EXITING         2
+#define PCH_SLEEP_TIME         10
+
+#define PCH_ADDRESS_SIZE       0x20
+
+#define SSN_LOW                        0x02U
+#define SSN_NO_CONTROL         0x00U
+#define PCH_MAX_CS             0xFF
+#define PCI_DEVICE_ID_GE_SPI   0x8816
+
+#define SPCR_SPE_BIT           (1 << 0)
+#define SPCR_MSTR_BIT          (1 << 1)
+#define SPCR_LSBF_BIT          (1 << 4)
+#define SPCR_CPHA_BIT          (1 << 5)
+#define SPCR_CPOL_BIT          (1 << 6)
+#define SPCR_TFIE_BIT          (1 << 8)
+#define SPCR_RFIE_BIT          (1 << 9)
+#define SPCR_FIE_BIT           (1 << 10)
+#define SPCR_ORIE_BIT          (1 << 11)
+#define SPCR_MDFIE_BIT         (1 << 12)
+#define SPCR_FICLR_BIT         (1 << 24)
+#define SPSR_TFI_BIT           (1 << 0)
+#define SPSR_RFI_BIT           (1 << 1)
+#define SPSR_FI_BIT            (1 << 2)
+#define SPBRR_SIZE_BIT         (1 << 10)
+
+#define PCH_ALL                        (SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
+
+#define SPCR_RFIC_FIELD                20
+#define SPCR_TFIC_FIELD                16
+
+#define SPSR_INT_BITS          0x1F
+#define MASK_SPBRR_SPBR_BITS   (~((1 << 10) - 1))
+#define MASK_RFIC_SPCR_BITS    (~(0xf << 20))
+#define MASK_TFIC_SPCR_BITS    (~(0xf000f << 12))
+
+#define PCH_CLOCK_HZ           50000000
+#define PCH_MAX_SPBR           1023
+
+
+/**
+ * struct pch_spi_data - Holds the SPI channel specific details
+ * @io_remap_addr:             The remapped PCI base address
+ * @master:                    Pointer to the SPI master structure
+ * @work:                      Reference to work queue handler
+ * @wk:                                Workqueue for carrying out execution of the
+ *                             requests
+ * @wait:                      Wait queue for waking up upon receiving an
+ *                             interrupt.
+ * @transfer_complete:         Status of SPI Transfer
+ * @bcurrent_msg_processing:   Status flag for message processing
+ * @lock:                      Lock for protecting this structure
+ * @queue:                     SPI Message queue
+ * @status:                    Status of the SPI driver
+ * @bpw_len:                   Length of data to be transferred in bits per
+ *                             word
+ * @transfer_active:           Flag showing active transfer
+ * @tx_index:                  Transmit data count; for bookkeeping during
+ *                             transfer
+ * @rx_index:                  Receive data count; for bookkeeping during
+ *                             transfer
+ * @tx_buff:                   Buffer for data to be transmitted
+ * @rx_index:                  Buffer for Received data
+ * @n_curnt_chip:              The chip number that this SPI driver currently
+ *                             operates on
+ * @current_chip:              Reference to the current chip that this SPI
+ *                             driver currently operates on
+ * @current_msg:               The current message that this SPI driver is
+ *                             handling
+ * @cur_trans:                 The current transfer that this SPI driver is
+ *                             handling
+ * @board_dat:                 Reference to the SPI device data structure
+ */
+struct pch_spi_data {
+       void __iomem *io_remap_addr;
+       struct spi_master *master;
+       struct work_struct work;
+       struct workqueue_struct *wk;
+       wait_queue_head_t wait;
+       u8 transfer_complete;
+       u8 bcurrent_msg_processing;
+       spinlock_t lock;
+       struct list_head queue;
+       u8 status;
+       u32 bpw_len;
+       u8 transfer_active;
+       u32 tx_index;
+       u32 rx_index;
+       u16 *pkt_tx_buff;
+       u16 *pkt_rx_buff;
+       u8 n_curnt_chip;
+       struct spi_device *current_chip;
+       struct spi_message *current_msg;
+       struct spi_transfer *cur_trans;
+       struct pch_spi_board_data *board_dat;
+};
+
+/**
+ * struct pch_spi_board_data - Holds the SPI device specific details
+ * @pdev:              Pointer to the PCI device
+ * @irq_reg_sts:       Status of IRQ registration
+ * @pci_req_sts:       Status of pci_request_regions
+ * @suspend_sts:       Status of suspend
+ * @data:              Pointer to SPI channel data structure
+ */
+struct pch_spi_board_data {
+       struct pci_dev *pdev;
+       u8 irq_reg_sts;
+       u8 pci_req_sts;
+       u8 suspend_sts;
+       struct pch_spi_data *data;
+};
+
+static struct pci_device_id pch_spi_pcidev_id[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)},
+       {0,}
+};
+
+/**
+ * pch_spi_writereg() - Performs  register writes
+ * @master:    Pointer to struct spi_master.
+ * @idx:       Register offset.
+ * @val:       Value to be written to register.
+ */
+static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
+{
+       struct pch_spi_data *data = spi_master_get_devdata(master);
+       iowrite32(val, (data->io_remap_addr + idx));
+}
+
+/**
+ * pch_spi_readreg() - Performs register reads
+ * @master:    Pointer to struct spi_master.
+ * @idx:       Register offset.
+ */
+static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
+{
+       struct pch_spi_data *data = spi_master_get_devdata(master);
+       return ioread32(data->io_remap_addr + idx);
+}
+
+static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
+                                     u32 set, u32 clr)
+{
+       u32 tmp = pch_spi_readreg(master, idx);
+       tmp = (tmp & ~clr) | set;
+       pch_spi_writereg(master, idx, tmp);
+}
+
+static void pch_spi_set_master_mode(struct spi_master *master)
+{
+       pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
+}
+
+/**
+ * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
+ * @master:    Pointer to struct spi_master.
+ */
+static void pch_spi_clear_fifo(struct spi_master *master)
+{
+       pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
+       pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
+}
+
+static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
+                               void __iomem *io_remap_addr)
+{
+       u32 n_read, tx_index, rx_index, bpw_len;
+       u16 *pkt_rx_buffer, *pkt_tx_buff;
+       int read_cnt;
+       u32 reg_spcr_val;
+       void __iomem *spsr;
+       void __iomem *spdrr;
+       void __iomem *spdwr;
+
+       spsr = io_remap_addr + PCH_SPSR;
+       iowrite32(reg_spsr_val, spsr);
+
+       if (data->transfer_active) {
+               rx_index = data->rx_index;
+               tx_index = data->tx_index;
+               bpw_len = data->bpw_len;
+               pkt_rx_buffer = data->pkt_rx_buff;
+               pkt_tx_buff = data->pkt_tx_buff;
+
+               spdrr = io_remap_addr + PCH_SPDRR;
+               spdwr = io_remap_addr + PCH_SPDWR;
+
+               n_read = PCH_READABLE(reg_spsr_val);
+
+               for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
+                       pkt_rx_buffer[rx_index++] = ioread32(spdrr);
+                       if (tx_index < bpw_len)
+                               iowrite32(pkt_tx_buff[tx_index++], spdwr);
+               }
+
+               /* disable RFI if not needed */
+               if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
+                       reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
+                       reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
+
+                       /* reset rx threshold */
+                       reg_spcr_val &= MASK_RFIC_SPCR_BITS;
+                       reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
+                       iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
+                                (io_remap_addr + PCH_SPCR));
+               }
+
+               /* update counts */
+               data->tx_index = tx_index;
+               data->rx_index = rx_index;
+
+       }
+
+       /* if transfer complete interrupt */
+       if (reg_spsr_val & SPSR_FI_BIT) {
+               /* disable FI & RFI interrupts */
+               pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
+                                  SPCR_FIE_BIT | SPCR_TFIE_BIT);
+
+               /* transfer is completed;inform pch_spi_process_messages */
+               data->transfer_complete = true;
+               wake_up(&data->wait);
+       }
+}
+
+/**
+ * pch_spi_handler() - Interrupt handler
+ * @irq:       The interrupt number.
+ * @dev_id:    Pointer to struct pch_spi_board_data.
+ */
+static irqreturn_t pch_spi_handler(int irq, void *dev_id)
+{
+       u32 reg_spsr_val;
+       struct pch_spi_data *data;
+       void __iomem *spsr;
+       void __iomem *io_remap_addr;
+       irqreturn_t ret = IRQ_NONE;
+       struct pch_spi_board_data *board_dat = dev_id;
+
+       if (board_dat->suspend_sts) {
+               dev_dbg(&board_dat->pdev->dev,
+                       "%s returning due to suspend\n", __func__);
+               return IRQ_NONE;
+       }
+
+       data = board_dat->data;
+       io_remap_addr = data->io_remap_addr;
+       spsr = io_remap_addr + PCH_SPSR;
+
+       reg_spsr_val = ioread32(spsr);
+
+       /* Check if the interrupt is for SPI device */
+       if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
+               pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
+               ret = IRQ_HANDLED;
+       }
+
+       dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
+               __func__, ret);
+
+       return ret;
+}
+
+/**
+ * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
+ * @master:    Pointer to struct spi_master.
+ * @speed_hz:  Baud rate.
+ */
+static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
+{
+       u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
+
+       /* if baud rate is less than we can support limit it */
+       if (n_spbr > PCH_MAX_SPBR)
+               n_spbr = PCH_MAX_SPBR;
+
+       pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
+}
+
+/**
+ * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR
+ * @master:            Pointer to struct spi_master.
+ * @bits_per_word:     Bits per word for SPI transfer.
+ */
+static void pch_spi_set_bits_per_word(struct spi_master *master,
+                                     u8 bits_per_word)
+{
+       if (bits_per_word == 8)
+               pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
+       else
+               pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
+}
+
+/**
+ * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
+ * @spi:       Pointer to struct spi_device.
+ */
+static void pch_spi_setup_transfer(struct spi_device *spi)
+{
+       u32 flags = 0;
+
+       dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
+               __func__, pch_spi_readreg(spi->master, PCH_SPBRR),
+               spi->max_speed_hz);
+       pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
+
+       /* set bits per word */
+       pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
+
+       if (!(spi->mode & SPI_LSB_FIRST))
+               flags |= SPCR_LSBF_BIT;
+       if (spi->mode & SPI_CPOL)
+               flags |= SPCR_CPOL_BIT;
+       if (spi->mode & SPI_CPHA)
+               flags |= SPCR_CPHA_BIT;
+       pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
+                          (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
+
+       /* Clear the FIFO by toggling  FICLR to 1 and back to 0 */
+       pch_spi_clear_fifo(spi->master);
+}
+
+/**
+ * pch_spi_reset() - Clears SPI registers
+ * @master:    Pointer to struct spi_master.
+ */
+static void pch_spi_reset(struct spi_master *master)
+{
+       /* write 1 to reset SPI */
+       pch_spi_writereg(master, PCH_SRST, 0x1);
+
+       /* clear reset */
+       pch_spi_writereg(master, PCH_SRST, 0x0);
+}
+
+static int pch_spi_setup(struct spi_device *pspi)
+{
+       /* check bits per word */
+       if (pspi->bits_per_word == 0) {
+               pspi->bits_per_word = 8;
+               dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
+       }
+
+       if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
+               dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Check baud rate setting */
+       /* if baud rate of chip is greater than
+          max we can support,return error */
+       if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
+               pspi->max_speed_hz = PCH_MAX_BAUDRATE;
+
+       dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
+               (pspi->mode) & (SPI_CPOL | SPI_CPHA));
+
+       return 0;
+}
+
+static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
+{
+
+       struct spi_transfer *transfer;
+       struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
+       int retval;
+       unsigned long flags;
+
+       /* validate spi message and baud rate */
+       if (unlikely(list_empty(&pmsg->transfers) == 1)) {
+               dev_err(&pspi->dev, "%s list empty\n", __func__);
+               retval = -EINVAL;
+               goto err_out;
+       }
+
+       if (unlikely(pspi->max_speed_hz == 0)) {
+               dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
+                       __func__, pspi->max_speed_hz);
+               retval = -EINVAL;
+               goto err_out;
+       }
+
+       dev_dbg(&pspi->dev, "%s Transfer List not empty. "
+               "Transfer Speed is set.\n", __func__);
+
+       /* validate Tx/Rx buffers and Transfer length */
+       list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
+               if (!transfer->tx_buf && !transfer->rx_buf) {
+                       dev_err(&pspi->dev,
+                               "%s Tx and Rx buffer NULL\n", __func__);
+                       retval = -EINVAL;
+                       goto err_out;
+               }
+
+               if (!transfer->len) {
+                       dev_err(&pspi->dev, "%s Transfer length invalid\n",
+                               __func__);
+                       retval = -EINVAL;
+                       goto err_out;
+               }
+
+               dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
+                       " valid\n", __func__);
+
+               /* if baud rate hs been specified validate the same */
+               if (transfer->speed_hz > PCH_MAX_BAUDRATE)
+                       transfer->speed_hz = PCH_MAX_BAUDRATE;
+
+               /* if bits per word has been specified validate the same */
+               if (transfer->bits_per_word) {
+                       if ((transfer->bits_per_word != 8)
+                           && (transfer->bits_per_word != 16)) {
+                               retval = -EINVAL;
+                               dev_err(&pspi->dev,
+                                       "%s Invalid bits per word\n", __func__);
+                               goto err_out;
+                       }
+               }
+       }
+
+       spin_lock_irqsave(&data->lock, flags);
+
+       /* We won't process any messages if we have been asked to terminate */
+       if (data->status == STATUS_EXITING) {
+               dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
+               retval = -ESHUTDOWN;
+               goto err_return_spinlock;
+       }
+
+       /* If suspended ,return -EINVAL */
+       if (data->board_dat->suspend_sts) {
+               dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
+               retval = -EINVAL;
+               goto err_return_spinlock;
+       }
+
+       /* set status of message */
+       pmsg->actual_length = 0;
+       dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
+
+       pmsg->status = -EINPROGRESS;
+
+       /* add message to queue */
+       list_add_tail(&pmsg->queue, &data->queue);
+       dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
+
+       /* schedule work queue to run */
+       queue_work(data->wk, &data->work);
+       dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
+
+       retval = 0;
+
+err_return_spinlock:
+       spin_unlock_irqrestore(&data->lock, flags);
+err_out:
+       dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+       return retval;
+}
+
+static inline void pch_spi_select_chip(struct pch_spi_data *data,
+                                      struct spi_device *pspi)
+{
+       if (data->current_chip != NULL) {
+               if (pspi->chip_select != data->n_curnt_chip) {
+                       dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
+                       data->current_chip = NULL;
+               }
+       }
+
+       data->current_chip = pspi;
+
+       data->n_curnt_chip = data->current_chip->chip_select;
+
+       dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
+       pch_spi_setup_transfer(pspi);
+}
+
+static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
+                          struct spi_message **ppmsg)
+{
+       int size;
+       u32 n_writes;
+       int j;
+       struct spi_message *pmsg;
+       const u8 *tx_buf;
+       const u16 *tx_sbuf;
+
+       pmsg = *ppmsg;
+
+       /* set baud rate if needed */
+       if (data->cur_trans->speed_hz) {
+               dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+               pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+       }
+
+       /* set bits per word if needed */
+       if (data->cur_trans->bits_per_word &&
+           (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) {
+               dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+               pch_spi_set_bits_per_word(data->master,
+                                         data->cur_trans->bits_per_word);
+               *bpw = data->cur_trans->bits_per_word;
+       } else {
+               *bpw = data->current_msg->spi->bits_per_word;
+       }
+
+       /* reset Tx/Rx index */
+       data->tx_index = 0;
+       data->rx_index = 0;
+
+       data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+       /* find alloc size */
+       size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
+
+       /* allocate memory for pkt_tx_buff & pkt_rx_buffer */
+       data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
+       if (data->pkt_tx_buff != NULL) {
+               data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
+               if (!data->pkt_rx_buff)
+                       kfree(data->pkt_tx_buff);
+       }
+
+       if (!data->pkt_rx_buff) {
+               /* flush queue and set status of all transfers to -ENOMEM */
+               dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
+               list_for_each_entry(pmsg, data->queue.next, queue) {
+                       pmsg->status = -ENOMEM;
+
+                       if (pmsg->complete != 0)
+                               pmsg->complete(pmsg->context);
+
+                       /* delete from queue */
+                       list_del_init(&pmsg->queue);
+               }
+               return;
+       }
+
+       /* copy Tx Data */
+       if (data->cur_trans->tx_buf != NULL) {
+               if (*bpw == 8) {
+                       tx_buf = data->cur_trans->tx_buf;
+                       for (j = 0; j < data->bpw_len; j++)
+                               data->pkt_tx_buff[j] = *tx_buf++;
+               } else {
+                       tx_sbuf = data->cur_trans->tx_buf;
+                       for (j = 0; j < data->bpw_len; j++)
+                               data->pkt_tx_buff[j] = *tx_sbuf++;
+               }
+       }
+
+       /* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
+       n_writes = data->bpw_len;
+       if (n_writes > PCH_MAX_FIFO_DEPTH)
+               n_writes = PCH_MAX_FIFO_DEPTH;
+
+       dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+               "0x2 to SSNXCR\n", __func__);
+       pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+
+       for (j = 0; j < n_writes; j++)
+               pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
+
+       /* update tx_index */
+       data->tx_index = j;
+
+       /* reset transfer complete flag */
+       data->transfer_complete = false;
+       data->transfer_active = true;
+}
+
+
+static void pch_spi_nomore_transfer(struct pch_spi_data *data,
+                                               struct spi_message *pmsg)
+{
+       dev_dbg(&data->master->dev, "%s called\n", __func__);
+       /* Invoke complete callback
+        * [To the spi core..indicating end of transfer] */
+       data->current_msg->status = 0;
+
+       if (data->current_msg->complete != 0) {
+               dev_dbg(&data->master->dev,
+                       "%s:Invoking callback of SPI core\n", __func__);
+               data->current_msg->complete(data->current_msg->context);
+       }
+
+       /* update status in global variable */
+       data->bcurrent_msg_processing = false;
+
+       dev_dbg(&data->master->dev,
+               "%s:data->bcurrent_msg_processing = false\n", __func__);
+
+       data->current_msg = NULL;
+       data->cur_trans = NULL;
+
+       /* check if we have items in list and not suspending
+        * return 1 if list empty */
+       if ((list_empty(&data->queue) == 0) &&
+           (!data->board_dat->suspend_sts) &&
+           (data->status != STATUS_EXITING)) {
+               /* We have some more work to do (either there is more tranint
+                * bpw;sfer requests in the current message or there are
+                *more messages)
+                */
+               dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
+               queue_work(data->wk, &data->work);
+       } else if (data->board_dat->suspend_sts ||
+                  data->status == STATUS_EXITING) {
+               dev_dbg(&data->master->dev,
+                       "%s suspend/remove initiated, flushing queue\n",
+                       __func__);
+               list_for_each_entry(pmsg, data->queue.next, queue) {
+                       pmsg->status = -EIO;
+
+                       if (pmsg->complete)
+                               pmsg->complete(pmsg->context);
+
+                       /* delete from queue */
+                       list_del_init(&pmsg->queue);
+               }
+       }
+}
+
+static void pch_spi_set_ir(struct pch_spi_data *data)
+{
+       /* enable interrupts */
+       if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
+               /* set receive threhold to PCH_RX_THOLD */
+               pch_spi_setclr_reg(data->master, PCH_SPCR,
+                                  PCH_RX_THOLD << SPCR_TFIC_FIELD,
+                                  ~MASK_TFIC_SPCR_BITS);
+               /* enable FI and RFI interrupts */
+               pch_spi_setclr_reg(data->master, PCH_SPCR,
+                                  SPCR_RFIE_BIT | SPCR_TFIE_BIT, 0);
+       } else {
+               /* set receive threhold to maximum */
+               pch_spi_setclr_reg(data->master, PCH_SPCR,
+                                  PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
+                                  ~MASK_TFIC_SPCR_BITS);
+               /* enable FI interrupt */
+               pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
+       }
+
+       dev_dbg(&data->master->dev,
+               "%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
+
+       /* SPI set enable */
+       pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
+
+       /* Wait until the transfer completes; go to sleep after
+                                initiating the transfer. */
+       dev_dbg(&data->master->dev,
+               "%s:waiting for transfer to get over\n", __func__);
+
+       wait_event_interruptible(data->wait, data->transfer_complete);
+
+       pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+       dev_dbg(&data->master->dev,
+               "%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+       data->transfer_active = false;
+       dev_dbg(&data->master->dev,
+               "%s set data->transfer_active = false\n", __func__);
+
+       /* clear all interrupts */
+       pch_spi_writereg(data->master, PCH_SPSR,
+                        pch_spi_readreg(data->master, PCH_SPSR));
+       /* disable interrupts */
+       pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+}
+
+static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
+{
+       int j;
+       u8 *rx_buf;
+       u16 *rx_sbuf;
+
+       /* copy Rx Data */
+       if (!data->cur_trans->rx_buf)
+               return;
+
+       if (bpw == 8) {
+               rx_buf = data->cur_trans->rx_buf;
+               for (j = 0; j < data->bpw_len; j++)
+                       *rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
+       } else {
+               rx_sbuf = data->cur_trans->rx_buf;
+               for (j = 0; j < data->bpw_len; j++)
+                       *rx_sbuf++ = data->pkt_rx_buff[j];
+       }
+}
+
+
+static void pch_spi_process_messages(struct work_struct *pwork)
+{
+       struct spi_message *pmsg;
+       struct pch_spi_data *data;
+       int bpw;
+
+       data = container_of(pwork, struct pch_spi_data, work);
+       dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
+
+       spin_lock(&data->lock);
+
+       /* check if suspend has been initiated;if yes flush queue */
+       if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
+               dev_dbg(&data->master->dev,
+                       "%s suspend/remove initiated,flushing queue\n",
+                       __func__);
+
+               list_for_each_entry(pmsg, data->queue.next, queue) {
+                       pmsg->status = -EIO;
+
+                       if (pmsg->complete != 0) {
+                               spin_unlock(&data->lock);
+                               pmsg->complete(pmsg->context);
+                               spin_lock(&data->lock);
+                       }
+
+                       /* delete from queue */
+                       list_del_init(&pmsg->queue);
+               }
+
+               spin_unlock(&data->lock);
+               return;
+       }
+
+       data->bcurrent_msg_processing = true;
+       dev_dbg(&data->master->dev,
+               "%s Set data->bcurrent_msg_processing= true\n", __func__);
+
+       /* Get the message from the queue and delete it from there. */
+       data->current_msg = list_entry(data->queue.next, struct spi_message,
+                                       queue);
+
+       list_del_init(&data->current_msg->queue);
+
+       data->current_msg->status = 0;
+
+       pch_spi_select_chip(data, data->current_msg->spi);
+
+       spin_unlock(&data->lock);
+
+       do {
+               /* If we are already processing a message get the next
+               transfer structure from the message otherwise retrieve
+               the 1st transfer request from the message. */
+               spin_lock(&data->lock);
+
+               if (data->cur_trans == NULL) {
+                       data->cur_trans =
+                           list_entry(data->current_msg->transfers.
+                                      next, struct spi_transfer,
+                                      transfer_list);
+                       dev_dbg(&data->master->dev,
+                               "%s :Getting 1st transfer message\n", __func__);
+               } else {
+                       data->cur_trans =
+                           list_entry(data->cur_trans->transfer_list.next,
+                                      struct spi_transfer,
+                                      transfer_list);
+                       dev_dbg(&data->master->dev,
+                               "%s :Getting next transfer message\n",
+                               __func__);
+               }
+
+               spin_unlock(&data->lock);
+
+               pch_spi_set_tx(data, &bpw, &pmsg);
+
+               /* Control interrupt*/
+               pch_spi_set_ir(data);
+
+               /* Disable SPI transfer */
+               pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
+                                  SPCR_SPE_BIT);
+
+               /* clear FIFO */
+               pch_spi_clear_fifo(data->master);
+
+               /* copy Rx Data */
+               pch_spi_copy_rx_data(data, bpw);
+
+               /* free memory */
+               kfree(data->pkt_rx_buff);
+               data->pkt_rx_buff = NULL;
+
+               kfree(data->pkt_tx_buff);
+               data->pkt_tx_buff = NULL;
+
+               /* increment message count */
+               data->current_msg->actual_length += data->cur_trans->len;
+
+               dev_dbg(&data->master->dev,
+                       "%s:data->current_msg->actual_length=%d\n",
+                       __func__, data->current_msg->actual_length);
+
+               /* check for delay */
+               if (data->cur_trans->delay_usecs) {
+                       dev_dbg(&data->master->dev, "%s:"
+                               "delay in usec=%d\n", __func__,
+                               data->cur_trans->delay_usecs);
+                       udelay(data->cur_trans->delay_usecs);
+               }
+
+               spin_lock(&data->lock);
+
+               /* No more transfer in this message. */
+               if ((data->cur_trans->transfer_list.next) ==
+                   &(data->current_msg->transfers)) {
+                       pch_spi_nomore_transfer(data, pmsg);
+               }
+
+               spin_unlock(&data->lock);
+
+       } while (data->cur_trans != NULL);
+}
+
+static void pch_spi_free_resources(struct pch_spi_board_data *board_dat)
+{
+       dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+       /* free workqueue */
+       if (board_dat->data->wk != NULL) {
+               destroy_workqueue(board_dat->data->wk);
+               board_dat->data->wk = NULL;
+               dev_dbg(&board_dat->pdev->dev,
+                       "%s destroy_workqueue invoked successfully\n",
+                       __func__);
+       }
+
+       /* disable interrupts & free IRQ */
+       if (board_dat->irq_reg_sts) {
+               /* disable interrupts */
+               pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
+                                  PCH_ALL);
+
+               /* free IRQ */
+               free_irq(board_dat->pdev->irq, board_dat);
+
+               dev_dbg(&board_dat->pdev->dev,
+                       "%s free_irq invoked successfully\n", __func__);
+
+               board_dat->irq_reg_sts = false;
+       }
+
+       /* unmap PCI base address */
+       if (board_dat->data->io_remap_addr != 0) {
+               pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr);
+
+               board_dat->data->io_remap_addr = 0;
+
+               dev_dbg(&board_dat->pdev->dev,
+                       "%s pci_iounmap invoked successfully\n", __func__);
+       }
+
+       /* release PCI region */
+       if (board_dat->pci_req_sts) {
+               pci_release_regions(board_dat->pdev);
+               dev_dbg(&board_dat->pdev->dev,
+                       "%s pci_release_regions invoked successfully\n",
+                       __func__);
+               board_dat->pci_req_sts = false;
+       }
+}
+
+static int pch_spi_get_resources(struct pch_spi_board_data *board_dat)
+{
+       void __iomem *io_remap_addr;
+       int retval;
+       dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+       /* create workqueue */
+       board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
+       if (!board_dat->data->wk) {
+               dev_err(&board_dat->pdev->dev,
+                       "%s create_singlet hread_workqueue failed\n", __func__);
+               retval = -EBUSY;
+               goto err_return;
+       }
+
+       dev_dbg(&board_dat->pdev->dev,
+               "%s create_singlethread_workqueue success\n", __func__);
+
+       retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME);
+       if (retval != 0) {
+               dev_err(&board_dat->pdev->dev,
+                       "%s request_region failed\n", __func__);
+               goto err_return;
+       }
+
+       board_dat->pci_req_sts = true;
+
+       io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
+       if (io_remap_addr == 0) {
+               dev_err(&board_dat->pdev->dev,
+                       "%s pci_iomap failed\n", __func__);
+               retval = -ENOMEM;
+               goto err_return;
+       }
+
+       /* calculate base address for all channels */
+       board_dat->data->io_remap_addr = io_remap_addr;
+
+       /* reset PCH SPI h/w */
+       pch_spi_reset(board_dat->data->master);
+       dev_dbg(&board_dat->pdev->dev,
+               "%s pch_spi_reset invoked successfully\n", __func__);
+
+       /* register IRQ */
+       retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
+                            IRQF_SHARED, KBUILD_MODNAME, board_dat);
+       if (retval != 0) {
+               dev_err(&board_dat->pdev->dev,
+                       "%s request_irq failed\n", __func__);
+               goto err_return;
+       }
+
+       dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n",
+               __func__, retval);
+
+       board_dat->irq_reg_sts = true;
+       dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
+
+err_return:
+       if (retval != 0) {
+               dev_err(&board_dat->pdev->dev,
+                       "%s FAIL:invoking pch_spi_free_resources\n", __func__);
+               pch_spi_free_resources(board_dat);
+       }
+
+       dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
+
+       return retval;
+}
+
+static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+
+       struct spi_master *master;
+
+       struct pch_spi_board_data *board_dat;
+       int retval;
+
+       dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+       /* allocate memory for private data */
+       board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
+       if (board_dat == NULL) {
+               dev_err(&pdev->dev,
+                       " %s memory allocation for private data failed\n",
+                       __func__);
+               retval = -ENOMEM;
+               goto err_kmalloc;
+       }
+
+       dev_dbg(&pdev->dev,
+               "%s memory allocation for private data success\n", __func__);
+
+       /* enable PCI device */
+       retval = pci_enable_device(pdev);
+       if (retval != 0) {
+               dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__);
+
+               goto err_pci_en_device;
+       }
+
+       dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n",
+               __func__, retval);
+
+       board_dat->pdev = pdev;
+
+       /* alllocate memory for SPI master */
+       master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data));
+       if (master == NULL) {
+               retval = -ENOMEM;
+               dev_err(&pdev->dev, "%s Fail.\n", __func__);
+               goto err_spi_alloc_master;
+       }
+
+       dev_dbg(&pdev->dev,
+               "%s spi_alloc_master returned non NULL\n", __func__);
+
+       /* initialize members of SPI master */
+       master->bus_num = -1;
+       master->num_chipselect = PCH_MAX_CS;
+       master->setup = pch_spi_setup;
+       master->transfer = pch_spi_transfer;
+       dev_dbg(&pdev->dev,
+               "%s transfer member of SPI master initialized\n", __func__);
+
+       board_dat->data = spi_master_get_devdata(master);
+
+       board_dat->data->master = master;
+       board_dat->data->n_curnt_chip = 255;
+       board_dat->data->board_dat = board_dat;
+       board_dat->data->status = STATUS_RUNNING;
+
+       INIT_LIST_HEAD(&board_dat->data->queue);
+       spin_lock_init(&board_dat->data->lock);
+       INIT_WORK(&board_dat->data->work, pch_spi_process_messages);
+       init_waitqueue_head(&board_dat->data->wait);
+
+       /* allocate resources for PCH SPI */
+       retval = pch_spi_get_resources(board_dat);
+       if (retval) {
+               dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval);
+               goto err_spi_get_resources;
+       }
+
+       dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n",
+               __func__, retval);
+
+       /* save private data in dev */
+       pci_set_drvdata(pdev, board_dat);
+       dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__);
+
+       /* set master mode */
+       pch_spi_set_master_mode(master);
+       dev_dbg(&pdev->dev,
+               "%s invoked pch_spi_set_master_mode\n", __func__);
+
+       /* Register the controller with the SPI core. */
+       retval = spi_register_master(master);
+       if (retval != 0) {
+               dev_err(&pdev->dev,
+                       "%s spi_register_master FAILED\n", __func__);
+               goto err_spi_reg_master;
+       }
+
+       dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n",
+               __func__, retval);
+
+
+       return 0;
+
+err_spi_reg_master:
+       spi_unregister_master(master);
+err_spi_get_resources:
+err_spi_alloc_master:
+       spi_master_put(master);
+       pci_disable_device(pdev);
+err_pci_en_device:
+       kfree(board_dat);
+err_kmalloc:
+       return retval;
+}
+
+static void pch_spi_remove(struct pci_dev *pdev)
+{
+       struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+       int count;
+
+       dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+       if (!board_dat) {
+               dev_err(&pdev->dev,
+                       "%s pci_get_drvdata returned NULL\n", __func__);
+               return;
+       }
+
+       /* check for any pending messages; no action is taken if the queue
+        * is still full; but at least we tried.  Unload anyway */
+       count = 500;
+       spin_lock(&board_dat->data->lock);
+       board_dat->data->status = STATUS_EXITING;
+       while ((list_empty(&board_dat->data->queue) == 0) && --count) {
+               dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
+                       __func__);
+               spin_unlock(&board_dat->data->lock);
+               msleep(PCH_SLEEP_TIME);
+               spin_lock(&board_dat->data->lock);
+       }
+       spin_unlock(&board_dat->data->lock);
+
+       /* Free resources allocated for PCH SPI */
+       pch_spi_free_resources(board_dat);
+
+       spi_unregister_master(board_dat->data->master);
+
+       /* free memory for private data */
+       kfree(board_dat);
+
+       pci_set_drvdata(pdev, NULL);
+
+       /* disable PCI device */
+       pci_disable_device(pdev);
+
+       dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__);
+}
+
+#ifdef CONFIG_PM
+static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       u8 count;
+       int retval;
+
+       struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+
+       dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+       if (!board_dat) {
+               dev_err(&pdev->dev,
+                       "%s pci_get_drvdata returned NULL\n", __func__);
+               return -EFAULT;
+       }
+
+       retval = 0;
+       board_dat->suspend_sts = true;
+
+       /* check if the current message is processed:
+          Only after thats done the transfer will be suspended */
+       count = 255;
+       while ((--count) > 0) {
+               if (!(board_dat->data->bcurrent_msg_processing)) {
+                       dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_"
+                               "msg_processing = false\n", __func__);
+                       break;
+               } else {
+                       dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_"
+                               "processing = true\n", __func__);
+               }
+               msleep(PCH_SLEEP_TIME);
+       }
+
+       /* Free IRQ */
+       if (board_dat->irq_reg_sts) {
+               /* disable all interrupts */
+               pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
+                                  PCH_ALL);
+               pch_spi_reset(board_dat->data->master);
+
+               free_irq(board_dat->pdev->irq, board_dat);
+
+               board_dat->irq_reg_sts = false;
+               dev_dbg(&pdev->dev,
+                       "%s free_irq invoked successfully.\n", __func__);
+       }
+
+       /* save config space */
+       retval = pci_save_state(pdev);
+
+       if (retval == 0) {
+               dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n",
+                       __func__, retval);
+               /* disable PM notifications */
+               pci_enable_wake(pdev, PCI_D3hot, 0);
+               dev_dbg(&pdev->dev,
+                       "%s pci_enable_wake invoked successfully\n", __func__);
+               /* disable PCI device */
+               pci_disable_device(pdev);
+               dev_dbg(&pdev->dev,
+                       "%s pci_disable_device invoked successfully\n",
+                       __func__);
+               /* move device to D3hot  state */
+               pci_set_power_state(pdev, PCI_D3hot);
+               dev_dbg(&pdev->dev,
+                       "%s pci_set_power_state invoked successfully\n",
+                       __func__);
+       } else {
+               dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
+       }
+
+       dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval);
+
+       return retval;
+}
+
+static int pch_spi_resume(struct pci_dev *pdev)
+{
+       int retval;
+
+       struct pch_spi_board_data *board = pci_get_drvdata(pdev);
+       dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+       if (!board) {
+               dev_err(&pdev->dev,
+                       "%s pci_get_drvdata returned NULL\n", __func__);
+               return -EFAULT;
+       }
+
+       /* move device to DO power state */
+       pci_set_power_state(pdev, PCI_D0);
+
+       /* restore state */
+       pci_restore_state(pdev);
+
+       retval = pci_enable_device(pdev);
+       if (retval < 0) {
+               dev_err(&pdev->dev,
+                       "%s pci_enable_device failed\n", __func__);
+       } else {
+               /* disable PM notifications */
+               pci_enable_wake(pdev, PCI_D3hot, 0);
+
+               /* register IRQ handler */
+               if (!board->irq_reg_sts) {
+                       /* register IRQ */
+                       retval = request_irq(board->pdev->irq, pch_spi_handler,
+                                            IRQF_SHARED, KBUILD_MODNAME,
+                                            board);
+                       if (retval < 0) {
+                               dev_err(&pdev->dev,
+                                       "%s request_irq failed\n", __func__);
+                               return retval;
+                       }
+                       board->irq_reg_sts = true;
+
+                       /* reset PCH SPI h/w */
+                       pch_spi_reset(board->data->master);
+                       pch_spi_set_master_mode(board->data->master);
+
+                       /* set suspend status to false */
+                       board->suspend_sts = false;
+
+               }
+       }
+
+       dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval);
+
+       return retval;
+}
+#else
+#define pch_spi_suspend NULL
+#define pch_spi_resume NULL
+
+#endif
+
+static struct pci_driver pch_spi_pcidev = {
+       .name = "pch_spi",
+       .id_table = pch_spi_pcidev_id,
+       .probe = pch_spi_probe,
+       .remove = pch_spi_remove,
+       .suspend = pch_spi_suspend,
+       .resume = pch_spi_resume,
+};
+
+static int __init pch_spi_init(void)
+{
+       return pci_register_driver(&pch_spi_pcidev);
+}
+module_init(pch_spi_init);
+
+static void __exit pch_spi_exit(void)
+{
+       pci_unregister_driver(&pch_spi_pcidev);
+}
+module_exit(pch_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver");
index ea1bec3c9a13359a4058a762e9f2f8de7755cc36..4e6245e67995b0b41395b63207e8edda43638b4b 100644 (file)
@@ -545,6 +545,7 @@ static const struct file_operations spidev_fops = {
        .unlocked_ioctl = spidev_ioctl,
        .open =         spidev_open,
        .release =      spidev_release,
+       .llseek =       no_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
index 7892ac163522cd0e62f568fbc7cefcea173f298e..c68b3dc19e11d3368cbd2c1dac1dc0a2d451ef48 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
index 526682d68de8b67247c65703ea1bcff83c1988a7..c7345dbf43fa75228637d914c9d3f153d712c25e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
index 9738cad4ba13fb9f269bfa37a451fe307fc3e276..ee079ab9fb2819b3c18a8e49f6ea5c00be340c79 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/pci.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
index 4a7a7a7f11b67b6efd6b559023824dadeefdff07..335311a98fdcb0d4451c8fa2bfd604f937bae637 100644 (file)
@@ -113,8 +113,6 @@ source "drivers/staging/vme/Kconfig"
 
 source "drivers/staging/memrar/Kconfig"
 
-source "drivers/staging/sep/Kconfig"
-
 source "drivers/staging/iio/Kconfig"
 
 source "drivers/staging/zram/Kconfig"
index ca5c03eb3ce36e233280f7f4bb00ceae5697e4e9..e3f1e1b6095e5e790db3b9af1de06e7e29d4f9b7 100644 (file)
@@ -38,7 +38,6 @@ obj-$(CONFIG_FB_UDL)          += udlfb/
 obj-$(CONFIG_HYPERV)           += hv/
 obj-$(CONFIG_VME_BUS)          += vme/
 obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
-obj-$(CONFIG_DX_SEP)           += sep/
 obj-$(CONFIG_IIO)              += iio/
 obj-$(CONFIG_ZRAM)             += zram/
 obj-$(CONFIG_WLAGS49_H2)       += wlags49_h2/
index b4a8d5eb64fabc4879bd11e27577c2ed12f5b00a..05ca15a6c9f8b7f919f587e35e856d6de1310c2a 100644 (file)
@@ -267,6 +267,10 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
        if (atomic_read(&bat_priv->log_level) == log_level_tmp)
                return count;
 
+       bat_info(net_dev, "Changing log level from: %i to: %li\n",
+                atomic_read(&bat_priv->log_level),
+                log_level_tmp);
+
        atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
        return count;
 }
index 92c216a568856b4592e6a38427163bcec386aab3..6e973a79aa25b6fec509639687fc4e196a568397 100644 (file)
@@ -30,7 +30,6 @@
 #include "hash.h"
 
 #include <linux/if_arp.h>
-#include <linux/netfilter_bridge.h>
 
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 
@@ -129,6 +128,9 @@ static bool hardif_is_iface_up(struct batman_if *batman_if)
 
 static void update_mac_addresses(struct batman_if *batman_if)
 {
+       if (!batman_if || !batman_if->packet_buff)
+               return;
+
        addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
 
        memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
@@ -194,8 +196,6 @@ static void hardif_activate_interface(struct net_device *net_dev,
        if (batman_if->if_status != IF_INACTIVE)
                return;
 
-       dev_hold(batman_if->net_dev);
-
        update_mac_addresses(batman_if);
        batman_if->if_status = IF_TO_BE_ACTIVATED;
 
@@ -222,8 +222,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev,
           (batman_if->if_status != IF_TO_BE_ACTIVATED))
                return;
 
-       dev_put(batman_if->net_dev);
-
        batman_if->if_status = IF_INACTIVE;
 
        bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
@@ -318,11 +316,13 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
        if (ret != 1)
                goto out;
 
+       dev_hold(net_dev);
+
        batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
        if (!batman_if) {
                pr_err("Can't add interface (%s): out of memory\n",
                       net_dev->name);
-               goto out;
+               goto release_dev;
        }
 
        batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
@@ -336,6 +336,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
        batman_if->if_num = -1;
        batman_if->net_dev = net_dev;
        batman_if->if_status = IF_NOT_IN_USE;
+       batman_if->packet_buff = NULL;
        INIT_LIST_HEAD(&batman_if->list);
 
        check_known_mac_addr(batman_if->net_dev->dev_addr);
@@ -346,6 +347,8 @@ free_dev:
        kfree(batman_if->dev);
 free_if:
        kfree(batman_if);
+release_dev:
+       dev_put(net_dev);
 out:
        return NULL;
 }
@@ -374,6 +377,7 @@ static void hardif_remove_interface(struct batman_if *batman_if)
        batman_if->if_status = IF_TO_BE_REMOVED;
        list_del_rcu(&batman_if->list);
        sysfs_del_hardif(&batman_if->hardif_obj);
+       dev_put(batman_if->net_dev);
        call_rcu(&batman_if->rcu, hardif_free_interface);
 }
 
@@ -393,15 +397,13 @@ static int hard_if_event(struct notifier_block *this,
        /* FIXME: each batman_if will be attached to a softif */
        struct bat_priv *bat_priv = netdev_priv(soft_device);
 
-       if (!batman_if)
-               batman_if = hardif_add_interface(net_dev);
+       if (!batman_if && event == NETDEV_REGISTER)
+                       batman_if = hardif_add_interface(net_dev);
 
        if (!batman_if)
                goto out;
 
        switch (event) {
-       case NETDEV_REGISTER:
-               break;
        case NETDEV_UP:
                hardif_activate_interface(soft_device, bat_priv, batman_if);
                break;
@@ -428,11 +430,6 @@ out:
        return NOTIFY_DONE;
 }
 
-static int batman_skb_recv_finish(struct sk_buff *skb)
-{
-       return NF_ACCEPT;
-}
-
 /* receive a packet with the batman ethertype coming on a hard
  * interface */
 int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
@@ -442,8 +439,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
        struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct batman_packet *batman_packet;
        struct batman_if *batman_if;
-       struct net_device_stats *stats;
-       struct rtnl_link_stats64 temp;
        int ret;
 
        skb = skb_share_check(skb, GFP_ATOMIC);
@@ -455,13 +450,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
        if (atomic_read(&module_state) != MODULE_ACTIVE)
                goto err_free;
 
-       /* if netfilter/ebtables wants to block incoming batman
-        * packets then give them a chance to do so here */
-       ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL,
-                     batman_skb_recv_finish);
-       if (ret != 1)
-               goto err_out;
-
        /* packet should hold at least type and version */
        if (unlikely(skb_headlen(skb) < 2))
                goto err_free;
@@ -479,12 +467,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
        if (batman_if->if_status != IF_ACTIVE)
                goto err_free;
 
-       stats = (struct net_device_stats *)dev_get_stats(skb->dev, &temp);
-       if (stats) {
-               stats->rx_packets++;
-               stats->rx_bytes += skb->len;
-       }
-
        batman_packet = (struct batman_packet *)skb->data;
 
        if (batman_packet->version != COMPAT_VERSION) {
index fc3d32c127292ab5dc717b59e169d6e19f52f10b..3ae7dd2d2d4d9fbea848b7b57a41a4e1d78b2b18 100644 (file)
@@ -67,6 +67,7 @@ static int bat_socket_open(struct inode *inode, struct file *file)
        INIT_LIST_HEAD(&socket_client->queue_list);
        socket_client->queue_len = 0;
        socket_client->index = i;
+       socket_client->bat_priv = inode->i_private;
        spin_lock_init(&socket_client->lock);
        init_waitqueue_head(&socket_client->queue_wait);
 
@@ -151,9 +152,8 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
 static ssize_t bat_socket_write(struct file *file, const char __user *buff,
                                size_t len, loff_t *off)
 {
-       /* FIXME: each orig_node->batman_if will be attached to a softif */
-       struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct socket_client *socket_client = file->private_data;
+       struct bat_priv *bat_priv = socket_client->bat_priv;
        struct icmp_packet_rr icmp_packet;
        struct orig_node *orig_node;
        struct batman_if *batman_if;
@@ -168,6 +168,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
                return -EINVAL;
        }
 
+       if (!bat_priv->primary_if)
+               return -EFAULT;
+
        if (len >= sizeof(struct icmp_packet_rr))
                packet_len = sizeof(struct icmp_packet_rr);
 
@@ -223,7 +226,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
        if (batman_if->if_status != IF_ACTIVE)
                goto dst_unreach;
 
-       memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN);
+       memcpy(icmp_packet.orig,
+              bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
 
        if (packet_len == sizeof(struct icmp_packet_rr))
                memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN);
@@ -271,7 +275,7 @@ int bat_socket_setup(struct bat_priv *bat_priv)
                goto err;
 
        d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
-                               bat_priv->debug_dir, NULL, &fops);
+                               bat_priv->debug_dir, bat_priv, &fops);
        if (d)
                goto err;
 
index 2686019fe4e133f60e445cf2f2b5eddcf211cd73..ef7c20ae7979af145b0dcf592bf1c226acdf9f71 100644 (file)
@@ -250,10 +250,13 @@ int choose_orig(void *data, int32_t size)
 int is_my_mac(uint8_t *addr)
 {
        struct batman_if *batman_if;
+
        rcu_read_lock();
        list_for_each_entry_rcu(batman_if, &if_list, list) {
-               if ((batman_if->net_dev) &&
-                   (compare_orig(batman_if->net_dev->dev_addr, addr))) {
+               if (batman_if->if_status != IF_ACTIVE)
+                       continue;
+
+               if (compare_orig(batman_if->net_dev->dev_addr, addr)) {
                        rcu_read_unlock();
                        return 1;
                }
index 28bb627ffa135ceb9022621d33362e8611887b46..de5a8c1a810462da1d2f7e8779afd582eb779784 100644 (file)
@@ -391,11 +391,12 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
 int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
 {
        struct orig_node *orig_node;
+       unsigned long flags;
        HASHIT(hashit);
 
        /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
         * if_num */
-       spin_lock(&orig_hash_lock);
+       spin_lock_irqsave(&orig_hash_lock, flags);
 
        while (hash_iterate(orig_hash, &hashit)) {
                orig_node = hashit.bucket->data;
@@ -404,11 +405,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
                        goto err;
        }
 
-       spin_unlock(&orig_hash_lock);
+       spin_unlock_irqrestore(&orig_hash_lock, flags);
        return 0;
 
 err:
-       spin_unlock(&orig_hash_lock);
+       spin_unlock_irqrestore(&orig_hash_lock, flags);
        return -ENOMEM;
 }
 
@@ -468,12 +469,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
 {
        struct batman_if *batman_if_tmp;
        struct orig_node *orig_node;
+       unsigned long flags;
        HASHIT(hashit);
        int ret;
 
        /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
         * if_num */
-       spin_lock(&orig_hash_lock);
+       spin_lock_irqsave(&orig_hash_lock, flags);
 
        while (hash_iterate(orig_hash, &hashit)) {
                orig_node = hashit.bucket->data;
@@ -500,10 +502,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
        rcu_read_unlock();
 
        batman_if->if_num = -1;
-       spin_unlock(&orig_hash_lock);
+       spin_unlock_irqrestore(&orig_hash_lock, flags);
        return 0;
 
 err:
-       spin_unlock(&orig_hash_lock);
+       spin_unlock_irqrestore(&orig_hash_lock, flags);
        return -ENOMEM;
 }
index 066cc9149bf1be3c38cb1984ea39c8a3201f1a68..032195e6de94a5eed40831c116246628fb2458f9 100644 (file)
@@ -783,6 +783,8 @@ int recv_bat_packet(struct sk_buff *skb,
 
 static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
 {
+       /* FIXME: each batman_if will be attached to a softif */
+       struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct orig_node *orig_node;
        struct icmp_packet_rr *icmp_packet;
        struct ethhdr *ethhdr;
@@ -801,6 +803,9 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
                return NET_RX_DROP;
        }
 
+       if (!bat_priv->primary_if)
+               return NET_RX_DROP;
+
        /* answer echo request (ping) */
        /* get routing information */
        spin_lock_irqsave(&orig_hash_lock, flags);
@@ -830,7 +835,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
                }
 
                memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-               memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+               memcpy(icmp_packet->orig,
+                      bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
                icmp_packet->msg_type = ECHO_REPLY;
                icmp_packet->ttl = TTL;
 
@@ -845,6 +851,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
 
 static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
 {
+       /* FIXME: each batman_if will be attached to a softif */
+       struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct orig_node *orig_node;
        struct icmp_packet *icmp_packet;
        struct ethhdr *ethhdr;
@@ -865,6 +873,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
                return NET_RX_DROP;
        }
 
+       if (!bat_priv->primary_if)
+               return NET_RX_DROP;
+
        /* get routing information */
        spin_lock_irqsave(&orig_hash_lock, flags);
        orig_node = ((struct orig_node *)
@@ -892,7 +903,8 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
                }
 
                memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-               memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+               memcpy(icmp_packet->orig,
+                      bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
                icmp_packet->msg_type = TTL_EXCEEDED;
                icmp_packet->ttl = TTL;
 
index 055edee7b4e401be0f9142d222fab9a52631c150..da3c82e47bbd6365788b827f9a1ee2e4a48be226 100644 (file)
@@ -29,7 +29,6 @@
 #include "vis.h"
 #include "aggregation.h"
 
-#include <linux/netfilter_bridge.h>
 
 static void send_outstanding_bcast_packet(struct work_struct *work);
 
@@ -92,12 +91,9 @@ int send_skb_packet(struct sk_buff *skb,
 
        /* dev_queue_xmit() returns a negative result on error.  However on
         * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
-        * (which is > 0). This will not be treated as an error.
-        * Also, if netfilter/ebtables wants to block outgoing batman
-        * packets then giving them a chance to do so here */
+        * (which is > 0). This will not be treated as an error. */
 
-       return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
-                      dev_queue_xmit);
+       return dev_queue_xmit(skb);
 send_skb_err:
        kfree_skb(skb);
        return NET_XMIT_DROP;
index 21d0717afb09ef7d7f4c6d066a6218c3085392bf..9aa9d369c7522cb9c1db35edab0af15e9e39419a 100644 (file)
@@ -126,6 +126,7 @@ struct socket_client {
        unsigned char index;
        spinlock_t lock;
        wait_queue_head_t queue_wait;
+       struct bat_priv *bat_priv;
 };
 
 struct socket_packet {
index 14091313cebbe66c419b73453ccd0b158d89c1da..fecb89e8c66365dd00cd7ed14f9012f064cf3160 100644 (file)
@@ -1922,6 +1922,7 @@ const struct file_operations comedi_fops = {
        .mmap = comedi_mmap,
        .poll = comedi_poll,
        .fasync = comedi_fasync,
+       .llseek = noop_llseek,
 };
 
 struct class *comedi_class;
index f8ede1182ccc5113b657a997b3df20460bf729fa..0345b4caba73c2ae9f093a7e76ceeac6d1ea59ee 100644 (file)
@@ -37,7 +37,6 @@ Status: experimental
 #include <linux/delay.h>
 #include <linux/pci.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -692,10 +691,6 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /* Initialize the pcmcia_device structure */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        cur_dev = link;
 
        das16cs_pcmcia_config(link);
@@ -715,37 +710,12 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
 
 
 static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
                                void *priv_data)
 {
-       if (cfg->index == 0)
+       if (p_dev->config_index == 0)
                return -EINVAL;
 
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               return pcmcia_request_io(p_dev);
-       }
-
-       return 0;
+       return pcmcia_request_io(p_dev);
 }
 
 static void das16cs_pcmcia_config(struct pcmcia_device *link)
@@ -754,6 +724,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
 
+       /* Do we need to allocate an interrupt? */
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -763,25 +736,10 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %u", link->irq);
-       if (link->resource[0])
-               printk(", io %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(", io %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -832,9 +790,7 @@ struct pcmcia_driver das16cs_driver = {
        .resume = das16cs_pcmcia_resume,
        .id_table = das16cs_id_table,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "cb_das16_cs",
-               },
+       .name = "cb_das16_cs",
 };
 
 static int __init init_das16cs_pcmcia_cs(void)
index c6aa52f8dcee3c5f97ea3df1a3f9374cf9a04f04..0b32a2df776829c497274fd8074b3b34e05d726e 100644 (file)
@@ -48,7 +48,6 @@ Command support does not exist, but could be added for this board.
 #include "das08.h"
 
 /* pcmcia includes */
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -115,40 +114,15 @@ static void das08_pcmcia_release(struct pcmcia_device *link);
 static int das08_pcmcia_suspend(struct pcmcia_device *p_dev);
 static int das08_pcmcia_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int das08_pcmcia_attach(struct pcmcia_device *);
 static void das08_pcmcia_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
        struct pcmcia_device *link;
        int stop;
        struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    das08_pcmcia_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int das08_pcmcia_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
@@ -162,16 +136,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /*
-          General socket configuration defaults can go here.  In this
-          client, we assume very little, and rely on the CIS for almost
-          everything.  In most clients, many details (i.e., number, sizes,
-          and attributes of IO windows) are fixed by the nature of the
-          device, and can be hard-wired here.
-        */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        cur_dev = link;
 
        das08_pcmcia_config(link);
@@ -179,15 +143,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)
        return 0;
 }                              /* das08_pcmcia_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void das08_pcmcia_detach(struct pcmcia_device *link)
 {
 
@@ -203,47 +158,13 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
 
 
 static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
                                void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               return pcmcia_request_io(p_dev);
-       }
-       return 0;
-}
-
-
-/*======================================================================
-
-    das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-======================================================================*/
+       return pcmcia_request_io(p_dev);
+}
 
 static void das08_pcmcia_config(struct pcmcia_device *link)
 {
@@ -251,6 +172,8 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "das08_pcmcia_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -260,25 +183,10 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %u", link->irq);
-       if (link->resource[0])
-               printk(", io %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -286,32 +194,12 @@ failed:
 
 }                              /* das08_pcmcia_config */
 
-/*======================================================================
-
-    After a card is removed, das08_pcmcia_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void das08_pcmcia_release(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "das08_pcmcia_release\n");
        pcmcia_disable_device(link);
 }                              /* das08_pcmcia_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int das08_pcmcia_suspend(struct pcmcia_device *link)
 {
        struct local_info_t *local = link->priv;
@@ -349,9 +237,7 @@ struct pcmcia_driver das08_cs_driver = {
        .resume = das08_pcmcia_resume,
        .id_table = das08_cs_id_table,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "pcm-das08",
-               },
+       .name = "pcm-das08",
 };
 
 static int __init init_das08_pcmcia_cs(void)
index cc15666e5cc195391d5fd5093dc90f4c30169943..6b7372eed90d639ecb0d475440be01857b1d9114 100644 (file)
@@ -47,7 +47,6 @@ IRQ is assigned but not used.
 
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -435,47 +434,20 @@ static int dio700_detach(struct comedi_device *dev)
        return 0;
 };
 
-/* PCMCIA crap -- watch your words, please! */
-
 static void dio700_config(struct pcmcia_device *link);
 static void dio700_release(struct pcmcia_device *link);
 static int dio700_cs_suspend(struct pcmcia_device *p_dev);
 static int dio700_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int dio700_cs_attach(struct pcmcia_device *);
 static void dio700_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
        struct pcmcia_device *link;
        int stop;
        struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    dio700_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int dio700_cs_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
@@ -491,16 +463,6 @@ static int dio700_cs_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /*
-          General socket configuration defaults can go here.  In this
-          client, we assume very little, and rely on the CIS for almost
-          everything.  In most clients, many details (i.e., number, sizes,
-          and attributes of IO windows) are fixed by the nature of the
-          device, and can be hard-wired here.
-        */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        pcmcia_cur_dev = link;
 
        dio700_config(link);
@@ -508,15 +470,6 @@ static int dio700_cs_attach(struct pcmcia_device *link)
        return 0;
 }                              /* dio700_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void dio700_cs_detach(struct pcmcia_device *link)
 {
 
@@ -532,65 +485,26 @@ static void dio700_cs_detach(struct pcmcia_device *link)
 
 }                              /* dio700_cs_detach */
 
-/*======================================================================
-
-    dio700_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
                                void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(p_dev) != 0)
-                       return -ENODEV;
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* If we got this far, we're cool! */
-       return 0;
+       return pcmcia_request_io(p_dev);
 }
 
 static void dio700_config(struct pcmcia_device *link)
 {
-       win_req_t req;
        int ret;
 
        printk(KERN_INFO "ni_daq_700:  cs-config\n");
 
        dev_dbg(&link->dev, "dio700_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+               CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -600,25 +514,10 @@ static void dio700_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret != 0)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %d", link->irq);
-       if (link->resource[0])
-               printk(", io %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -634,18 +533,6 @@ static void dio700_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }                              /* dio700_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int dio700_cs_suspend(struct pcmcia_device *link)
 {
        struct local_info_t *local = link->priv;
@@ -685,9 +572,7 @@ struct pcmcia_driver dio700_cs_driver = {
        .resume = dio700_cs_resume,
        .id_table = dio700_cs_ids,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "ni_daq_700",
-               },
+       .name = "ni_daq_700",
 };
 
 static int __init init_dio700_cs(void)
index 773ae2044e0ee8a52435f14879563dd37597d6f4..c9c28584db67dbc910c0c1882a2e071d6198c2e4 100644 (file)
@@ -48,7 +48,6 @@ the PCMCIA interface.
 
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -187,47 +186,20 @@ static int dio24_detach(struct comedi_device *dev)
        return 0;
 };
 
-/* PCMCIA crap -- watch your words! */
-
 static void dio24_config(struct pcmcia_device *link);
 static void dio24_release(struct pcmcia_device *link);
 static int dio24_cs_suspend(struct pcmcia_device *p_dev);
 static int dio24_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int dio24_cs_attach(struct pcmcia_device *);
 static void dio24_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
        struct pcmcia_device *link;
        int stop;
        struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    dio24_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int dio24_cs_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
@@ -243,16 +215,6 @@ static int dio24_cs_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /*
-          General socket configuration defaults can go here.  In this
-          client, we assume very little, and rely on the CIS for almost
-          everything.  In most clients, many details (i.e., number, sizes,
-          and attributes of IO windows) are fixed by the nature of the
-          device, and can be hard-wired here.
-        */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        pcmcia_cur_dev = link;
 
        dio24_config(link);
@@ -260,15 +222,6 @@ static int dio24_cs_attach(struct pcmcia_device *link)
        return 0;
 }                              /* dio24_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void dio24_cs_detach(struct pcmcia_device *link)
 {
 
@@ -284,54 +237,13 @@ static void dio24_cs_detach(struct pcmcia_device *link)
 
 }                              /* dio24_cs_detach */
 
-/*======================================================================
-
-    dio24_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
                                void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(p_dev) != 0)
-                       return -ENODEV;
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* If we got this far, we're cool! */
-       return 0;
+       return pcmcia_request_io(p_dev);
 }
 
 static void dio24_config(struct pcmcia_device *link)
@@ -342,6 +254,9 @@ static void dio24_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "dio24_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+               CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -351,25 +266,10 @@ static void dio24_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %d", link->irq);
-       if (link->resource[0])
-               printk(" & %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -385,18 +285,6 @@ static void dio24_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }                              /* dio24_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int dio24_cs_suspend(struct pcmcia_device *link)
 {
        struct local_info_t *local = link->priv;
@@ -435,9 +323,7 @@ struct pcmcia_driver dio24_cs_driver = {
        .resume = dio24_cs_resume,
        .id_table = dio24_cs_ids,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "ni_daq_dio24",
-               },
+       .name = "ni_daq_dio24",
 };
 
 static int __init init_dio24_cs(void)
index 68c4ecbd93ae83728c422f00da13e273a13d63a1..6facbc8bf77660093b7b504cb65eb08c737589e1 100644 (file)
@@ -71,7 +71,6 @@ NI manuals:
 #include "comedi_fc.h"
 #include "ni_labpc.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -153,59 +152,20 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        return labpc_common_attach(dev, iobase, irq, 0);
 }
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the dummy
-   event handler.
-
-   Kernel version 2.6.16 upwards uses suspend() and resume() functions
-   instead of an event() function.
-*/
-
 static void labpc_config(struct pcmcia_device *link);
 static void labpc_release(struct pcmcia_device *link);
 static int labpc_cs_suspend(struct pcmcia_device *p_dev);
 static int labpc_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int labpc_cs_attach(struct pcmcia_device *);
 static void labpc_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
        struct pcmcia_device *link;
        int stop;
        struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    labpc_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int labpc_cs_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
@@ -219,16 +179,6 @@ static int labpc_cs_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /*
-          General socket configuration defaults can go here.  In this
-          client, we assume very little, and rely on the CIS for almost
-          everything.  In most clients, many details (i.e., number, sizes,
-          and attributes of IO windows) are fixed by the nature of the
-          device, and can be hard-wired here.
-        */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        pcmcia_cur_dev = link;
 
        labpc_config(link);
@@ -236,15 +186,6 @@ static int labpc_cs_attach(struct pcmcia_device *link)
        return 0;
 }                              /* labpc_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void labpc_cs_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "labpc_cs_detach\n");
@@ -263,54 +204,13 @@ static void labpc_cs_detach(struct pcmcia_device *link)
 
 }                              /* labpc_cs_detach */
 
-/*======================================================================
-
-    labpc_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
 static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
                                void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Does this card need audio output? */
-       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-               p_dev->conf.Status = CCSR_AUDIO_ENA;
-       }
-
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(p_dev) != 0)
-                       return -ENODEV;
-       }
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* If we got this far, we're cool! */
-       return 0;
+       return pcmcia_request_io(p_dev);
 }
 
 
@@ -320,6 +220,9 @@ static void labpc_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "labpc_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
+               CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -329,25 +232,10 @@ static void labpc_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %d", link->irq);
-       if (link->resource[0])
-               printk(" & %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -362,18 +250,6 @@ static void labpc_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }                              /* labpc_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int labpc_cs_suspend(struct pcmcia_device *link)
 {
        struct local_info_t *local = link->priv;
@@ -391,8 +267,6 @@ static int labpc_cs_resume(struct pcmcia_device *link)
        return 0;
 }                              /* labpc_cs_resume */
 
-/*====================================================================*/
-
 static struct pcmcia_device_id labpc_cs_ids[] = {
        /* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103),        /* daqcard-1200 */
@@ -411,9 +285,7 @@ struct pcmcia_driver labpc_cs_driver = {
        .resume = labpc_cs_resume,
        .id_table = labpc_cs_ids,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "daqcard-1200",
-               },
+       .name = "daqcard-1200",
 };
 
 static int __init init_labpc_cs(void)
index 1f2426352eb57d82cc0c18ba98d738d224fe31cf..49563273f605c659b05467f25d836d912291b796 100644 (file)
@@ -48,7 +48,6 @@ See the notes in the ni_atmio.o driver.
 #include "ni_stc.h"
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -263,11 +262,6 @@ static struct pcmcia_device *cur_dev = NULL;
 
 static int cs_attach(struct pcmcia_device *link)
 {
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-       link->resource[0]->end = 16;
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        cur_dev = link;
 
        mio_cs_config(link);
@@ -301,16 +295,12 @@ static int mio_cs_resume(struct pcmcia_device *link)
 }
 
 
-static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
        int base, ret;
 
-       p_dev->resource[0]->end = cfg->io.win[0].len;
-       p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
        for (base = 0x000; base < 0x400; base += 0x20) {
                p_dev->resource[0]->start = base;
@@ -327,6 +317,7 @@ static void mio_cs_config(struct pcmcia_device *link)
        int ret;
 
        DPRINTK("mio_cs_config(link=%p)\n", link);
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
        ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
        if (ret) {
@@ -337,7 +328,7 @@ static void mio_cs_config(struct pcmcia_device *link)
        if (!link->irq)
                dev_info(&link->dev, "no IRQ available\n");
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
 }
 
 static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -446,9 +437,7 @@ struct pcmcia_driver ni_mio_cs_driver = {
        .resume = &mio_cs_resume,
        .id_table = ni_mio_cs_ids,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "ni_mio_cs",
-               },
+       .name = "ni_mio_cs",
 };
 
 int init_module(void)
index bf489d7f49909ce75bc9e9b2c3990b1b840218f6..ebba9bb47777cfba6edbe6856ee88840967589b7 100644 (file)
@@ -50,7 +50,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -969,43 +968,14 @@ static int daqp_detach(struct comedi_device *dev)
 
 ======================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.
-
-   Kernel version 2.6.16 upwards uses suspend() and resume() functions
-   instead of an event() function.
-*/
-
 static void daqp_cs_config(struct pcmcia_device *link);
 static void daqp_cs_release(struct pcmcia_device *link);
 static int daqp_cs_suspend(struct pcmcia_device *p_dev);
 static int daqp_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int daqp_cs_attach(struct pcmcia_device *);
 static void daqp_cs_detach(struct pcmcia_device *);
 
-/*======================================================================
-
-    daqp_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link structure is initialized, but we don't actually
-    configure the card at this point -- we wait until we receive a
-    card insertion event.
-
-======================================================================*/
-
 static int daqp_cs_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
@@ -1031,30 +1001,11 @@ static int daqp_cs_attach(struct pcmcia_device *link)
        local->link = link;
        link->priv = local;
 
-       /*
-          General socket configuration defaults can go here.  In this
-          client, we assume very little, and rely on the CIS for almost
-          everything.  In most clients, many details (i.e., number, sizes,
-          and attributes of IO windows) are fixed by the nature of the
-          device, and can be hard-wired here.
-        */
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        daqp_cs_config(link);
 
        return 0;
 }                              /* daqp_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void daqp_cs_detach(struct pcmcia_device *link)
 {
        struct local_info_t *dev = link->priv;
@@ -1070,45 +1021,11 @@ static void daqp_cs_detach(struct pcmcia_device *link)
 
 }                              /* daqp_cs_detach */
 
-/*======================================================================
-
-    daqp_cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    device available to the system.
-
-======================================================================*/
-
-
-static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
-                               cistpl_cftable_entry_t *cfg,
-                               cistpl_cftable_entry_t *dflt,
-                               unsigned int vcc,
-                               void *priv_data)
+static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
+       if (p_dev->config_index == 0)
+               return -EINVAL;
 
-       /* Do we need to allocate an interrupt? */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-               p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-               p_dev->resource[0]->flags |=
-                       pcmcia_io_cfg_data_width(io->flags);
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               if (io->nwin > 1) {
-                       p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-       }
-
-       /* This reserves IO space but doesn't actually enable it */
        return pcmcia_request_io(p_dev);
 }
 
@@ -1118,6 +1035,8 @@ static void daqp_cs_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "daqp_cs_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
        ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL);
        if (ret) {
                dev_warn(&link->dev, "no configuration found\n");
@@ -1128,25 +1047,10 @@ static void daqp_cs_config(struct pcmcia_device *link)
        if (ret)
                goto failed;
 
-       /*
-          This actually configures the PCMCIA socket -- setting up
-          the I/O windows and the interrupt mapping, and putting the
-          card and host interface into "Memory and IO" mode.
-        */
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       /* Finally, report what we've done */
-       dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-       if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               printk(", irq %u", link->irq);
-       if (link->resource[0])
-               printk(" & %pR", link->resource[0]);
-       if (link->resource[1])
-               printk(" & %pR", link->resource[1]);
-       printk("\n");
-
        return;
 
 failed:
@@ -1161,18 +1065,6 @@ static void daqp_cs_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }                              /* daqp_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int daqp_cs_suspend(struct pcmcia_device *link)
 {
        struct local_info_t *local = link->priv;
@@ -1212,9 +1104,7 @@ static struct pcmcia_driver daqp_cs_driver = {
        .resume = daqp_cs_resume,
        .id_table = daqp_cs_id_table,
        .owner = THIS_MODULE,
-       .drv = {
-               .name = "quatech_daqp_cs",
-               },
+       .name = "quatech_daqp_cs",
 };
 
 int __init init_module(void)
index fbb80f09a3d9213f85b8091c965a2c2e5642886d..af258991fe7fc8f653ecc5d862adb8fb59161257 100644 (file)
@@ -351,6 +351,7 @@ static const struct file_operations chd_dec_fops = {
        .unlocked_ioctl = chd_dec_ioctl,
        .open    = chd_dec_open,
        .release = chd_dec_close,
+       .llseek = noop_llseek,
 };
 
 static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
index df7756a95fadee7c8168ca1b1f72a9f11dae6e2c..813cb355ac01645069461b022b165f79054b3ab6 100644 (file)
@@ -1,6 +1,7 @@
 config VIDEO_CX25821
        tristate "Conexant cx25821 support"
        depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+       depends on BKL # please fix
        select I2C_ALGOBIT
        select VIDEO_BTCX
        select VIDEO_TVEEPROM
index 81bd71fd816ee69a56d928b9122dc50fa34fa129..de4ab61efd4b72b75f62bef0fb3259a491a7f65f 100644 (file)
@@ -1941,6 +1941,7 @@ static const struct file_operations msm_fops_config = {
        .open = msm_open,
        .unlocked_ioctl = msm_ioctl_config,
        .release = msm_release_config,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_control = {
@@ -1948,6 +1949,7 @@ static const struct file_operations msm_fops_control = {
        .open = msm_open_control,
        .unlocked_ioctl = msm_ioctl_control,
        .release = msm_release_control,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_frame = {
@@ -1956,6 +1958,7 @@ static const struct file_operations msm_fops_frame = {
        .unlocked_ioctl = msm_ioctl_frame,
        .release = msm_release_frame,
        .poll = msm_poll_frame,
+       .llseek = no_llseek,
 };
 
 static int msm_setup_cdev(struct msm_device *msm,
index 7d6bbadd7fc72164d3d879dd3a4a147b614287fe..3640d1f2376d62cf4c7d57802675a7a27c8f40fd 100644 (file)
@@ -180,6 +180,7 @@ const struct file_operations pmem_fops = {
        .mmap = pmem_mmap,
        .open = pmem_open,
        .unlocked_ioctl = pmem_ioctl,
+       .llseek = noop_llseek,
 };
 
 static int get_id(struct file *file)
@@ -1204,6 +1205,7 @@ static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
 static struct file_operations debug_fops = {
        .read = debug_read,
        .open = debug_open,
+       .llseek = default_llseek,
 };
 #endif
 
index 8197765aae1e8d8b173ff120473e3f9eda421385..28a6f8da94777c43440089a886e979775ffd958c 100644 (file)
@@ -582,6 +582,7 @@ static struct file_operations adsp_fops = {
        .open = adsp_open,
        .unlocked_ioctl = adsp_ioctl,
        .release = adsp_release,
+       .llseek = no_llseek,
 };
 
 static void adsp_create(struct adsp_device *adev, const char *name,
index a373f3522384aba567ba33213aad568ee55d8a5a..45f4c78ab6e777d855761e7881382ffb887b1826 100644 (file)
@@ -1030,6 +1030,7 @@ static struct file_operations audio_aac_fops = {
        .read = audio_read,
        .write = audio_write,
        .unlocked_ioctl = audio_ioctl,
+       .llseek = noop_llseek,
 };
 
 struct miscdevice audio_aac_misc = {
index 07b79d5836e5e984ac834f77695b7ee7596c80ce..402bbc13281a566e5915e85ff56d95ea1d9d5542 100644 (file)
@@ -841,6 +841,7 @@ static struct file_operations audio_amrnb_fops = {
        .read = audamrnb_read,
        .write = audamrnb_write,
        .unlocked_ioctl = audamrnb_ioctl,
+       .llseek = noop_llseek,
 };
 
 struct miscdevice audio_amrnb_misc = {
index ad989ee87690a13dd53ed8f05f2c65c6bd868d2d..24a8926473702bc4b2919c93618eae8751ba5d54 100644 (file)
@@ -813,6 +813,7 @@ static struct file_operations audio_evrc_fops = {
        .read = audevrc_read,
        .write = audevrc_write,
        .unlocked_ioctl = audevrc_ioctl,
+       .llseek = noop_llseek,
 };
 
 struct miscdevice audio_evrc_misc = {
index 6ae48e72d1459cdb938a062bed40a9ed5b05c6a3..b51fa096074e3949ed2fef6104c8b9cd217149d5 100644 (file)
@@ -921,12 +921,14 @@ static struct file_operations audio_fops = {
        .read           = audio_in_read,
        .write          = audio_in_write,
        .unlocked_ioctl = audio_in_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct file_operations audpre_fops = {
        .owner          = THIS_MODULE,
        .open           = audpre_open,
        .unlocked_ioctl = audpre_ioctl,
+       .llseek         = noop_llseek,
 };
 
 struct miscdevice audio_in_misc = {
index 530e1f35eed35946a799800ec28386a691b0ef4a..409a19ce6039ecc2bcc4e755c01661da41014c04 100644 (file)
@@ -948,6 +948,7 @@ static struct file_operations audio_mp3_fops = {
        .read           = audio_read,
        .write          = audio_write,
        .unlocked_ioctl = audio_ioctl,
+       .llseek         = noop_llseek,
 };
 
 struct miscdevice audio_mp3_misc = {
index 76d7fa5667d549dcfab4f8d921dee15a52a5ae12..d20e895415676146cb2a1802114968074bf5ab85 100644 (file)
@@ -807,12 +807,14 @@ static struct file_operations audio_fops = {
        .read           = audio_read,
        .write          = audio_write,
        .unlocked_ioctl = audio_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct file_operations audpp_fops = {
        .owner          = THIS_MODULE,
        .open           = audpp_open,
        .unlocked_ioctl = audpp_ioctl,
+       .llseek         = noop_llseek,
 };
 
 struct miscdevice audio_misc = {
index effa96f34fdceddfe020fce8b656b4e4faa6d23e..911bab416b853ca43f27267de82e63742c51c6ac 100644 (file)
@@ -824,6 +824,7 @@ static struct file_operations audio_qcelp_fops = {
        .read = audqcelp_read,
        .write = audqcelp_write,
        .unlocked_ioctl = audqcelp_ioctl,
+       .llseek = noop_llseek,
 };
 
 struct miscdevice audio_qcelp_misc = {
index 922ce670a32a40276835c98fff78dfcba0ac123b..e5ab86b9dd7c80b246f3ecb9bf3048ddfaaade5b 100644 (file)
@@ -123,6 +123,7 @@ static int ev_log_open(struct inode *inode, struct file *file)
 static const struct file_operations ev_log_ops = {
        .read = ev_log_read,
        .open = ev_log_open,
+       .llseek = default_llseek,
 };
 
 static int ev_log_init(struct ev_log *log)
index 037d7ffb7e67030519bd92283cdb09b44893cada..e0f2f7bca29e11836586c0836a786c069b6c2768 100644 (file)
@@ -247,6 +247,7 @@ static struct file_operations snd_fops = {
        .open           = snd_open,
        .release        = snd_release,
        .unlocked_ioctl = snd_ioctl,
+       .llseek         = noop_llseek,
 };
 
 struct miscdevice snd_misc = {
index bd96f39f2735b375cdeeda41e62b1ef2fac4b314..9d5fe4ddc30a8154f62f0e3e52451a3f69bc39e1 100644 (file)
@@ -1,6 +1,7 @@
 config EASYCAP
        tristate "EasyCAP USB ID 05e1:0408 support"
        depends on USB && VIDEO_DEV
+       depends on BKL # please fix
 
        ---help---
          This is an integrated audio/video driver for EasyCAP cards with
index 4e52105e6070a9776c051311bd5df2fbb8a425d1..689099b57fd2244ccd6d37798b87a203859013db 100644 (file)
@@ -641,6 +641,7 @@ static const struct file_operations usb_alphatrack_fops = {
        .open = usb_alphatrack_open,
        .release = usb_alphatrack_release,
        .poll = usb_alphatrack_poll,
+       .llseek = no_llseek,
 };
 
 /*
index eed74f0fe0b634c9d2f8cea5a6ad9df5ce41eed8..3d12c1737edce5e3d5c9e0971bf988cab6063c9e 100644 (file)
@@ -767,6 +767,7 @@ static const struct file_operations usb_tranzport_fops = {
        .open = usb_tranzport_open,
        .release = usb_tranzport_release,
        .poll = usb_tranzport_poll,
+       .llseek = no_llseek,
 };
 
 /*
index e47f683a323e0fb1d2d1a21e45557605eabf6603..75fa46805527c94313b20a89bb9ce4b5c781be58 100644 (file)
@@ -1,6 +1,7 @@
 config VIDEO_GO7007
        tristate "WIS GO7007 MPEG encoder support"
        depends on VIDEO_DEV && PCI && I2C && INPUT
+       depends on BKL # please fix
        depends on SND
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
index ff1d24720f11cf68f30e4c7aa8e5f2c108a1d304..8284297b30e9bbb4951ae71c53be5d5565677155 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -124,6 +124,7 @@ struct blkvsc_driver_context {
 };
 
 /* Static decl */
+static DEFINE_MUTEX(blkvsc_mutex);
 static int blkvsc_probe(struct device *dev);
 static int blkvsc_remove(struct device *device);
 static void blkvsc_shutdown(struct device *device);
@@ -1309,7 +1310,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode)
        DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
                   blkdev->gd->disk_name);
 
-       lock_kernel();
+       mutex_lock(&blkvsc_mutex);
        spin_lock(&blkdev->lock);
 
        if (!blkdev->users && blkdev->device_type == DVD_TYPE) {
@@ -1321,7 +1322,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode)
        blkdev->users++;
 
        spin_unlock(&blkdev->lock);
-       unlock_kernel();
+       mutex_unlock(&blkvsc_mutex);
        return 0;
 }
 
@@ -1332,7 +1333,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode)
        DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
                   blkdev->gd->disk_name);
 
-       lock_kernel();
+       mutex_lock(&blkvsc_mutex);
        spin_lock(&blkdev->lock);
        if (blkdev->users == 1) {
                spin_unlock(&blkdev->lock);
@@ -1343,7 +1344,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode)
        blkdev->users--;
 
        spin_unlock(&blkdev->lock);
-       unlock_kernel();
+       mutex_unlock(&blkvsc_mutex);
        return 0;
 }
 
index 56e11575c97763f1747a35ae67db81b49cdd6325..64a01147ecaeffc17863bd0002df415da56da8f2 100644 (file)
@@ -327,6 +327,9 @@ static const struct net_device_ops device_ops = {
        .ndo_stop =                     netvsc_close,
        .ndo_start_xmit =               netvsc_start_xmit,
        .ndo_set_multicast_list =       netvsc_set_multicast_list,
+       .ndo_change_mtu =               eth_change_mtu,
+       .ndo_validate_addr =            eth_validate_addr,
+       .ndo_set_mac_address =          eth_mac_addr,
 };
 
 static int netvsc_probe(struct device *device)
index 17bc7626f70a71d991aa2bdc9c50a960657e4f90..d78c569ac94a2aa7ae4ba6b2325dbf6d2b93c45c 100644 (file)
@@ -193,8 +193,7 @@ Description:
 static inline u64
 GetRingBufferIndices(struct hv_ring_buffer_info *RingInfo)
 {
-       return ((u64)RingInfo->RingBuffer->WriteIndex << 32)
-       || RingInfo->RingBuffer->ReadIndex;
+       return (u64)RingInfo->RingBuffer->WriteIndex << 32;
 }
 
 
index 0063bde9a4b23ac22bbaad19d1912518a855c008..8505a1c5f9ee6bab72259539fa0d1c845fbba1c9 100644 (file)
 #include "vmbus_api.h"
 
 /* Defines */
-#define STORVSC_RING_BUFFER_SIZE                       (10*PAGE_SIZE)
+#define STORVSC_RING_BUFFER_SIZE                       (20*PAGE_SIZE)
 #define BLKVSC_RING_BUFFER_SIZE                                (20*PAGE_SIZE)
 
-#define STORVSC_MAX_IO_REQUESTS                                64
+#define STORVSC_MAX_IO_REQUESTS                                128
 
 /*
  * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
index 075b61bd492f19918c1ee3027994362b2b6aa900..62882a437aa45abb072fede360ffa3672dc37b9d 100644 (file)
@@ -495,7 +495,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 
                /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
 
-               if (j == 0)
+               if (bounce_addr == 0)
                        bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
 
                while (srclen) {
@@ -556,7 +556,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
                destlen = orig_sgl[i].length;
                /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
 
-               if (j == 0)
+               if (bounce_addr == 0)
                        bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
 
                while (destlen) {
@@ -615,6 +615,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
        unsigned int request_size = 0;
        int i;
        struct scatterlist *sgl;
+       unsigned int sg_count = 0;
 
        DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d "
                   "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction,
@@ -697,6 +698,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
        request->DataBuffer.Length = scsi_bufflen(scmnd);
        if (scsi_sg_count(scmnd)) {
                sgl = (struct scatterlist *)scsi_sglist(scmnd);
+               sg_count = scsi_sg_count(scmnd);
 
                /* check if we need to bounce the sgl */
                if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
@@ -731,15 +733,16 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
                                              scsi_sg_count(scmnd));
 
                        sgl = cmd_request->bounce_sgl;
+                       sg_count = cmd_request->bounce_sgl_count;
                }
 
                request->DataBuffer.Offset = sgl[0].offset;
 
-               for (i = 0; i < scsi_sg_count(scmnd); i++) {
+               for (i = 0; i < sg_count; i++) {
                        DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n",
                                   i, sgl[i].length, sgl[i].offset);
                        request->DataBuffer.PfnArray[i] =
-                                       page_to_pfn(sg_page((&sgl[i])));
+                               page_to_pfn(sg_page((&sgl[i])));
                }
        } else if (scsi_sglist(scmnd)) {
                /* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */
index dd4d87a8bcaf1f101cc40ca4949eaafb1cecc3db..92a212f064bdfcfa319d5e4cfe030317b3684e17 100644 (file)
@@ -349,6 +349,7 @@ static const struct file_operations iio_event_chrdev_fileops = {
        .release = iio_event_chrdev_release,
        .open = iio_event_chrdev_open,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static void iio_event_dev_release(struct device *dev)
index 6ab578e4f5f36c99ffa9c938204dc06c84a40952..1c5f67253b823ba53291764d8e7dd7b757b317bb 100644 (file)
@@ -133,6 +133,7 @@ static const struct file_operations iio_ring_fileops = {
        .release = iio_ring_release,
        .open = iio_ring_open,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 /**
index 66493253042e8ccedfa7be8e21c317f8845c7093..ed5c5fe022c9f6a197e358059962f3d3bfc6b848 100644 (file)
@@ -115,7 +115,8 @@ static const struct file_operations display_fops = {
        .owner          = THIS_MODULE,
        .open           = &display_open,
        .write          = &vfd_write,
-       .release        = &display_close
+       .release        = &display_close,
+       .llseek         = noop_llseek,
 };
 
 /*
index ec11c0e949a059476ff252c6ac7daeff4e75d414..543c5c3bf90715f7fa2a87afee2da18772217183 100644 (file)
@@ -342,6 +342,7 @@ static const struct file_operations lirc_fops = {
        .unlocked_ioctl = lirc_ioctl,
        .open           = lirc_open,
        .release        = lirc_close,
+       .llseek         = noop_llseek,
 };
 
 static int set_use_inc(void *data)
index 73166c3f581fd3ed8b7ef805fd27613212817c43..8f72a84f34ec5ef0d98c330a2fb68d6206206626 100644 (file)
@@ -125,6 +125,7 @@ static const struct file_operations vfd_fops = {
        .write          = &vfd_write,
        .unlocked_ioctl = &vfd_ioctl,
        .release        = &vfd_close,
+       .llseek         = noop_llseek,
 };
 
 /* USB Device ID for Sasem USB Control Board */
index 9456f8e3f9ef37f75b71a1146ea2e1199c851fd0..8da38249261295273dc609535c069dc399157331 100644 (file)
@@ -1058,6 +1058,7 @@ static const struct file_operations lirc_fops = {
        .poll           = lirc_dev_fop_poll,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
+       .llseek         = no_llseek,
 };
 
 static struct lirc_driver driver = {
index eb08fa7138bab4418ba5a4ae8d40022c6eb5e406..2478871bd95efbedd72f7e09b7f6cb451ecf0f0b 100644 (file)
@@ -459,6 +459,7 @@ static const struct file_operations lirc_fops = {
        .unlocked_ioctl = lirc_ioctl,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
+       .llseek         = no_llseek,
 };
 
 static int set_use_inc(void *data)
index a98b3f1f11e00a11293c548b2389ed684714c818..cfcaa8e5b8e619a8a1bfb4baa131c1a0fad49a7e 100644 (file)
@@ -890,6 +890,7 @@ static const struct file_operations memrar_fops = {
        .mmap           = memrar_mmap,
        .open           = memrar_open,
        .release        = memrar_release,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice memrar_miscdev = {
index 638ad6b3589107d6f6f146e64eb6f4011d425597..9493128e5fd2d7a743521781eddcd507622310a2 100644 (file)
@@ -1,6 +1,6 @@
 config OCTEON_ETHERNET
        tristate "Cavium Networks Octeon Ethernet support"
-       depends on CPU_CAVIUM_OCTEON
+       depends on CPU_CAVIUM_OCTEON && NETDEVICES
        select PHYLIB
        select MDIO_OCTEON
        help
index 3221814a856ea3b8dab8befa616ab03f50da0fbf..6885f9a46609e05a549ce5fc4a57662de855b4d4 100644 (file)
@@ -1631,6 +1631,7 @@ static const struct file_operations keypad_fops = {
        .read    = keypad_read,         /* read */
        .open    = keypad_open,         /* open */
        .release = keypad_release,      /* close */
+       .llseek  = default_llseek,
 };
 
 static struct miscdevice keypad_dev = {
index a0fe31de0a6d1299c802062cff4007b971d6a594..ebf9074a90838367fc7dde6aac3cba0fe6a3e131 100644 (file)
@@ -44,6 +44,7 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x07B8, 0x2870)},   /* AboCom */
        {USB_DEVICE(0x07B8, 0x2770)},   /* AboCom */
        {USB_DEVICE(0x0DF6, 0x0039)},   /* Sitecom 2770 */
+       {USB_DEVICE(0x0DF6, 0x003F)},   /* Sitecom 2770 */
        {USB_DEVICE(0x083A, 0x7512)},   /* Arcadyan 2770 */
        {USB_DEVICE(0x0789, 0x0162)},   /* Logitec 2870 */
        {USB_DEVICE(0x0789, 0x0163)},   /* Logitec 2870 */
@@ -95,7 +96,8 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x050d, 0x815c)},
        {USB_DEVICE(0x1482, 0x3C09)},   /* Abocom */
        {USB_DEVICE(0x14B2, 0x3C09)},   /* Alpha */
-       {USB_DEVICE(0x04E8, 0x2018)},   /* samsung */
+       {USB_DEVICE(0x04E8, 0x2018)},   /* samsung linkstick2 */
+       {USB_DEVICE(0x1690, 0x0740)},   /* Askey */
        {USB_DEVICE(0x5A57, 0x0280)},   /* Zinwell */
        {USB_DEVICE(0x5A57, 0x0282)},   /* Zinwell */
        {USB_DEVICE(0x7392, 0x7718)},
@@ -105,21 +107,34 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x1737, 0x0071)},   /* Linksys WUSB600N */
        {USB_DEVICE(0x0411, 0x00e8)},   /* Buffalo WLI-UC-G300N */
        {USB_DEVICE(0x050d, 0x815c)},   /* Belkin F5D8053 */
+       {USB_DEVICE(0x100D, 0x9031)},   /* Motorola 2770 */
 #endif /* RT2870 // */
 #ifdef RT3070
        {USB_DEVICE(0x148F, 0x3070)},   /* Ralink 3070 */
        {USB_DEVICE(0x148F, 0x3071)},   /* Ralink 3071 */
        {USB_DEVICE(0x148F, 0x3072)},   /* Ralink 3072 */
        {USB_DEVICE(0x0DB0, 0x3820)},   /* Ralink 3070 */
+       {USB_DEVICE(0x0DB0, 0x871C)},   /* Ralink 3070 */
+       {USB_DEVICE(0x0DB0, 0x822C)},   /* Ralink 3070 */
+       {USB_DEVICE(0x0DB0, 0x871B)},   /* Ralink 3070 */
+       {USB_DEVICE(0x0DB0, 0x822B)},   /* Ralink 3070 */
        {USB_DEVICE(0x0DF6, 0x003E)},   /* Sitecom 3070 */
        {USB_DEVICE(0x0DF6, 0x0042)},   /* Sitecom 3072 */
+       {USB_DEVICE(0x0DF6, 0x0048)},   /* Sitecom 3070 */
+       {USB_DEVICE(0x0DF6, 0x0047)},   /* Sitecom 3071 */
        {USB_DEVICE(0x14B2, 0x3C12)},   /* AL 3070 */
        {USB_DEVICE(0x18C5, 0x0012)},   /* Corega 3070 */
        {USB_DEVICE(0x083A, 0x7511)},   /* Arcadyan 3070 */
+       {USB_DEVICE(0x083A, 0xA701)},   /* SMC 3070 */
+       {USB_DEVICE(0x083A, 0xA702)},   /* SMC 3072 */
        {USB_DEVICE(0x1740, 0x9703)},   /* EnGenius 3070 */
        {USB_DEVICE(0x1740, 0x9705)},   /* EnGenius 3071 */
        {USB_DEVICE(0x1740, 0x9706)},   /* EnGenius 3072 */
+       {USB_DEVICE(0x1740, 0x9707)},   /* EnGenius 3070 */
+       {USB_DEVICE(0x1740, 0x9708)},   /* EnGenius 3071 */
+       {USB_DEVICE(0x1740, 0x9709)},   /* EnGenius 3072 */
        {USB_DEVICE(0x13D3, 0x3273)},   /* AzureWave 3070 */
+       {USB_DEVICE(0x13D3, 0x3305)},   /* AzureWave 3070*/
        {USB_DEVICE(0x1044, 0x800D)},   /* Gigabyte GN-WB32L 3070 */
        {USB_DEVICE(0x2019, 0xAB25)},   /* Planex Communications, Inc. RT3070 */
        {USB_DEVICE(0x07B8, 0x3070)},   /* AboCom 3070 */
@@ -132,14 +147,36 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x07D1, 0x3C0D)},   /* D-Link 3070 */
        {USB_DEVICE(0x07D1, 0x3C0E)},   /* D-Link 3070 */
        {USB_DEVICE(0x07D1, 0x3C0F)},   /* D-Link 3070 */
+       {USB_DEVICE(0x07D1, 0x3C16)},   /* D-Link 3070 */
+       {USB_DEVICE(0x07D1, 0x3C17)},   /* D-Link 8070 */
        {USB_DEVICE(0x1D4D, 0x000C)},   /* Pegatron Corporation 3070 */
        {USB_DEVICE(0x1D4D, 0x000E)},   /* Pegatron Corporation 3070 */
        {USB_DEVICE(0x5A57, 0x5257)},   /* Zinwell 3070 */
        {USB_DEVICE(0x5A57, 0x0283)},   /* Zinwell 3072 */
        {USB_DEVICE(0x04BB, 0x0945)},   /* I-O DATA 3072 */
+       {USB_DEVICE(0x04BB, 0x0947)},   /* I-O DATA 3070 */
+       {USB_DEVICE(0x04BB, 0x0948)},   /* I-O DATA 3072 */
        {USB_DEVICE(0x203D, 0x1480)},   /* Encore 3070 */
+       {USB_DEVICE(0x20B8, 0x8888)},   /* PARA INDUSTRIAL 3070 */
+       {USB_DEVICE(0x0B05, 0x1784)},   /* Asus 3072 */
+       {USB_DEVICE(0x203D, 0x14A9)},   /* Encore 3070*/
+       {USB_DEVICE(0x0DB0, 0x899A)},   /* MSI 3070*/
+       {USB_DEVICE(0x0DB0, 0x3870)},   /* MSI 3070*/
+       {USB_DEVICE(0x0DB0, 0x870A)},   /* MSI 3070*/
+       {USB_DEVICE(0x0DB0, 0x6899)},   /* MSI 3070 */
+       {USB_DEVICE(0x0DB0, 0x3822)},   /* MSI 3070 */
+       {USB_DEVICE(0x0DB0, 0x3871)},   /* MSI 3070 */
+       {USB_DEVICE(0x0DB0, 0x871A)},   /* MSI 3070 */
+       {USB_DEVICE(0x0DB0, 0x822A)},   /* MSI 3070 */
+       {USB_DEVICE(0x0DB0, 0x3821)},   /* Ralink 3070 */
+       {USB_DEVICE(0x0DB0, 0x821A)},   /* Ralink 3070 */
+       {USB_DEVICE(0x083A, 0xA703)},   /* IO-MAGIC */
+       {USB_DEVICE(0x13D3, 0x3307)},   /* Azurewave */
+       {USB_DEVICE(0x13D3, 0x3321)},   /* Azurewave */
+       {USB_DEVICE(0x07FA, 0x7712)},   /* Edimax */
+       {USB_DEVICE(0x0789, 0x0166)},   /* Edimax */
+       {USB_DEVICE(0x148F, 0x2070)},   /* Edimax */
 #endif /* RT3070 // */
-       {USB_DEVICE(0x0DF6, 0x003F)},   /* Sitecom WL-608 */
        {USB_DEVICE(0x1737, 0x0077)},   /* Linksys WUSB54GC-EU v3 */
        {USB_DEVICE(0x2001, 0x3C09)},   /* D-Link */
        {USB_DEVICE(0x2001, 0x3C0A)},   /* D-Link 3072 */
diff --git a/drivers/staging/sep/Kconfig b/drivers/staging/sep/Kconfig
deleted file mode 100644 (file)
index 0a9c39c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-config DX_SEP
-       tristate "Discretix SEP driver"
-#      depends on MRST
-       depends on RAR_REGISTER && PCI
-       default y
-       help
-         Discretix SEP driver
-
-         If unsure say M. The compiled module will be
-         called sep_driver.ko
diff --git a/drivers/staging/sep/Makefile b/drivers/staging/sep/Makefile
deleted file mode 100644 (file)
index 628d5f9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_DX_SEP) := sep_driver.o
-
diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO
deleted file mode 100644 (file)
index ff0e931..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-Todo's so far (from Alan Cox)
-- Fix firmware loading
-- Get firmware into firmware git tree
-- Review and tidy each algorithm function
-- Check whether it can be plugged into any of the kernel crypto API
-  interfaces
-- Do something about the magic shared memory interface and replace it
-  with something saner (in Linux terms)
diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h
deleted file mode 100644 (file)
index 9200524..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef __SEP_DEV_H__
-#define __SEP_DEV_H__
-
-/*
- *
- *  sep_dev.h - Security Processor Device Structures
- *
- *  Copyright(c) 2009 Intel Corporation. All rights reserved.
- *  Copyright(c) 2009 Discretix. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License 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.
- *
- *  CONTACTS:
- *
- *  Alan Cox           alan@linux.intel.com
- *
- */
-
-struct sep_device {
-       /* pointer to pci dev */
-       struct pci_dev *pdev;
-
-       unsigned long in_use;
-
-       /* address of the shared memory allocated during init for SEP driver
-          (coherent alloc) */
-       void *shared_addr;
-       /* the physical address of the shared area */
-       dma_addr_t shared_bus;
-
-       /* restricted access region (coherent alloc) */
-       dma_addr_t rar_bus;
-       void *rar_addr;
-       /* firmware regions: cache is at rar_addr */
-       unsigned long cache_size;
-
-       /* follows the cache */
-       dma_addr_t resident_bus;
-       unsigned long resident_size;
-       void *resident_addr;
-
-       /* start address of the access to the SEP registers from driver */
-       void __iomem *reg_addr;
-       /* transaction counter that coordinates the transactions between SEP and HOST */
-       unsigned long send_ct;
-       /* counter for the messages from sep */
-       unsigned long reply_ct;
-       /* counter for the number of bytes allocated in the pool for the current
-          transaction */
-       unsigned long data_pool_bytes_allocated;
-
-       /* array of pointers to the pages that represent input data for the synchronic
-          DMA action */
-       struct page **in_page_array;
-
-       /* array of pointers to the pages that represent out data for the synchronic
-          DMA action */
-       struct page **out_page_array;
-
-       /* number of pages in the sep_in_page_array */
-       unsigned long in_num_pages;
-
-       /* number of pages in the sep_out_page_array */
-       unsigned long out_num_pages;
-
-       /* global data for every flow */
-       struct sep_flow_context_t flows[SEP_DRIVER_NUM_FLOWS];
-
-       /* pointer to the workqueue that handles the flow done interrupts */
-       struct workqueue_struct *flow_wq;
-
-};
-
-static struct sep_device *sep_dev;
-
-static inline void sep_write_reg(struct sep_device *dev, int reg, u32 value)
-{
-       void __iomem *addr = dev->reg_addr + reg;
-       writel(value, addr);
-}
-
-static inline u32 sep_read_reg(struct sep_device *dev, int reg)
-{
-       void __iomem *addr = dev->reg_addr + reg;
-       return readl(addr);
-}
-
-/* wait for SRAM write complete(indirect write */
-static inline void sep_wait_sram_write(struct sep_device *dev)
-{
-       u32 reg_val;
-       do
-               reg_val = sep_read_reg(dev, HW_SRAM_DATA_READY_REG_ADDR);
-       while (!(reg_val & 1));
-}
-
-
-#endif
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
deleted file mode 100644 (file)
index ecbde34..0000000
+++ /dev/null
@@ -1,2742 +0,0 @@
-/*
- *
- *  sep_driver.c - Security Processor Driver main group of functions
- *
- *  Copyright(c) 2009 Intel Corporation. All rights reserved.
- *  Copyright(c) 2009 Discretix. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License 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.
- *
- *  CONTACTS:
- *
- *  Mark Allyn         mark.a.allyn@intel.com
- *
- *  CHANGES:
- *
- *  2009.06.26 Initial publish
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/kdev_t.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <asm/ioctl.h>
-#include <linux/ioport.h>
-#include <asm/io.h>
-#include <linux/interrupt.h>
-#include <linux/pagemap.h>
-#include <asm/cacheflush.h>
-#include "sep_driver_hw_defs.h"
-#include "sep_driver_config.h"
-#include "sep_driver_api.h"
-#include "sep_dev.h"
-
-#if SEP_DRIVER_ARM_DEBUG_MODE
-
-#define  CRYS_SEP_ROM_length                  0x4000
-#define  CRYS_SEP_ROM_start_address           0x8000C000UL
-#define  CRYS_SEP_ROM_start_address_offset    0xC000UL
-#define  SEP_ROM_BANK_register                0x80008420UL
-#define  SEP_ROM_BANK_register_offset         0x8420UL
-#define SEP_RAR_IO_MEM_REGION_START_ADDRESS   0x82000000
-
-/*
- * THESE 2 definitions are specific to the board - must be
- * defined during integration
- */
-#define SEP_RAR_IO_MEM_REGION_START_ADDRESS   0xFF0D0000
-
-/* 2M size */
-
-static void sep_load_rom_code(struct sep_device *sep)
-{
-       /* Index variables */
-       unsigned long i, k, j;
-       u32 reg;
-       u32 error;
-       u32 warning;
-
-       /* Loading ROM from SEP_ROM_image.h file */
-       k = sizeof(CRYS_SEP_ROM);
-
-       edbg("SEP Driver: DX_CC_TST_SepRomLoader start\n");
-
-       edbg("SEP Driver: k is %lu\n", k);
-       edbg("SEP Driver: sep->reg_addr is %p\n", sep->reg_addr);
-       edbg("SEP Driver: CRYS_SEP_ROM_start_address_offset is %p\n", CRYS_SEP_ROM_start_address_offset);
-
-       for (i = 0; i < 4; i++) {
-               /* write bank */
-               sep_write_reg(sep, SEP_ROM_BANK_register_offset, i);
-
-               for (j = 0; j < CRYS_SEP_ROM_length / 4; j++) {
-                       sep_write_reg(sep, CRYS_SEP_ROM_start_address_offset + 4 * j, CRYS_SEP_ROM[i * 0x1000 + j]);
-
-                       k = k - 4;
-
-                       if (k == 0) {
-                               j = CRYS_SEP_ROM_length;
-                               i = 4;
-                       }
-               }
-       }
-
-       /* reset the SEP */
-       sep_write_reg(sep, HW_HOST_SEP_SW_RST_REG_ADDR, 0x1);
-
-       /* poll for SEP ROM boot finish */
-       do
-               reg = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-       while (!reg);
-
-       edbg("SEP Driver: ROM polling ended\n");
-
-       switch (reg) {
-       case 0x1:
-               /* fatal error - read erro status from GPRO */
-               error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-               edbg("SEP Driver: ROM polling case 1\n");
-               break;
-       case 0x4:
-               /* Cold boot ended successfully  */
-       case 0x8:
-               /* Warmboot ended successfully */
-       case 0x10:
-               /* ColdWarm boot ended successfully */
-               error = 0;
-       case 0x2:
-               /* Boot First Phase ended  */
-               warning = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-       case 0x20:
-               edbg("SEP Driver: ROM polling case %d\n", reg);
-               break;
-       }
-
-}
-
-#else
-static void sep_load_rom_code(struct sep_device *sep) { }
-#endif                         /* SEP_DRIVER_ARM_DEBUG_MODE */
-
-
-
-/*----------------------------------------
-       DEFINES
------------------------------------------*/
-
-#define BASE_ADDRESS_FOR_SYSTEM 0xfffc0000
-#define SEP_RAR_IO_MEM_REGION_SIZE 0x40000
-
-/*--------------------------------------------
-       GLOBAL variables
---------------------------------------------*/
-
-/* debug messages level */
-static int debug;
-module_param(debug, int , 0);
-MODULE_PARM_DESC(debug, "Flag to enable SEP debug messages");
-
-/* Keep this a single static object for now to keep the conversion easy */
-
-static struct sep_device sep_instance;
-static struct sep_device *sep_dev = &sep_instance;
-
-/*
-  mutex for the access to the internals of the sep driver
-*/
-static DEFINE_MUTEX(sep_mutex);
-
-
-/* wait queue head (event) of the driver */
-static DECLARE_WAIT_QUEUE_HEAD(sep_event);
-
-/**
- *     sep_load_firmware       -       copy firmware cache/resident
- *     @sep: device we are loading
- *
- *     This functions copies the cache and resident from their source
- *     location into destination shared memory.
- */
-
-static int sep_load_firmware(struct sep_device *sep)
-{
-       const struct firmware *fw;
-       char *cache_name = "sep/cache.image.bin";
-       char *res_name = "sep/resident.image.bin";
-       int error;
-
-       edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr);
-       edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus);
-
-       /* load cache */
-       error = request_firmware(&fw, cache_name, &sep->pdev->dev);
-       if (error) {
-               edbg("SEP Driver:cant request cache fw\n");
-               return error;
-       }
-       edbg("SEP Driver:cache %08Zx@%p\n", fw->size, (void *) fw->data);
-
-       memcpy(sep->rar_addr, (void *)fw->data, fw->size);
-       sep->cache_size = fw->size;
-       release_firmware(fw);
-
-       sep->resident_bus = sep->rar_bus + sep->cache_size;
-       sep->resident_addr = sep->rar_addr + sep->cache_size;
-
-       /* load resident */
-       error = request_firmware(&fw, res_name, &sep->pdev->dev);
-       if (error) {
-               edbg("SEP Driver:cant request res fw\n");
-               return error;
-       }
-       edbg("sep: res %08Zx@%p\n", fw->size, (void *)fw->data);
-
-       memcpy(sep->resident_addr, (void *) fw->data, fw->size);
-       sep->resident_size = fw->size;
-       release_firmware(fw);
-
-       edbg("sep: resident v %p b %08llx cache v %p b %08llx\n",
-               sep->resident_addr, (unsigned long long)sep->resident_bus,
-               sep->rar_addr, (unsigned long long)sep->rar_bus);
-       return 0;
-}
-
-MODULE_FIRMWARE("sep/cache.image.bin");
-MODULE_FIRMWARE("sep/resident.image.bin");
-
-/**
- *     sep_map_and_alloc_shared_area   -       allocate shared block
- *     @sep: security processor
- *     @size: size of shared area
- *
- *     Allocate a shared buffer in host memory that can be used by both the
- *     kernel and also the hardware interface via DMA.
- */
-
-static int sep_map_and_alloc_shared_area(struct sep_device *sep,
-                                                       unsigned long size)
-{
-       /* shared_addr = ioremap_nocache(0xda00000,shared_area_size); */
-       sep->shared_addr = dma_alloc_coherent(&sep->pdev->dev, size,
-                                       &sep->shared_bus, GFP_KERNEL);
-
-       if (!sep->shared_addr) {
-               edbg("sep_driver :shared memory dma_alloc_coherent failed\n");
-               return -ENOMEM;
-       }
-       /* set the bus address of the shared area */
-       edbg("sep: shared_addr %ld bytes @%p (bus %08llx)\n",
-               size, sep->shared_addr, (unsigned long long)sep->shared_bus);
-       return 0;
-}
-
-/**
- *     sep_unmap_and_free_shared_area  -       free shared block
- *     @sep: security processor
- *
- *     Free the shared area allocated to the security processor. The
- *     processor must have finished with this and any final posted
- *     writes cleared before we do so.
- */
-static void sep_unmap_and_free_shared_area(struct sep_device *sep, int size)
-{
-       dma_free_coherent(&sep->pdev->dev, size,
-                               sep->shared_addr, sep->shared_bus);
-}
-
-/**
- *     sep_shared_virt_to_bus  -       convert bus/virt addresses
- *
- *     Returns the bus address inside the shared area according
- *     to the virtual address.
- */
-
-static dma_addr_t sep_shared_virt_to_bus(struct sep_device *sep,
-                                               void *virt_address)
-{
-       dma_addr_t pa = sep->shared_bus + (virt_address - sep->shared_addr);
-       edbg("sep: virt to bus b %08llx v %p\n", (unsigned long long) pa,
-                                                               virt_address);
-       return pa;
-}
-
-/**
- *     sep_shared_bus_to_virt  -       convert bus/virt addresses
- *
- *     Returns virtual address inside the shared area according
- *     to the bus address.
- */
-
-static void *sep_shared_bus_to_virt(struct sep_device *sep,
-                                               dma_addr_t bus_address)
-{
-       return sep->shared_addr + (bus_address - sep->shared_bus);
-}
-
-
-/**
- *     sep_try_open            -       attempt to open a SEP device
- *     @sep: device to attempt to open
- *
- *     Atomically attempt to get ownership of a SEP device.
- *     Returns 1 if the device was opened, 0 on failure.
- */
-
-static int sep_try_open(struct sep_device *sep)
-{
-       if (!test_and_set_bit(0, &sep->in_use))
-               return 1;
-       return 0;
-}
-
-/**
- *     sep_open                -       device open method
- *     @inode: inode of sep device
- *     @filp: file handle to sep device
- *
- *     Open method for the SEP device. Called when userspace opens
- *     the SEP device node. Must also release the memory data pool
- *     allocations.
- *
- *     Returns zero on success otherwise an error code.
- */
-
-static int sep_open(struct inode *inode, struct file *filp)
-{
-       if (sep_dev == NULL)
-               return -ENODEV;
-
-       /* check the blocking mode */
-       if (filp->f_flags & O_NDELAY) {
-               if (sep_try_open(sep_dev) == 0)
-                       return -EAGAIN;
-       } else
-               if (wait_event_interruptible(sep_event, sep_try_open(sep_dev)) < 0)
-                       return -EINTR;
-
-       /* Bind to the device, we only have one which makes it easy */
-       filp->private_data = sep_dev;
-       /* release data pool allocations */
-       sep_dev->data_pool_bytes_allocated = 0;
-       return 0;
-}
-
-
-/**
- *     sep_release             -       close a SEP device
- *     @inode: inode of SEP device
- *     @filp: file handle being closed
- *
- *     Called on the final close of a SEP device. As the open protects against
- *     multiple simultaenous opens that means this method is called when the
- *     final reference to the open handle is dropped.
- */
-
-static int sep_release(struct inode *inode, struct file *filp)
-{
-       struct sep_device *sep =  filp->private_data;
-#if 0                          /*!SEP_DRIVER_POLLING_MODE */
-       /* close IMR */
-       sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF);
-       /* release IRQ line */
-       free_irq(SEP_DIRVER_IRQ_NUM, sep);
-
-#endif
-       /* Ensure any blocked open progresses */
-       clear_bit(0, &sep->in_use);
-       wake_up(&sep_event);
-       return 0;
-}
-
-/*---------------------------------------------------------------
-  map function - this functions maps the message shared area
------------------------------------------------------------------*/
-static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       dma_addr_t bus_addr;
-       struct sep_device *sep = filp->private_data;
-
-       dbg("-------->SEP Driver: mmap start\n");
-
-       /* check that the size of the mapped range is as the size of the message
-          shared area */
-       if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
-               edbg("SEP Driver mmap requested size is more than allowed\n");
-               printk(KERN_WARNING "SEP Driver mmap requested size is more than allowed\n");
-               printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
-               printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
-               return -EAGAIN;
-       }
-
-       edbg("SEP Driver:sep->shared_addr is %p\n", sep->shared_addr);
-
-       /* get bus address */
-       bus_addr = sep->shared_bus;
-
-       edbg("SEP Driver: phys_addr is %08llx\n", (unsigned long long)bus_addr);
-
-       if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
-               edbg("SEP Driver remap_page_range failed\n");
-               printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
-               return -EAGAIN;
-       }
-
-       dbg("SEP Driver:<-------- mmap end\n");
-
-       return 0;
-}
-
-
-/*-----------------------------------------------
-  poll function
-*----------------------------------------------*/
-static unsigned int sep_poll(struct file *filp, poll_table * wait)
-{
-       unsigned long count;
-       unsigned int mask = 0;
-       unsigned long retval = 0;       /* flow id */
-       struct sep_device *sep = filp->private_data;
-
-       dbg("---------->SEP Driver poll: start\n");
-
-
-#if SEP_DRIVER_POLLING_MODE
-
-       while (sep->send_ct != (retval & 0x7FFFFFFF)) {
-               retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
-
-               for (count = 0; count < 10 * 4; count += 4)
-                       edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
-       }
-
-       sep->reply_ct++;
-#else
-       /* add the event to the polling wait table */
-       poll_wait(filp, &sep_event, wait);
-
-#endif
-
-       edbg("sep->send_ct is %lu\n", sep->send_ct);
-       edbg("sep->reply_ct is %lu\n", sep->reply_ct);
-
-       /* check if the data is ready */
-       if (sep->send_ct == sep->reply_ct) {
-               for (count = 0; count < 12 * 4; count += 4)
-                       edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + count)));
-
-               for (count = 0; count < 10 * 4; count += 4)
-                       edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + 0x1800 + count)));
-
-               retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
-               edbg("retval is %lu\n", retval);
-               /* check if the this is sep reply or request */
-               if (retval >> 31) {
-                       edbg("SEP Driver: sep request in\n");
-                       /* request */
-                       mask |= POLLOUT | POLLWRNORM;
-               } else {
-                       edbg("SEP Driver: sep reply in\n");
-                       mask |= POLLIN | POLLRDNORM;
-               }
-       }
-       dbg("SEP Driver:<-------- poll exit\n");
-       return mask;
-}
-
-/**
- *     sep_time_address        -       address in SEP memory of time
- *     @sep: SEP device we want the address from
- *
- *     Return the address of the two dwords in memory used for time
- *     setting.
- */
-
-static u32 *sep_time_address(struct sep_device *sep)
-{
-       return sep->shared_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
-}
-
-/**
- *     sep_set_time            -       set the SEP time
- *     @sep: the SEP we are setting the time for
- *
- *     Calculates time and sets it at the predefined address.
- *     Called with the sep mutex held.
- */
-static unsigned long sep_set_time(struct sep_device *sep)
-{
-       struct timeval time;
-       u32 *time_addr; /* address of time as seen by the kernel */
-
-
-       dbg("sep:sep_set_time start\n");
-
-       do_gettimeofday(&time);
-
-       /* set value in the SYSTEM MEMORY offset */
-       time_addr = sep_time_address(sep);
-
-       time_addr[0] = SEP_TIME_VAL_TOKEN;
-       time_addr[1] = time.tv_sec;
-
-       edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
-       edbg("SEP Driver:time_addr is %p\n", time_addr);
-       edbg("SEP Driver:sep->shared_addr is %p\n", sep->shared_addr);
-
-       return time.tv_sec;
-}
-
-/**
- *     sep_dump_message        - dump the message that is pending
- *     @sep: sep device
- *
- *     Dump out the message pending in the shared message area
- */
-
-static void sep_dump_message(struct sep_device *sep)
-{
-       int count;
-       for (count = 0; count < 12 * 4; count += 4)
-               edbg("Word %d of the message is %u\n", count, *((u32 *) (sep->shared_addr + count)));
-}
-
-/**
- *     sep_send_command_handler        -       kick off a command
- *     @sep: sep being signalled
- *
- *     This function raises interrupt to SEP that signals that is has a new
- *     command from the host
- */
-
-static void sep_send_command_handler(struct sep_device *sep)
-{
-       dbg("sep:sep_send_command_handler start\n");
-
-       mutex_lock(&sep_mutex);
-       sep_set_time(sep);
-
-       /* FIXME: flush cache */
-       flush_cache_all();
-
-       sep_dump_message(sep);
-       /* update counter */
-       sep->send_ct++;
-       /* send interrupt to SEP */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
-       dbg("SEP Driver:<-------- sep_send_command_handler end\n");
-       mutex_unlock(&sep_mutex);
-       return;
-}
-
-/**
- *     sep_send_reply_command_handler  -       kick off a command reply
- *     @sep: sep being signalled
- *
- *     This function raises interrupt to SEP that signals that is has a new
- *     command from the host
- */
-
-static void sep_send_reply_command_handler(struct sep_device *sep)
-{
-       dbg("sep:sep_send_reply_command_handler start\n");
-
-       /* flash cache */
-       flush_cache_all();
-
-       sep_dump_message(sep);
-
-       mutex_lock(&sep_mutex);
-       sep->send_ct++;         /* update counter */
-       /* send the interrupt to SEP */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep->send_ct);
-       /* update both counters */
-       sep->send_ct++;
-       sep->reply_ct++;
-       mutex_unlock(&sep_mutex);
-       dbg("sep: sep_send_reply_command_handler end\n");
-}
-
-/*
-  This function handles the allocate data pool memory request
-  This function returns calculates the bus address of the
-  allocated memory, and the offset of this area from the mapped address.
-  Therefore, the FVOs in user space can calculate the exact virtual
-  address of this allocated memory
-*/
-static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
-                                                       unsigned long arg)
-{
-       int error;
-       struct sep_driver_alloc_t command_args;
-
-       dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       /* allocate memory */
-       if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
-               error = -ENOMEM;
-               goto end_function;
-       }
-
-       /* set the virtual and bus address */
-       command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep->data_pool_bytes_allocated;
-       command_args.phys_address = sep->shared_bus + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep->data_pool_bytes_allocated;
-
-       /* write the memory back to the user space */
-       error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       /* set the allocation */
-       sep->data_pool_bytes_allocated += command_args.num_bytes;
-
-end_function:
-       dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
-       return error;
-}
-
-/*
-  This function  handles write into allocated data pool command
-*/
-static int sep_write_into_data_pool_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       void *virt_address;
-       unsigned long va;
-       unsigned long app_in_address;
-       unsigned long num_bytes;
-       void *data_pool_area_addr;
-
-       dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
-
-       /* get the application address */
-       error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address));
-       if (error)
-               goto end_function;
-
-       /* get the virtual kernel address address */
-       error = get_user(va, &(((struct sep_driver_write_t *) arg)->datapool_address));
-       if (error)
-               goto end_function;
-       virt_address = (void *)va;
-
-       /* get the number of bytes */
-       error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
-       if (error)
-               goto end_function;
-
-       /* calculate the start of the data pool */
-       data_pool_area_addr = sep->shared_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
-
-
-       /* check that the range of the virtual kernel address is correct */
-       if (virt_address < data_pool_area_addr || virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES)) {
-               error = -EINVAL;
-               goto end_function;
-       }
-       /* copy the application data */
-       error = copy_from_user(virt_address, (void *) app_in_address, num_bytes);
-       if (error)
-               error = -EFAULT;
-end_function:
-       dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
-       return error;
-}
-
-/*
-  this function handles the read from data pool command
-*/
-static int sep_read_from_data_pool_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       /* virtual address of dest application buffer */
-       unsigned long app_out_address;
-       /* virtual address of the data pool */
-       unsigned long va;
-       void *virt_address;
-       unsigned long num_bytes;
-       void *data_pool_area_addr;
-
-       dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
-
-       /* get the application address */
-       error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address));
-       if (error)
-               goto end_function;
-
-       /* get the virtual kernel address address */
-       error = get_user(va, &(((struct sep_driver_write_t *) arg)->datapool_address));
-       if (error)
-               goto end_function;
-       virt_address = (void *)va;
-
-       /* get the number of bytes */
-       error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
-       if (error)
-               goto end_function;
-
-       /* calculate the start of the data pool */
-       data_pool_area_addr = sep->shared_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
-
-       /* FIXME: These are incomplete all over the driver: what about + len
-          and when doing that also overflows */
-       /* check that the range of the virtual kernel address is correct */
-       if (virt_address < data_pool_area_addr || virt_address > data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
-               error = -EINVAL;
-               goto end_function;
-       }
-
-       /* copy the application data */
-       error = copy_to_user((void *) app_out_address, virt_address, num_bytes);
-       if (error)
-               error = -EFAULT;
-end_function:
-       dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
-       return error;
-}
-
-/*
-  This function releases all the application virtual buffer physical pages,
-       that were previously locked
-*/
-static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag)
-{
-       unsigned long count;
-
-       if (dirtyFlag) {
-               for (count = 0; count < num_pages; count++) {
-                       /* the out array was written, therefore the data was changed */
-                       if (!PageReserved(page_array_ptr[count]))
-                               SetPageDirty(page_array_ptr[count]);
-                       page_cache_release(page_array_ptr[count]);
-               }
-       } else {
-               /* free in pages - the data was only read, therefore no update was done
-                  on those pages */
-               for (count = 0; count < num_pages; count++)
-                       page_cache_release(page_array_ptr[count]);
-       }
-
-       if (page_array_ptr)
-               /* free the array */
-               kfree(page_array_ptr);
-
-       return 0;
-}
-
-/*
-  This function locks all the physical pages of the kernel virtual buffer
-  and construct a basic lli  array, where each entry holds the physical
-  page address and the size that application data holds in this physical pages
-*/
-static int sep_lock_kernel_pages(struct sep_device *sep,
-                                unsigned long kernel_virt_addr,
-                                unsigned long data_size,
-                                unsigned long *num_pages_ptr,
-                                struct sep_lli_entry_t **lli_array_ptr,
-                                struct page ***page_array_ptr)
-{
-       int error = 0;
-       /* the the page of the end address of the user space buffer */
-       unsigned long end_page;
-       /* the page of the start address of the user space buffer */
-       unsigned long start_page;
-       /* the range in pages */
-       unsigned long num_pages;
-       struct sep_lli_entry_t *lli_array;
-       /* next kernel address to map */
-       unsigned long next_kernel_address;
-       unsigned long count;
-
-       dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
-
-       /* set start and end pages  and num pages */
-       end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
-       start_page = kernel_virt_addr >> PAGE_SHIFT;
-       num_pages = end_page - start_page + 1;
-
-       edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr);
-       edbg("SEP Driver: data_size is %lu\n", data_size);
-       edbg("SEP Driver: start_page is %lx\n", start_page);
-       edbg("SEP Driver: end_page is %lx\n", end_page);
-       edbg("SEP Driver: num_pages is %lu\n", num_pages);
-
-       lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
-       if (!lli_array) {
-               edbg("SEP Driver: kmalloc for lli_array failed\n");
-               error = -ENOMEM;
-               goto end_function;
-       }
-
-       /* set the start address of the first page - app data may start not at
-          the beginning of the page */
-       lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr);
-
-       /* check that not all the data is in the first page only */
-       if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
-               lli_array[0].block_size = data_size;
-       else
-               lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
-
-       /* debug print */
-       dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
-
-       /* advance the address to the start of the next page */
-       next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
-
-       /* go from the second page to the prev before last */
-       for (count = 1; count < (num_pages - 1); count++) {
-               lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
-               lli_array[count].block_size = PAGE_SIZE;
-
-               edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
-               next_kernel_address += PAGE_SIZE;
-       }
-
-       /* if more then 1 pages locked - then update for the last page size needed */
-       if (num_pages > 1) {
-               /* update the address of the last page */
-               lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
-
-               /* set the size of the last page */
-               lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK);
-
-               if (lli_array[count].block_size == 0) {
-                       dbg("app_virt_addr is %08lx\n", kernel_virt_addr);
-                       dbg("data_size is %lu\n", data_size);
-                       while (1);
-               }
-
-               edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
-       }
-       /* set output params */
-       *lli_array_ptr = lli_array;
-       *num_pages_ptr = num_pages;
-       *page_array_ptr = 0;
-end_function:
-       dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
-       return 0;
-}
-
-/*
-  This function locks all the physical pages of the application virtual buffer
-  and construct a basic lli  array, where each entry holds the physical page
-  address and the size that application data holds in this physical pages
-*/
-static int sep_lock_user_pages(struct sep_device *sep,
-                       unsigned long app_virt_addr,
-                       unsigned long data_size,
-                       unsigned long *num_pages_ptr,
-                       struct sep_lli_entry_t **lli_array_ptr,
-                       struct page ***page_array_ptr)
-{
-       int error = 0;
-       /* the the page of the end address of the user space buffer */
-       unsigned long end_page;
-       /* the page of the start address of the user space buffer */
-       unsigned long start_page;
-       /* the range in pages */
-       unsigned long num_pages;
-       struct page **page_array;
-       struct sep_lli_entry_t *lli_array;
-       unsigned long count;
-       int result;
-
-       dbg("SEP Driver:--------> sep_lock_user_pages start\n");
-
-       /* set start and end pages  and num pages */
-       end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
-       start_page = app_virt_addr >> PAGE_SHIFT;
-       num_pages = end_page - start_page + 1;
-
-       edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr);
-       edbg("SEP Driver: data_size is %lu\n", data_size);
-       edbg("SEP Driver: start_page is %lu\n", start_page);
-       edbg("SEP Driver: end_page is %lu\n", end_page);
-       edbg("SEP Driver: num_pages is %lu\n", num_pages);
-
-       /* allocate array of pages structure pointers */
-       page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
-       if (!page_array) {
-               edbg("SEP Driver: kmalloc for page_array failed\n");
-
-               error = -ENOMEM;
-               goto end_function;
-       }
-
-       lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
-       if (!lli_array) {
-               edbg("SEP Driver: kmalloc for lli_array failed\n");
-
-               error = -ENOMEM;
-               goto end_function_with_error1;
-       }
-
-       /* convert the application virtual address into a set of physical */
-       down_read(&current->mm->mmap_sem);
-       result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0);
-       up_read(&current->mm->mmap_sem);
-
-       /* check the number of pages locked - if not all then exit with error */
-       if (result != num_pages) {
-               dbg("SEP Driver: not all pages locked by get_user_pages\n");
-
-               error = -ENOMEM;
-               goto end_function_with_error2;
-       }
-
-       /* flush the cache */
-       for (count = 0; count < num_pages; count++)
-               flush_dcache_page(page_array[count]);
-
-       /* set the start address of the first page - app data may start not at
-          the beginning of the page */
-       lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK));
-
-       /* check that not all the data is in the first page only */
-       if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
-               lli_array[0].block_size = data_size;
-       else
-               lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
-
-       /* debug print */
-       dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
-
-       /* go from the second page to the prev before last */
-       for (count = 1; count < (num_pages - 1); count++) {
-               lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
-               lli_array[count].block_size = PAGE_SIZE;
-
-               edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
-       }
-
-       /* if more then 1 pages locked - then update for the last page size needed */
-       if (num_pages > 1) {
-               /* update the address of the last page */
-               lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
-
-               /* set the size of the last page */
-               lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK);
-
-               if (lli_array[count].block_size == 0) {
-                       dbg("app_virt_addr is %08lx\n", app_virt_addr);
-                       dbg("data_size is %lu\n", data_size);
-                       while (1);
-               }
-               edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n",
-                    count, lli_array[count].physical_address,
-                    count, lli_array[count].block_size);
-       }
-
-       /* set output params */
-       *lli_array_ptr = lli_array;
-       *num_pages_ptr = num_pages;
-       *page_array_ptr = page_array;
-       goto end_function;
-
-end_function_with_error2:
-       /* release the cache */
-       for (count = 0; count < num_pages; count++)
-               page_cache_release(page_array[count]);
-       kfree(lli_array);
-end_function_with_error1:
-       kfree(page_array);
-end_function:
-       dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
-       return 0;
-}
-
-
-/*
-  this function calculates the size of data that can be inserted into the lli
-  table from this array the condition is that either the table is full
-  (all etnries are entered), or there are no more entries in the lli array
-*/
-static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
-{
-       unsigned long table_data_size = 0;
-       unsigned long counter;
-
-       /* calculate the data in the out lli table if till we fill the whole
-          table or till the data has ended */
-       for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++)
-               table_data_size += lli_in_array_ptr[counter].block_size;
-       return table_data_size;
-}
-
-/*
-  this functions builds ont lli table from the lli_array according to
-  the given size of data
-*/
-static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size)
-{
-       unsigned long curr_table_data_size;
-       /* counter of lli array entry */
-       unsigned long array_counter;
-
-       dbg("SEP Driver:--------> sep_build_lli_table start\n");
-
-       /* init currrent table data size and lli array entry counter */
-       curr_table_data_size = 0;
-       array_counter = 0;
-       *num_table_entries_ptr = 1;
-
-       edbg("SEP Driver:table_data_size is %lu\n", table_data_size);
-
-       /* fill the table till table size reaches the needed amount */
-       while (curr_table_data_size < table_data_size) {
-               /* update the number of entries in table */
-               (*num_table_entries_ptr)++;
-
-               lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address;
-               lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
-               curr_table_data_size += lli_table_ptr->block_size;
-
-               edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
-               edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
-               edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
-
-               /* check for overflow of the table data */
-               if (curr_table_data_size > table_data_size) {
-                       edbg("SEP Driver:curr_table_data_size > table_data_size\n");
-
-                       /* update the size of block in the table */
-                       lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
-
-                       /* update the physical address in the lli array */
-                       lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size;
-
-                       /* update the block size left in the lli array */
-                       lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size);
-               } else
-                       /* advance to the next entry in the lli_array */
-                       array_counter++;
-
-               edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
-               edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
-
-               /* move to the next entry in table */
-               lli_table_ptr++;
-       }
-
-       /* set the info entry to default */
-       lli_table_ptr->physical_address = 0xffffffff;
-       lli_table_ptr->block_size = 0;
-
-       edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
-       edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
-       edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
-
-       /* set the output parameter */
-       *num_processed_entries_ptr += array_counter;
-
-       edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr);
-       dbg("SEP Driver:<-------- sep_build_lli_table end\n");
-       return;
-}
-
-/*
-  this function goes over the list of the print created tables and
-  prints all the data
-*/
-static void sep_debug_print_lli_tables(struct sep_device *sep, struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size)
-{
-       unsigned long table_count;
-       unsigned long entries_count;
-
-       dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
-
-       table_count = 1;
-       while ((unsigned long) lli_table_ptr != 0xffffffff) {
-               edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size);
-               edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
-
-               /* print entries of the table (without info entry) */
-               for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) {
-                       edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr);
-                       edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size);
-               }
-
-               /* point to the info entry */
-               lli_table_ptr--;
-
-               edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
-               edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
-
-
-               table_data_size = lli_table_ptr->block_size & 0xffffff;
-               num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
-               lli_table_ptr = (struct sep_lli_entry_t *)
-                   (lli_table_ptr->physical_address);
-
-               edbg("SEP Driver:phys table_data_size is %lu num_table_entries is %lu lli_table_ptr is%lu\n", table_data_size, num_table_entries, (unsigned long) lli_table_ptr);
-
-               if ((unsigned long) lli_table_ptr != 0xffffffff)
-                       lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_bus_to_virt(sep, (unsigned long) lli_table_ptr);
-
-               table_count++;
-       }
-       dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
-}
-
-
-/*
-  This function prepares only input DMA table for synhronic symmetric
-  operations (HASH)
-*/
-static int sep_prepare_input_dma_table(struct sep_device *sep,
-                               unsigned long app_virt_addr,
-                               unsigned long data_size,
-                               unsigned long block_size,
-                               unsigned long *lli_table_ptr,
-                               unsigned long *num_entries_ptr,
-                               unsigned long *table_data_size_ptr,
-                               bool isKernelVirtualAddress)
-{
-       /* pointer to the info entry of the table - the last entry */
-       struct sep_lli_entry_t *info_entry_ptr;
-       /* array of pointers ot page */
-       struct sep_lli_entry_t *lli_array_ptr;
-       /* points to the first entry to be processed in the lli_in_array */
-       unsigned long current_entry;
-       /* num entries in the virtual buffer */
-       unsigned long sep_lli_entries;
-       /* lli table pointer */
-       struct sep_lli_entry_t *in_lli_table_ptr;
-       /* the total data in one table */
-       unsigned long table_data_size;
-       /* number of entries in lli table */
-       unsigned long num_entries_in_table;
-       /* next table address */
-       void *lli_table_alloc_addr;
-       unsigned long result;
-
-       dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
-
-       edbg("SEP Driver:data_size is %lu\n", data_size);
-       edbg("SEP Driver:block_size is %lu\n", block_size);
-
-       /* initialize the pages pointers */
-       sep->in_page_array = 0;
-       sep->in_num_pages = 0;
-
-       if (data_size == 0) {
-               /* special case  - created 2 entries table with zero data */
-               in_lli_table_ptr = (struct sep_lli_entry_t *) (sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
-               /* FIXME: Should the entry below not be for _bus */
-               in_lli_table_ptr->physical_address = (unsigned long)sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
-               in_lli_table_ptr->block_size = 0;
-
-               in_lli_table_ptr++;
-               in_lli_table_ptr->physical_address = 0xFFFFFFFF;
-               in_lli_table_ptr->block_size = 0;
-
-               *lli_table_ptr = sep->shared_bus + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
-               *num_entries_ptr = 2;
-               *table_data_size_ptr = 0;
-
-               goto end_function;
-       }
-
-       /* check if the pages are in Kernel Virtual Address layout */
-       if (isKernelVirtualAddress == true)
-               /* lock the pages of the kernel buffer and translate them to pages */
-               result = sep_lock_kernel_pages(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array);
-       else
-               /* lock the pages of the user buffer and translate them to pages */
-               result = sep_lock_user_pages(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array);
-
-       if (result)
-               return result;
-
-       edbg("SEP Driver:output sep->in_num_pages is %lu\n", sep->in_num_pages);
-
-       current_entry = 0;
-       info_entry_ptr = 0;
-       sep_lli_entries = sep->in_num_pages;
-
-       /* initiate to point after the message area */
-       lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
-
-       /* loop till all the entries in in array are not processed */
-       while (current_entry < sep_lli_entries) {
-               /* set the new input and output tables */
-               in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
-
-               lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
-
-               /* calculate the maximum size of data for input table */
-               table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
-
-               /* now calculate the table size so that it will be module block size */
-               table_data_size = (table_data_size / block_size) * block_size;
-
-               edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
-
-               /* construct input lli table */
-               sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, &current_entry, &num_entries_in_table, table_data_size);
-
-               if (info_entry_ptr == 0) {
-                       /* set the output parameters to physical addresses */
-                       *lli_table_ptr = sep_shared_virt_to_bus(sep, in_lli_table_ptr);
-                       *num_entries_ptr = num_entries_in_table;
-                       *table_data_size_ptr = table_data_size;
-
-                       edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
-               } else {
-                       /* update the info entry of the previous in table */
-                       info_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, in_lli_table_ptr);
-                       info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
-               }
-
-               /* save the pointer to the info entry of the current tables */
-               info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
-       }
-
-       /* print input tables */
-       sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
-                                  sep_shared_bus_to_virt(sep, *lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
-
-       /* the array of the pages */
-       kfree(lli_array_ptr);
-end_function:
-       dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
-       return 0;
-
-}
-
-/*
- This function creates the input and output dma tables for
- symmetric operations (AES/DES) according to the block size from LLI arays
-*/
-static int sep_construct_dma_tables_from_lli(struct sep_device *sep,
-                                     struct sep_lli_entry_t *lli_in_array,
-                                     unsigned long sep_in_lli_entries,
-                                     struct sep_lli_entry_t *lli_out_array,
-                                     unsigned long sep_out_lli_entries,
-                                     unsigned long block_size, unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr)
-{
-       /* points to the area where next lli table can be allocated: keep void *
-          as there is pointer scaling to fix otherwise */
-       void *lli_table_alloc_addr;
-       /* input lli table */
-       struct sep_lli_entry_t *in_lli_table_ptr;
-       /* output lli table */
-       struct sep_lli_entry_t *out_lli_table_ptr;
-       /* pointer to the info entry of the table - the last entry */
-       struct sep_lli_entry_t *info_in_entry_ptr;
-       /* pointer to the info entry of the table - the last entry */
-       struct sep_lli_entry_t *info_out_entry_ptr;
-       /* points to the first entry to be processed in the lli_in_array */
-       unsigned long current_in_entry;
-       /* points to the first entry to be processed in the lli_out_array */
-       unsigned long current_out_entry;
-       /* max size of the input table */
-       unsigned long in_table_data_size;
-       /* max size of the output table */
-       unsigned long out_table_data_size;
-       /* flag te signifies if this is the first tables build from the arrays */
-       unsigned long first_table_flag;
-       /* the data size that should be in table */
-       unsigned long table_data_size;
-       /* number of etnries in the input table */
-       unsigned long num_entries_in_table;
-       /* number of etnries in the output table */
-       unsigned long num_entries_out_table;
-
-       dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
-
-       /* initiate to pint after the message area */
-       lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
-
-       current_in_entry = 0;
-       current_out_entry = 0;
-       first_table_flag = 1;
-       info_in_entry_ptr = 0;
-       info_out_entry_ptr = 0;
-
-       /* loop till all the entries in in array are not processed */
-       while (current_in_entry < sep_in_lli_entries) {
-               /* set the new input and output tables */
-               in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
-
-               lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
-
-               /* set the first output tables */
-               out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
-
-               lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
-
-               /* calculate the maximum size of data for input table */
-               in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
-
-               /* calculate the maximum size of data for output table */
-               out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
-
-               edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
-               edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
-
-               /* check where the data is smallest */
-               table_data_size = in_table_data_size;
-               if (table_data_size > out_table_data_size)
-                       table_data_size = out_table_data_size;
-
-               /* now calculate the table size so that it will be module block size */
-               table_data_size = (table_data_size / block_size) * block_size;
-
-               dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
-
-               /* construct input lli table */
-               sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, &current_in_entry, &num_entries_in_table, table_data_size);
-
-               /* construct output lli table */
-               sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, &current_out_entry, &num_entries_out_table, table_data_size);
-
-               /* if info entry is null - this is the first table built */
-               if (info_in_entry_ptr == 0) {
-                       /* set the output parameters to physical addresses */
-                       *lli_table_in_ptr = sep_shared_virt_to_bus(sep, in_lli_table_ptr);
-                       *in_num_entries_ptr = num_entries_in_table;
-                       *lli_table_out_ptr = sep_shared_virt_to_bus(sep, out_lli_table_ptr);
-                       *out_num_entries_ptr = num_entries_out_table;
-                       *table_data_size_ptr = table_data_size;
-
-                       edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
-                       edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
-               } else {
-                       /* update the info entry of the previous in table */
-                       info_in_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, in_lli_table_ptr);
-                       info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
-
-                       /* update the info entry of the previous in table */
-                       info_out_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, out_lli_table_ptr);
-                       info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
-               }
-
-               /* save the pointer to the info entry of the current tables */
-               info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
-               info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
-
-               edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
-               edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
-               edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
-       }
-
-       /* print input tables */
-       sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
-                                  sep_shared_bus_to_virt(sep, *lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
-       /* print output tables */
-       sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
-                                  sep_shared_bus_to_virt(sep, *lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
-       dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
-       return 0;
-}
-
-
-/*
-  This function builds input and output DMA tables for synhronic
-  symmetric operations (AES, DES). It also checks that each table
-  is of the modular block size
-*/
-static int sep_prepare_input_output_dma_table(struct sep_device *sep,
-                                      unsigned long app_virt_in_addr,
-                                      unsigned long app_virt_out_addr,
-                                      unsigned long data_size,
-                                      unsigned long block_size,
-                                      unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
-{
-       /* array of pointers of page */
-       struct sep_lli_entry_t *lli_in_array;
-       /* array of pointers of page */
-       struct sep_lli_entry_t *lli_out_array;
-       int result = 0;
-
-       dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
-
-       /* initialize the pages pointers */
-       sep->in_page_array = 0;
-       sep->out_page_array = 0;
-
-       /* check if the pages are in Kernel Virtual Address layout */
-       if (isKernelVirtualAddress == true) {
-               /* lock the pages of the kernel buffer and translate them to pages */
-               result = sep_lock_kernel_pages(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array);
-               if (result) {
-                       edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
-                       goto end_function;
-               }
-       } else {
-               /* lock the pages of the user buffer and translate them to pages */
-               result = sep_lock_user_pages(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array);
-               if (result) {
-                       edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
-                       goto end_function;
-               }
-       }
-
-       if (isKernelVirtualAddress == true) {
-               result = sep_lock_kernel_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array);
-               if (result) {
-                       edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
-                       goto end_function_with_error1;
-               }
-       } else {
-               result = sep_lock_user_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array);
-               if (result) {
-                       edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
-                       goto end_function_with_error1;
-               }
-       }
-       edbg("sep->in_num_pages is %lu\n", sep->in_num_pages);
-       edbg("sep->out_num_pages is %lu\n", sep->out_num_pages);
-       edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
-
-
-       /* call the fucntion that creates table from the lli arrays */
-       result = sep_construct_dma_tables_from_lli(sep, lli_in_array, sep->in_num_pages, lli_out_array, sep->out_num_pages, block_size, lli_table_in_ptr, lli_table_out_ptr, in_num_entries_ptr, out_num_entries_ptr, table_data_size_ptr);
-       if (result) {
-               edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n");
-               goto end_function_with_error2;
-       }
-
-       /* fall through - free the lli entry arrays */
-       dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr);
-       dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr);
-       dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr);
-end_function_with_error2:
-       kfree(lli_out_array);
-end_function_with_error1:
-       kfree(lli_in_array);
-end_function:
-       dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
-       return result;
-
-}
-
-/*
-  this function handles tha request for creation of the DMA table
-  for the synchronic symmetric operations (AES,DES)
-*/
-static int sep_create_sync_dma_tables_handler(struct sep_device *sep,
-                                               unsigned long arg)
-{
-       int error;
-       /* command arguments */
-       struct sep_driver_build_sync_table_t command_args;
-
-       dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       edbg("app_in_address is %08lx\n", command_args.app_in_address);
-       edbg("app_out_address is %08lx\n", command_args.app_out_address);
-       edbg("data_size is %lu\n", command_args.data_in_size);
-       edbg("block_size is %lu\n", command_args.block_size);
-
-       /* check if we need to build only input table or input/output */
-       if (command_args.app_out_address)
-               /* prepare input and output tables */
-               error = sep_prepare_input_output_dma_table(sep,
-                                                          command_args.app_in_address,
-                                                          command_args.app_out_address,
-                                                          command_args.data_in_size,
-                                                          command_args.block_size,
-                                                          &command_args.in_table_address,
-                                                          &command_args.out_table_address, &command_args.in_table_num_entries, &command_args.out_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
-       else
-               /* prepare input tables */
-               error = sep_prepare_input_dma_table(sep,
-                                                   command_args.app_in_address,
-                                                   command_args.data_in_size, command_args.block_size, &command_args.in_table_address, &command_args.in_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
-
-       if (error)
-               goto end_function;
-       /* copy to user */
-       if (copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t)))
-               error = -EFAULT;
-end_function:
-       dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
-       return error;
-}
-
-/*
-  this function handles the request for freeing dma table for synhronic actions
-*/
-static int sep_free_dma_table_data_handler(struct sep_device *sep)
-{
-       dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
-
-       /* free input pages array */
-       sep_free_dma_pages(sep->in_page_array, sep->in_num_pages, 0);
-
-       /* free output pages array if needed */
-       if (sep->out_page_array)
-               sep_free_dma_pages(sep->out_page_array, sep->out_num_pages, 1);
-
-       /* reset all the values */
-       sep->in_page_array = 0;
-       sep->out_page_array = 0;
-       sep->in_num_pages = 0;
-       sep->out_num_pages = 0;
-       dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
-       return 0;
-}
-
-/*
-  this function find a space for the new flow dma table
-*/
-static int sep_find_free_flow_dma_table_space(struct sep_device *sep,
-                                       unsigned long **table_address_ptr)
-{
-       int error = 0;
-       /* pointer to the id field of the flow dma table */
-       unsigned long *start_table_ptr;
-       /* Do not make start_addr unsigned long * unless fixing the offset
-          computations ! */
-       void *flow_dma_area_start_addr;
-       unsigned long *flow_dma_area_end_addr;
-       /* maximum table size in words */
-       unsigned long table_size_in_words;
-
-       /* find the start address of the flow DMA table area */
-       flow_dma_area_start_addr = sep->shared_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
-
-       /* set end address of the flow table area */
-       flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
-
-       /* set table size in words */
-       table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
-
-       /* set the pointer to the start address of DMA area */
-       start_table_ptr = flow_dma_area_start_addr;
-
-       /* find the space for the next table */
-       while (((*start_table_ptr & 0x7FFFFFFF) != 0) && start_table_ptr < flow_dma_area_end_addr)
-               start_table_ptr += table_size_in_words;
-
-       /* check if we reached the end of floa tables area */
-       if (start_table_ptr >= flow_dma_area_end_addr)
-               error = -1;
-       else
-               *table_address_ptr = start_table_ptr;
-
-       return error;
-}
-
-/*
-  This function creates one DMA table for flow and returns its data,
-  and pointer to its info entry
-*/
-static int sep_prepare_one_flow_dma_table(struct sep_device *sep,
-                                       unsigned long virt_buff_addr,
-                                       unsigned long virt_buff_size,
-                                       struct sep_lli_entry_t *table_data,
-                                       struct sep_lli_entry_t **info_entry_ptr,
-                                       struct sep_flow_context_t *flow_data_ptr,
-                                       bool isKernelVirtualAddress)
-{
-       int error;
-       /* the range in pages */
-       unsigned long lli_array_size;
-       struct sep_lli_entry_t *lli_array;
-       struct sep_lli_entry_t *flow_dma_table_entry_ptr;
-       unsigned long *start_dma_table_ptr;
-       /* total table data counter */
-       unsigned long dma_table_data_count;
-       /* pointer that will keep the pointer to the pages of the virtual buffer */
-       struct page **page_array_ptr;
-       unsigned long entry_count;
-
-       /* find the space for the new table */
-       error = sep_find_free_flow_dma_table_space(sep, &start_dma_table_ptr);
-       if (error)
-               goto end_function;
-
-       /* check if the pages are in Kernel Virtual Address layout */
-       if (isKernelVirtualAddress == true)
-               /* lock kernel buffer in the memory */
-               error = sep_lock_kernel_pages(sep, virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
-       else
-               /* lock user buffer in the memory */
-               error = sep_lock_user_pages(sep, virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
-
-       if (error)
-               goto end_function;
-
-       /* set the pointer to page array at the beginning of table - this table is
-          now considered taken */
-       *start_dma_table_ptr = lli_array_size;
-
-       /* point to the place of the pages pointers of the table */
-       start_dma_table_ptr++;
-
-       /* set the pages pointer */
-       *start_dma_table_ptr = (unsigned long) page_array_ptr;
-
-       /* set the pointer to the first entry */
-       flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
-
-       /* now create the entries for table */
-       for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
-               flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
-
-               flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
-
-               /* set the total data of a table */
-               dma_table_data_count += lli_array[entry_count].block_size;
-
-               flow_dma_table_entry_ptr++;
-       }
-
-       /* set the physical address */
-       table_data->physical_address = virt_to_phys(start_dma_table_ptr);
-
-       /* set the num_entries and total data size */
-       table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
-
-       /* set the info entry */
-       flow_dma_table_entry_ptr->physical_address = 0xffffffff;
-       flow_dma_table_entry_ptr->block_size = 0;
-
-       /* set the pointer to info entry */
-       *info_entry_ptr = flow_dma_table_entry_ptr;
-
-       /* the array of the lli entries */
-       kfree(lli_array);
-end_function:
-       return error;
-}
-
-
-
-/*
-  This function creates a list of tables for flow and returns the data for
-       the first and last tables of the list
-*/
-static int sep_prepare_flow_dma_tables(struct sep_device *sep,
-                                       unsigned long num_virtual_buffers,
-                                       unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress)
-{
-       int error;
-       unsigned long virt_buff_addr;
-       unsigned long virt_buff_size;
-       struct sep_lli_entry_t table_data;
-       struct sep_lli_entry_t *info_entry_ptr;
-       struct sep_lli_entry_t *prev_info_entry_ptr;
-       unsigned long i;
-
-       /* init vars */
-       error = 0;
-       prev_info_entry_ptr = 0;
-
-       /* init the first table to default */
-       table_data.physical_address = 0xffffffff;
-       first_table_data_ptr->physical_address = 0xffffffff;
-       table_data.block_size = 0;
-
-       for (i = 0; i < num_virtual_buffers; i++) {
-               /* get the virtual buffer address */
-               error = get_user(virt_buff_addr, &first_buff_addr);
-               if (error)
-                       goto end_function;
-
-               /* get the virtual buffer size */
-               first_buff_addr++;
-               error = get_user(virt_buff_size, &first_buff_addr);
-               if (error)
-                       goto end_function;
-
-               /* advance the address to point to the next pair of address|size */
-               first_buff_addr++;
-
-               /* now prepare the one flow LLI table from the data */
-               error = sep_prepare_one_flow_dma_table(sep, virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
-               if (error)
-                       goto end_function;
-
-               if (i == 0) {
-                       /* if this is the first table - save it to return to the user
-                          application */
-                       *first_table_data_ptr = table_data;
-
-                       /* set the pointer to info entry */
-                       prev_info_entry_ptr = info_entry_ptr;
-               } else {
-                       /* not first table - the previous table info entry should
-                          be updated */
-                       prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
-
-                       /* set the pointer to info entry */
-                       prev_info_entry_ptr = info_entry_ptr;
-               }
-       }
-
-       /* set the last table data */
-       *last_table_data_ptr = table_data;
-end_function:
-       return error;
-}
-
-/*
-  this function goes over all the flow tables connected to the given
-       table and deallocate them
-*/
-static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
-{
-       /* id pointer */
-       unsigned long *table_ptr;
-       /* end address of the flow dma area */
-       unsigned long num_entries;
-       unsigned long num_pages;
-       struct page **pages_ptr;
-       /* maximum table size in words */
-       struct sep_lli_entry_t *info_entry_ptr;
-
-       /* set the pointer to the first table */
-       table_ptr = (unsigned long *) first_table_ptr->physical_address;
-
-       /* set the num of entries */
-       num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
-           & SEP_NUM_ENTRIES_MASK;
-
-       /* go over all the connected tables */
-       while (*table_ptr != 0xffffffff) {
-               /* get number of pages */
-               num_pages = *(table_ptr - 2);
-
-               /* get the pointer to the pages */
-               pages_ptr = (struct page **) (*(table_ptr - 1));
-
-               /* free the pages */
-               sep_free_dma_pages(pages_ptr, num_pages, 1);
-
-               /* goto to the info entry */
-               info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
-
-               table_ptr = (unsigned long *) info_entry_ptr->physical_address;
-               num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
-       }
-
-       return;
-}
-
-/**
- *     sep_find_flow_context   -       find a flow
- *     @sep: the SEP we are working with
- *     @flow_id: flow identifier
- *
- *     Returns a pointer the matching flow, or NULL if the flow does not
- *     exist.
- */
-
-static struct sep_flow_context_t *sep_find_flow_context(struct sep_device *sep,
-                               unsigned long flow_id)
-{
-       int count;
-       /*
-        *  always search for flow with id default first - in case we
-        *  already started working on the flow there can be no situation
-        *  when 2 flows are with default flag
-        */
-       for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
-               if (sep->flows[count].flow_id == flow_id)
-                       return &sep->flows[count];
-       }
-       return NULL;
-}
-
-
-/*
-  this function handles the request to create the DMA tables for flow
-*/
-static int sep_create_flow_dma_tables_handler(struct sep_device *sep,
-                                                       unsigned long arg)
-{
-       int error = -ENOENT;
-       struct sep_driver_build_flow_table_t command_args;
-       /* first table - output */
-       struct sep_lli_entry_t first_table_data;
-       /* dma table data */
-       struct sep_lli_entry_t last_table_data;
-       /* pointer to the info entry of the previuos DMA table */
-       struct sep_lli_entry_t *prev_info_entry_ptr;
-       /* pointer to the flow data strucutre */
-       struct sep_flow_context_t *flow_context_ptr;
-
-       dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
-
-       /* init variables */
-       prev_info_entry_ptr = 0;
-       first_table_data.physical_address = 0xffffffff;
-
-       /* find the free structure for flow data */
-       error = -EINVAL;
-       flow_context_ptr = sep_find_flow_context(sep, SEP_FREE_FLOW_ID);
-       if (flow_context_ptr == NULL)
-               goto end_function;
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       /* create flow tables */
-       error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
-       if (error)
-               goto end_function_with_error;
-
-       /* check if flow is static */
-       if (!command_args.flow_type)
-               /* point the info entry of the last to the info entry of the first */
-               last_table_data = first_table_data;
-
-       /* set output params */
-       command_args.first_table_addr = first_table_data.physical_address;
-       command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
-       command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
-
-       /* send the parameters to user application */
-       error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function_with_error;
-       }
-
-       /* all the flow created  - update the flow entry with temp id */
-       flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
-
-       /* set the processing tables data in the context */
-       if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
-               flow_context_ptr->input_tables_in_process = first_table_data;
-       else
-               flow_context_ptr->output_tables_in_process = first_table_data;
-
-       goto end_function;
-
-end_function_with_error:
-       /* free the allocated tables */
-       sep_deallocated_flow_tables(&first_table_data);
-end_function:
-       dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
-       return error;
-}
-
-/*
-  this function handles add tables to flow
-*/
-static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       unsigned long num_entries;
-       struct sep_driver_add_flow_table_t command_args;
-       struct sep_flow_context_t *flow_context_ptr;
-       /* first dma table data */
-       struct sep_lli_entry_t first_table_data;
-       /* last dma table data */
-       struct sep_lli_entry_t last_table_data;
-       /* pointer to the info entry of the current DMA table */
-       struct sep_lli_entry_t *info_entry_ptr;
-
-       dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
-
-       /* get input parameters */
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       /* find the flow structure for the flow id */
-       flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id);
-       if (flow_context_ptr == NULL)
-               goto end_function;
-
-       /* prepare the flow dma tables */
-       error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
-       if (error)
-               goto end_function_with_error;
-
-       /* now check if there is already an existing add table for this flow */
-       if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
-               /* this buffer was for input buffers */
-               if (flow_context_ptr->input_tables_flag) {
-                       /* add table already exists - add the new tables to the end
-                          of the previous */
-                       num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
-
-                       info_entry_ptr = (struct sep_lli_entry_t *)
-                           (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
-
-                       /* connect to list of tables */
-                       *info_entry_ptr = first_table_data;
-
-                       /* set the first table data */
-                       first_table_data = flow_context_ptr->first_input_table;
-               } else {
-                       /* set the input flag */
-                       flow_context_ptr->input_tables_flag = 1;
-
-                       /* set the first table data */
-                       flow_context_ptr->first_input_table = first_table_data;
-               }
-               /* set the last table data */
-               flow_context_ptr->last_input_table = last_table_data;
-       } else {                /* this is output tables */
-
-               /* this buffer was for input buffers */
-               if (flow_context_ptr->output_tables_flag) {
-                       /* add table already exists - add the new tables to
-                          the end of the previous */
-                       num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
-
-                       info_entry_ptr = (struct sep_lli_entry_t *)
-                           (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
-
-                       /* connect to list of tables */
-                       *info_entry_ptr = first_table_data;
-
-                       /* set the first table data */
-                       first_table_data = flow_context_ptr->first_output_table;
-               } else {
-                       /* set the input flag */
-                       flow_context_ptr->output_tables_flag = 1;
-
-                       /* set the first table data */
-                       flow_context_ptr->first_output_table = first_table_data;
-               }
-               /* set the last table data */
-               flow_context_ptr->last_output_table = last_table_data;
-       }
-
-       /* set output params */
-       command_args.first_table_addr = first_table_data.physical_address;
-       command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
-       command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
-
-       /* send the parameters to user application */
-       error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
-       if (error)
-               error = -EFAULT;
-end_function_with_error:
-       /* free the allocated tables */
-       sep_deallocated_flow_tables(&first_table_data);
-end_function:
-       dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
-       return error;
-}
-
-/*
-  this function add the flow add message to the specific flow
-*/
-static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       struct sep_driver_add_message_t command_args;
-       struct sep_flow_context_t *flow_context_ptr;
-
-       dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       /* check input */
-       if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
-               error = -ENOMEM;
-               goto end_function;
-       }
-
-       /* find the flow context */
-       flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id);
-       if (flow_context_ptr == NULL)
-               goto end_function;
-
-       /* copy the message into context */
-       flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
-       error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
-       if (error)
-               error = -EFAULT;
-end_function:
-       dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
-       return error;
-}
-
-
-/*
-  this function returns the bus and virtual addresses of the static pool
-*/
-static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       struct sep_driver_static_pool_addr_t command_args;
-
-       dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
-
-       /*prepare the output parameters in the struct */
-       command_args.physical_static_address = sep->shared_bus + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
-       command_args.virtual_static_address = (unsigned long)sep->shared_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
-
-       edbg("SEP Driver:bus_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
-
-       /* send the parameters to user application */
-       error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
-       if (error)
-               error = -EFAULT;
-       dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
-       return error;
-}
-
-/*
-  this address gets the offset of the physical address from the start
-  of the mapped area
-*/
-static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsigned long arg)
-{
-       int error;
-       struct sep_driver_get_mapped_offset_t command_args;
-
-       dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-
-       if (command_args.physical_address < sep->shared_bus) {
-               error = -EINVAL;
-               goto end_function;
-       }
-
-       /*prepare the output parameters in the struct */
-       command_args.offset = command_args.physical_address - sep->shared_bus;
-
-       edbg("SEP Driver:bus_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
-
-       /* send the parameters to user application */
-       error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
-       if (error)
-               error = -EFAULT;
-end_function:
-       dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
-       return error;
-}
-
-
-/*
-  ?
-*/
-static int sep_start_handler(struct sep_device *sep)
-{
-       unsigned long reg_val;
-       unsigned long error = 0;
-
-       dbg("SEP Driver:--------> sep_start_handler start\n");
-
-       /* wait in polling for message from SEP */
-       do
-               reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-       while (!reg_val);
-
-       /* check the value */
-       if (reg_val == 0x1)
-               /* fatal error - read error status from GPRO */
-               error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-       dbg("SEP Driver:<-------- sep_start_handler end\n");
-       return error;
-}
-
-/*
-  this function handles the request for SEP initialization
-*/
-static int sep_init_handler(struct sep_device *sep, unsigned long arg)
-{
-       unsigned long message_word;
-       unsigned long *message_ptr;
-       struct sep_driver_init_t command_args;
-       unsigned long counter;
-       unsigned long error;
-       unsigned long reg_val;
-
-       dbg("SEP Driver:--------> sep_init_handler start\n");
-       error = 0;
-
-       error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
-       if (error) {
-               error = -EFAULT;
-               goto end_function;
-       }
-       dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n");
-
-       /* PATCH - configure the DMA to single -burst instead of multi-burst */
-       /*sep_configure_dma_burst(); */
-
-       dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
-
-       message_ptr = (unsigned long *) command_args.message_addr;
-
-       /* set the base address of the SRAM  */
-       sep_write_reg(sep, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
-
-       for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
-               get_user(message_word, message_ptr);
-               /* write data to SRAM */
-               sep_write_reg(sep, HW_SRAM_DATA_REG_ADDR, message_word);
-               edbg("SEP Driver:message_word is %lu\n", message_word);
-               /* wait for write complete */
-               sep_wait_sram_write(sep);
-       }
-       dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
-       /* signal SEP */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
-
-       do
-               reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-       while (!(reg_val & 0xFFFFFFFD));
-
-       dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
-
-       /* check the value */
-       if (reg_val == 0x1) {
-               edbg("SEP Driver:init failed\n");
-
-               error = sep_read_reg(sep, 0x8060);
-               edbg("SEP Driver:sw monitor is %lu\n", error);
-
-               /* fatal error - read erro status from GPRO */
-               error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-               edbg("SEP Driver:error is %lu\n", error);
-       }
-end_function:
-       dbg("SEP Driver:<-------- sep_init_handler end\n");
-       return error;
-
-}
-
-/*
-  this function handles the request cache and resident reallocation
-*/
-static int sep_realloc_cache_resident_handler(struct sep_device *sep,
-                                               unsigned long arg)
-{
-       struct sep_driver_realloc_cache_resident_t command_args;
-       int error;
-
-       /* copy cache and resident to the their intended locations */
-       error = sep_load_firmware(sep);
-       if (error)
-               return error;
-
-       command_args.new_base_addr = sep->shared_bus;
-
-       /* find the new base address according to the lowest address between
-          cache, resident and shared area */
-       if (sep->resident_bus < command_args.new_base_addr)
-               command_args.new_base_addr = sep->resident_bus;
-       if (sep->rar_bus < command_args.new_base_addr)
-               command_args.new_base_addr = sep->rar_bus;
-
-       /* set the return parameters */
-       command_args.new_cache_addr = sep->rar_bus;
-       command_args.new_resident_addr = sep->resident_bus;
-
-       /* set the new shared area */
-       command_args.new_shared_area_addr = sep->shared_bus;
-
-       edbg("SEP Driver:command_args.new_shared_addr is %08llx\n", command_args.new_shared_area_addr);
-       edbg("SEP Driver:command_args.new_base_addr is %08llx\n", command_args.new_base_addr);
-       edbg("SEP Driver:command_args.new_resident_addr is %08llx\n", command_args.new_resident_addr);
-       edbg("SEP Driver:command_args.new_rar_addr is %08llx\n", command_args.new_cache_addr);
-
-       /* return to user */
-       if (copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_realloc_cache_resident_t)))
-               return -EFAULT;
-       return 0;
-}
-
-/**
- *     sep_get_time_handler    -       time request from user space
- *     @sep: sep we are to set the time for
- *     @arg: pointer to user space arg buffer
- *
- *     This function reports back the time and the address in the SEP
- *     shared buffer at which it has been placed. (Do we really need this!!!)
- */
-
-static int sep_get_time_handler(struct sep_device *sep, unsigned long arg)
-{
-       struct sep_driver_get_time_t command_args;
-
-       mutex_lock(&sep_mutex);
-       command_args.time_value = sep_set_time(sep);
-       command_args.time_physical_address = (unsigned long)sep_time_address(sep);
-       mutex_unlock(&sep_mutex);
-       if (copy_to_user((void __user *)arg,
-                       &command_args, sizeof(struct sep_driver_get_time_t)))
-                       return -EFAULT;
-       return 0;
-
-}
-
-/*
-  This API handles the end transaction request
-*/
-static int sep_end_transaction_handler(struct sep_device *sep, unsigned long arg)
-{
-       dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
-
-#if 0                          /*!SEP_DRIVER_POLLING_MODE */
-       /* close IMR */
-       sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF);
-
-       /* release IRQ line */
-       free_irq(SEP_DIRVER_IRQ_NUM, sep);
-
-       /* lock the sep mutex */
-       mutex_unlock(&sep_mutex);
-#endif
-
-       dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
-
-       return 0;
-}
-
-
-/**
- *     sep_set_flow_id_handler -       handle flow setting
- *     @sep: the SEP we are configuring
- *     @flow_id: the flow we are setting
- *
- * This function handler the set flow id command
- */
-static int sep_set_flow_id_handler(struct sep_device *sep,
-                                               unsigned long flow_id)
-{
-       int error = 0;
-       struct sep_flow_context_t *flow_data_ptr;
-
-       /* find the flow data structure that was just used for creating new flow
-          - its id should be default */
-
-       mutex_lock(&sep_mutex);
-       flow_data_ptr = sep_find_flow_context(sep, SEP_TEMP_FLOW_ID);
-       if (flow_data_ptr)
-               flow_data_ptr->flow_id = flow_id;       /* set flow id */
-       else
-               error = -EINVAL;
-       mutex_unlock(&sep_mutex);
-       return error;
-}
-
-static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       int error = 0;
-       struct sep_device *sep = filp->private_data;
-
-       dbg("------------>SEP Driver: ioctl start\n");
-
-       edbg("SEP Driver: cmd is %x\n", cmd);
-
-       switch (cmd) {
-       case SEP_IOCSENDSEPCOMMAND:
-               /* send command to SEP */
-               sep_send_command_handler(sep);
-               edbg("SEP Driver: after sep_send_command_handler\n");
-               break;
-       case SEP_IOCSENDSEPRPLYCOMMAND:
-               /* send reply command to SEP */
-               sep_send_reply_command_handler(sep);
-               break;
-       case SEP_IOCALLOCDATAPOLL:
-               /* allocate data pool */
-               error = sep_allocate_data_pool_memory_handler(sep, arg);
-               break;
-       case SEP_IOCWRITEDATAPOLL:
-               /* write data into memory pool */
-               error = sep_write_into_data_pool_handler(sep, arg);
-               break;
-       case SEP_IOCREADDATAPOLL:
-               /* read data from data pool into application memory */
-               error = sep_read_from_data_pool_handler(sep, arg);
-               break;
-       case SEP_IOCCREATESYMDMATABLE:
-               /* create dma table for synhronic operation */
-               error = sep_create_sync_dma_tables_handler(sep, arg);
-               break;
-       case SEP_IOCCREATEFLOWDMATABLE:
-               /* create flow dma tables */
-               error = sep_create_flow_dma_tables_handler(sep, arg);
-               break;
-       case SEP_IOCFREEDMATABLEDATA:
-               /* free the pages */
-               error = sep_free_dma_table_data_handler(sep);
-               break;
-       case SEP_IOCSETFLOWID:
-               /* set flow id */
-               error = sep_set_flow_id_handler(sep, (unsigned long)arg);
-               break;
-       case SEP_IOCADDFLOWTABLE:
-               /* add tables to the dynamic flow */
-               error = sep_add_flow_tables_handler(sep, arg);
-               break;
-       case SEP_IOCADDFLOWMESSAGE:
-               /* add message of add tables to flow */
-               error = sep_add_flow_tables_message_handler(sep, arg);
-               break;
-       case SEP_IOCSEPSTART:
-               /* start command to sep */
-               error = sep_start_handler(sep);
-               break;
-       case SEP_IOCSEPINIT:
-               /* init command to sep */
-               error = sep_init_handler(sep, arg);
-               break;
-       case SEP_IOCGETSTATICPOOLADDR:
-               /* get the physical and virtual addresses of the static pool */
-               error = sep_get_static_pool_addr_handler(sep, arg);
-               break;
-       case SEP_IOCENDTRANSACTION:
-               error = sep_end_transaction_handler(sep, arg);
-               break;
-       case SEP_IOCREALLOCCACHERES:
-               error = sep_realloc_cache_resident_handler(sep, arg);
-               break;
-       case SEP_IOCGETMAPPEDADDROFFSET:
-               error = sep_get_physical_mapped_offset_handler(sep, arg);
-               break;
-       case SEP_IOCGETIME:
-               error = sep_get_time_handler(sep, arg);
-               break;
-       default:
-               error = -ENOTTY;
-               break;
-       }
-       dbg("SEP Driver:<-------- ioctl end\n");
-       return error;
-}
-
-
-
-#if !SEP_DRIVER_POLLING_MODE
-
-/* handler for flow done interrupt */
-
-static void sep_flow_done_handler(struct work_struct *work)
-{
-       struct sep_flow_context_t *flow_data_ptr;
-
-       /* obtain the mutex */
-       mutex_lock(&sep_mutex);
-
-       /* get the pointer to context */
-       flow_data_ptr = (struct sep_flow_context_t *) work;
-
-       /* free all the current input tables in sep */
-       sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
-
-       /* free all the current tables output tables in SEP (if needed) */
-       if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
-               sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
-
-       /* check if we have additional tables to be sent to SEP only input
-          flag may be checked */
-       if (flow_data_ptr->input_tables_flag) {
-               /* copy the message to the shared RAM and signal SEP */
-               memcpy((void *) flow_data_ptr->message, (void *) sep->shared_addr, flow_data_ptr->message_size_in_bytes);
-
-               sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
-       }
-       mutex_unlock(&sep_mutex);
-}
-/*
-  interrupt handler function
-*/
-static irqreturn_t sep_inthandler(int irq, void *dev_id)
-{
-       irqreturn_t int_error;
-       unsigned long reg_val;
-       unsigned long flow_id;
-       struct sep_flow_context_t *flow_context_ptr;
-       struct sep_device *sep = dev_id;
-
-       int_error = IRQ_HANDLED;
-
-       /* read the IRR register to check if this is SEP interrupt */
-       reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR);
-       edbg("SEP Interrupt - reg is %08lx\n", reg_val);
-
-       /* check if this is the flow interrupt */
-       if (0 /*reg_val & (0x1 << 11) */ ) {
-               /* read GPRO to find out the which flow is done */
-               flow_id = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR);
-
-               /* find the contex of the flow */
-               flow_context_ptr = sep_find_flow_context(sep, flow_id >> 28);
-               if (flow_context_ptr == NULL)
-                       goto end_function_with_error;
-
-               /* queue the work */
-               INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
-               queue_work(sep->flow_wq, &flow_context_ptr->flow_wq);
-
-       } else {
-               /* check if this is reply interrupt from SEP */
-               if (reg_val & (0x1 << 13)) {
-                       /* update the counter of reply messages */
-                       sep->reply_ct++;
-                       /* wake up the waiting process */
-                       wake_up(&sep_event);
-               } else {
-                       int_error = IRQ_NONE;
-                       goto end_function;
-               }
-       }
-end_function_with_error:
-       /* clear the interrupt */
-       sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, reg_val);
-end_function:
-       return int_error;
-}
-
-#endif
-
-
-
-#if 0
-
-static void sep_wait_busy(struct sep_device *sep)
-{
-       u32 reg;
-
-       do {
-               reg = sep_read_reg(sep, HW_HOST_SEP_BUSY_REG_ADDR);
-       } while (reg);
-}
-
-/*
-  PATCH for configuring the DMA to single burst instead of multi-burst
-*/
-static void sep_configure_dma_burst(struct sep_device *sep)
-{
-#define         HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
-
-       dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
-
-       /* request access to registers from SEP */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
-
-       dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
-
-       sep_wait_busy(sep);
-
-       dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
-
-       /* set the DMA burst register to single burst */
-       sep_write_reg(sep, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
-
-       /* release the sep busy */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
-       sep_wait_busy(sep);
-
-       dbg("SEP Driver:<-------- sep_configure_dma_burst done  \n");
-
-}
-
-#endif
-
-/*
-  Function that is activated on the successful probe of the SEP device
-*/
-static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       int error = 0;
-       struct sep_device *sep;
-       int counter;
-       int size;               /* size of memory for allocation */
-
-       edbg("Sep pci probe starting\n");
-       if (sep_dev != NULL) {
-               dev_warn(&pdev->dev, "only one SEP supported.\n");
-               return -EBUSY;
-       }
-
-       /* enable the device */
-       error = pci_enable_device(pdev);
-       if (error) {
-               edbg("error enabling pci device\n");
-               goto end_function;
-       }
-
-       /* set the pci dev pointer */
-       sep_dev = &sep_instance;
-       sep = &sep_instance;
-
-       edbg("sep->shared_addr = %p\n", sep->shared_addr);
-       /* transaction counter that coordinates the transactions between SEP
-       and HOST */
-       sep->send_ct = 0;
-       /* counter for the messages from sep */
-       sep->reply_ct = 0;
-       /* counter for the number of bytes allocated in the pool
-       for the current transaction */
-       sep->data_pool_bytes_allocated = 0;
-
-       /* calculate the total size for allocation */
-       size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
-           SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
-
-       /* allocate the shared area */
-       if (sep_map_and_alloc_shared_area(sep, size)) {
-               error = -ENOMEM;
-               /* allocation failed */
-               goto end_function_error;
-       }
-       /* now set the memory regions */
-#if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
-       /* Note: this test section will need moving before it could ever
-          work as the registers are not yet mapped ! */
-       /* send the new SHARED MESSAGE AREA to the SEP */
-       sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus);
-
-       /* poll for SEP response */
-       retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
-       while (retval != 0xffffffff && retval != sep->shared_bus)
-               retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
-
-       /* check the return value (register) */
-       if (retval != sep->shared_bus) {
-               error = -ENOMEM;
-               goto end_function_deallocate_sep_shared_area;
-       }
-#endif
-       /* init the flow contextes */
-       for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
-               sep->flows[counter].flow_id = SEP_FREE_FLOW_ID;
-
-       sep->flow_wq = create_singlethread_workqueue("sepflowwq");
-       if (sep->flow_wq == NULL) {
-               error = -ENOMEM;
-               edbg("sep_driver:flow queue creation failed\n");
-               goto end_function_deallocate_sep_shared_area;
-       }
-       edbg("SEP Driver: create flow workqueue \n");
-       sep->pdev = pci_dev_get(pdev);
-
-       sep->reg_addr = pci_ioremap_bar(pdev, 0);
-       if (!sep->reg_addr) {
-               edbg("sep: ioremap of registers failed.\n");
-               goto end_function_deallocate_sep_shared_area;
-       }
-       edbg("SEP Driver:reg_addr is %p\n", sep->reg_addr);
-
-       /* load the rom code */
-       sep_load_rom_code(sep);
-
-       /* set up system base address and shared memory location */
-       sep->rar_addr = dma_alloc_coherent(&sep->pdev->dev,
-                       2 * SEP_RAR_IO_MEM_REGION_SIZE,
-                       &sep->rar_bus, GFP_KERNEL);
-
-       if (!sep->rar_addr) {
-               edbg("SEP Driver:can't allocate rar\n");
-               goto end_function_uniomap;
-       }
-
-
-       edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus);
-       edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr);
-
-#if !SEP_DRIVER_POLLING_MODE
-
-       edbg("SEP Driver: about to write IMR and ICR REG_ADDR\n");
-
-       /* clear ICR register */
-       sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF);
-
-       /* set the IMR register - open only GPR 2 */
-       sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
-
-       edbg("SEP Driver: about to call request_irq\n");
-       /* get the interrupt line */
-       error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, "sep_driver", sep);
-       if (error)
-               goto end_function_free_res;
-       return 0;
-       edbg("SEP Driver: about to write IMR REG_ADDR");
-
-       /* set the IMR register - open only GPR 2 */
-       sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
-
-end_function_free_res:
-       dma_free_coherent(&sep->pdev->dev, 2 * SEP_RAR_IO_MEM_REGION_SIZE,
-                       sep->rar_addr, sep->rar_bus);
-#endif                         /* SEP_DRIVER_POLLING_MODE */
-end_function_uniomap:
-       iounmap(sep->reg_addr);
-end_function_deallocate_sep_shared_area:
-       /* de-allocate shared area */
-       sep_unmap_and_free_shared_area(sep, size);
-end_function_error:
-       sep_dev = NULL;
-end_function:
-       return error;
-}
-
-static const struct pci_device_id sep_pci_id_tbl[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
-       {0}
-};
-
-MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl);
-
-/* field for registering driver to PCI device */
-static struct pci_driver sep_pci_driver = {
-       .name = "sep_sec_driver",
-       .id_table = sep_pci_id_tbl,
-       .probe = sep_probe
-       /* FIXME: remove handler */
-};
-
-/* major and minor device numbers */
-static dev_t sep_devno;
-
-/* the files operations structure of the driver */
-static struct file_operations sep_file_operations = {
-       .owner = THIS_MODULE,
-       .unlocked_ioctl = sep_ioctl,
-       .poll = sep_poll,
-       .open = sep_open,
-       .release = sep_release,
-       .mmap = sep_mmap,
-};
-
-
-/* cdev struct of the driver */
-static struct cdev sep_cdev;
-
-/*
-  this function registers the driver to the file system
-*/
-static int sep_register_driver_to_fs(void)
-{
-       int ret_val = alloc_chrdev_region(&sep_devno, 0, 1, "sep_sec_driver");
-       if (ret_val) {
-               edbg("sep: major number allocation failed, retval is %d\n",
-                                                               ret_val);
-               return ret_val;
-       }
-       /* init cdev */
-       cdev_init(&sep_cdev, &sep_file_operations);
-       sep_cdev.owner = THIS_MODULE;
-
-       /* register the driver with the kernel */
-       ret_val = cdev_add(&sep_cdev, sep_devno, 1);
-       if (ret_val) {
-               edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
-               /* unregister dev numbers */
-               unregister_chrdev_region(sep_devno, 1);
-       }
-       return ret_val;
-}
-
-
-/*--------------------------------------------------------------
-  init function
-----------------------------------------------------------------*/
-static int __init sep_init(void)
-{
-       int ret_val = 0;
-       dbg("SEP Driver:-------->Init start\n");
-       /* FIXME: Probe can occur before we are ready to survive a probe */
-       ret_val = pci_register_driver(&sep_pci_driver);
-       if (ret_val) {
-               edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
-               goto end_function_unregister_from_fs;
-       }
-       /* register driver to fs */
-       ret_val = sep_register_driver_to_fs();
-       if (ret_val)
-               goto end_function_unregister_pci;
-       goto end_function;
-end_function_unregister_pci:
-       pci_unregister_driver(&sep_pci_driver);
-end_function_unregister_from_fs:
-       /* unregister from fs */
-       cdev_del(&sep_cdev);
-       /* unregister dev numbers */
-       unregister_chrdev_region(sep_devno, 1);
-end_function:
-       dbg("SEP Driver:<-------- Init end\n");
-       return ret_val;
-}
-
-
-/*-------------------------------------------------------------
-  exit function
---------------------------------------------------------------*/
-static void __exit sep_exit(void)
-{
-       int size;
-
-       dbg("SEP Driver:--------> Exit start\n");
-
-       /* unregister from fs */
-       cdev_del(&sep_cdev);
-       /* unregister dev numbers */
-       unregister_chrdev_region(sep_devno, 1);
-       /* calculate the total size for de-allocation */
-       size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
-           SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
-       /* FIXME: We need to do this in the unload for the device */
-       /* free shared area  */
-       if (sep_dev) {
-               sep_unmap_and_free_shared_area(sep_dev, size);
-               edbg("SEP Driver: free pages SEP SHARED AREA \n");
-               iounmap((void *) sep_dev->reg_addr);
-               edbg("SEP Driver: iounmap \n");
-       }
-       edbg("SEP Driver: release_mem_region \n");
-       dbg("SEP Driver:<-------- Exit end\n");
-}
-
-
-module_init(sep_init);
-module_exit(sep_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h
deleted file mode 100644 (file)
index 7ef16da..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- *
- *  sep_driver_api.h - Security Processor Driver api definitions
- *
- *  Copyright(c) 2009 Intel Corporation. All rights reserved.
- *  Copyright(c) 2009 Discretix. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License 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.
- *
- *  CONTACTS:
- *
- *  Mark Allyn         mark.a.allyn@intel.com
- *
- *  CHANGES:
- *
- *  2009.06.26 Initial publish
- *
- */
-
-#ifndef __SEP_DRIVER_API_H__
-#define __SEP_DRIVER_API_H__
-
-
-
-/*----------------------------------------------------------------
-  IOCTL command defines
-  -----------------------------------------------------------------*/
-
-/* magic number 1 of the sep IOCTL command */
-#define SEP_IOC_MAGIC_NUMBER                           's'
-
-/* sends interrupt to sep that message is ready */
-#define SEP_IOCSENDSEPCOMMAND                 _IO(SEP_IOC_MAGIC_NUMBER , 0)
-
-/* sends interrupt to sep that message is ready */
-#define SEP_IOCSENDSEPRPLYCOMMAND             _IO(SEP_IOC_MAGIC_NUMBER , 1)
-
-/* allocate memory in data pool */
-#define SEP_IOCALLOCDATAPOLL                  _IO(SEP_IOC_MAGIC_NUMBER , 2)
-
-/* write to pre-allocated  memory in data pool */
-#define SEP_IOCWRITEDATAPOLL                  _IO(SEP_IOC_MAGIC_NUMBER , 3)
-
-/* read from  pre-allocated  memory in data pool */
-#define SEP_IOCREADDATAPOLL                   _IO(SEP_IOC_MAGIC_NUMBER , 4)
-
-/* create sym dma lli tables */
-#define SEP_IOCCREATESYMDMATABLE              _IO(SEP_IOC_MAGIC_NUMBER , 5)
-
-/* create flow dma lli tables */
-#define SEP_IOCCREATEFLOWDMATABLE             _IO(SEP_IOC_MAGIC_NUMBER , 6)
-
-/* free dynamic data aalocated during table creation */
-#define SEP_IOCFREEDMATABLEDATA                _IO(SEP_IOC_MAGIC_NUMBER , 7)
-
-/* get the static pool area addresses (physical and virtual) */
-#define SEP_IOCGETSTATICPOOLADDR               _IO(SEP_IOC_MAGIC_NUMBER , 8)
-
-/* set flow id command */
-#define SEP_IOCSETFLOWID                       _IO(SEP_IOC_MAGIC_NUMBER , 9)
-
-/* add tables to the dynamic flow */
-#define SEP_IOCADDFLOWTABLE                    _IO(SEP_IOC_MAGIC_NUMBER , 10)
-
-/* add flow add tables message */
-#define SEP_IOCADDFLOWMESSAGE                  _IO(SEP_IOC_MAGIC_NUMBER , 11)
-
-/* start sep command */
-#define SEP_IOCSEPSTART                        _IO(SEP_IOC_MAGIC_NUMBER , 12)
-
-/* init sep command */
-#define SEP_IOCSEPINIT                         _IO(SEP_IOC_MAGIC_NUMBER , 13)
-
-/* end transaction command */
-#define SEP_IOCENDTRANSACTION                  _IO(SEP_IOC_MAGIC_NUMBER , 15)
-
-/* reallocate cache and resident */
-#define SEP_IOCREALLOCCACHERES                 _IO(SEP_IOC_MAGIC_NUMBER , 16)
-
-/* get the offset of the address starting from the beginnnig of the map area */
-#define SEP_IOCGETMAPPEDADDROFFSET             _IO(SEP_IOC_MAGIC_NUMBER , 17)
-
-/* get time address and value */
-#define SEP_IOCGETIME                          _IO(SEP_IOC_MAGIC_NUMBER , 19)
-
-/*-------------------------------------------
-    TYPEDEFS
-----------------------------------------------*/
-
-/*
-  init command struct
-*/
-struct sep_driver_init_t {
-       /* start of the 1G of the host memory address that SEP can access */
-       unsigned long message_addr;
-
-       /* start address of resident */
-       unsigned long message_size_in_words;
-
-};
-
-
-/*
-  realloc cache resident command
-*/
-struct sep_driver_realloc_cache_resident_t {
-       /* new cache address */
-       u64 new_cache_addr;
-       /* new resident address */
-       u64 new_resident_addr;
-       /* new resident address */
-       u64  new_shared_area_addr;
-       /* new base address */
-       u64 new_base_addr;
-};
-
-struct sep_driver_alloc_t {
-       /* virtual address of allocated space */
-       unsigned long offset;
-
-       /* physical address of allocated space */
-       unsigned long phys_address;
-
-       /* number of bytes to allocate */
-       unsigned long num_bytes;
-};
-
-/*
- */
-struct sep_driver_write_t {
-       /* application space address */
-       unsigned long app_address;
-
-       /* address of the data pool */
-       unsigned long datapool_address;
-
-       /* number of bytes to write */
-       unsigned long num_bytes;
-};
-
-/*
- */
-struct sep_driver_read_t {
-       /* application space address */
-       unsigned long app_address;
-
-       /* address of the data pool */
-       unsigned long datapool_address;
-
-       /* number of bytes to read */
-       unsigned long num_bytes;
-};
-
-/*
-*/
-struct sep_driver_build_sync_table_t {
-       /* address value of the data in */
-       unsigned long app_in_address;
-
-       /* size of data in */
-       unsigned long data_in_size;
-
-       /* address of the data out */
-       unsigned long app_out_address;
-
-       /* the size of the block of the operation - if needed,
-          every table will be modulo this parameter */
-       unsigned long block_size;
-
-       /* the physical address of the first input DMA table */
-       unsigned long in_table_address;
-
-       /* number of entries in the first input DMA table */
-       unsigned long in_table_num_entries;
-
-       /* the physical address of the first output DMA table */
-       unsigned long out_table_address;
-
-       /* number of entries in the first output DMA table */
-       unsigned long out_table_num_entries;
-
-       /* data in the first input table */
-       unsigned long table_data_size;
-
-       /* distinct user/kernel layout */
-       bool isKernelVirtualAddress;
-
-};
-
-/*
-*/
-struct sep_driver_build_flow_table_t {
-       /* flow type */
-       unsigned long flow_type;
-
-       /* flag for input output */
-       unsigned long input_output_flag;
-
-       /* address value of the data in */
-       unsigned long virt_buff_data_addr;
-
-       /* size of data in */
-       unsigned long num_virtual_buffers;
-
-       /* the physical address of the first input DMA table */
-       unsigned long first_table_addr;
-
-       /* number of entries in the first input DMA table */
-       unsigned long first_table_num_entries;
-
-       /* data in the first input table */
-       unsigned long first_table_data_size;
-
-       /* distinct user/kernel layout */
-       bool isKernelVirtualAddress;
-};
-
-
-struct sep_driver_add_flow_table_t {
-       /* flow id  */
-       unsigned long flow_id;
-
-       /* flag for input output */
-       unsigned long inputOutputFlag;
-
-       /* address value of the data in */
-       unsigned long virt_buff_data_addr;
-
-       /* size of data in */
-       unsigned long num_virtual_buffers;
-
-       /* address of the first table */
-       unsigned long first_table_addr;
-
-       /* number of entries in the first table */
-       unsigned long first_table_num_entries;
-
-       /* data size of the first table */
-       unsigned long first_table_data_size;
-
-       /* distinct user/kernel layout */
-       bool isKernelVirtualAddress;
-
-};
-
-/*
-  command struct for set flow id
-*/
-struct sep_driver_set_flow_id_t {
-       /* flow id to set */
-       unsigned long flow_id;
-};
-
-
-/* command struct for add tables message */
-struct sep_driver_add_message_t {
-       /* flow id to set */
-       unsigned long flow_id;
-
-       /* message size in bytes */
-       unsigned long message_size_in_bytes;
-
-       /* address of the message */
-       unsigned long message_address;
-};
-
-/* command struct for static pool addresses  */
-struct sep_driver_static_pool_addr_t {
-       /* physical address of the static pool */
-       unsigned long physical_static_address;
-
-       /* virtual address of the static pool */
-       unsigned long virtual_static_address;
-};
-
-/* command struct for getiing offset of the physical address from
-       the start of the mapped area  */
-struct sep_driver_get_mapped_offset_t {
-       /* physical address of the static pool */
-       unsigned long physical_address;
-
-       /* virtual address of the static pool */
-       unsigned long offset;
-};
-
-/* command struct for getting time value and address */
-struct sep_driver_get_time_t {
-       /* physical address of stored time */
-       unsigned long time_physical_address;
-
-       /* value of the stored time */
-       unsigned long time_value;
-};
-
-
-/*
-  structure that represent one entry in the DMA LLI table
-*/
-struct sep_lli_entry_t {
-       /* physical address */
-       unsigned long physical_address;
-
-       /* block size */
-       unsigned long block_size;
-};
-
-/*
-  structure that reperesents data needed for lli table construction
-*/
-struct sep_lli_prepare_table_data_t {
-       /* pointer to the memory where the first lli entry to be built */
-       struct sep_lli_entry_t *lli_entry_ptr;
-
-       /* pointer to the array of lli entries from which the table is to be built */
-       struct sep_lli_entry_t *lli_array_ptr;
-
-       /* number of elements in lli array */
-       int lli_array_size;
-
-       /* number of entries in the created table */
-       int num_table_entries;
-
-       /* number of array entries processed during table creation */
-       int num_array_entries_processed;
-
-       /* the totatl data size in the created table */
-       int lli_table_total_data_size;
-};
-
-/*
-  structure that represent tone table - it is not used in code, jkust
-  to show what table looks like
-*/
-struct sep_lli_table_t {
-       /* number of pages mapped in this tables. If 0 - means that the table
-          is not defined (used as a valid flag) */
-       unsigned long num_pages;
-       /*
-          pointer to array of page pointers that represent the mapping of the
-          virtual buffer defined by the table to the physical memory. If this
-          pointer is NULL, it means that the table is not defined
-          (used as a valid flag)
-        */
-       struct page **table_page_array_ptr;
-
-       /* maximum flow entries in table */
-       struct sep_lli_entry_t lli_entries[SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE];
-};
-
-
-/*
-  structure for keeping the mapping of the virtual buffer into physical pages
-*/
-struct sep_flow_buffer_data {
-       /* pointer to the array of page structs pointers to the pages of the
-          virtual buffer */
-       struct page **page_array_ptr;
-
-       /* number of pages taken by the virtual buffer */
-       unsigned long num_pages;
-
-       /* this flag signals if this page_array is the last one among many that were
-          sent in one setting to SEP */
-       unsigned long last_page_array_flag;
-};
-
-/*
-  struct that keeps all the data for one flow
-*/
-struct sep_flow_context_t {
-       /*
-          work struct for handling the flow done interrupt in the workqueue
-          this structure must be in the first place, since it will be used
-          forcasting to the containing flow context
-        */
-       struct work_struct flow_wq;
-
-       /* flow id */
-       unsigned long flow_id;
-
-       /* additional input tables exists */
-       unsigned long input_tables_flag;
-
-       /* additional output tables exists */
-       unsigned long output_tables_flag;
-
-       /*  data of the first input file */
-       struct sep_lli_entry_t first_input_table;
-
-       /* data of the first output table */
-       struct sep_lli_entry_t first_output_table;
-
-       /* last input table data */
-       struct sep_lli_entry_t last_input_table;
-
-       /* last output table data */
-       struct sep_lli_entry_t last_output_table;
-
-       /* first list of table */
-       struct sep_lli_entry_t input_tables_in_process;
-
-       /* output table in process (in sep) */
-       struct sep_lli_entry_t output_tables_in_process;
-
-       /* size of messages in bytes */
-       unsigned long message_size_in_bytes;
-
-       /* message */
-       unsigned char message[SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES];
-};
-
-
-#endif
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
deleted file mode 100644 (file)
index 6008fe5..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- *
- *  sep_driver_config.h - Security Processor Driver configuration
- *
- *  Copyright(c) 2009 Intel Corporation. All rights reserved.
- *  Copyright(c) 2009 Discretix. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License 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.
- *
- *  CONTACTS:
- *
- *  Mark Allyn         mark.a.allyn@intel.com
- *
- *  CHANGES:
- *
- *  2009.06.26 Initial publish
- *
- */
-
-#ifndef __SEP_DRIVER_CONFIG_H__
-#define __SEP_DRIVER_CONFIG_H__
-
-
-/*--------------------------------------
-  DRIVER CONFIGURATION FLAGS
-  -------------------------------------*/
-
-/* if flag is on , then the driver is running in polling and
-       not interrupt mode */
-#define SEP_DRIVER_POLLING_MODE                         1
-
-/* flag which defines if the shared area address should be
-       reconfiged (send to SEP anew) during init of the driver */
-#define SEP_DRIVER_RECONFIG_MESSAGE_AREA                0
-
-/* the mode for running on the ARM1172 Evaluation platform (flag is 1) */
-#define SEP_DRIVER_ARM_DEBUG_MODE                       0
-
-/*-------------------------------------------
-       INTERNAL DATA CONFIGURATION
-       -------------------------------------------*/
-
-/* flag for the input array */
-#define SEP_DRIVER_IN_FLAG                              0
-
-/* flag for output array */
-#define SEP_DRIVER_OUT_FLAG                             1
-
-/* maximum number of entries in one LLI tables */
-#define SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP             8
-
-
-/*--------------------------------------------------------
-       SHARED AREA  memory total size is 36K
-       it is divided is following:
-
-       SHARED_MESSAGE_AREA                     8K         }
-                                                                       }
-       STATIC_POOL_AREA                        4K         } MAPPED AREA ( 24 K)
-                                                                       }
-       DATA_POOL_AREA                          12K        }
-
-       SYNCHRONIC_DMA_TABLES_AREA              5K
-
-       FLOW_DMA_TABLES_AREA                    4K
-
-       SYSTEM_MEMORY_AREA                      3k
-
-       SYSTEM_MEMORY total size is 3k
-       it is divided as following:
-
-       TIME_MEMORY_AREA                     8B
------------------------------------------------------------*/
-
-
-
-/*
-       the maximum length of the message - the rest of the message shared
-       area will be dedicated to the dma lli tables
-*/
-#define SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES                  (8 * 1024)
-
-/* the size of the message shared area in pages */
-#define SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES          (8 * 1024)
-
-/* the size of the data pool static area in pages */
-#define SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES                  (4 * 1024)
-
-/* the size of the data pool shared area size in pages */
-#define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES        (12 * 1024)
-
-/* the size of the message shared area in pages */
-#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES   (1024 * 5)
-
-
-/* the size of the data pool shared area size in pages */
-#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES         (1024 * 4)
-
-/* system data (time, caller id etc') pool */
-#define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES           100
-
-
-/* area size that is mapped  - we map the MESSAGE AREA, STATIC POOL and
-       DATA POOL areas. area must be module 4k */
-#define SEP_DRIVER_MMMAP_AREA_SIZE                            (1024 * 24)
-
-
-/*-----------------------------------------------
-       offsets of the areas starting from the shared area start address
-*/
-
-/* message area offset */
-#define SEP_DRIVER_MESSAGE_AREA_OFFSET_IN_BYTES               0
-
-/* static pool area offset */
-#define SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES \
-               (SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES)
-
-/* data pool area offset */
-#define SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES \
-       (SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \
-       SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES)
-
-/* synhronic dma tables area offset */
-#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES \
-       (SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \
-       SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES)
-
-/* sep driver flow dma tables area offset */
-#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES \
-       (SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
-       SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES)
-
-/* system memory offset in bytes */
-#define SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES \
-       (SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
-       SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES)
-
-/* offset of the time area */
-#define SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES \
-       (SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES)
-
-
-
-/* start physical address of the SEP registers memory in HOST */
-#define SEP_IO_MEM_REGION_START_ADDRESS                       0x80000000
-
-/* size of the SEP registers memory region  in HOST (for now 100 registers) */
-#define SEP_IO_MEM_REGION_SIZE                                (2 * 0x100000)
-
-/* define the number of IRQ for SEP interrupts */
-#define SEP_DIRVER_IRQ_NUM                                    1
-
-/* maximum number of add buffers */
-#define SEP_MAX_NUM_ADD_BUFFERS                               100
-
-/* number of flows */
-#define SEP_DRIVER_NUM_FLOWS                                  4
-
-/* maximum number of entries in flow table */
-#define SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE              25
-
-/* offset of the num entries in the block length entry of the LLI */
-#define SEP_NUM_ENTRIES_OFFSET_IN_BITS                        24
-
-/* offset of the interrupt flag in the block length entry of the LLI */
-#define SEP_INT_FLAG_OFFSET_IN_BITS                           31
-
-/* mask for extracting data size from LLI */
-#define SEP_TABLE_DATA_SIZE_MASK                              0xFFFFFF
-
-/* mask for entries after being shifted left */
-#define SEP_NUM_ENTRIES_MASK                                  0x7F
-
-/* default flow id */
-#define SEP_FREE_FLOW_ID                                      0xFFFFFFFF
-
-/* temp flow id used during cretiong of new flow until receiving
-       real flow id from sep */
-#define SEP_TEMP_FLOW_ID                   (SEP_DRIVER_NUM_FLOWS + 1)
-
-/* maximum add buffers message length in bytes */
-#define SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES                   (7 * 4)
-
-/* maximum number of concurrent virtual buffers */
-#define SEP_MAX_VIRT_BUFFERS_CONCURRENT                       100
-
-/* the token that defines the start of time address */
-#define SEP_TIME_VAL_TOKEN                                    0x12345678
-
-/* DEBUG LEVEL MASKS */
-#define SEP_DEBUG_LEVEL_BASIC       0x1
-
-#define SEP_DEBUG_LEVEL_EXTENDED    0x4
-
-
-/* Debug helpers */
-
-#define dbg(fmt, args...) \
-do {\
-       if (debug & SEP_DEBUG_LEVEL_BASIC) \
-               printk(KERN_DEBUG fmt, ##args); \
-} while(0);
-
-#define edbg(fmt, args...) \
-do { \
-       if (debug & SEP_DEBUG_LEVEL_EXTENDED) \
-               printk(KERN_DEBUG fmt, ##args); \
-} while(0);
-
-
-
-#endif
diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h
deleted file mode 100644 (file)
index ea6abd8..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *
- *  sep_driver_hw_defs.h - Security Processor Driver hardware definitions
- *
- *  Copyright(c) 2009 Intel Corporation. All rights reserved.
- *  Copyright(c) 2009 Discretix. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License 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.
- *
- *  CONTACTS:
- *
- *  Mark Allyn         mark.a.allyn@intel.com
- *
- *  CHANGES:
- *
- *  2009.06.26 Initial publish
- *
- */
-
-#ifndef SEP_DRIVER_HW_DEFS__H
-#define SEP_DRIVER_HW_DEFS__H
-
-/*--------------------------------------------------------------------------*/
-/* Abstract: HW Registers Defines.                                          */
-/*                                                                          */
-/* Note: This file was automatically created !!!                            */
-/*       DO NOT EDIT THIS FILE !!!                                          */
-/*--------------------------------------------------------------------------*/
-
-
-/* cf registers */
-#define         HW_R0B_ADDR_0_REG_ADDR                  0x0000UL
-#define         HW_R0B_ADDR_1_REG_ADDR                  0x0004UL
-#define         HW_R0B_ADDR_2_REG_ADDR                  0x0008UL
-#define         HW_R0B_ADDR_3_REG_ADDR                  0x000cUL
-#define         HW_R0B_ADDR_4_REG_ADDR                  0x0010UL
-#define         HW_R0B_ADDR_5_REG_ADDR                  0x0014UL
-#define         HW_R0B_ADDR_6_REG_ADDR                  0x0018UL
-#define         HW_R0B_ADDR_7_REG_ADDR                  0x001cUL
-#define         HW_R0B_ADDR_8_REG_ADDR                  0x0020UL
-#define         HW_R2B_ADDR_0_REG_ADDR                  0x0080UL
-#define         HW_R2B_ADDR_1_REG_ADDR                  0x0084UL
-#define         HW_R2B_ADDR_2_REG_ADDR                  0x0088UL
-#define         HW_R2B_ADDR_3_REG_ADDR                  0x008cUL
-#define         HW_R2B_ADDR_4_REG_ADDR                  0x0090UL
-#define         HW_R2B_ADDR_5_REG_ADDR                  0x0094UL
-#define         HW_R2B_ADDR_6_REG_ADDR                  0x0098UL
-#define         HW_R2B_ADDR_7_REG_ADDR                  0x009cUL
-#define         HW_R2B_ADDR_8_REG_ADDR                  0x00a0UL
-#define         HW_R3B_REG_ADDR                         0x00C0UL
-#define         HW_R4B_REG_ADDR                         0x0100UL
-#define         HW_CSA_ADDR_0_REG_ADDR                  0x0140UL
-#define         HW_CSA_ADDR_1_REG_ADDR                  0x0144UL
-#define         HW_CSA_ADDR_2_REG_ADDR                  0x0148UL
-#define         HW_CSA_ADDR_3_REG_ADDR                  0x014cUL
-#define         HW_CSA_ADDR_4_REG_ADDR                  0x0150UL
-#define         HW_CSA_ADDR_5_REG_ADDR                  0x0154UL
-#define         HW_CSA_ADDR_6_REG_ADDR                  0x0158UL
-#define         HW_CSA_ADDR_7_REG_ADDR                  0x015cUL
-#define         HW_CSA_ADDR_8_REG_ADDR                  0x0160UL
-#define         HW_CSA_REG_ADDR                         0x0140UL
-#define         HW_SINB_REG_ADDR                        0x0180UL
-#define         HW_SOUTB_REG_ADDR                       0x0184UL
-#define         HW_PKI_CONTROL_REG_ADDR                 0x01C0UL
-#define         HW_PKI_STATUS_REG_ADDR                  0x01C4UL
-#define         HW_PKI_BUSY_REG_ADDR                0x01C8UL
-#define         HW_PKI_A_1025_REG_ADDR                  0x01CCUL
-#define         HW_PKI_SDMA_CTL_REG_ADDR                0x01D0UL
-#define         HW_PKI_SDMA_OFFSET_REG_ADDR     0x01D4UL
-#define         HW_PKI_SDMA_POINTERS_REG_ADDR   0x01D8UL
-#define         HW_PKI_SDMA_DLENG_REG_ADDR              0x01DCUL
-#define         HW_PKI_SDMA_EXP_POINTERS_REG_ADDR       0x01E0UL
-#define         HW_PKI_SDMA_RES_POINTERS_REG_ADDR       0x01E4UL
-#define         HW_PKI_CLR_REG_ADDR                     0x01E8UL
-#define         HW_PKI_SDMA_BUSY_REG_ADDR                   0x01E8UL
-#define         HW_PKI_SDMA_FIRST_EXP_N_REG_ADDR        0x01ECUL
-#define         HW_PKI_SDMA_MUL_BY1_REG_ADDR            0x01F0UL
-#define         HW_PKI_SDMA_RMUL_SEL_REG_ADDR           0x01F4UL
-#define         HW_DES_KEY_0_REG_ADDR                   0x0208UL
-#define         HW_DES_KEY_1_REG_ADDR                   0x020CUL
-#define         HW_DES_KEY_2_REG_ADDR                   0x0210UL
-#define         HW_DES_KEY_3_REG_ADDR                   0x0214UL
-#define         HW_DES_KEY_4_REG_ADDR                   0x0218UL
-#define         HW_DES_KEY_5_REG_ADDR                   0x021CUL
-#define         HW_DES_CONTROL_0_REG_ADDR               0x0220UL
-#define         HW_DES_CONTROL_1_REG_ADDR               0x0224UL
-#define         HW_DES_IV_0_REG_ADDR                    0x0228UL
-#define         HW_DES_IV_1_REG_ADDR                    0x022CUL
-#define         HW_AES_KEY_0_ADDR_0_REG_ADDR            0x0400UL
-#define         HW_AES_KEY_0_ADDR_1_REG_ADDR            0x0404UL
-#define         HW_AES_KEY_0_ADDR_2_REG_ADDR            0x0408UL
-#define         HW_AES_KEY_0_ADDR_3_REG_ADDR            0x040cUL
-#define         HW_AES_KEY_0_ADDR_4_REG_ADDR            0x0410UL
-#define         HW_AES_KEY_0_ADDR_5_REG_ADDR            0x0414UL
-#define         HW_AES_KEY_0_ADDR_6_REG_ADDR            0x0418UL
-#define         HW_AES_KEY_0_ADDR_7_REG_ADDR            0x041cUL
-#define         HW_AES_KEY_0_REG_ADDR                   0x0400UL
-#define         HW_AES_IV_0_ADDR_0_REG_ADDR             0x0440UL
-#define         HW_AES_IV_0_ADDR_1_REG_ADDR             0x0444UL
-#define         HW_AES_IV_0_ADDR_2_REG_ADDR             0x0448UL
-#define         HW_AES_IV_0_ADDR_3_REG_ADDR             0x044cUL
-#define         HW_AES_IV_0_REG_ADDR                    0x0440UL
-#define         HW_AES_CTR1_ADDR_0_REG_ADDR             0x0460UL
-#define         HW_AES_CTR1_ADDR_1_REG_ADDR             0x0464UL
-#define         HW_AES_CTR1_ADDR_2_REG_ADDR             0x0468UL
-#define         HW_AES_CTR1_ADDR_3_REG_ADDR             0x046cUL
-#define         HW_AES_CTR1_REG_ADDR                    0x0460UL
-#define         HW_AES_SK_REG_ADDR                      0x0478UL
-#define         HW_AES_MAC_OK_REG_ADDR                      0x0480UL
-#define         HW_AES_PREV_IV_0_ADDR_0_REG_ADDR        0x0490UL
-#define         HW_AES_PREV_IV_0_ADDR_1_REG_ADDR        0x0494UL
-#define         HW_AES_PREV_IV_0_ADDR_2_REG_ADDR        0x0498UL
-#define         HW_AES_PREV_IV_0_ADDR_3_REG_ADDR        0x049cUL
-#define         HW_AES_PREV_IV_0_REG_ADDR                   0x0490UL
-#define         HW_AES_CONTROL_REG_ADDR                     0x04C0UL
-#define         HW_HASH_H0_REG_ADDR                 0x0640UL
-#define         HW_HASH_H1_REG_ADDR                 0x0644UL
-#define         HW_HASH_H2_REG_ADDR                 0x0648UL
-#define         HW_HASH_H3_REG_ADDR                 0x064CUL
-#define         HW_HASH_H4_REG_ADDR                 0x0650UL
-#define         HW_HASH_H5_REG_ADDR                 0x0654UL
-#define         HW_HASH_H6_REG_ADDR                 0x0658UL
-#define         HW_HASH_H7_REG_ADDR                 0x065CUL
-#define         HW_HASH_H8_REG_ADDR                 0x0660UL
-#define         HW_HASH_H9_REG_ADDR                 0x0664UL
-#define         HW_HASH_H10_REG_ADDR                0x0668UL
-#define         HW_HASH_H11_REG_ADDR                0x066CUL
-#define         HW_HASH_H12_REG_ADDR                0x0670UL
-#define         HW_HASH_H13_REG_ADDR                0x0674UL
-#define         HW_HASH_H14_REG_ADDR                0x0678UL
-#define         HW_HASH_H15_REG_ADDR                0x067CUL
-#define         HW_HASH_CONTROL_REG_ADDR                0x07C0UL
-#define         HW_HASH_PAD_EN_REG_ADDR                 0x07C4UL
-#define         HW_HASH_PAD_CFG_REG_ADDR                0x07C8UL
-#define         HW_HASH_CUR_LEN_0_REG_ADDR      0x07CCUL
-#define         HW_HASH_CUR_LEN_1_REG_ADDR      0x07D0UL
-#define         HW_HASH_CUR_LEN_2_REG_ADDR      0x07D4UL
-#define         HW_HASH_CUR_LEN_3_REG_ADDR      0x07D8UL
-#define         HW_HASH_PARAM_REG_ADDR                  0x07DCUL
-#define         HW_HASH_INT_BUSY_REG_ADDR               0x07E0UL
-#define         HW_HASH_SW_RESET_REG_ADDR               0x07E4UL
-#define         HW_HASH_ENDIANESS_REG_ADDR      0x07E8UL
-#define         HW_HASH_DATA_REG_ADDR               0x07ECUL
-#define         HW_DRNG_CONTROL_REG_ADDR                0x0800UL
-#define         HW_DRNG_VALID_REG_ADDR                  0x0804UL
-#define         HW_DRNG_DATA_REG_ADDR               0x0808UL
-#define         HW_RND_SRC_EN_REG_ADDR                  0x080CUL
-#define         HW_AES_CLK_ENABLE_REG_ADDR      0x0810UL
-#define         HW_DES_CLK_ENABLE_REG_ADDR      0x0814UL
-#define         HW_HASH_CLK_ENABLE_REG_ADDR     0x0818UL
-#define         HW_PKI_CLK_ENABLE_REG_ADDR      0x081CUL
-#define         HW_CLK_STATUS_REG_ADDR                  0x0824UL
-#define         HW_CLK_ENABLE_REG_ADDR                  0x0828UL
-#define         HW_DRNG_SAMPLE_REG_ADDR                 0x0850UL
-#define         HW_RND_SRC_CTL_REG_ADDR                 0x0858UL
-#define         HW_CRYPTO_CTL_REG_ADDR                  0x0900UL
-#define         HW_CRYPTO_STATUS_REG_ADDR               0x090CUL
-#define         HW_CRYPTO_BUSY_REG_ADDR                 0x0910UL
-#define         HW_AES_BUSY_REG_ADDR                0x0914UL
-#define         HW_DES_BUSY_REG_ADDR                0x0918UL
-#define         HW_HASH_BUSY_REG_ADDR               0x091CUL
-#define         HW_CONTENT_REG_ADDR                 0x0924UL
-#define         HW_VERSION_REG_ADDR                 0x0928UL
-#define         HW_CONTEXT_ID_REG_ADDR                  0x0930UL
-#define         HW_DIN_BUFFER_REG_ADDR                  0x0C00UL
-#define         HW_DIN_MEM_DMA_BUSY_REG_ADDR    0x0c20UL
-#define         HW_SRC_LLI_MEM_ADDR_REG_ADDR    0x0c24UL
-#define         HW_SRC_LLI_WORD0_REG_ADDR               0x0C28UL
-#define         HW_SRC_LLI_WORD1_REG_ADDR               0x0C2CUL
-#define         HW_SRAM_SRC_ADDR_REG_ADDR               0x0c30UL
-#define         HW_DIN_SRAM_BYTES_LEN_REG_ADDR  0x0c34UL
-#define         HW_DIN_SRAM_DMA_BUSY_REG_ADDR   0x0C38UL
-#define         HW_WRITE_ALIGN_REG_ADDR                 0x0C3CUL
-#define         HW_OLD_DATA_REG_ADDR                0x0C48UL
-#define         HW_WRITE_ALIGN_LAST_REG_ADDR    0x0C4CUL
-#define         HW_DOUT_BUFFER_REG_ADDR                 0x0C00UL
-#define         HW_DST_LLI_WORD0_REG_ADDR               0x0D28UL
-#define         HW_DST_LLI_WORD1_REG_ADDR               0x0D2CUL
-#define         HW_DST_LLI_MEM_ADDR_REG_ADDR    0x0D24UL
-#define         HW_DOUT_MEM_DMA_BUSY_REG_ADDR   0x0D20UL
-#define         HW_SRAM_DEST_ADDR_REG_ADDR      0x0D30UL
-#define         HW_DOUT_SRAM_BYTES_LEN_REG_ADDR 0x0D34UL
-#define         HW_DOUT_SRAM_DMA_BUSY_REG_ADDR  0x0D38UL
-#define         HW_READ_ALIGN_REG_ADDR                  0x0D3CUL
-#define         HW_READ_LAST_DATA_REG_ADDR      0x0D44UL
-#define         HW_RC4_THRU_CPU_REG_ADDR                0x0D4CUL
-#define         HW_AHB_SINGLE_REG_ADDR                  0x0E00UL
-#define         HW_SRAM_DATA_REG_ADDR               0x0F00UL
-#define         HW_SRAM_ADDR_REG_ADDR               0x0F04UL
-#define         HW_SRAM_DATA_READY_REG_ADDR     0x0F08UL
-#define         HW_HOST_IRR_REG_ADDR                     0x0A00UL
-#define         HW_HOST_IMR_REG_ADDR                     0x0A04UL
-#define         HW_HOST_ICR_REG_ADDR                     0x0A08UL
-#define         HW_HOST_SEP_SRAM_THRESHOLD_REG_ADDR  0x0A10UL
-#define         HW_HOST_SEP_BUSY_REG_ADDR                    0x0A14UL
-#define         HW_HOST_SEP_LCS_REG_ADDR                     0x0A18UL
-#define         HW_HOST_CC_SW_RST_REG_ADDR               0x0A40UL
-#define         HW_HOST_SEP_SW_RST_REG_ADDR              0x0A44UL
-#define         HW_HOST_FLOW_DMA_SW_INT0_REG_ADDR        0x0A80UL
-#define         HW_HOST_FLOW_DMA_SW_INT1_REG_ADDR        0x0A84UL
-#define         HW_HOST_FLOW_DMA_SW_INT2_REG_ADDR        0x0A88UL
-#define         HW_HOST_FLOW_DMA_SW_INT3_REG_ADDR        0x0A8cUL
-#define         HW_HOST_FLOW_DMA_SW_INT4_REG_ADDR        0x0A90UL
-#define         HW_HOST_FLOW_DMA_SW_INT5_REG_ADDR        0x0A94UL
-#define         HW_HOST_FLOW_DMA_SW_INT6_REG_ADDR    0x0A98UL
-#define         HW_HOST_FLOW_DMA_SW_INT7_REG_ADDR        0x0A9cUL
-#define         HW_HOST_SEP_HOST_GPR0_REG_ADDR           0x0B00UL
-#define         HW_HOST_SEP_HOST_GPR1_REG_ADDR           0x0B04UL
-#define         HW_HOST_SEP_HOST_GPR2_REG_ADDR           0x0B08UL
-#define         HW_HOST_SEP_HOST_GPR3_REG_ADDR       0x0B0CUL
-#define         HW_HOST_HOST_SEP_GPR0_REG_ADDR       0x0B80UL
-#define         HW_HOST_HOST_SEP_GPR1_REG_ADDR       0x0B84UL
-#define         HW_HOST_HOST_SEP_GPR2_REG_ADDR       0x0B88UL
-#define         HW_HOST_HOST_SEP_GPR3_REG_ADDR       0x0B8CUL
-#define         HW_HOST_HOST_ENDIAN_REG_ADDR         0x0B90UL
-#define         HW_HOST_HOST_COMM_CLK_EN_REG_ADDR        0x0B94UL
-#define         HW_CLR_SRAM_BUSY_REG_REG_ADDR        0x0F0CUL
-#define    HW_CC_SRAM_BASE_ADDRESS              0x5800UL
-
-#endif                         /* ifndef HW_DEFS */
index 5e2ffefb60af9c86c384eff40baaaacca3a279f1..d231ae27299d42b796d7c9f1dec2a83ee2e1694c 100644 (file)
@@ -2,6 +2,7 @@
 menuconfig SPECTRA
        tristate "Denali Spectra Flash Translation Layer"
        depends on BLOCK
+       depends on X86_MRST
        default n
        ---help---
          Enable the FTL pseudo-filesystem used with the NAND Flash
index d0c5c97eda3e6a3791bf91454f63c3a86bf79944..c7932da03c56df5d40182e24c039b28762fe8ba4 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kthread.h>
 #include <linux/log2.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 /**** Helper functions used for Div, Remainder operation on u64 ****/
 
@@ -113,7 +114,6 @@ u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type)
 
 #define GLOB_SBD_NAME          "nd"
 #define GLOB_SBD_IRQ_NUM       (29)
-#define GLOB_VERSION           "driver version 20091110"
 
 #define GLOB_SBD_IOCTL_GC                        (0x7701)
 #define GLOB_SBD_IOCTL_WL                        (0x7702)
@@ -272,13 +272,6 @@ static int get_res_blk_num_os(void)
        return res_blks;
 }
 
-static void SBD_prepare_flush(struct request_queue *q, struct request *rq)
-{
-       rq->cmd_type = REQ_TYPE_LINUX_BLOCK;
-       /* rq->timeout = 5 * HZ; */
-       rq->cmd[0] = REQ_LB_OP_FLUSH;
-}
-
 /* Transfer a full request. */
 static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
 {
@@ -296,8 +289,7 @@ static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
                        IdentifyDeviceData.PagesPerBlock *
                        res_blks_os;
 
-       if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
-                       req->cmd[0] == REQ_LB_OP_FLUSH) {
+       if (req->cmd_type & REQ_FLUSH) {
                if (force_flush_cache()) /* Fail to flush cache */
                        return -EIO;
                else
@@ -597,11 +589,25 @@ int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode,
        return -ENOTTY;
 }
 
+static DEFINE_MUTEX(ffsport_mutex);
+
+int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
+               unsigned int cmd, unsigned long arg)
+{
+       int ret;
+
+       mutex_lock(&ffsport_mutex);
+       ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
+       mutex_unlock(&ffsport_mutex);
+
+       return ret;
+}
+
 static struct block_device_operations GLOB_SBD_ops = {
        .owner = THIS_MODULE,
        .open = GLOB_SBD_open,
        .release = GLOB_SBD_release,
-       .locked_ioctl = GLOB_SBD_ioctl,
+       .ioctl = GLOB_SBD_unlocked_ioctl,
        .getgeo = GLOB_SBD_getgeo,
 };
 
@@ -650,8 +656,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
        /* Here we force report 512 byte hardware sector size to Kernel */
        blk_queue_logical_block_size(dev->queue, 512);
 
-       blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH,
-                                       SBD_prepare_flush);
+       blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH);
 
        dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
        if (IS_ERR(dev->thread)) {
index 134aa5166a8d5321cb377c82f0603284e9aaeb8a..9b5218b6ada80095a7a525749c58c0ad619a46f8 100644 (file)
@@ -61,7 +61,6 @@ static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr,
 static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr,
                                 u8 cache_blk, u16 flag);
 static int FTL_Cache_Write(void);
-static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr);
 static void FTL_Calculate_LRU(void);
 static u32 FTL_Get_Block_Index(u32 wBlockNum);
 
@@ -86,8 +85,6 @@ static u32 FTL_Replace_MWBlock(void);
 static int FTL_Replace_Block(u64 blk_addr);
 static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX);
 
-static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr);
-
 struct device_info_tag DeviceInfo;
 struct flash_cache_tag Cache;
 static struct spectra_l2_cache_info cache_l2;
@@ -775,7 +772,7 @@ static void dump_cache_l2_table(void)
 {
        struct list_head *p;
        struct spectra_l2_cache_list *pnd;
-       int n, i;
+       int n;
 
        n = 0;
        list_for_each(p, &cache_l2.table.list) {
@@ -1537,79 +1534,6 @@ static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr)
        return wResult;
 }
 
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function:     FTL_Cache_Update_Block
-* Inputs:       pointer to buffer,page address,block address
-* Outputs:      PASS=0 / FAIL=1
-* Description:  It updates the cache
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Update_Block(u8 *pData,
-                       u64 old_page_addr, u64 blk_addr)
-{
-       int i, j;
-       u8 *buf = pData;
-       int wResult = PASS;
-       int wFoundInCache;
-       u64 page_addr;
-       u64 addr;
-       u64 old_blk_addr;
-       u16 page_offset;
-
-       nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
-                               __FILE__, __LINE__, __func__);
-
-       old_blk_addr = (u64)(old_page_addr >>
-               DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize;
-       page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >>
-               DeviceInfo.nBitsInPageDataSize);
-
-       for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) {
-               page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize;
-               if (i != page_offset) {
-                       wFoundInCache = FAIL;
-                       for (j = 0; j < CACHE_ITEM_NUM; j++) {
-                               addr = Cache.array[j].address;
-                               addr = FTL_Get_Physical_Block_Addr(addr) +
-                                       GLOB_u64_Remainder(addr, 2);
-                               if ((addr >= page_addr) && addr <
-                                       (page_addr + Cache.cache_item_size)) {
-                                       wFoundInCache = PASS;
-                                       buf = Cache.array[j].buf;
-                                       Cache.array[j].changed = SET;
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
-                                       int_cache[ftl_cmd_cnt].item = j;
-                                       int_cache[ftl_cmd_cnt].cache.address =
-                                               Cache.array[j].address;
-                                       int_cache[ftl_cmd_cnt].cache.changed =
-                                               Cache.array[j].changed;
-#endif
-#endif
-                                       break;
-                               }
-                       }
-                       if (FAIL == wFoundInCache) {
-                               if (ERR == FTL_Cache_Read_All(g_pTempBuf,
-                                       page_addr)) {
-                                       wResult = FAIL;
-                                       break;
-                               }
-                               buf = g_pTempBuf;
-                       }
-               } else {
-                       buf = pData;
-               }
-
-               if (FAIL == FTL_Cache_Write_All(buf,
-                       blk_addr + (page_addr - old_blk_addr))) {
-                       wResult = FAIL;
-                       break;
-               }
-       }
-
-       return wResult;
-}
-
 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
 * Function:     FTL_Copy_Block
 * Inputs:       source block address
@@ -1698,7 +1622,7 @@ static int get_l2_cache_blks(void)
 static int erase_l2_cache_blocks(void)
 {
        int i, ret = PASS;
-       u32 pblk, lblk;
+       u32 pblk, lblk = BAD_BLOCK;
        u64 addr;
        u32 *pbt = (u32 *)g_pBlockTable;
 
@@ -2004,87 +1928,6 @@ static int search_l2_cache(u8 *buf, u64 logical_addr)
        return ret;
 }
 
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function:     FTL_Cache_Write_Back
-* Inputs:       pointer to data cached in sys memory
-*               address of free block in flash
-* Outputs:      PASS=0 / FAIL=1
-* Description:  writes all the pages of Cache Block to flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr)
-{
-       int i, j, iErase;
-       u64 old_page_addr, addr, phy_addr;
-       u32 *pbt = (u32 *)g_pBlockTable;
-       u32 lba;
-       
-       nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
-                              __FILE__, __LINE__, __func__);
-
-       old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) +
-               GLOB_u64_Remainder(blk_addr, 2);
-
-       iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL;
-
-       pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK);
-
-#if CMD_DMA
-       p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free;
-       g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
-       p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
-       p_BTableChangesDelta->BT_Index = (u32)(blk_addr >>
-               DeviceInfo.nBitsInBlockDataSize);
-       p_BTableChangesDelta->BT_Entry_Value =
-               pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)];
-       p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
-
-       if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
-               g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
-               FTL_Write_IN_Progress_Block_Table_Page();
-       }
-
-       for (i = 0; i < RETRY_TIMES; i++) {
-               if (PASS == iErase) {
-                       phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
-                       if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) {
-                               lba = BLK_FROM_ADDR(blk_addr);
-                               MARK_BLOCK_AS_BAD(pbt[lba]);
-                               i = RETRY_TIMES;
-                               break;
-                       }
-               }
-
-               for (j = 0; j < CACHE_ITEM_NUM; j++) {
-                       addr = Cache.array[j].address;
-                       if ((addr <= blk_addr) &&
-                               ((addr + Cache.cache_item_size) > blk_addr))
-                               cache_block_to_write = j;
-               }
-
-               phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
-               if (PASS == FTL_Cache_Update_Block(pData,
-                                       old_page_addr, phy_addr)) {
-                       cache_block_to_write = UNHIT_CACHE_ITEM;
-                       break;
-               } else {
-                       iErase = PASS;
-               }
-       }
-
-       if (i >= RETRY_TIMES) {
-               if (ERR == FTL_Flash_Error_Handle(pData,
-                                       old_page_addr, blk_addr))
-                       return ERR;
-               else
-                       return FAIL;
-       }
-
-       return PASS;
-}
-
 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
 * Function:     FTL_Cache_Write_Page
 * Inputs:       Pointer to buffer, page address, cache block number
@@ -2370,159 +2213,6 @@ static int FTL_Write_Block_Table(int wForce)
        return 1;
 }
 
-/******************************************************************
-* Function:     GLOB_FTL_Flash_Format
-* Inputs:       none
-* Outputs:      PASS
-* Description:  The block table stores bad block info, including MDF+
-*               blocks gone bad over the ages. Therefore, if we have a
-*               block table in place, then use it to scan for bad blocks
-*               If not, then scan for MDF.
-*               Now, a block table will only be found if spectra was already
-*               being used. For a fresh flash, we'll go thru scanning for
-*               MDF. If spectra was being used, then there is a chance that
-*               the MDF has been corrupted. Spectra avoids writing to the
-*               first 2 bytes of the spare area to all pages in a block. This
-*               covers all known flash devices. However, since flash
-*               manufacturers have no standard of where the MDF is stored,
-*               this cannot guarantee that the MDF is protected for future
-*               devices too. The initial scanning for the block table assures
-*               this. It is ok even if the block table is outdated, as all
-*               we're looking for are bad block markers.
-*               Use this when mounting a file system or starting a
-*               new flash.
-*
-*********************************************************************/
-static int  FTL_Format_Flash(u8 valid_block_table)
-{
-       u32 i, j;
-       u32 *pbt = (u32 *)g_pBlockTable;
-       u32 tempNode;
-       int ret;
-
-#if CMD_DMA
-       u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy;
-       if (ftl_cmd_cnt)
-               return FAIL;
-#endif
-
-       if (FAIL == FTL_Check_Block_Table(FAIL))
-               valid_block_table = 0;
-
-       if (valid_block_table) {
-               u8 switched = 1;
-               u32 block, k;
-
-               k = DeviceInfo.wSpectraStartBlock;
-               while (switched && (k < DeviceInfo.wSpectraEndBlock)) {
-                       switched = 0;
-                       k++;
-                       for (j = DeviceInfo.wSpectraStartBlock, i = 0;
-                       j <= DeviceInfo.wSpectraEndBlock;
-                       j++, i++) {
-                               block = (pbt[i] & ~BAD_BLOCK) -
-                                       DeviceInfo.wSpectraStartBlock;
-                               if (block != i) {
-                                       switched = 1;
-                                       tempNode = pbt[i];
-                                       pbt[i] = pbt[block];
-                                       pbt[block] = tempNode;
-                               }
-                       }
-               }
-               if ((k == DeviceInfo.wSpectraEndBlock) && switched)
-                       valid_block_table = 0;
-       }
-
-       if (!valid_block_table) {
-               memset(g_pBlockTable, 0,
-                       DeviceInfo.wDataBlockNum * sizeof(u32));
-               memset(g_pWearCounter, 0,
-                       DeviceInfo.wDataBlockNum * sizeof(u8));
-               if (DeviceInfo.MLCDevice)
-                       memset(g_pReadCounter, 0,
-                               DeviceInfo.wDataBlockNum * sizeof(u16));
-#if CMD_DMA
-               memset(g_pBTStartingCopy, 0,
-                       DeviceInfo.wDataBlockNum * sizeof(u32));
-               memset(g_pWearCounterCopy, 0,
-                               DeviceInfo.wDataBlockNum * sizeof(u8));
-               if (DeviceInfo.MLCDevice)
-                       memset(g_pReadCounterCopy, 0,
-                               DeviceInfo.wDataBlockNum * sizeof(u16));
-#endif
-               for (j = DeviceInfo.wSpectraStartBlock, i = 0;
-                       j <= DeviceInfo.wSpectraEndBlock;
-                       j++, i++) {
-                       if (GLOB_LLD_Get_Bad_Block((u32)j))
-                               pbt[i] = (u32)(BAD_BLOCK | j);
-               }
-       }
-
-       nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n");
-
-       for (j = DeviceInfo.wSpectraStartBlock, i = 0;
-               j <= DeviceInfo.wSpectraEndBlock;
-               j++, i++) {
-               if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) {
-                       ret = GLOB_LLD_Erase_Block(j);
-                       if (FAIL == ret) {
-                               pbt[i] = (u32)(j);
-                               MARK_BLOCK_AS_BAD(pbt[i]);
-                               nand_dbg_print(NAND_DBG_WARN,
-                              "NAND Program fail in %s, Line %d, "
-                              "Function: %s, new Bad Block %d generated!\n",
-                              __FILE__, __LINE__, __func__, (int)j);
-                       } else {
-                               pbt[i] = (u32)(SPARE_BLOCK | j);
-                       }
-               }
-#if CMD_DMA
-               pbtStartingCopy[i] = pbt[i];
-#endif
-       }
-
-       g_wBlockTableOffset = 0;
-       for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock -
-                       DeviceInfo.wSpectraStartBlock))
-                       && ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++)
-               ;
-       if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) {
-               printk(KERN_ERR "All blocks bad!\n");
-               return FAIL;
-       } else {
-               g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK;
-               if (i != BLOCK_TABLE_INDEX) {
-                       tempNode = pbt[i];
-                       pbt[i] = pbt[BLOCK_TABLE_INDEX];
-                       pbt[BLOCK_TABLE_INDEX] = tempNode;
-               }
-       }
-       pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK);
-
-#if CMD_DMA
-       pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK);
-#endif
-
-       g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
-       memset(g_pBTBlocks, 0xFF,
-                       (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32));
-       g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex;
-       FTL_Write_Block_Table(FAIL);
-
-       for (i = 0; i < CACHE_ITEM_NUM; i++) {
-               Cache.array[i].address = NAND_CACHE_INIT_ADDR;
-               Cache.array[i].use_cnt = 0;
-               Cache.array[i].changed  = CLEAR;
-       }
-
-#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA)
-       memcpy((void *)&cache_start_copy, (void *)&Cache,
-                       sizeof(struct flash_cache_tag));
-#endif
-       return PASS;
-}
-
 static int  force_format_nand(void)
 {
        u32 i;
@@ -3031,112 +2721,6 @@ static int FTL_Read_Block_Table(void)
        return wResult;
 }
 
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function:     FTL_Flash_Error_Handle
-* Inputs:       Pointer to data
-*               Page address
-*               Block address
-* Outputs:      PASS=0 / FAIL=1
-* Description:  It handles any error occured during Spectra operation
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr,
-                               u64 blk_addr)
-{
-       u32 i;
-       int j;
-       u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr);
-       u64 phy_addr;
-       int wErase = FAIL;
-       int wResult = FAIL;
-       u32 *pbt = (u32 *)g_pBlockTable;
-
-       nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
-                      __FILE__, __LINE__, __func__);
-
-       if (ERR == GLOB_FTL_Garbage_Collection())
-               return ERR;
-
-       do {
-               for (i = DeviceInfo.wSpectraEndBlock -
-                       DeviceInfo.wSpectraStartBlock;
-                                       i > 0; i--) {
-                       if (IS_SPARE_BLOCK(i)) {
-                               tmp_node = (u32)(BAD_BLOCK |
-                                       pbt[blk_node]);
-                               pbt[blk_node] = (u32)(pbt[i] &
-                                       (~SPARE_BLOCK));
-                               pbt[i] = tmp_node;
-#if CMD_DMA
-                               p_BTableChangesDelta =
-                                   (struct BTableChangesDelta *)
-                                   g_pBTDelta_Free;
-                               g_pBTDelta_Free +=
-                                   sizeof(struct BTableChangesDelta);
-
-                               p_BTableChangesDelta->ftl_cmd_cnt =
-                                   ftl_cmd_cnt;
-                               p_BTableChangesDelta->BT_Index =
-                                   blk_node;
-                               p_BTableChangesDelta->BT_Entry_Value =
-                                   pbt[blk_node];
-                               p_BTableChangesDelta->ValidFields = 0x0C;
-
-                               p_BTableChangesDelta =
-                                   (struct BTableChangesDelta *)
-                                   g_pBTDelta_Free;
-                               g_pBTDelta_Free +=
-                                   sizeof(struct BTableChangesDelta);
-
-                               p_BTableChangesDelta->ftl_cmd_cnt =
-                                   ftl_cmd_cnt;
-                               p_BTableChangesDelta->BT_Index = i;
-                               p_BTableChangesDelta->BT_Entry_Value = pbt[i];
-                               p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
-                               wResult = PASS;
-                               break;
-                       }
-               }
-
-               if (FAIL == wResult) {
-                       if (FAIL == GLOB_FTL_Garbage_Collection())
-                               break;
-                       else
-                               continue;
-               }
-
-               if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
-                       g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
-                       FTL_Write_IN_Progress_Block_Table_Page();
-               }
-
-               phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
-
-               for (j = 0; j < RETRY_TIMES; j++) {
-                       if (PASS == wErase) {
-                               if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) {
-                                       MARK_BLOCK_AS_BAD(pbt[blk_node]);
-                                       break;
-                               }
-                       }
-                       if (PASS == FTL_Cache_Update_Block(pData,
-                                                          old_page_addr,
-                                                          phy_addr)) {
-                               wResult = PASS;
-                               break;
-                       } else {
-                               wResult = FAIL;
-                               wErase = PASS;
-                       }
-               }
-       } while (FAIL == wResult);
-
-       FTL_Write_Block_Table(FAIL);
-
-       return wResult;
-}
-
 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
 * Function:     FTL_Get_Page_Num
 * Inputs:       Size in bytes
index 9952579425b99a477c29e488243337e9372b2200..1b3060eb2921c9da66fb2f0844de4a2d1afa4ce0 100644 (file)
@@ -80,5 +80,4 @@ struct st_proto_s {
 extern long st_register(struct st_proto_s *);
 extern long st_unregister(enum proto_type);
 
-extern struct platform_device *st_get_plat_device(void);
 #endif /* ST_H */
index 063c9b1db1ab655504f5908e7c4598418dafd0fd..b85d8bfdf600ad22cd4d62636b521bfb3ac38fa5 100644 (file)
@@ -38,7 +38,6 @@
 #include "st_ll.h"
 #include "st.h"
 
-#define VERBOSE
 /* strings to be used for rfkill entries and by
  * ST Core to be used for sysfs debug entry
  */
@@ -581,7 +580,7 @@ long st_register(struct st_proto_s *new_proto)
        long err = 0;
        unsigned long flags = 0;
 
-       st_kim_ref(&st_gdata);
+       st_kim_ref(&st_gdata, 0);
        pr_info("%s(%d) ", __func__, new_proto->type);
        if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
            || new_proto->reg_complete_cb == NULL) {
@@ -713,7 +712,7 @@ long st_unregister(enum proto_type type)
 
        pr_debug("%s: %d ", __func__, type);
 
-       st_kim_ref(&st_gdata);
+       st_kim_ref(&st_gdata, 0);
        if (type < ST_BT || type >= ST_MAX) {
                pr_err(" protocol %d not supported", type);
                return -EPROTONOSUPPORT;
@@ -767,7 +766,7 @@ long st_write(struct sk_buff *skb)
 #endif
        long len;
 
-       st_kim_ref(&st_gdata);
+       st_kim_ref(&st_gdata, 0);
        if (unlikely(skb == NULL || st_gdata == NULL
                || st_gdata->tty == NULL)) {
                pr_err("data/tty unavailable to perform write");
@@ -818,7 +817,7 @@ static int st_tty_open(struct tty_struct *tty)
        struct st_data_s *st_gdata;
        pr_info("%s ", __func__);
 
-       st_kim_ref(&st_gdata);
+       st_kim_ref(&st_gdata, 0);
        st_gdata->tty = tty;
        tty->disc_data = st_gdata;
 
index e0c32d149f5f294878d22597bec9c1bfc05660a4..8601320a679ee8ce5dda5ea9d36f8c85798dd23e 100644 (file)
@@ -117,7 +117,7 @@ int st_core_init(struct st_data_s **);
 void st_core_exit(struct st_data_s *);
 
 /* ask for reference from KIM */
-void st_kim_ref(struct st_data_s **);
+void st_kim_ref(struct st_data_s **, int);
 
 #define GPS_STUB_TEST
 #ifdef GPS_STUB_TEST
index b4a6c7fdc4e6ca59283dd3e64736c0efdfd97407..9e99463f76e8a0d048f7ec8667a455125d88cb0b 100644 (file)
@@ -72,10 +72,25 @@ const unsigned char *protocol_names[] = {
        PROTO_ENTRY(ST_GPS, "GPS"),
 };
 
+#define MAX_ST_DEVICES 3       /* Imagine 1 on each UART for now */
+struct platform_device *st_kim_devices[MAX_ST_DEVICES];
 
 /**********************************************************************/
 /* internal functions */
 
+/**
+ * st_get_plat_device -
+ *     function which returns the reference to the platform device
+ *     requested by id. As of now only 1 such device exists (id=0)
+ *     the context requesting for reference can get the id to be
+ *     requested by a. The protocol driver which is registering or
+ *     b. the tty device which is opened.
+ */
+static struct platform_device *st_get_plat_device(int id)
+{
+       return st_kim_devices[id];
+}
+
 /**
  * validate_firmware_response -
  *     function to return whether the firmware response was proper
@@ -353,7 +368,7 @@ void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state)
        struct kim_data_s       *kim_gdata;
        pr_info(" %s ", __func__);
 
-       kim_pdev = st_get_plat_device();
+       kim_pdev = st_get_plat_device(0);
        kim_gdata = dev_get_drvdata(&kim_pdev->dev);
 
        if (kim_gdata->gpios[type] == -1) {
@@ -574,12 +589,12 @@ static int kim_toggle_radio(void *data, bool blocked)
  *     This would enable multiple such platform devices to exist
  *     on a given platform
  */
-void st_kim_ref(struct st_data_s **core_data)
+void st_kim_ref(struct st_data_s **core_data, int id)
 {
        struct platform_device  *pdev;
        struct kim_data_s       *kim_gdata;
        /* get kim_gdata reference from platform device */
-       pdev = st_get_plat_device();
+       pdev = st_get_plat_device(id);
        kim_gdata = dev_get_drvdata(&pdev->dev);
        *core_data = kim_gdata->core_data;
 }
@@ -623,6 +638,7 @@ static int kim_probe(struct platform_device *pdev)
        long *gpios = pdev->dev.platform_data;
        struct kim_data_s       *kim_gdata;
 
+       st_kim_devices[pdev->id] = pdev;
        kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_ATOMIC);
        if (!kim_gdata) {
                pr_err("no mem to allocate");
index 7ee89492a755564ca0947622cc2663a72a5c2d37..7b3a7d04a1095adbcad1d6ec1470884f1ce027f5 100644 (file)
@@ -144,6 +144,7 @@ static const struct file_operations bridge_fops = {
        .release = bridge_release,
        .unlocked_ioctl = bridge_ioctl,
        .mmap = bridge_mmap,
+       .llseek = noop_llseek,
 };
 
 #ifdef CONFIG_PM
index c725356cc3466ec5963290415765aab5fb50188a..de7ebb99d8f6cc61ff600b2d9580627f1a12e78d 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_TM6000
        tristate "TV Master TM5600/6000/6010 driver"
-       depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL
+       depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL
        select VIDEO_TUNER
        select MEDIA_TUNER_XC2028
        select MEDIA_TUNER_XC5000
index 32f7a0af6938094380e9de73b933f652f0a00612..54f7667cc7062b640f2fb97717f7c7c26768f2cf 100644 (file)
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(enable_ir, "enable ir (default is enable");
        }
 
 struct tm6000_ir_poll_result {
-       u8 rc_data[4];
+       u16 rc_data;
 };
 
 struct tm6000_IR {
@@ -60,9 +60,9 @@ struct tm6000_IR {
        int                     polling;
        struct delayed_work     work;
        u8                      wait:1;
+       u8                      key:1;
        struct urb              *int_urb;
        u8                      *urb_data;
-       u8                      key:1;
 
        int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
 
@@ -122,13 +122,14 @@ static void tm6000_ir_urb_received(struct urb *urb)
 
        if (urb->status != 0)
                printk(KERN_INFO "not ready\n");
-       else if (urb->actual_length > 0)
+       else if (urb->actual_length > 0) {
                memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
 
-       dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
-       ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+               dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
+                       ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
 
-       ir->key = 1;
+               ir->key = 1;
+       }
 
        rc = usb_submit_urb(urb, GFP_ATOMIC);
 }
@@ -140,30 +141,47 @@ static int default_polling_getkey(struct tm6000_IR *ir,
        int rc;
        u8 buf[2];
 
-       if (ir->wait && !&dev->int_in) {
-               poll_result->rc_data[0] = 0xff;
+       if (ir->wait && !&dev->int_in)
                return 0;
-       }
 
        if (&dev->int_in) {
-               poll_result->rc_data[0] = ir->urb_data[0];
-               poll_result->rc_data[1] = ir->urb_data[1];
+               if (ir->ir.ir_type == IR_TYPE_RC5)
+                       poll_result->rc_data = ir->urb_data[0];
+               else
+                       poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8;
        } else {
                tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
                msleep(10);
                tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
                msleep(10);
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-                USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1);
+               if (ir->ir.ir_type == IR_TYPE_RC5) {
+                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               REQ_02_GET_IR_CODE, 0, 0, buf, 1);
 
-               msleep(10);
+                       msleep(10);
 
-               dprintk("read data=%02x\n", buf[0]);
-               if (rc < 0)
-                       return rc;
+                       dprintk("read data=%02x\n", buf[0]);
+                       if (rc < 0)
+                               return rc;
 
-               poll_result->rc_data[0] = buf[0];
+                       poll_result->rc_data = buf[0];
+               } else {
+                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+
+                       msleep(10);
+
+                       dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
+                       if (rc < 0)
+                               return rc;
+
+                       poll_result->rc_data = buf[0] | buf[1] << 8;
+               }
+               if ((poll_result->rc_data & 0x00ff) != 0xff)
+                       ir->key = 1;
        }
        return 0;
 }
@@ -180,12 +198,11 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir)
                return;
        }
 
-       dprintk("ir->get_key result data=%02x %02x\n",
-               poll_result.rc_data[0], poll_result.rc_data[1]);
+       dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
 
-       if (poll_result.rc_data[0] != 0xff && ir->key == 1) {
+       if (ir->key) {
                ir_input_keydown(ir->input->input_dev, &ir->ir,
-                       poll_result.rc_data[0] | poll_result.rc_data[1] << 8);
+                               (u32)poll_result.rc_data);
 
                ir_input_nokey(ir->input->input_dev, &ir->ir);
                ir->key = 0;
index 2c1d10acb8b52c6022461d9babb48c521f4bb93b..b11ec379b5c248ea75e7bed01c0d5aef6b23ce01 100644 (file)
@@ -1,6 +1,6 @@
 config USB_IP_COMMON
        tristate "USB IP support (EXPERIMENTAL)"
-       depends on USB && NET && EXPERIMENTAL
+       depends on USB && NET && EXPERIMENTAL && BKL
        default N
        ---help---
          This enables pushing USB packets over IP to allow remote
index 0142338bcafe7fc0440edbf3c65a12d7f9b0df85..4bdb8362de827cdb5c820e2bcb3ca65f9a9226e7 100644 (file)
@@ -766,9 +766,14 @@ static int wpa_set_associate(PSDevice pDevice,
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
 
 
-       if (param->u.wpa_associate.wpa_ie &&
-           copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
-           return -EINVAL;
+       if (param->u.wpa_associate.wpa_ie_len) {
+               if (!param->u.wpa_associate.wpa_ie)
+                       return -EINVAL;
+               if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
+                       return -EINVAL;
+               if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
+                       return -EFAULT;
+       }
 
        if (param->u.wpa_associate.mode == 1)
            pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
index 19c335458653fc1a293c2533017a5d426cdf4805..6555891e149c809c56a014f7f1511a063a3cb8df 100644 (file)
@@ -83,7 +83,6 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -147,10 +146,9 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 
        link->resource[0]->end  = HCF_NUM_IO_PORTS;
        link->resource[0]->flags= IO_DATA_PATH_WIDTH_16;
-       link->conf.Attributes   = CONF_ENABLE_IRQ;
-       link->conf.IntType      = INT_MEMORY_AND_IO;
-       link->conf.ConfigIndex  = 5;
-       link->conf.Present      = PRESENT_OPTION;
+       link->config_flags     |= CONF_ENABLE_IRQ;
+       link->config_index      = 5;
+       link->config_regs       = PRESENT_OPTION;
 
        link->priv = dev;
        lp = wl_priv(dev);
@@ -165,27 +163,6 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 
 
 
-/*******************************************************************************
- *     wl_adapter_detach()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      This deletes a driver "instance". The device is de-registered with Card
- *  Services. If it has been released, then the net device is unregistered, and
- *  all local data structures are freed. Otherwise, the structures will be
- *  freed when the device is released.
- *
- *  PARAMETERS:
- *
- *      link    - pointer to the dev_link_t structure representing the device to
- *                detach
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 static void wl_adapter_detach(struct pcmcia_device *link)
 {
        struct net_device   *dev = link->priv;
@@ -209,26 +186,6 @@ static void wl_adapter_detach(struct pcmcia_device *link)
 /*============================================================================*/
 
 
-/*******************************************************************************
- *     wl_adapter_release()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      After a card is removed, this routine will release the PCMCIA
- *  configuration. If the device is still open, this will be postponed until it
- *  is closed.
- *
- *  PARAMETERS:
- *
- *      arg - a u_long representing a pointer to a dev_link_t structure for the
- *            device to be released.
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 void wl_adapter_release(struct pcmcia_device *link)
 {
        DBG_FUNC("wl_adapter_release");
@@ -268,26 +225,6 @@ static int wl_adapter_resume(struct pcmcia_device *link)
        return 0;
 } /* wl_adapter_resume */
 
-/*******************************************************************************
- *     wl_adapter_insert()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      wl_adapter_insert() is scheduled to run after a CARD_INSERTION event is
- *  received, to configure the PCMCIA socket, and to make the ethernet device
- *  available to the system.
- *
- *  PARAMETERS:
- *
- *      link    - pointer to the dev_link_t structure representing the device to
- *                insert
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 void wl_adapter_insert(struct pcmcia_device *link)
 {
        struct net_device *dev;
@@ -302,7 +239,7 @@ void wl_adapter_insert(struct pcmcia_device *link)
        dev     = link->priv;
 
        /* Do we need to allocate an interrupt? */
-       link->conf.Attributes |= CONF_ENABLE_IRQ;
+       link->config_flags |= CONF_ENABLE_IRQ;
        link->io_lines = 6;
 
        ret = pcmcia_request_io(link);
@@ -313,7 +250,7 @@ void wl_adapter_insert(struct pcmcia_device *link)
        if (ret != 0)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret != 0)
                goto failed;
 
@@ -457,9 +394,7 @@ MODULE_DEVICE_TABLE(pcmcia, wl_adapter_ids);
 
 static struct pcmcia_driver wlags49_driver = {
        .owner      = THIS_MODULE,
-       .drv        = {
-               .name = DRIVER_NAME,
-       },
+       .name       = DRIVER_NAME,
        .probe      = wl_adapter_attach,
        .remove     = wl_adapter_detach,
        .id_table   = wl_adapter_ids,
index 02f0a20e178a1cbcd72d413ec3e4973afff9794c..cd129b3ee6c0e100312bf5cfca0b98c5ab5bae1e 100644 (file)
@@ -69,7 +69,6 @@
  ******************************************************************************/
 #include <linux/version.h>
 #ifdef BUS_PCMCIA
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
index 88d0d472142fde3334516a2166ce6e80904f945f..8e3536acbf46e1bac00327ff0f6baa0f05f7b916 100644 (file)
@@ -414,25 +414,6 @@ extern memimage fw_image;            // firmware image to be downloaded
 #endif /* HCF_STA */
 
 
-/*******************************************************************************
- *     wl_insert()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      wl_insert() is scheduled to run after a CARD_INSERTION event is
- *  received, to configure the PCMCIA socket, and to make the ethernet device
- *  available to the system.
- *
- *  PARAMETERS:
- *
- *      dev - a pointer to the net_device struct of the wireless device
- *
- *  RETURNS:
- *
- *      TRUE or FALSE
- *
- ******************************************************************************/
 int wl_insert( struct net_device *dev )
 {
        int                     result = 0;
index 368c30a9d5ffa6da6e7a2065a279fc9825357239..4af83d5318f2705d551cd65fc898645e217e339d 100644 (file)
@@ -219,6 +219,7 @@ int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
                return -ENOENT;
        params.key_len = len;
        params.key = wlandev->wep_keys[key_index];
+       params.seq_len = 0;
 
        callback(cookie, &params);
 
@@ -735,6 +736,8 @@ struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
        priv->band.n_channels = ARRAY_SIZE(prism2_channels);
        priv->band.bitrates = priv->rates;
        priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
+       priv->band.band = IEEE80211_BAND_2GHZ;
+       priv->band.ht_cap.ht_supported = false;
        wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
 
        set_wiphy_dev(wiphy, dev);
index 77d4d715a78936b01795667215875adf17781fc2..722c840ac6387456b5825feaf8375195c8bce5ac 100644 (file)
@@ -769,6 +769,7 @@ static int __init zram_init(void)
 free_devices:
        while (dev_id)
                destroy_device(&devices[--dev_id]);
+       kfree(devices);
 unregister:
        unregister_blkdev(zram_major, "zram");
 out:
index b53deee25d74d525faa4692e3539af0cd3ceb369..0d236f4bb8c2daf64c8e6b344752f4b71157dbbd 100644 (file)
 #include <linux/fs.h>          /* everything... */
 #include <linux/errno.h>       /* error codes */
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #define TYPE(inode) (iminor(inode) >> 4)
 #define NUM(inode) (iminor(inode) & 0xf)
 
+static DEFINE_MUTEX(ixj_mutex);
 static int ixjdebug;
 static int hertz = HZ;
 static int samplerate = 100;
@@ -6655,9 +6656,9 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
 static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
 {
        long ret;
-       lock_kernel();
+       mutex_lock(&ixj_mutex);
        ret = do_ixj_ioctl(file_p, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&ixj_mutex);
        return ret;
 }
 
@@ -6676,7 +6677,8 @@ static const struct file_operations ixj_fops =
         .poll           = ixj_poll,
         .unlocked_ioctl = ixj_ioctl,
         .release        = ixj_release,
-        .fasync         = ixj_fasync
+        .fasync         = ixj_fasync,
+        .llseek         = default_llseek,
 };
 
 static int ixj_linetest(IXJ *j)
index a1900e5025184521e0fe1c6f0c39b233e43026fe..d005b9eeebbcc1f751763c7ab039c9dea13333ca 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/errno.h>       /* error codes */
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -32,9 +31,6 @@ static int ixj_probe(struct pcmcia_device *p_dev)
 {
        dev_dbg(&p_dev->dev, "ixj_attach()\n");
        /* Create new ixj device */
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-       p_dev->conf.IntType = INT_MEMORY_AND_IO;
        p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
        if (!p_dev->priv) {
                return -ENOMEM;
@@ -111,40 +107,31 @@ failed:
        return;
 }
 
-static int ixj_config_check(struct pcmcia_device *p_dev,
-                           cistpl_cftable_entry_t *cfg,
-                           cistpl_cftable_entry_t *dflt,
-                           unsigned int vcc,
-                           void *priv_data)
+static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-               p_dev->io_lines = 3;
-               if (io->nwin == 2) {
-                       p_dev->resource[1]->start = io->win[1].base;
-                       p_dev->resource[1]->end = io->win[1].len;
-               }
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -ENODEV;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->io_lines = 3;
+
+       return pcmcia_request_io(p_dev);
 }
 
 static int ixj_config(struct pcmcia_device * link)
 {
        IXJ *j;
        ixj_info_t *info;
-       cistpl_cftable_entry_t dflt = { 0 };
 
        info = link->priv;
        dev_dbg(&link->dev, "ixj_config\n");
 
-       if (pcmcia_loop_config(link, ixj_config_check, &dflt))
+       link->config_flags = CONF_AUTO_SET_IO;
+
+       if (pcmcia_loop_config(link, ixj_config_check, NULL))
                goto failed;
 
-       if (pcmcia_request_configuration(link, &link->conf))
+       if (pcmcia_enable_device(link))
                goto failed;
 
        /*
@@ -178,9 +165,7 @@ MODULE_DEVICE_TABLE(pcmcia, ixj_ids);
 
 static struct pcmcia_driver ixj_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "ixj_cs",
-       },
+       .name           = "ixj_cs",
        .probe          = ixj_probe,
        .remove         = ixj_detach,
        .id_table       = ixj_ids,
index f3873f650bb43f7f68f79ee87a8c8cdf13784b3a..1915af2011757d581cee0e163052fd4b94c35e45 100644 (file)
@@ -130,6 +130,7 @@ static const struct file_operations phone_fops =
 {
        .owner          = THIS_MODULE,
        .open           = phone_open,
+       .llseek         = noop_llseek,
 };
 
 /*
index bff1afbde5a4b0ad01d0314b1661d43c972c3d84..4d3a6fd1a152901a91f45d3f64e72e3b080e3ad3 100644 (file)
@@ -740,6 +740,7 @@ static const struct file_operations uio_fops = {
        .mmap           = uio_mmap,
        .poll           = uio_poll,
        .fasync         = uio_fasync,
+       .llseek         = noop_llseek,
 };
 
 static int uio_major_init(void)
index 593fc5e2d2e6074da4b9238b4136cc791d9dee0a..5af23cc5ea9fe6cf8c9ded25ccea29f172dc5a8e 100644 (file)
@@ -1127,6 +1127,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
 {
        struct cxacru_data *instance;
        struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
        int ret;
 
        /* instance init */
@@ -1171,15 +1172,34 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
                goto fail;
        }
 
-       usb_fill_int_urb(instance->rcv_urb,
+       if (!cmd_ep) {
+               dbg("cxacru_bind: no command endpoint");
+               ret = -ENODEV;
+               goto fail;
+       }
+
+       if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                       == USB_ENDPOINT_XFER_INT) {
+               usb_fill_int_urb(instance->rcv_urb,
                        usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
                        instance->rcv_buf, PAGE_SIZE,
                        cxacru_blocking_completion, &instance->rcv_done, 1);
 
-       usb_fill_int_urb(instance->snd_urb,
+               usb_fill_int_urb(instance->snd_urb,
                        usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
                        instance->snd_buf, PAGE_SIZE,
                        cxacru_blocking_completion, &instance->snd_done, 4);
+       } else {
+               usb_fill_bulk_urb(instance->rcv_urb,
+                       usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD),
+                       instance->rcv_buf, PAGE_SIZE,
+                       cxacru_blocking_completion, &instance->rcv_done);
+
+               usb_fill_bulk_urb(instance->snd_urb,
+                       usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD),
+                       instance->snd_buf, PAGE_SIZE,
+                       cxacru_blocking_completion, &instance->snd_done);
+       }
 
        mutex_init(&instance->cm_serialize);
 
index 1833b3a71515bb65f9be08bafb2bf329996dc71d..bc62fae0680fe4bd1ae67e5ef6af8e10374a6b49 100644 (file)
@@ -965,7 +965,8 @@ static int acm_probe(struct usb_interface *intf,
        }
 
        if (!buflen) {
-               if (intf->cur_altsetting->endpoint->extralen &&
+               if (intf->cur_altsetting->endpoint &&
+                               intf->cur_altsetting->endpoint->extralen &&
                                intf->cur_altsetting->endpoint->extra) {
                        dev_dbg(&intf->dev,
                                "Seeking extra descriptors on endpoint\n");
@@ -1481,6 +1482,11 @@ static int acm_reset_resume(struct usb_interface *intf)
                USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \
                USB_CDC_ACM_PROTO_VENDOR)
 
+#define SAMSUNG_PCSUITE_ACM_INFO(x) \
+               USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \
+               USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \
+               USB_CDC_ACM_PROTO_VENDOR)
+
 /*
  * USB driver structure.
  */
@@ -1591,6 +1597,17 @@ static const struct usb_device_id acm_ids[] = {
        { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */
        { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */
        { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */
+       { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */
+       { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */
+       { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */
+       { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */
+       { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */
+       { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */
+       { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */
+       { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */
+       { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */
+       { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */
+       { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
 
        /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
 
@@ -1599,6 +1616,10 @@ static const struct usb_device_id acm_ids[] = {
        .driver_info = NOT_A_MODEM,
                },
 
+       /* control interfaces without any protocol set */
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+               USB_CDC_PROTO_NONE) },
+
        /* control interfaces with various AT-command sets */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
                USB_CDC_ACM_PROTO_AT_V25TER) },
index 094c76b5de17114e83a886b872ec4e58579220da..6ee4451bfe2d204ebc8ecba57c7129fd494308e8 100644 (file)
@@ -584,7 +584,8 @@ static const struct file_operations wdm_fops = {
        .open =         wdm_open,
        .flush =        wdm_flush,
        .release =      wdm_release,
-       .poll =         wdm_poll
+       .poll =         wdm_poll,
+       .llseek =       noop_llseek,
 };
 
 static struct usb_class_driver wdm_class = {
index e325162859b0b50722e5c107854636843a9d54e1..9eca4053312efa320cea4b63325dd839b46f4185 100644 (file)
@@ -1043,6 +1043,7 @@ static const struct file_operations usblp_fops = {
        .compat_ioctl =         usblp_ioctl,
        .open =         usblp_open,
        .release =      usblp_release,
+       .llseek =       noop_llseek,
 };
 
 static char *usblp_devnode(struct device *dev, mode_t *mode)
index 3e7c1b800ebb03e8668ac6a506cc137d26bcf41a..6a54634ab823df7628b1a52c2cf1542233cf5696 100644 (file)
@@ -987,6 +987,7 @@ static const struct file_operations fops = {
        .open           = usbtmc_open,
        .release        = usbtmc_release,
        .unlocked_ioctl = usbtmc_ioctl,
+       .llseek         = default_llseek,
 };
 
 static struct usb_class_driver usbtmc_class = {
index 7e594449600e004c7f6ba14fa2dce39ebee25d20..9eed5b52d9de22647f6ca7e94791cd97f6e60122 100644 (file)
@@ -91,12 +91,12 @@ config USB_DYNAMIC_MINORS
          If you are unsure about this, say N here.
 
 config USB_SUSPEND
-       bool "USB runtime power management (suspend/resume and wakeup)"
+       bool "USB runtime power management (autosuspend) and wakeup"
        depends on USB && PM_RUNTIME
        help
          If you say Y here, you can use driver calls or the sysfs
-         "power/level" file to suspend or resume individual USB
-         peripherals and to enable or disable autosuspend (see
+         "power/control" file to enable or disable autosuspend for
+         individual USB peripherals (see
          Documentation/usb/power-management.txt for more details).
 
          Also, USB "remote wakeup" signaling is supported, whereby some
index f06f5dbc8cdc22fbedfa463c05b18672cbb99516..9fe34fb78ef11c4d0dd88065502c6e92cd4398f3 100644 (file)
@@ -59,6 +59,7 @@ static int usb_open(struct inode * inode, struct file * file)
 static const struct file_operations usb_fops = {
        .owner =        THIS_MODULE,
        .open =         usb_open,
+       .llseek =       noop_llseek,
 };
 
 static struct usb_class {
@@ -159,9 +160,9 @@ void usb_major_cleanup(void)
 int usb_register_dev(struct usb_interface *intf,
                     struct usb_class_driver *class_driver)
 {
-       int retval = -EINVAL;
+       int retval;
        int minor_base = class_driver->minor_base;
-       int minor = 0;
+       int minor;
        char name[20];
        char *temp;
 
@@ -173,12 +174,17 @@ int usb_register_dev(struct usb_interface *intf,
         */
        minor_base = 0;
 #endif
-       intf->minor = -1;
-
-       dbg ("looking for a minor, starting at %d", minor_base);
 
        if (class_driver->fops == NULL)
-               goto exit;
+               return -EINVAL;
+       if (intf->minor >= 0)
+               return -EADDRINUSE;
+
+       retval = init_usb_class();
+       if (retval)
+               return retval;
+
+       dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
 
        down_write(&minor_rwsem);
        for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
@@ -186,20 +192,12 @@ int usb_register_dev(struct usb_interface *intf,
                        continue;
 
                usb_minors[minor] = class_driver->fops;
-
-               retval = 0;
+               intf->minor = minor;
                break;
        }
        up_write(&minor_rwsem);
-
-       if (retval)
-               goto exit;
-
-       retval = init_usb_class();
-       if (retval)
-               goto exit;
-
-       intf->minor = minor;
+       if (intf->minor < 0)
+               return -EXFULL;
 
        /* create a usb class device for this usb interface */
        snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -213,11 +211,11 @@ int usb_register_dev(struct usb_interface *intf,
                                      "%s", temp);
        if (IS_ERR(intf->usb_dev)) {
                down_write(&minor_rwsem);
-               usb_minors[intf->minor] = NULL;
+               usb_minors[minor] = NULL;
+               intf->minor = -1;
                up_write(&minor_rwsem);
                retval = PTR_ERR(intf->usb_dev);
        }
-exit:
        return retval;
 }
 EXPORT_SYMBOL_GPL(usb_register_dev);
index fd4c36ea5e4688971afc9c2f32e3668429d0ae63..9f0ce7de0e366fb0066dfb92d6a6403aa5f4a2b3 100644 (file)
@@ -1724,6 +1724,15 @@ free_interfaces:
        if (ret)
                goto free_interfaces;
 
+       /* if it's already configured, clear out old state first.
+        * getting rid of old interfaces means unbinding their drivers.
+        */
+       if (dev->state != USB_STATE_ADDRESS)
+               usb_disable_device(dev, 1);     /* Skip ep0 */
+
+       /* Get rid of pending async Set-Config requests for this device */
+       cancel_async_set_config(dev);
+
        /* Make sure we have bandwidth (and available HCD resources) for this
         * configuration.  Remove endpoints from the schedule if we're dropping
         * this configuration to set configuration 0.  After this point, the
@@ -1733,20 +1742,11 @@ free_interfaces:
        mutex_lock(&hcd->bandwidth_mutex);
        ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
        if (ret < 0) {
-               usb_autosuspend_device(dev);
                mutex_unlock(&hcd->bandwidth_mutex);
+               usb_autosuspend_device(dev);
                goto free_interfaces;
        }
 
-       /* if it's already configured, clear out old state first.
-        * getting rid of old interfaces means unbinding their drivers.
-        */
-       if (dev->state != USB_STATE_ADDRESS)
-               usb_disable_device(dev, 1);     /* Skip ep0 */
-
-       /* Get rid of pending async Set-Config requests for this device */
-       cancel_async_set_config(dev);
-
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                              USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
                              NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -1761,8 +1761,8 @@ free_interfaces:
        if (!cp) {
                usb_set_device_state(dev, USB_STATE_ADDRESS);
                usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
-               usb_autosuspend_device(dev);
                mutex_unlock(&hcd->bandwidth_mutex);
+               usb_autosuspend_device(dev);
                goto free_interfaces;
        }
        mutex_unlock(&hcd->bandwidth_mutex);
@@ -1802,6 +1802,7 @@ free_interfaces:
                intf->dev.groups = usb_interface_groups;
                intf->dev.dma_mask = dev->dev.dma_mask;
                INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
+               intf->minor = -1;
                device_initialize(&intf->dev);
                dev_set_name(&intf->dev, "%d-%s:%d.%d",
                        dev->bus->busnum, dev->devpath,
index e483f80822d27003c7da89f0b472a91cde93b110..1160c55de7f280122038aa21ee063ac1cfa06cb3 100644 (file)
@@ -723,12 +723,12 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
 
 /**
  * usb_string_ids_n() - allocate unused string IDs in batch
- * @cdev: the device whose string descriptor IDs are being allocated
+ * @c: the device whose string descriptor IDs are being allocated
  * @n: number of string IDs to allocate
  * Context: single threaded during gadget setup
  *
  * Returns the first requested ID.  This ID and next @n-1 IDs are now
- * valid IDs.  At least providind that @n is non zore because if it
+ * valid IDs.  At least provided that @n is non-zero because if it
  * is, returns last requested ID which is now very useful information.
  *
  * @usb_string_ids_n() is called from bind() callbacks to allocate
index 53e120208e990c5a423b76dfa5578b5991aabf17..2b98bd26364b45f6edda06d5582540b151af934e 100644 (file)
@@ -451,6 +451,7 @@ const struct file_operations f_hidg_fops = {
        .write          = f_hidg_write,
        .read           = f_hidg_read,
        .poll           = f_hidg_poll,
+       .llseek         = noop_llseek,
 };
 
 static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
index fc35406fc80c3e72562bbb96068f99e462663842..3f1d771c8be584c28c54d356e8238de954626c32 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
index 166bf71fd3482252e00fde5455fc529e8f22337b..e03058fe23cbc91394474e1130aed8fcaa6c5f84 100644 (file)
@@ -1609,6 +1609,7 @@ static int __init m66592_probe(struct platform_device *pdev)
        /* initialize ucd */
        m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
        if (m66592 == NULL) {
+               ret = -ENOMEM;
                pr_err("kzalloc error\n");
                goto clean_up;
        }
index cf241c371a71ffba80b55ef213d9d1f3019aa608..327a92a137b4613d76b1838e742177d7f931c6fe 100644 (file)
@@ -884,7 +884,8 @@ static const struct file_operations printer_io_operations = {
        .fsync =        printer_fsync,
        .poll =         printer_poll,
        .unlocked_ioctl = printer_ioctl,
-       .release =      printer_close
+       .release =      printer_close,
+       .llseek =       noop_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
index 70a817842755484f5ee0b19e51db505b32532bf5..2456ccd9965e3432ab4fd32a33052c104e725698 100644 (file)
@@ -1557,6 +1557,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
        /* initialize ucd */
        r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
        if (r8a66597 == NULL) {
+               ret = -ENOMEM;
                printk(KERN_ERR "kzalloc error\n");
                goto clean_up;
        }
index 020fa5a25fda8fe7bb6c1ca23f28f90d120bd537..972d5ddd1e18043f23281b3282681c6c9eb0ea62 100644 (file)
@@ -293,9 +293,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_VENDOR_DESCRIPTION:
                pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
-               length = strlen (rndis_per_dev_params [configNr].vendorDescr);
-               memcpy (outbuf,
-                       rndis_per_dev_params [configNr].vendorDescr, length);
+               if ( rndis_per_dev_params [configNr].vendorDescr ) {
+                       length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+                       memcpy (outbuf,
+                               rndis_per_dev_params [configNr].vendorDescr, length);
+               } else {
+                       outbuf[0] = 0;
+               }
                retval = 0;
                break;
 
@@ -1148,7 +1152,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
-int __init rndis_init (void)
+int rndis_init(void)
 {
        u8 i;
 
index c236aaa9dcd174db90b7991f719bdda860658b9d..907c33008118b1e880b87fc52166237a2e1152e6 100644 (file)
@@ -262,7 +262,7 @@ int  rndis_signal_disconnect (int configNr);
 int  rndis_state (int configNr);
 extern void rndis_set_host_mac (int configNr, const u8 *addr);
 
-int __devinit rndis_init (void);
+int rndis_init(void);
 void rndis_exit (void);
 
 #endif  /* _LINUX_RNDIS_H */
index 521ebed0118d0fbdc8228ec6d9506abc17fe99e1..a229744a8c7dfa4d5f284165800a455d8f687b26 100644 (file)
@@ -12,8 +12,6 @@
  * published by the Free Software Foundation.
 */
 
-#define DEBUG
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
index 2dcffdac86d29d061a150706cf5bbfc4d95f8064..5e807f083bc820e1251fbb7a08e8c023ed462edd 100644 (file)
@@ -94,7 +94,7 @@ uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt)
                        break;
        }
 
-       if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
+       if (i == ARRAY_SIZE(uvc_formats)) {
                printk(KERN_INFO "Unsupported format 0x%08x.\n",
                        fmt->fmt.pix.pixelformat);
                return -EINVAL;
index 76b7fd2d838a32a9abdaae48d8c862090b3a0ed9..86afdc73322f21787bf0d1e003acbe563f8f316e 100644 (file)
@@ -369,18 +369,21 @@ static const struct file_operations debug_async_fops = {
        .open           = debug_async_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
        .owner          = THIS_MODULE,
        .open           = debug_periodic_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
        .owner          = THIS_MODULE,
        .open           = debug_registers_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 static const struct file_operations debug_lpm_fops = {
        .owner          = THIS_MODULE,
@@ -388,6 +391,7 @@ static const struct file_operations debug_lpm_fops = {
        .read           = debug_lpm_read,
        .write          = debug_lpm_write,
        .release        = debug_lpm_close,
+       .llseek         = noop_llseek,
 };
 
 static struct dentry *ehci_debug_root;
index 58b72d741d9313b1f393a033cd0ed4cb89ad32ac..a1e8d273103f77b2d237a5f68438b289b51bb92a 100644 (file)
@@ -119,6 +119,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        ehci->broken_periodic = 1;
                        ehci_info(ehci, "using broken periodic workaround\n");
                }
+               if (pdev->device == 0x0806 || pdev->device == 0x0811
+                               || pdev->device == 0x0829) {
+                       ehci_info(ehci, "disable lpm for langwell/penwell\n");
+                       ehci->has_lpm = 0;
+               }
                break;
        case PCI_VENDOR_ID_TDI:
                if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
index 335ee699fd85bde5637fc6991809ddfdab8f506d..ba52be473027a82dd20bcb20aa724f4c4b472f78 100644 (file)
@@ -192,17 +192,19 @@ ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *mat
        }
 
        rv = usb_add_hcd(hcd, irq, 0);
-       if (rv == 0)
-               return 0;
+       if (rv)
+               goto err_ehci;
+
+       return 0;
 
+err_ehci:
+       if (ehci->has_amcc_usb23)
+               iounmap(ehci->ohci_hcctrl_reg);
        iounmap(hcd->regs);
 err_ioremap:
        irq_dispose_mapping(irq);
 err_irq:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-       if (ehci->has_amcc_usb23)
-               iounmap(ehci->ohci_hcctrl_reg);
 err_rmr:
        usb_put_hcd(hcd);
 
index d1a3dfc9a40873ea46df2a81668b065d105fb9cc..bdba8c5d844aa4ba099e128e1ed5f765d2ae349b 100644 (file)
@@ -829,6 +829,7 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
         * almost immediately. With ISP1761, this register requires a delay of
         * 195ns between a write and subsequent read (see section 15.1.1.3).
         */
+       mmiowb();
        ndelay(195);
        skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
 
@@ -870,6 +871,7 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
         * almost immediately. With ISP1761, this register requires a delay of
         * 195ns between a write and subsequent read (see section 15.1.1.3).
         */
+       mmiowb();
        ndelay(195);
        skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
 
index 36abd2baa3ea6671d185a62cbf2918d15410c1df..d7d34492934a55532eb200da71c93a2975dbdd7a 100644 (file)
@@ -413,18 +413,21 @@ static const struct file_operations debug_async_fops = {
        .open           = debug_async_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
        .owner          = THIS_MODULE,
        .open           = debug_periodic_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
        .owner          = THIS_MODULE,
        .open           = debug_registers_open,
        .read           = debug_output,
        .release        = debug_close,
+       .llseek         = default_llseek,
 };
 
 static struct dentry *ohci_debug_root;
index 418163894775e36ff129aa96ba107f7e6145ca20..afef7b0a419567ab92643d0809a1da5f1a4f13a9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <mach/ohci.h>
+#include <mach/pxa3xx-u2d.h>
 
 /*
  * UHC: USB Host Controller (OHCI-like) register definitions
@@ -235,6 +236,9 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
        if (retval < 0)
                return retval;
 
+       if (cpu_is_pxa3xx())
+               pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
+
        uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
        __raw_writel(uhchr, ohci->mmio_base + UHCHR);
        __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE);
@@ -251,6 +255,9 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
 
        inf = dev->platform_data;
 
+       if (cpu_is_pxa3xx())
+               pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
+
        if (inf->exit)
                inf->exit(dev);
 
index 0e13a00eb2ed51ea38126fa954a5e3a4723d87c0..3775c035a6c56c994078357e9f1a55c5b2b02312 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -132,49 +131,12 @@ static void sl811_cs_release(struct pcmcia_device * link)
        platform_device_unregister(&platform_dev);
 }
 
-static int sl811_cs_config_check(struct pcmcia_device *p_dev,
-                                cistpl_cftable_entry_t *cfg,
-                                cistpl_cftable_entry_t *dflt,
-                                unsigned int vcc,
-                                void *priv_data)
+static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-       if (cfg->index == 0)
-               return -ENODEV;
-
-       /* Use power settings for Vcc and Vpp if present */
-       /*  Note that the CIS values need to be rescaled */
-       if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-               if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-                       return -ENODEV;
-       } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-               if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-                       return -ENODEV;
-               }
-
-       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-               p_dev->conf.Vpp =
-                       dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-       /* we need an interrupt */
-       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-       /* IO window settings */
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-               p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-               p_dev->resource[0]->start = io->win[0].base;
-               p_dev->resource[0]->end = io->win[0].len;
-
-               return pcmcia_request_io(p_dev);
-       }
-       pcmcia_disable_device(p_dev);
-       return -ENODEV;
+       if (p_dev->config_index == 0)
+               return -EINVAL;
+
+       return pcmcia_request_io(p_dev);
 }
 
 
@@ -185,6 +147,9 @@ static int sl811_cs_config(struct pcmcia_device *link)
 
        dev_dbg(&link->dev, "sl811_cs_config\n");
 
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+               CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO;
+
        if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
                goto failed;
 
@@ -195,18 +160,10 @@ static int sl811_cs_config(struct pcmcia_device *link)
        if (!link->irq)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
-       dev_info(&link->dev, "index 0x%02x: ",
-               link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-       printk(", irq %d", link->irq);
-       printk(", io %pR", link->resource[0]);
-       printk("\n");
-
        if (sl811_hc_init(parent, link->resource[0]->start, link->irq)
                        < 0) {
 failed:
@@ -227,9 +184,6 @@ static int sl811_cs_probe(struct pcmcia_device *link)
        local->p_dev = link;
        link->priv = local;
 
-       link->conf.Attributes = 0;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
        return sl811_cs_config(link);
 }
 
@@ -241,9 +195,7 @@ MODULE_DEVICE_TABLE(pcmcia, sl811_ids);
 
 static struct pcmcia_driver sl811_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "sl811_cs",
-       },
+       .name           = "sl811_cs",
        .probe          = sl811_cs_probe,
        .remove         = sl811_cs_detach,
        .id_table       = sl811_ids,
index bc3f4f427065901059737ca960bd03d0fa75a8fc..48e60d166ff04c3b749607ebab77f1b797321875 100644 (file)
@@ -131,7 +131,7 @@ static void next_trb(struct xhci_hcd *xhci,
                *seg = (*seg)->next;
                *trb = ((*seg)->trbs);
        } else {
-               *trb = (*trb)++;
+               (*trb)++;
        }
 }
 
@@ -1551,6 +1551,10 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        /* calc actual length */
        if (ep->skip) {
                td->urb->iso_frame_desc[idx].actual_length = 0;
+               /* Update ring dequeue pointer */
+               while (ep_ring->dequeue != td->last_trb)
+                       inc_deq(xhci, ep_ring, false);
+               inc_deq(xhci, ep_ring, false);
                return finish_td(xhci, td, event_trb, event, ep, status, true);
        }
 
index e192e8f7c5601cdc7eda7c4ac72a1e425729a46b..575b56c79e9724b120bf00638eda3333da583f4f 100644 (file)
@@ -963,6 +963,7 @@ static const struct file_operations mdc800_device_ops =
        .write =        mdc800_device_write,
        .open =         mdc800_device_open,
        .release =      mdc800_device_release,
+       .llseek =       noop_llseek,
 };
 
 
index d240de097c6211afd6ff2ef1399c1b2add9ca751..44f8b922505465b4d3dc1f7cfc6e983a0ded5cfe 100644 (file)
@@ -439,7 +439,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
                        /* drain secondary buffer */
                        int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary;
                        i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount);
-                       if (i < 0) {
+                       if (i) {
                                retval = -EFAULT;
                                goto exit;
                        }
@@ -679,6 +679,7 @@ static const struct file_operations adu_fops = {
        .write = adu_write,
        .open = adu_open,
        .release = adu_release,
+       .llseek = noop_llseek,
 };
 
 /*
index a54c3cb804ce4a5e6cf315aa03508ac3231ee0c8..c6184b4d169551d8c3795971377d8069d81fccf2 100644 (file)
@@ -105,6 +105,7 @@ static const struct file_operations idmouse_fops = {
        .read = idmouse_read,
        .open = idmouse_open,
        .release = idmouse_release,
+       .llseek = default_llseek,
 };
 
 /* class driver information */
index 2de49c8887c5f772b0f166cc7b98354f4ad902ea..9b50db2570194404313c2b894227cc0dd3dba4c8 100644 (file)
@@ -542,7 +542,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
                        retval = io_res;
                else {
                        io_res = copy_to_user(user_buffer, buffer, dev->report_size);
-                       if (io_res < 0)
+                       if (io_res)
                                retval = -EFAULT;
                }
                break;
@@ -574,7 +574,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
                        }
                        io_res = copy_to_user((struct iowarrior_info __user *)arg, &info,
                                         sizeof(struct iowarrior_info));
-                       if (io_res < 0)
+                       if (io_res)
                                retval = -EFAULT;
                        break;
                }
@@ -730,6 +730,7 @@ static const struct file_operations iowarrior_fops = {
        .open = iowarrior_open,
        .release = iowarrior_release,
        .poll = iowarrior_poll,
+       .llseek = noop_llseek,
 };
 
 static char *iowarrior_devnode(struct device *dev, mode_t *mode)
index dd41d871004353b5e8bccba16b8899d4aa53aa5a..edffef6423375e44ada7e0088287ddd97dda34e1 100644 (file)
@@ -613,6 +613,7 @@ static const struct file_operations ld_usb_fops = {
        .open =         ld_usb_open,
        .release =      ld_usb_release,
        .poll =         ld_usb_poll,
+       .llseek =       no_llseek,
 };
 
 /*
index cc13ae61712a2a81915e6f0582ecc174ac8c90ed..4e23d3841b43df3a2ddd914181f6ccb581715c78 100644 (file)
@@ -439,6 +439,7 @@ static const struct file_operations usb_rio_fops = {
        .unlocked_ioctl = ioctl_rio,
        .open =         open_rio,
        .release =      close_rio,
+       .llseek =       noop_llseek,
 };
 
 static struct usb_class_driver usb_rio_class = {
index d00dde19194ca45560046493c880779f5534b8c0..51648154bb44c418309b8f573da7f3f644755853 100644 (file)
@@ -282,6 +282,7 @@ static const struct file_operations lcd_fops = {
         .open =         lcd_open,
        .unlocked_ioctl = lcd_ioctl,
         .release =      lcd_release,
+        .llseek =       noop_llseek,
 };
 
 /*
index 59dc3d351b60269f3c3872b859c0b39d7fcbe449..5ab5bb89bae3558cfe6f296e37931680afa0e323 100644 (file)
@@ -322,6 +322,7 @@ cppi_channel_allocate(struct dma_controller *c,
                                index, transmit ? 'T' : 'R', cppi_ch);
        cppi_ch->hw_ep = ep;
        cppi_ch->channel.status = MUSB_DMA_STATUS_FREE;
+       cppi_ch->channel.max_len = 0x7fffffff;
 
        DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R');
        return &cppi_ch->channel;
index c79a5e30d43735bb285300152ade427fd81dac6a..9e8639d4e862b65a2b23bc27a29fd09ba0b60ec1 100644 (file)
@@ -195,15 +195,14 @@ static const struct file_operations musb_regdump_fops = {
 
 static int musb_test_mode_open(struct inode *inode, struct file *file)
 {
-       file->private_data = inode->i_private;
-
        return single_open(file, musb_test_mode_show, inode->i_private);
 }
 
 static ssize_t musb_test_mode_write(struct file *file,
                const char __user *ubuf, size_t count, loff_t *ppos)
 {
-       struct musb             *musb = file->private_data;
+       struct seq_file         *s = file->private_data;
+       struct musb             *musb = s->private;
        u8                      test = 0;
        char                    buf[18];
 
index 6fca870e957ed3b5061f19deec76a9472d6d5211..d065e23f123ee755f9e6fe0e661823f48d917727 100644 (file)
@@ -300,6 +300,11 @@ static void txstate(struct musb *musb, struct musb_request *req)
 #ifndef        CONFIG_MUSB_PIO_ONLY
        if (is_dma_capable() && musb_ep->dma) {
                struct dma_controller   *c = musb->dma_controller;
+               size_t request_size;
+
+               /* setup DMA, then program endpoint CSR */
+               request_size = min_t(size_t, request->length - request->actual,
+                                       musb_ep->dma->max_len);
 
                use_dma = (request->dma != DMA_ADDR_INVALID);
 
@@ -307,11 +312,6 @@ static void txstate(struct musb *musb, struct musb_request *req)
 
 #ifdef CONFIG_USB_INVENTRA_DMA
                {
-                       size_t request_size;
-
-                       /* setup DMA, then program endpoint CSR */
-                       request_size = min_t(size_t, request->length,
-                                               musb_ep->dma->max_len);
                        if (request_size < musb_ep->packet_sz)
                                musb_ep->dma->desired_mode = 0;
                        else
@@ -373,8 +373,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
                use_dma = use_dma && c->channel_program(
                                musb_ep->dma, musb_ep->packet_sz,
                                0,
-                               request->dma,
-                               request->length);
+                               request->dma + request->actual,
+                               request_size);
                if (!use_dma) {
                        c->channel_release(musb_ep->dma);
                        musb_ep->dma = NULL;
@@ -386,8 +386,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
                use_dma = use_dma && c->channel_program(
                                musb_ep->dma, musb_ep->packet_sz,
                                request->zero,
-                               request->dma,
-                               request->length);
+                               request->dma + request->actual,
+                               request_size);
 #endif
        }
 #endif
@@ -501,26 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                                request->zero = 0;
                        }
 
-                       /* ... or if not, then complete it. */
-                       musb_g_giveback(musb_ep, request, 0);
-
-                       /*
-                        * Kickstart next transfer if appropriate;
-                        * the packet that just completed might not
-                        * be transmitted for hours or days.
-                        * REVISIT for double buffering...
-                        * FIXME revisit for stalls too...
-                        */
-                       musb_ep_select(mbase, epnum);
-                       csr = musb_readw(epio, MUSB_TXCSR);
-                       if (csr & MUSB_TXCSR_FIFONOTEMPTY)
-                               return;
-
-                       request = musb_ep->desc ? next_request(musb_ep) : NULL;
-                       if (!request) {
-                               DBG(4, "%s idle now\n",
-                                       musb_ep->end_point.name);
-                               return;
+                       if (request->actual == request->length) {
+                               musb_g_giveback(musb_ep, request, 0);
+                               request = musb_ep->desc ? next_request(musb_ep) : NULL;
+                               if (!request) {
+                                       DBG(4, "%s idle now\n",
+                                               musb_ep->end_point.name);
+                                       return;
+                               }
                        }
                }
 
@@ -568,11 +556,19 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 {
        const u8                epnum = req->epnum;
        struct usb_request      *request = &req->request;
-       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
+       struct musb_ep          *musb_ep;
        void __iomem            *epio = musb->endpoints[epnum].regs;
        unsigned                fifo_count = 0;
-       u16                     len = musb_ep->packet_sz;
+       u16                     len;
        u16                     csr = musb_readw(epio, MUSB_RXCSR);
+       struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
+
+       if (hw_ep->is_shared_fifo)
+               musb_ep = &hw_ep->ep_in;
+       else
+               musb_ep = &hw_ep->ep_out;
+
+       len = musb_ep->packet_sz;
 
        /* We shouldn't get here while DMA is active, but we do... */
        if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
@@ -647,8 +643,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
         */
 
                                csr |= MUSB_RXCSR_DMAENAB;
-#ifdef USE_MODE1
                                csr |= MUSB_RXCSR_AUTOCLEAR;
+#ifdef USE_MODE1
                                /* csr |= MUSB_RXCSR_DMAMODE; */
 
                                /* this special sequence (enabling and then
@@ -663,10 +659,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                if (request->actual < request->length) {
                                        int transfer_size = 0;
 #ifdef USE_MODE1
-                                       transfer_size = min(request->length,
+                                       transfer_size = min(request->length - request->actual,
                                                        channel->max_len);
 #else
-                                       transfer_size = len;
+                                       transfer_size = min(request->length - request->actual,
+                                                       (unsigned)len);
 #endif
                                        if (transfer_size <= musb_ep->packet_sz)
                                                musb_ep->dma->desired_mode = 0;
@@ -740,9 +737,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
        u16                     csr;
        struct usb_request      *request;
        void __iomem            *mbase = musb->mregs;
-       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
+       struct musb_ep          *musb_ep;
        void __iomem            *epio = musb->endpoints[epnum].regs;
        struct dma_channel      *dma;
+       struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
+
+       if (hw_ep->is_shared_fifo)
+               musb_ep = &hw_ep->ep_in;
+       else
+               musb_ep = &hw_ep->ep_out;
 
        musb_ep_select(mbase, epnum);
 
@@ -1081,7 +1084,7 @@ struct free_record {
 /*
  * Context: controller locked, IRQs blocked.
  */
-static void musb_ep_restart(struct musb *musb, struct musb_request *req)
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
 {
        DBG(3, "<== %s request %p len %u on hw_ep%d\n",
                req->tx ? "TX/IN" : "RX/OUT",
index c8b140325d82bf4bb6cd3ad85216fa24ec308ce7..572b1da7f2dc45ea1fd3d9bb67d3ea273d56cfae 100644 (file)
@@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct musb *);
 
 extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
 
+extern void musb_ep_restart(struct musb *, struct musb_request *);
+
 #endif         /* __MUSB_GADGET_H */
index 59bef8f3a3585100310bbb43848ea56603a82c28..6dd03f4c5f4956983c2d1bf2552c248f6a1702a0 100644 (file)
@@ -261,6 +261,7 @@ __acquires(musb->lock)
                                        ctrlrequest->wIndex & 0x0f;
                                struct musb_ep          *musb_ep;
                                struct musb_hw_ep       *ep;
+                               struct musb_request     *request;
                                void __iomem            *regs;
                                int                     is_in;
                                u16                     csr;
@@ -302,6 +303,14 @@ __acquires(musb->lock)
                                        musb_writew(regs, MUSB_RXCSR, csr);
                                }
 
+                               /* Maybe start the first request in the queue */
+                               request = to_musb_request(
+                                               next_request(musb_ep));
+                               if (!musb_ep->busy && request) {
+                                       DBG(3, "restarting the request\n");
+                                       musb_ep_restart(musb, request);
+                               }
+
                                /* select ep0 again */
                                musb_ep_select(mbase, 0);
                                } break;
index 877d20b1dff973fd6975f258bb0b18267df1f5f5..9e65c47cc98b95761daba7186dd180550b954def 100644 (file)
@@ -660,6 +660,12 @@ static bool musb_tx_dma_program(struct dma_controller *dma,
 
        qh->segsize = length;
 
+       /*
+        * Ensure the data reaches to main memory before starting
+        * DMA transfer
+        */
+       wmb();
+
        if (!dma->channel_program(channel, pkt_size, mode,
                        urb->transfer_dma + offset, length)) {
                dma->channel_release(channel);
index 0e8888588d4e01db602762276d0561d15739ed27..0bc97698af157d2cc25e4309a0da34ac2ad4e317 100644 (file)
@@ -347,11 +347,20 @@ static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
        }
 }
 
-static void twl4030_phy_power(struct twl4030_usb *twl, int on)
+static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
 {
-       u8 pwr;
+       u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
+
+       if (on)
+               pwr &= ~PHY_PWR_PHYPWD;
+       else
+               pwr |= PHY_PWR_PHYPWD;
 
-       pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
+       WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+}
+
+static void twl4030_phy_power(struct twl4030_usb *twl, int on)
+{
        if (on) {
                regulator_enable(twl->usb3v1);
                regulator_enable(twl->usb1v8);
@@ -365,15 +374,13 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
                twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
                                                        VUSB_DEDICATED2);
                regulator_enable(twl->usb1v5);
-               pwr &= ~PHY_PWR_PHYPWD;
-               WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+               __twl4030_phy_power(twl, 1);
                twl4030_usb_write(twl, PHY_CLK_CTRL,
                                  twl4030_usb_read(twl, PHY_CLK_CTRL) |
                                        (PHY_CLK_CTRL_CLOCKGATING_EN |
                                                PHY_CLK_CTRL_CLK32K_EN));
-       } else  {
-               pwr |= PHY_PWR_PHYPWD;
-               WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+       } else {
+               __twl4030_phy_power(twl, 0);
                regulator_disable(twl->usb1v5);
                regulator_disable(twl->usb1v8);
                regulator_disable(twl->usb3v1);
@@ -387,19 +394,25 @@ static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
 
        twl4030_phy_power(twl, 0);
        twl->asleep = 1;
+       dev_dbg(twl->dev, "%s\n", __func__);
 }
 
-static void twl4030_phy_resume(struct twl4030_usb *twl)
+static void __twl4030_phy_resume(struct twl4030_usb *twl)
 {
-       if (!twl->asleep)
-               return;
-
        twl4030_phy_power(twl, 1);
        twl4030_i2c_access(twl, 1);
        twl4030_usb_set_mode(twl, twl->usb_mode);
        if (twl->usb_mode == T2_USB_MODE_ULPI)
                twl4030_i2c_access(twl, 0);
+}
+
+static void twl4030_phy_resume(struct twl4030_usb *twl)
+{
+       if (!twl->asleep)
+               return;
+       __twl4030_phy_resume(twl);
        twl->asleep = 0;
+       dev_dbg(twl->dev, "%s\n", __func__);
 }
 
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
@@ -408,8 +421,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
        twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
        twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY);
 
-       /* put VUSB3V1 LDO in active state */
-       twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
+       /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
+       /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
 
        /* input to VUSB3V1 LDO is from VBAT, not VBUS */
        twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
@@ -502,6 +515,26 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
        return IRQ_HANDLED;
 }
 
+static void twl4030_usb_phy_init(struct twl4030_usb *twl)
+{
+       int status;
+
+       status = twl4030_usb_linkstat(twl);
+       if (status >= 0) {
+               if (status == USB_EVENT_NONE) {
+                       __twl4030_phy_power(twl, 0);
+                       twl->asleep = 1;
+               } else {
+                       __twl4030_phy_resume(twl);
+                       twl->asleep = 0;
+               }
+
+               blocking_notifier_call_chain(&twl->otg.notifier, status,
+                               twl->otg.gadget);
+       }
+       sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+}
+
 static int twl4030_set_suspend(struct otg_transceiver *x, int suspend)
 {
        struct twl4030_usb *twl = xceiv_to_twl(x);
@@ -568,7 +601,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
        twl->otg.set_peripheral = twl4030_set_peripheral;
        twl->otg.set_suspend    = twl4030_set_suspend;
        twl->usb_mode           = pdata->usb_mode;
-       twl->asleep             = 1;
+       twl->asleep = 1;
 
        /* init spinlock for workqueue */
        spin_lock_init(&twl->lock);
@@ -606,15 +639,10 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
                return status;
        }
 
-       /* The IRQ handler just handles changes from the previous states
-        * of the ID and VBUS pins ... in probe() we must initialize that
-        * previous state.  The easy way:  fake an IRQ.
-        *
-        * REVISIT:  a real IRQ might have happened already, if PREEMPT is
-        * enabled.  Else the IRQ may not yet be configured or enabled,
-        * because of scheduling delays.
+       /* Power down phy or make it work according to
+        * current link state.
         */
-       twl4030_usb_irq(twl->irq, twl);
+       twl4030_usb_phy_init(twl);
 
        dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
        return 0;
index 2bef4415c19c6627ef2555ab9a7f462bb8ed71f2..4f1744c5871fa74443bdae1800e8376b083e561d 100644 (file)
@@ -56,6 +56,7 @@ static int debug;
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
        { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
+       { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
@@ -88,6 +89,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+       { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
        { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
        { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
@@ -109,6 +111,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
        { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
        { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
+       { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
@@ -122,14 +125,14 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
        { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
-       { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
-       { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
-       { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
-       { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
        { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
        { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
        { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
        { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+       { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+       { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
+       { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+       { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
        { } /* Terminating Entry */
 };
 
@@ -222,8 +225,8 @@ static struct usb_serial_driver cp210x_device = {
 #define BITS_STOP_2            0x0002
 
 /* CP210X_SET_BREAK */
-#define BREAK_ON               0x0000
-#define BREAK_OFF              0x0001
+#define BREAK_ON               0x0001
+#define BREAK_OFF              0x0000
 
 /* CP210X_(SET_MHS|GET_MDMSTS) */
 #define CONTROL_DTR            0x0001
index eb12d9b096b4f54f803b9ee34e9302e694a799b8..97cc87d654ce3258a931a8bfbd0bcd36a2d5622b 100644 (file)
@@ -180,6 +180,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
+       { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
@@ -750,6 +751,16 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
+       { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -1376,7 +1387,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)
        }
 
        /* set max packet size based on descriptor */
-       priv->max_packet_size = ep_desc->wMaxPacketSize;
+       priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize);
 
        dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
 }
@@ -1831,7 +1842,7 @@ static int ftdi_process_packet(struct tty_struct *tty,
 
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, flag);
                }
        } else {
index 6e612c52e763a0095bcb4e0f377cf02eaca8b1b8..15a4583775ad236a359c3dec0c02c0aa7f5f7f4e 100644 (file)
 /* Propox devices */
 #define FTDI_PROPOX_JTAGCABLEII_PID    0xD738
 
+/* Lenz LI-USB Computer Interface. */
+#define FTDI_LENZ_LIUSB_PID    0xD780
+
 /*
  * Xsens Technologies BV products (http://www.xsens.com).
  */
 #define FTDI_NDI_FUTURE_3_PID          0xDA73  /* NDI future device #3 */
 #define FTDI_NDI_AURORA_SCU_PID                0xDA74  /* NDI Aurora SCU */
 
+/*
+ * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs
+ */
+#define FTDI_CHAMSYS_24_MASTER_WING_PID        0xDAF8
+#define FTDI_CHAMSYS_PC_WING_PID       0xDAF9
+#define FTDI_CHAMSYS_USB_DMX_PID       0xDAFA
+#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB
+#define FTDI_CHAMSYS_MINI_WING_PID     0xDAFC
+#define FTDI_CHAMSYS_MAXI_WING_PID     0xDAFD
+#define FTDI_CHAMSYS_MEDIA_WING_PID    0xDAFE
+#define FTDI_CHAMSYS_WING_PID  0xDAFF
+
 /*
  * Westrex International devices submitted by Cory Lee
  */
 #define ALTI2_VID      0x1BC9
 #define ALTI2_N3_PID   0x6001  /* Neptune 3 */
 
+/*
+ * Ionics PlugComputer
+ */
+#define IONICS_VID                     0x1c0c
+#define IONICS_PLUGCOMPUTER_PID                0x0102
+
 /*
  * Dresden Elektronik Sensor Terminal Board
  */
index ca92f67747cc2f2c4b1f5a411bc3763be9a0b009..e6833e216fc9fa4e3628813d57f14891835caf6a 100644 (file)
@@ -343,7 +343,7 @@ void usb_serial_generic_process_read_urb(struct urb *urb)
                tty_insert_flip_string(tty, ch, urb->actual_length);
        else {
                for (i = 0; i < urb->actual_length; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, TTY_NORMAL);
                }
        }
@@ -448,12 +448,11 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
 EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
 
 #ifdef CONFIG_MAGIC_SYSRQ
-int usb_serial_handle_sysrq_char(struct tty_struct *tty,
-                       struct usb_serial_port *port, unsigned int ch)
+int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
 {
        if (port->sysrq && port->port.console) {
                if (ch && time_before(jiffies, port->sysrq)) {
-                       handle_sysrq(ch, tty);
+                       handle_sysrq(ch);
                        port->sysrq = 0;
                        return 1;
                }
@@ -462,8 +461,7 @@ int usb_serial_handle_sysrq_char(struct tty_struct *tty,
        return 0;
 }
 #else
-int usb_serial_handle_sysrq_char(struct tty_struct *tty,
-                       struct usb_serial_port *port, unsigned int ch)
+int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
 {
        return 0;
 }
@@ -518,6 +516,7 @@ void usb_serial_generic_disconnect(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i)
                generic_cleanup(serial->port[i]);
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
 
 void usb_serial_generic_release(struct usb_serial *serial)
 {
index dc47f986df57f739b18ceb121dc8f19b0acd8c23..a7cfc59529377b16f084e6bd6e2bf118d4cc9cb5 100644 (file)
@@ -1151,7 +1151,7 @@ static int download_fw(struct edgeport_serial *serial)
 
                        /* Check if we have an old version in the I2C and
                           update if necessary */
-                       if (download_cur_ver != download_new_ver) {
+                       if (download_cur_ver < download_new_ver) {
                                dbg("%s - Update I2C dld from %d.%d to %d.%d",
                                    __func__,
                                    firmware_version->Ver_Major,
@@ -1284,7 +1284,7 @@ static int download_fw(struct edgeport_serial *serial)
                                kfree(header);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
-                               return status;
+                               return -EINVAL;
                        }
 
                        /* Update I2C with type 0xf2 record with correct
index 30922a7e3347494b5ca30b81ea77e53ea767e91e..aa665817a2720414a7e669b20499d62ebca4b6db 100644 (file)
@@ -2024,6 +2024,9 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
 
        case TIOCGICOUNT:
                cnow = mos7720_port->icount;
+
+               memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
                icount.cts = cnow.cts;
                icount.dsr = cnow.dsr;
                icount.rng = cnow.rng;
index 585b7e6637405981e5019790bbdb0700109f87d0..1a42bc2137995bea0b70905cfe518674242141fd 100644 (file)
  * by making a change here, in moschip_port_id_table, and in
  * moschip_id_table_combined
  */
-#define USB_VENDOR_ID_BANDB             0x0856
-#define BANDB_DEVICE_ID_USO9ML2_2      0xAC22
-#define BANDB_DEVICE_ID_USO9ML2_4      0xAC24
-#define BANDB_DEVICE_ID_US9ML2_2       0xAC29
-#define BANDB_DEVICE_ID_US9ML2_4       0xAC30
-#define BANDB_DEVICE_ID_USPTL4_2       0xAC31
-#define BANDB_DEVICE_ID_USPTL4_4       0xAC32
-#define BANDB_DEVICE_ID_USOPTL4_2      0xAC42
-#define BANDB_DEVICE_ID_USOPTL4_4      0xAC44
-#define BANDB_DEVICE_ID_USOPTL2_4      0xAC24
+#define USB_VENDOR_ID_BANDB              0x0856
+#define BANDB_DEVICE_ID_USO9ML2_2        0xAC22
+#define BANDB_DEVICE_ID_USO9ML2_2P       0xBC00
+#define BANDB_DEVICE_ID_USO9ML2_4        0xAC24
+#define BANDB_DEVICE_ID_USO9ML2_4P       0xBC01
+#define BANDB_DEVICE_ID_US9ML2_2         0xAC29
+#define BANDB_DEVICE_ID_US9ML2_4         0xAC30
+#define BANDB_DEVICE_ID_USPTL4_2         0xAC31
+#define BANDB_DEVICE_ID_USPTL4_4         0xAC32
+#define BANDB_DEVICE_ID_USOPTL4_2        0xAC42
+#define BANDB_DEVICE_ID_USOPTL4_2P       0xBC02
+#define BANDB_DEVICE_ID_USOPTL4_4        0xAC44
+#define BANDB_DEVICE_ID_USOPTL4_4P       0xBC03
+#define BANDB_DEVICE_ID_USOPTL2_4        0xAC24
 
 /* This driver also supports
  * ATEN UC2324 device using Moschip MCS7840
@@ -184,13 +188,17 @@ static const struct usb_device_id moschip_port_id_table[] = {
        {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
        {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
@@ -201,13 +209,17 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
        {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
        {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
@@ -2273,6 +2285,9 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
        case TIOCGICOUNT:
                cnow = mos7840_port->icount;
                smp_rmb();
+
+               memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
                icount.cts = cnow.cts;
                icount.dsr = cnow.dsr;
                icount.rng = cnow.rng;
index a6b207c84917425db5f4c9ea1a1da075a6798002..1f00f243c26cf5e1825632e40fc9c2a60287f9e3 100644 (file)
@@ -25,6 +25,7 @@ static int debug;
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */
+       { USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 9fc6ea2c681fae8ce6a43404109ca23c3177a310..c46911af282f01c82eb8cc34e312db994173d38c 100644 (file)
@@ -164,6 +164,14 @@ static void option_instat_callback(struct urb *urb);
 #define YISO_VENDOR_ID                         0x0EAB
 #define YISO_PRODUCT_U893                      0xC893
 
+/*
+ * NOVATEL WIRELESS PRODUCTS
+ *
+ * Note from Novatel Wireless:
+ * If your Novatel modem does not work on linux, don't
+ * change the option module, but check our website. If
+ * that does not help, contact ddeschepper@nvtl.com
+*/
 /* MERLIN EVDO PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_V640           0x1100
 #define NOVATELWIRELESS_PRODUCT_V620           0x1110
@@ -185,24 +193,39 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EU730          0x2400
 #define NOVATELWIRELESS_PRODUCT_EU740          0x2410
 #define NOVATELWIRELESS_PRODUCT_EU870D         0x2420
-
 /* OVATION PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_MC727          0x4100
 #define NOVATELWIRELESS_PRODUCT_MC950D         0x4400
-#define NOVATELWIRELESS_PRODUCT_U727           0x5010
-#define NOVATELWIRELESS_PRODUCT_MC727_NEW      0x5100
-#define NOVATELWIRELESS_PRODUCT_MC760          0x6000
+/*
+ * Note from Novatel Wireless:
+ * All PID in the 5xxx range are currently reserved for
+ * auto-install CDROMs, and should not be added to this
+ * module.
+ *
+ * #define NOVATELWIRELESS_PRODUCT_U727                0x5010
+ * #define NOVATELWIRELESS_PRODUCT_MC727_NEW   0x5100
+*/
 #define NOVATELWIRELESS_PRODUCT_OVMC760                0x6002
-
-/* FUTURE NOVATEL PRODUCTS */
-#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001
-#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0X7000
-#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0X7001
-#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED        0X8000
-#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0X8001
-#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0X9000
-#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0X9001
-#define NOVATELWIRELESS_PRODUCT_GLOBAL         0XA001
+#define NOVATELWIRELESS_PRODUCT_MC780          0x6010
+#define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0x6000
+#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0x6001
+#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0x7000
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0x7001
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3        0x7003
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4        0x7004
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5        0x7005
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6        0x7006
+#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7        0x7007
+#define NOVATELWIRELESS_PRODUCT_MC996D         0x7030
+#define NOVATELWIRELESS_PRODUCT_MF3470         0x7041
+#define NOVATELWIRELESS_PRODUCT_MC547          0x7042
+#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED        0x8000
+#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0x8001
+#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
+#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
+#define NOVATELWIRELESS_PRODUCT_G1             0xA001
+#define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
+#define NOVATELWIRELESS_PRODUCT_G2             0xA010
 
 /* AMOI PRODUCTS */
 #define AMOI_VENDOR_ID                         0x1614
@@ -365,6 +388,10 @@ static void option_instat_callback(struct urb *urb);
 #define OLIVETTI_VENDOR_ID                     0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100            0xc000
 
+/* Celot products */
+#define CELOT_VENDOR_ID                                0x211f
+#define CELOT_PRODUCT_CT680M                   0x6801
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -486,36 +513,44 @@ 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(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, /* Novatel EVDO product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, /* Novatel HSPA product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, /* Novatel EVDO Embedded product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, /* Novatel HSPA Embedded product */
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL) }, /* Novatel Global product */
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC780) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC996D) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MF3470) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -887,10 +922,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
        { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
        { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
-
        { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
-
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+       { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 6b60018222790bed2ec8f77b637a19bfd08caa2a..8ae4c6cbc38a04ea250d43aad68aa43081098245 100644 (file)
@@ -86,6 +86,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
        { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
        { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
+       { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
        { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
@@ -788,7 +789,7 @@ static void pl2303_process_read_urb(struct urb *urb)
 
        if (port->port.console && port->sysrq) {
                for (i = 0; i < urb->actual_length; ++i)
-                       if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
+                       if (!usb_serial_handle_sysrq_char(port, data[i]))
                                tty_insert_flip_char(tty, data[i], tty_flag);
        } else {
                tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
index a871645389dd365764485481bc8ba773c6c68f37..43eb9bdad422c91e4290f2204ee2f178d393b002 100644 (file)
 #define CRESSI_VENDOR_ID       0x04b8
 #define CRESSI_EDY_PRODUCT_ID  0x0521
 
+/* Zeagle dive computer interface */
+#define ZEAGLE_VENDOR_ID       0x04b8
+#define ZEAGLE_N2ITION3_PRODUCT_ID     0x0522
+
 /* Sony, USB data cable for CMD-Jxx mobile phones */
 #define SONY_VENDOR_ID         0x054c
 #define SONY_QN3USB_PRODUCT_ID 0x0437
index 6e82d4f54bc87c167e6052119f052ca35bbfcf14..e986002b3844c07d24b292344258286434820d8b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/serial.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial_reg.h>
 #include <linux/uaccess.h>
 
 #define QT_OPEN_CLOSE_CHANNEL       0xca
 #define QT_HW_FLOW_CONTROL_MASK     0xc5
 #define QT_SW_FLOW_CONTROL_MASK     0xc6
 
-#define MODEM_CTL_REGISTER         0x04
-#define MODEM_STATUS_REGISTER      0x06
-
-
-#define SERIAL_LSR_OE       0x02
-#define SERIAL_LSR_PE       0x04
-#define SERIAL_LSR_FE       0x08
-#define SERIAL_LSR_BI       0x10
-
-#define SERIAL_LSR_TEMT     0x40
-
-#define  SERIAL_MCR_DTR             0x01
-#define  SERIAL_MCR_RTS             0x02
-#define  SERIAL_MCR_LOOP            0x10
-
-#define  SERIAL_MSR_CTS             0x10
-#define  SERIAL_MSR_CD              0x80
-#define  SERIAL_MSR_RI              0x40
-#define  SERIAL_MSR_DSR             0x20
 #define  SERIAL_MSR_MASK            0xf0
 
-#define  SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS)
+#define  SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
 
-#define  SERIAL_8_DATA              0x03
-#define  SERIAL_7_DATA              0x02
-#define  SERIAL_6_DATA              0x01
-#define  SERIAL_5_DATA              0x00
-
-#define  SERIAL_ODD_PARITY          0X08
-#define  SERIAL_EVEN_PARITY         0X18
+#define  SERIAL_EVEN_PARITY         (UART_LCR_PARITY | UART_LCR_EPAR)
 
 #define  MAX_BAUD_RATE              460800
 
@@ -70,7 +46,7 @@
 #define FULLPWRBIT          0x00000080
 #define NEXT_BOARD_POWER_BIT        0x00000004
 
-static int debug = 1;
+static int debug;
 
 /* Version Information */
 #define DRIVER_VERSION "v0.1"
@@ -99,10 +75,12 @@ static struct usb_driver ssu100_driver = {
 };
 
 struct ssu100_port_private {
+       spinlock_t status_lock;
        u8 shadowLSR;
        u8 shadowMSR;
        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
        unsigned short max_packet_size;
+       struct async_icount icount;
 };
 
 static void ssu100_release(struct usb_serial *serial)
@@ -150,9 +128,10 @@ static inline int ssu100_getregister(struct usb_device *dev,
 
 static inline int ssu100_setregister(struct usb_device *dev,
                                     unsigned short uart,
+                                    unsigned short reg,
                                     u16 data)
 {
-       u16 value = (data << 8) | MODEM_CTL_REGISTER;
+       u16 value = (data << 8) | reg;
 
        return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                               QT_SET_GET_REGISTER, 0x40, value, uart,
@@ -178,11 +157,11 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set,
        clear &= ~set;  /* 'set' takes precedence over 'clear' */
        urb_value = 0;
        if (set & TIOCM_DTR)
-               urb_value |= SERIAL_MCR_DTR;
+               urb_value |= UART_MCR_DTR;
        if (set & TIOCM_RTS)
-               urb_value |= SERIAL_MCR_RTS;
+               urb_value |= UART_MCR_RTS;
 
-       result = ssu100_setregister(dev, 0, urb_value);
+       result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
        if (result < 0)
                dbg("%s Error from MODEM_CTRL urb", __func__);
 
@@ -264,24 +243,24 @@ static void ssu100_set_termios(struct tty_struct *tty,
 
        if (cflag & PARENB) {
                if (cflag & PARODD)
-                       urb_value |= SERIAL_ODD_PARITY;
+                       urb_value |= UART_LCR_PARITY;
                else
                        urb_value |= SERIAL_EVEN_PARITY;
        }
 
        switch (cflag & CSIZE) {
        case CS5:
-               urb_value |= SERIAL_5_DATA;
+               urb_value |= UART_LCR_WLEN5;
                break;
        case CS6:
-               urb_value |= SERIAL_6_DATA;
+               urb_value |= UART_LCR_WLEN6;
                break;
        case CS7:
-               urb_value |= SERIAL_7_DATA;
+               urb_value |= UART_LCR_WLEN7;
                break;
        default:
        case CS8:
-               urb_value |= SERIAL_8_DATA;
+               urb_value |= UART_LCR_WLEN8;
                break;
        }
 
@@ -333,6 +312,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
        u8 *data;
        int result;
+       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
@@ -350,11 +330,10 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
                return result;
        }
 
-       priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
-                                     SERIAL_LSR_FE | SERIAL_LSR_BI);
-
-       priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
-                                     SERIAL_MSR_RI | SERIAL_MSR_CD);
+       spin_lock_irqsave(&priv->status_lock, flags);
+       priv->shadowLSR = data[0];
+       priv->shadowMSR = data[1];
+       spin_unlock_irqrestore(&priv->status_lock, flags);
 
        kfree(data);
 
@@ -398,11 +377,51 @@ static int get_serial_info(struct usb_serial_port *port,
        return 0;
 }
 
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+       struct async_icount prev, cur;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->status_lock, flags);
+       prev = priv->icount;
+       spin_unlock_irqrestore(&priv->status_lock, flags);
+
+       while (1) {
+               wait_event_interruptible(priv->delta_msr_wait,
+                                        ((priv->icount.rng != prev.rng) ||
+                                         (priv->icount.dsr != prev.dsr) ||
+                                         (priv->icount.dcd != prev.dcd) ||
+                                         (priv->icount.cts != prev.cts)));
+
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+
+               spin_lock_irqsave(&priv->status_lock, flags);
+               cur = priv->icount;
+               spin_unlock_irqrestore(&priv->status_lock, flags);
+
+               if ((prev.rng == cur.rng) &&
+                   (prev.dsr == cur.dsr) &&
+                   (prev.dcd == cur.dcd) &&
+                   (prev.cts == cur.cts))
+                       return -EIO;
+
+               if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
+                   (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
+                   (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) ||
+                   (arg & TIOCM_CTS && (prev.cts != cur.cts)))
+                       return 0;
+       }
+       return 0;
+}
+
 static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+       void __user *user_arg = (void __user *)arg;
 
        dbg("%s cmd 0x%04x", __func__, cmd);
 
@@ -412,28 +431,28 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
                                       (struct serial_struct __user *) arg);
 
        case TIOCMIWAIT:
-               while (priv != NULL) {
-                       u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK;
-                       interruptible_sleep_on(&priv->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       else {
-                               u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR;
-                               if (!diff)
-                                       return -EIO; /* no change => error */
-
-                               /* Return 0 if caller wanted to know about
-                                  these bits */
-
-                               if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) ||
-                                   ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) ||
-                                   ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) ||
-                                   ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS)))
-                                       return 0;
-                       }
-               }
+               return wait_modem_info(port, arg);
+
+       case TIOCGICOUNT:
+       {
+               struct serial_icounter_struct icount;
+               struct async_icount cnow = priv->icount;
+               memset(&icount, 0, sizeof(icount));
+               icount.cts = cnow.cts;
+               icount.dsr = cnow.dsr;
+               icount.rng = cnow.rng;
+               icount.dcd = cnow.dcd;
+               icount.rx = cnow.rx;
+               icount.tx = cnow.tx;
+               icount.frame = cnow.frame;
+               icount.overrun = cnow.overrun;
+               icount.parity = cnow.parity;
+               icount.brk = cnow.brk;
+               icount.buf_overrun = cnow.buf_overrun;
+               if (copy_to_user(user_arg, &icount, sizeof(icount)))
+                       return -EFAULT;
                return 0;
+       }
 
        default:
                break;
@@ -455,6 +474,7 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port)
 
        unsigned num_endpoints;
        int i;
+       unsigned long flags;
 
        num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
        dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
@@ -466,7 +486,9 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port)
        }
 
        /* set max packet size based on descriptor */
+       spin_lock_irqsave(&priv->status_lock, flags);
        priv->max_packet_size = ep_desc->wMaxPacketSize;
+       spin_unlock_irqrestore(&priv->status_lock, flags);
 
        dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
 }
@@ -485,9 +507,9 @@ static int ssu100_attach(struct usb_serial *serial)
                return -ENOMEM;
        }
 
+       spin_lock_init(&priv->status_lock);
        init_waitqueue_head(&priv->delta_msr_wait);
        usb_set_serial_port_data(port, priv);
-
        ssu100_set_max_packet_size(port);
 
        return ssu100_initdevice(serial->dev);
@@ -506,20 +528,20 @@ static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
        if (!d)
                return -ENOMEM;
 
-       r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d);
+       r = ssu100_getregister(dev, 0, UART_MCR, d);
        if (r < 0)
                goto mget_out;
 
-       r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1);
+       r = ssu100_getregister(dev, 0, UART_MSR, d+1);
        if (r < 0)
                goto mget_out;
 
-       r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) |
-               (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) |
-               (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) |
-               (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) |
-               (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) |
-               (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0);
+       r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
+               (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
+               (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
+               (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
+               (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
+               (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
 
 mget_out:
        kfree(d);
@@ -546,7 +568,7 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
        if (!port->serial->disconnected) {
                /* Disable flow control */
                if (!on &&
-                   ssu100_setregister(dev, 0, 0) < 0)
+                   ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
                        dev_err(&port->dev, "error from flowcontrol urb\n");
                /* drop RTS and DTR */
                if (on)
@@ -557,34 +579,88 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
        mutex_unlock(&port->serial->disc_mutex);
 }
 
+static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
+{
+       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->status_lock, flags);
+       priv->shadowMSR = msr;
+       spin_unlock_irqrestore(&priv->status_lock, flags);
+
+       if (msr & UART_MSR_ANY_DELTA) {
+               /* update input line counters */
+               if (msr & UART_MSR_DCTS)
+                       priv->icount.cts++;
+               if (msr & UART_MSR_DDSR)
+                       priv->icount.dsr++;
+               if (msr & UART_MSR_DDCD)
+                       priv->icount.dcd++;
+               if (msr & UART_MSR_TERI)
+                       priv->icount.rng++;
+               wake_up_interruptible(&priv->delta_msr_wait);
+       }
+}
+
+static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
+                             char *tty_flag)
+{
+       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->status_lock, flags);
+       priv->shadowLSR = lsr;
+       spin_unlock_irqrestore(&priv->status_lock, flags);
+
+       *tty_flag = TTY_NORMAL;
+       if (lsr & UART_LSR_BRK_ERROR_BITS) {
+               /* we always want to update icount, but we only want to
+                * update tty_flag for one case */
+               if (lsr & UART_LSR_BI) {
+                       priv->icount.brk++;
+                       *tty_flag = TTY_BREAK;
+                       usb_serial_handle_break(port);
+               }
+               if (lsr & UART_LSR_PE) {
+                       priv->icount.parity++;
+                       if (*tty_flag == TTY_NORMAL)
+                               *tty_flag = TTY_PARITY;
+               }
+               if (lsr & UART_LSR_FE) {
+                       priv->icount.frame++;
+                       if (*tty_flag == TTY_NORMAL)
+                               *tty_flag = TTY_FRAME;
+               }
+               if (lsr & UART_LSR_OE){
+                       priv->icount.overrun++;
+                       if (*tty_flag == TTY_NORMAL)
+                               *tty_flag = TTY_OVERRUN;
+               }
+       }
+
+}
+
 static int ssu100_process_packet(struct tty_struct *tty,
                                 struct usb_serial_port *port,
                                 struct ssu100_port_private *priv,
                                 char *packet, int len)
 {
        int i;
-       char flag;
+       char flag = TTY_NORMAL;
        char *ch;
 
        dbg("%s - port %d", __func__, port->number);
 
-       if (len < 4) {
-               dbg("%s - malformed packet", __func__);
-               return 0;
-       }
-
-       if ((packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+       if ((len >= 4) &&
+           (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
            ((packet[2] == 0x00) || (packet[2] == 0x01))) {
-               if (packet[2] == 0x00)
-                       priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |
-                                                      SERIAL_LSR_PE |
-                                                      SERIAL_LSR_FE |
-                                                      SERIAL_LSR_BI);
-
-               if (packet[2] == 0x01) {
-                       priv->shadowMSR = packet[3];
-                       wake_up_interruptible(&priv->delta_msr_wait);
+               if (packet[2] == 0x00) {
+                       ssu100_update_lsr(port, packet[3], &flag);
+                       if (flag == TTY_OVERRUN)
+                               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
+               if (packet[2] == 0x01)
+                       ssu100_update_msr(port, packet[3]);
 
                len -= 4;
                ch = packet + 4;
@@ -596,7 +672,7 @@ static int ssu100_process_packet(struct tty_struct *tty,
 
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, flag);
                }
        } else
@@ -631,7 +707,6 @@ static void ssu100_process_read_urb(struct urb *urb)
        tty_kref_put(tty);
 }
 
-
 static struct usb_serial_driver ssu100_device = {
        .driver = {
                .owner = THIS_MODULE,
@@ -653,6 +728,7 @@ static struct usb_serial_driver ssu100_device = {
        .tiocmset            = ssu100_tiocmset,
        .ioctl               = ssu100_ioctl,
        .set_termios         = ssu100_set_termios,
+       .disconnect          = usb_serial_generic_disconnect,
 };
 
 static int __init ssu100_init(void)
index 2a982e62963b5b76a7bd894c412690b1ddb9381d..7a2177c79bdefb05fe88d6c67ee5b19cd7fae0f5 100644 (file)
@@ -736,6 +736,7 @@ int usb_serial_probe(struct usb_interface *interface,
 
        serial = create_serial(dev, interface, type);
        if (!serial) {
+               module_put(type->driver.owner);
                dev_err(&interface->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
@@ -746,11 +747,11 @@ int usb_serial_probe(struct usb_interface *interface,
 
                id = get_iface_id(type, interface);
                retval = type->probe(serial, id);
-               module_put(type->driver.owner);
 
                if (retval) {
                        dbg("sub driver rejected device");
                        kfree(serial);
+                       module_put(type->driver.owner);
                        return retval;
                }
        }
@@ -822,6 +823,7 @@ int usb_serial_probe(struct usb_interface *interface,
                if (num_bulk_in == 0 || num_bulk_out == 0) {
                        dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
                        kfree(serial);
+                       module_put(type->driver.owner);
                        return -ENODEV;
                }
        }
@@ -835,22 +837,15 @@ int usb_serial_probe(struct usb_interface *interface,
                        dev_err(&interface->dev,
                            "Generic device with no bulk out, not allowed.\n");
                        kfree(serial);
+                       module_put(type->driver.owner);
                        return -EIO;
                }
        }
 #endif
        if (!num_ports) {
                /* if this device type has a calc_num_ports function, call it */
-               if (type->calc_num_ports) {
-                       if (!try_module_get(type->driver.owner)) {
-                               dev_err(&interface->dev,
-                                       "module get failed, exiting\n");
-                               kfree(serial);
-                               return -EIO;
-                       }
+               if (type->calc_num_ports)
                        num_ports = type->calc_num_ports(serial);
-                       module_put(type->driver.owner);
-               }
                if (!num_ports)
                        num_ports = type->num_ports;
        }
@@ -1039,13 +1034,7 @@ int usb_serial_probe(struct usb_interface *interface,
 
        /* if this device type has an attach function, call it */
        if (type->attach) {
-               if (!try_module_get(type->driver.owner)) {
-                       dev_err(&interface->dev,
-                                       "module get failed, exiting\n");
-                       goto probe_error;
-               }
                retval = type->attach(serial);
-               module_put(type->driver.owner);
                if (retval < 0)
                        goto probe_error;
                serial->attached = 1;
@@ -1088,10 +1077,12 @@ int usb_serial_probe(struct usb_interface *interface,
 exit:
        /* success */
        usb_set_intfdata(interface, serial);
+       module_put(type->driver.owner);
        return 0;
 
 probe_error:
        usb_serial_put(serial);
+       module_put(type->driver.owner);
        return -EIO;
 }
 EXPORT_SYMBOL_GPL(usb_serial_probe);
index 552679b8dbd194406d2ee4a39932d8aa2c8bd784..e24ce31230712e4ee4f4fa1f439cab445c6917c5 100644 (file)
@@ -507,6 +507,7 @@ static const struct file_operations skel_fops = {
        .open =         skel_open,
        .release =      skel_release,
        .flush =        skel_flush,
+       .llseek =       noop_llseek,
 };
 
 /*
index 29e850a7a2f9871b7c9658e0717f8926dc5bc4ac..861af4a8b79cd0b1968ffa91019934b460b61821 100644 (file)
@@ -127,7 +127,10 @@ static void handle_tx(struct vhost_net *net)
        size_t len, total_len = 0;
        int err, wmem;
        size_t hdr_size;
-       struct socket *sock = rcu_dereference(vq->private_data);
+       struct socket *sock;
+
+       sock = rcu_dereference_check(vq->private_data,
+                                    lockdep_is_held(&vq->mutex));
        if (!sock)
                return;
 
@@ -243,7 +246,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
        int r, nlogs = 0;
 
        while (datalen > 0) {
-               if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
+               if (unlikely(seg >= VHOST_NET_MAX_SG)) {
                        r = -ENOBUFS;
                        goto err;
                }
@@ -582,7 +585,10 @@ static void vhost_net_disable_vq(struct vhost_net *n,
 static void vhost_net_enable_vq(struct vhost_net *n,
                                struct vhost_virtqueue *vq)
 {
-       struct socket *sock = vq->private_data;
+       struct socket *sock;
+
+       sock = rcu_dereference_protected(vq->private_data,
+                                        lockdep_is_held(&vq->mutex));
        if (!sock)
                return;
        if (vq == n->vqs + VHOST_NET_VQ_TX) {
@@ -598,7 +604,8 @@ static struct socket *vhost_net_stop_vq(struct vhost_net *n,
        struct socket *sock;
 
        mutex_lock(&vq->mutex);
-       sock = vq->private_data;
+       sock = rcu_dereference_protected(vq->private_data,
+                                        lockdep_is_held(&vq->mutex));
        vhost_net_disable_vq(n, vq);
        rcu_assign_pointer(vq->private_data, NULL);
        mutex_unlock(&vq->mutex);
@@ -736,7 +743,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        }
 
        /* start polling new socket */
-       oldsock = vq->private_data;
+       oldsock = rcu_dereference_protected(vq->private_data,
+                                           lockdep_is_held(&vq->mutex));
        if (sock != oldsock) {
                 vhost_net_disable_vq(n, vq);
                 rcu_assign_pointer(vq->private_data, sock);
@@ -869,6 +877,7 @@ static const struct file_operations vhost_net_fops = {
        .compat_ioctl   = vhost_net_compat_ioctl,
 #endif
        .open           = vhost_net_open,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice vhost_net_misc = {
index e05557d529992ec4deb1827a32574043bcd00925..8b5a1b33d0fed906ef6d0873027a3275858e8c2c 100644 (file)
@@ -60,22 +60,25 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
        return 0;
 }
 
+static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn)
+{
+       INIT_LIST_HEAD(&work->node);
+       work->fn = fn;
+       init_waitqueue_head(&work->done);
+       work->flushing = 0;
+       work->queue_seq = work->done_seq = 0;
+}
+
 /* Init poll structure */
 void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
                     unsigned long mask, struct vhost_dev *dev)
 {
-       struct vhost_work *work = &poll->work;
-
        init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
        init_poll_funcptr(&poll->table, vhost_poll_func);
        poll->mask = mask;
        poll->dev = dev;
 
-       INIT_LIST_HEAD(&work->node);
-       work->fn = fn;
-       init_waitqueue_head(&work->done);
-       work->flushing = 0;
-       work->queue_seq = work->done_seq = 0;
+       vhost_work_init(&poll->work, fn);
 }
 
 /* Start polling a file. We add ourselves to file's wait queue. The caller must
@@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll)
        remove_wait_queue(poll->wqh, &poll->wait);
 }
 
-/* Flush any work that has been scheduled. When calling this, don't hold any
- * locks that are also used by the callback. */
-void vhost_poll_flush(struct vhost_poll *poll)
+static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work)
 {
-       struct vhost_work *work = &poll->work;
        unsigned seq;
        int left;
        int flushing;
 
-       spin_lock_irq(&poll->dev->work_lock);
+       spin_lock_irq(&dev->work_lock);
        seq = work->queue_seq;
        work->flushing++;
-       spin_unlock_irq(&poll->dev->work_lock);
+       spin_unlock_irq(&dev->work_lock);
        wait_event(work->done, ({
-                  spin_lock_irq(&poll->dev->work_lock);
+                  spin_lock_irq(&dev->work_lock);
                   left = seq - work->done_seq <= 0;
-                  spin_unlock_irq(&poll->dev->work_lock);
+                  spin_unlock_irq(&dev->work_lock);
                   left;
        }));
-       spin_lock_irq(&poll->dev->work_lock);
+       spin_lock_irq(&dev->work_lock);
        flushing = --work->flushing;
-       spin_unlock_irq(&poll->dev->work_lock);
+       spin_unlock_irq(&dev->work_lock);
        BUG_ON(flushing < 0);
 }
 
-void vhost_poll_queue(struct vhost_poll *poll)
+/* Flush any work that has been scheduled. When calling this, don't hold any
+ * locks that are also used by the callback. */
+void vhost_poll_flush(struct vhost_poll *poll)
+{
+       vhost_work_flush(poll->dev, &poll->work);
+}
+
+static inline void vhost_work_queue(struct vhost_dev *dev,
+                                   struct vhost_work *work)
 {
-       struct vhost_dev *dev = poll->dev;
-       struct vhost_work *work = &poll->work;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->work_lock, flags);
@@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll)
        spin_unlock_irqrestore(&dev->work_lock, flags);
 }
 
+void vhost_poll_queue(struct vhost_poll *poll)
+{
+       vhost_work_queue(poll->dev, &poll->work);
+}
+
 static void vhost_vq_reset(struct vhost_dev *dev,
                           struct vhost_virtqueue *vq)
 {
@@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
        return dev->mm == current->mm ? 0 : -EPERM;
 }
 
+struct vhost_attach_cgroups_struct {
+        struct vhost_work work;
+        struct task_struct *owner;
+        int ret;
+};
+
+static void vhost_attach_cgroups_work(struct vhost_work *work)
+{
+        struct vhost_attach_cgroups_struct *s;
+        s = container_of(work, struct vhost_attach_cgroups_struct, work);
+        s->ret = cgroup_attach_task_all(s->owner, current);
+}
+
+static int vhost_attach_cgroups(struct vhost_dev *dev)
+{
+        struct vhost_attach_cgroups_struct attach;
+        attach.owner = current;
+        vhost_work_init(&attach.work, vhost_attach_cgroups_work);
+        vhost_work_queue(dev, &attach.work);
+        vhost_work_flush(dev, &attach.work);
+        return attach.ret;
+}
+
 /* Caller should have device mutex */
 static long vhost_dev_set_owner(struct vhost_dev *dev)
 {
@@ -255,14 +289,16 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
        }
 
        dev->worker = worker;
-       err = cgroup_attach_task_current_cg(worker);
+       wake_up_process(worker);        /* avoid contributing to loadavg */
+
+       err = vhost_attach_cgroups(dev);
        if (err)
                goto err_cgroup;
-       wake_up_process(worker);        /* avoid contributing to loadavg */
 
        return 0;
 err_cgroup:
        kthread_stop(worker);
+       dev->worker = NULL;
 err_worker:
        if (dev->mm)
                mmput(dev->mm);
@@ -284,7 +320,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
        vhost_dev_cleanup(dev);
 
        memory->nregions = 0;
-       dev->memory = memory;
+       RCU_INIT_POINTER(dev->memory, memory);
        return 0;
 }
 
@@ -316,14 +352,18 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
                fput(dev->log_file);
        dev->log_file = NULL;
        /* No one will access memory at this point */
-       kfree(dev->memory);
-       dev->memory = NULL;
+       kfree(rcu_dereference_protected(dev->memory,
+                                       lockdep_is_held(&dev->mutex)));
+       RCU_INIT_POINTER(dev->memory, NULL);
        if (dev->mm)
                mmput(dev->mm);
        dev->mm = NULL;
 
        WARN_ON(!list_empty(&dev->work_list));
-       kthread_stop(dev->worker);
+       if (dev->worker) {
+               kthread_stop(dev->worker);
+               dev->worker = NULL;
+       }
 }
 
 static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
@@ -401,14 +441,22 @@ static int vq_access_ok(unsigned int num,
 /* Caller should have device mutex but not vq mutex */
 int vhost_log_access_ok(struct vhost_dev *dev)
 {
-       return memory_access_ok(dev, dev->memory, 1);
+       struct vhost_memory *mp;
+
+       mp = rcu_dereference_protected(dev->memory,
+                                      lockdep_is_held(&dev->mutex));
+       return memory_access_ok(dev, mp, 1);
 }
 
 /* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
 static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base)
 {
-       return vq_memory_access_ok(log_base, vq->dev->memory,
+       struct vhost_memory *mp;
+
+       mp = rcu_dereference_protected(vq->dev->memory,
+                                      lockdep_is_held(&vq->mutex));
+       return vq_memory_access_ok(log_base, mp,
                            vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) &&
                (!vq->log_used || log_access_ok(log_base, vq->log_addr,
                                        sizeof *vq->used +
@@ -448,7 +496,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
                kfree(newmem);
                return -EFAULT;
        }
-       oldmem = d->memory;
+       oldmem = rcu_dereference_protected(d->memory,
+                                          lockdep_is_held(&d->mutex));
        rcu_assign_pointer(d->memory, newmem);
        synchronize_rcu();
        kfree(oldmem);
@@ -819,11 +868,12 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
                if (r < 0)
                        return r;
                len -= l;
-               if (!len)
+               if (!len) {
+                       if (vq->log_ctx)
+                               eventfd_signal(vq->log_ctx, 1);
                        return 0;
+               }
        }
-       if (vq->log_ctx)
-               eventfd_signal(vq->log_ctx, 1);
        /* Length written exceeds what we have stored. This is a bug. */
        BUG();
        return 0;
index afd77295971ce3044117d0d6e5ea8f4e20f655fe..af3c11ded5fd4910ed0dccea161a801298036731 100644 (file)
@@ -106,7 +106,7 @@ struct vhost_virtqueue {
         * vhost_work execution acts instead of rcu_read_lock() and the end of
         * vhost_work execution acts instead of rcu_read_lock().
         * Writers use virtqueue mutex. */
-       void *private_data;
+       void __rcu *private_data;
        /* Log write descriptors */
        void __user *log_base;
        struct vhost_log log[VHOST_NET_MAX_SG];
@@ -116,7 +116,7 @@ struct vhost_dev {
        /* Readers use RCU to access memory table pointer
         * log base pointer and features.
         * Writers use mutex below.*/
-       struct vhost_memory *memory;
+       struct vhost_memory __rcu *memory;
        struct mm_struct *mm;
        struct mutex mutex;
        unsigned acked_features;
@@ -173,7 +173,11 @@ enum {
 
 static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
 {
-       unsigned acked_features = rcu_dereference(dev->acked_features);
+       unsigned acked_features;
+
+       acked_features =
+               rcu_dereference_index_check(dev->acked_features,
+                                           lockdep_is_held(&dev->mutex));
        return acked_features & (1 << bit);
 }
 
index 84f842331dfae0d7c4b194b42f283fae44e8a6af..7ccc967831f05bca5aba179bb88ff7880f55b92f 100644 (file)
@@ -3508,7 +3508,7 @@ static void fbcon_exit(void)
        softback_buf = 0UL;
 
        for (i = 0; i < FB_MAX; i++) {
-               int pending;
+               int pending = 0;
 
                mapped = 0;
                info = registered_fb[i];
@@ -3516,7 +3516,8 @@ static void fbcon_exit(void)
                if (info == NULL)
                        continue;
 
-               pending = cancel_work_sync(&info->queue);
+               if (info->queue.func)
+                       pending = cancel_work_sync(&info->queue);
                DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" :
                        "no"));
 
index 815f84b07933f7b97dc1fab249055531f6cc65b2..70477c2e4b619cd6a2ca5562771e15243cd647a3 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
 #include <linux/dmi.h>
-
+#include <linux/pci.h>
 #include <video/vga.h>
 
 static struct fb_var_screeninfo efifb_defined __devinitdata = {
@@ -39,17 +39,31 @@ enum {
        M_I20,          /* 20-Inch iMac */
        M_I20_SR,       /* 20-Inch iMac (Santa Rosa) */
        M_I24,          /* 24-Inch iMac */
+       M_I24_8_1,      /* 24-Inch iMac, 8,1th gen */
+       M_I24_10_1,     /* 24-Inch iMac, 10,1th gen */
+       M_I27_11_1,     /* 27-Inch iMac, 11,1th gen */
        M_MINI,         /* Mac Mini */
+       M_MINI_3_1,     /* Mac Mini, 3,1th gen */
+       M_MINI_4_1,     /* Mac Mini, 4,1th gen */
        M_MB,           /* MacBook */
        M_MB_2,         /* MacBook, 2nd rev. */
        M_MB_3,         /* MacBook, 3rd rev. */
+       M_MB_5_1,       /* MacBook, 5th rev. */
+       M_MB_6_1,       /* MacBook, 6th rev. */
+       M_MB_7_1,       /* MacBook, 7th rev. */
        M_MB_SR,        /* MacBook, 2nd gen, (Santa Rosa) */
        M_MBA,          /* MacBook Air */
        M_MBP,          /* MacBook Pro */
        M_MBP_2,        /* MacBook Pro 2nd gen */
+       M_MBP_2_2,      /* MacBook Pro 2,2nd gen */
        M_MBP_SR,       /* MacBook Pro (Santa Rosa) */
        M_MBP_4,        /* MacBook Pro, 4th gen */
        M_MBP_5_1,    /* MacBook Pro, 5,1th gen */
+       M_MBP_5_2,      /* MacBook Pro, 5,2th gen */
+       M_MBP_5_3,      /* MacBook Pro, 5,3rd gen */
+       M_MBP_6_1,      /* MacBook Pro, 6,1th gen */
+       M_MBP_6_2,      /* MacBook Pro, 6,2th gen */
+       M_MBP_7_1,      /* MacBook Pro, 7,1th gen */
        M_UNKNOWN       /* placeholder */
 };
 
@@ -64,14 +78,28 @@ static struct efifb_dmi_info {
        [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
        [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
        [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
+       [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 },
+       [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 },
+       [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 },
        [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
+       [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 },
+       [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 },
        [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
+       [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 },
+       [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 },
+       [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 },
        [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
        [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
        [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
+       [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 },
        [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
        [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
        [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
+       [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 },
+       [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 },
+       [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
+       [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
+       [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
        [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
 };
 
@@ -92,7 +120,12 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
        /* At least one of these two will be right; maybe both? */
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
@@ -101,14 +134,23 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
        {},
 };
 
@@ -116,7 +158,7 @@ static int set_system(const struct dmi_system_id *id)
 {
        struct efifb_dmi_info *info = id->driver_data;
        if (info->base == 0)
-               return -ENODEV;
+               return 0;
 
        printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
                         "(%dx%d, stride %d)\n", id->ident,
@@ -124,18 +166,55 @@ static int set_system(const struct dmi_system_id *id)
                         info->stride);
 
        /* Trust the bootloader over the DMI tables */
-       if (screen_info.lfb_base == 0)
+       if (screen_info.lfb_base == 0) {
+#if defined(CONFIG_PCI)
+               struct pci_dev *dev = NULL;
+               int found_bar = 0;
+#endif
                screen_info.lfb_base = info->base;
-       if (screen_info.lfb_linelength == 0)
-               screen_info.lfb_linelength = info->stride;
-       if (screen_info.lfb_width == 0)
-               screen_info.lfb_width = info->width;
-       if (screen_info.lfb_height == 0)
-               screen_info.lfb_height = info->height;
-       if (screen_info.orig_video_isVGA == 0)
-               screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
 
-       return 0;
+#if defined(CONFIG_PCI)
+               /* make sure that the address in the table is actually on a
+                * VGA device's PCI BAR */
+
+               for_each_pci_dev(dev) {
+                       int i;
+                       if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+                               continue;
+                       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+                               resource_size_t start, end;
+
+                               start = pci_resource_start(dev, i);
+                               if (start == 0)
+                                       break;
+                               end = pci_resource_end(dev, i);
+                               if (screen_info.lfb_base >= start &&
+                                               screen_info.lfb_base < end) {
+                                       found_bar = 1;
+                               }
+                       }
+               }
+               if (!found_bar)
+                       screen_info.lfb_base = 0;
+#endif
+       }
+       if (screen_info.lfb_base) {
+               if (screen_info.lfb_linelength == 0)
+                       screen_info.lfb_linelength = info->stride;
+               if (screen_info.lfb_width == 0)
+                       screen_info.lfb_width = info->width;
+               if (screen_info.lfb_height == 0)
+                       screen_info.lfb_height = info->height;
+               if (screen_info.orig_video_isVGA == 0)
+                       screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
+       } else {
+               screen_info.lfb_linelength = 0;
+               screen_info.lfb_width = 0;
+               screen_info.lfb_height = 0;
+               screen_info.orig_video_isVGA = 0;
+               return 0;
+       }
+       return 1;
 }
 
 static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
index b06647517c0e6a9523a690460c7b56ba61e89252..42e303ff862a43199172f8479eedecfb1bc11394 100644 (file)
@@ -1439,6 +1439,7 @@ static const struct file_operations fb_fops = {
 #ifdef CONFIG_FB_DEFERRED_IO
        .fsync =        fb_deferred_io_fsync,
 #endif
+       .llseek =       default_llseek,
 };
 
 struct class *fb_class;
index ecad96524570882b143827c9cfc10aa29c0b9a97..12dec7634c5548b4c10c5ba88c0c1d0acb1fa4d5 100644 (file)
@@ -175,36 +175,42 @@ static const struct file_operations sysconf_fops = {
        .read = sysconf_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations clock_fops = {
        .read = clock_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations display_fops = {
        .read = display_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations gsctl_fops = {
        .read = gsctl_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations sdram_fops = {
        .read = sdram_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations misc_fops = {
        .read = misc_read_file,
        .write = write_file_dummy,
        .open = open_file_generic,
+       .llseek = default_llseek,
 };
 
 static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
index f6fdc2085f3e20147a4e9b0ae8ab4080c4fa4728..fed2a72bc6b60a1986172298fbb67bc0eca2b3bc 100644 (file)
@@ -554,12 +554,8 @@ void __init omap_vram_reserve_sdram_memblock(void)
        size = PAGE_ALIGN(size);
 
        if (paddr) {
-               struct memblock_property res;
-
-               res.base = paddr;
-               res.size = size;
-               if ((paddr & ~PAGE_MASK) || memblock_find(&res) ||
-                   res.base != paddr || res.size != size) {
+               if ((paddr & ~PAGE_MASK) ||
+                   !memblock_is_region_memory(paddr, size)) {
                        pr_err("Illegal SDRAM region for VRAM\n");
                        return;
                }
index c91a7f70f7b086f56882ba07f97ba38e314adfd6..cea6403ae71c16ffbcded14282db1552244f8833 100644 (file)
@@ -298,8 +298,8 @@ static void set_dma_control0(struct pxa168fb_info *fbi)
         * Set bit to enable graphics DMA.
         */
        x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
-       x |= fbi->active ? 0x00000100 : 0;
-       fbi->active = 0;
+       x &= ~CFG_GRA_ENA_MASK;
+       x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
 
        /*
         * If we are in a pseudo-color mode, we need to enable
@@ -559,7 +559,7 @@ static struct fb_ops pxa168fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int __init pxa168fb_init_mode(struct fb_info *info,
+static int __devinit pxa168fb_init_mode(struct fb_info *info,
                              struct pxa168fb_mach_info *mi)
 {
        struct pxa168fb_info *fbi = info->par;
@@ -599,7 +599,7 @@ static int __init pxa168fb_init_mode(struct fb_info *info,
        return ret;
 }
 
-static int __init pxa168fb_probe(struct platform_device *pdev)
+static int __devinit pxa168fb_probe(struct platform_device *pdev)
 {
        struct pxa168fb_mach_info *mi;
        struct fb_info *info = 0;
@@ -784,20 +784,67 @@ failed:
        return ret;
 }
 
+static int __devexit pxa168fb_remove(struct platform_device *pdev)
+{
+       struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
+       struct fb_info *info;
+       int irq;
+       unsigned int data;
+
+       if (!fbi)
+               return 0;
+
+       /* disable DMA transfer */
+       data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
+       data &= ~CFG_GRA_ENA_MASK;
+       writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
+
+       info = fbi->info;
+
+       unregister_framebuffer(info);
+
+       writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
+
+       if (info->cmap.len)
+               fb_dealloc_cmap(&info->cmap);
+
+       irq = platform_get_irq(pdev, 0);
+       free_irq(irq, fbi);
+
+       dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+                               info->screen_base, info->fix.smem_start);
+
+       iounmap(fbi->reg_base);
+
+       clk_disable(fbi->clk);
+       clk_put(fbi->clk);
+
+       framebuffer_release(info);
+
+       return 0;
+}
+
 static struct platform_driver pxa168fb_driver = {
        .driver         = {
                .name   = "pxa168-fb",
                .owner  = THIS_MODULE,
        },
        .probe          = pxa168fb_probe,
+       .remove         = __devexit_p(pxa168fb_remove),
 };
 
-static int __devinit pxa168fb_init(void)
+static int __init pxa168fb_init(void)
 {
        return platform_driver_register(&pxa168fb_driver);
 }
 module_init(pxa168fb_init);
 
+static void __exit pxa168fb_exit(void)
+{
+       platform_driver_unregister(&pxa168fb_driver);
+}
+module_exit(pxa168fb_exit);
+
 MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
              "Green Wan <gwan@marvell.com>");
 MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
index 559bf1727a2b8f252a193d6fac276aed56124428..b52f8e4ef1fdbe3cd19c70d4fb282d15f5b99f85 100644 (file)
@@ -1701,6 +1701,9 @@ static int        sisfb_ioctl(struct fb_info *info, unsigned int cmd,
                break;
 
           case FBIOGET_VBLANK:
+
+               memset(&sisvbblank, 0, sizeof(struct fb_vblank));
+
                sisvbblank.count = 0;
                sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
 
index da03c074e32aad8b909c4b11c57a4c5a9f9d9285..4d553d0b8d7a450b9337a9b4375856c5b304217c 100644 (file)
@@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg)
 {
        struct viafb_ioctl_info viainfo;
 
+       memset(&viainfo, 0, sizeof(struct viafb_ioctl_info));
+
        viainfo.viafb_id = VIAID;
        viainfo.vendor_id = PCI_VIA_VENDOR_ID;
 
index f2d9e667972da120d3c39ab87965566fe5c13506..f885c868a04de186fe917bc01db66d55b2c846fd 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <linux/vlynq.h>
 
index b036677df8c445420906c722d00611dedcaf8b0a..c356146bd712bbe1b7a3af255f0d1f8fd9bd6646 100644 (file)
@@ -213,11 +213,11 @@ config OMAP_WATCHDOG
          here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer.
 
 config PNX4008_WATCHDOG
-       tristate "PNX4008 Watchdog"
-       depends on ARCH_PNX4008
+       tristate "PNX4008 and LPC32XX Watchdog"
+       depends on ARCH_PNX4008 || ARCH_LPC32XX
        help
          Say Y here if to include support for the watchdog timer
-         in the PNX4008 processor.
+         in the PNX4008 or LPC32XX processor.
          This driver can be built as a module by choosing M. The module
          will be called pnx4008_wdt.
 
@@ -957,12 +957,32 @@ config PIKA_WDT
          the Warp platform.
 
 config BOOKE_WDT
-       bool "PowerPC Book-E Watchdog Timer"
+       tristate "PowerPC Book-E Watchdog Timer"
        depends on BOOKE || 4xx
        ---help---
+         Watchdog driver for PowerPC Book-E chips, such as the Freescale
+         MPC85xx SOCs and the IBM PowerPC 440.
+
          Please see Documentation/watchdog/watchdog-api.txt for
          more information.
 
+config BOOKE_WDT_DEFAULT_TIMEOUT
+       int "PowerPC Book-E Watchdog Timer Default Timeout"
+       depends on BOOKE_WDT
+       default 38 if FSL_BOOKE
+       range 0 63 if FSL_BOOKE
+       default 3 if !FSL_BOOKE
+       range 0 3 if !FSL_BOOKE
+       help
+         Select the default watchdog timer period to be used by the PowerPC
+         Book-E watchdog driver.  A watchdog "event" occurs when the bit
+         position represented by this number transitions from zero to one.
+
+         For Freescale Book-E processors, this is a number between 0 and 63.
+         For other Book-E processors, this is a number between 0 and 3.
+
+         The value can be overidden by the wdt_period command-line parameter.
+
 # PPC64 Architecture
 
 config WATCHDOG_RTAS
index c764c52412e4054e6d40bd0e558991714aea9b49..b29221783598f7ab2cfc2030d702b6263089a719 100644 (file)
@@ -267,6 +267,7 @@ static const struct file_operations ar7_wdt_fops = {
        .unlocked_ioctl = ar7_wdt_ioctl,
        .open           = ar7_wdt_open,
        .release        = ar7_wdt_release,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice ar7_wdt_miscdev = {
index 3d49671cdf5aebf1f78e52d0a92a185dd9026a31..d11ffb091b0dfc0fa67edb4422145ce959091182 100644 (file)
@@ -4,7 +4,7 @@
  * Author: Matthew McClintock
  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2005, 2008 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * occur, and the final time the board will reset.
  */
 
-#ifdef CONFIG_FSL_BOOKE
-#define WDT_PERIOD_DEFAULT 38  /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
-#else
-#define WDT_PERIOD_DEFAULT 3   /* Refer to the PPC40x and PPC4xx manuals */
-#endif                         /* for timing information */
-
 u32 booke_wdt_enabled;
-u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
+u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
 
 #ifdef CONFIG_FSL_BOOKE
 #define WDTP(x)                ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
@@ -114,6 +108,27 @@ static void __booke_wdt_enable(void *data)
        mtspr(SPRN_TCR, val);
 }
 
+/**
+ * booke_wdt_disable - disable the watchdog on the given CPU
+ *
+ * This function is called on each CPU.  It disables the watchdog on that CPU.
+ *
+ * TCR[WRC] cannot be changed once it has been set to non-zero, but we can
+ * effectively disable the watchdog by setting its period to the maximum value.
+ */
+static void __booke_wdt_disable(void *data)
+{
+       u32 val;
+
+       val = mfspr(SPRN_TCR);
+       val &= ~(TCR_WIE | WDTP_MASK);
+       mtspr(SPRN_TCR, val);
+
+       /* clear status to make sure nothing is pending */
+       __booke_wdt_ping(NULL);
+
+}
+
 static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
 {
@@ -193,12 +208,21 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
        return nonseekable_open(inode, file);
 }
 
+static int booke_wdt_release(struct inode *inode, struct file *file)
+{
+       on_each_cpu(__booke_wdt_disable, NULL, 0);
+       booke_wdt_enabled = 0;
+
+       return 0;
+}
+
 static const struct file_operations booke_wdt_fops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
        .write = booke_wdt_write,
        .unlocked_ioctl = booke_wdt_ioctl,
        .open = booke_wdt_open,
+       .release = booke_wdt_release,
 };
 
 static struct miscdevice booke_wdt_miscdev = {
@@ -237,4 +261,9 @@ static int __init booke_wdt_init(void)
 
        return ret;
 }
-device_initcall(booke_wdt_init);
+
+module_init(booke_wdt_init);
+module_exit(booke_wdt_exit);
+
+MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
+MODULE_LICENSE("GPL");
index 566343b3c131fc3f6d3ce17b6bc7bd1e2c724ac4..eca855a55c0d6abf96096e6b41847c93b06675db 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -89,6 +89,7 @@ struct cpwd {
        } devs[WD_NUMDEVS];
 };
 
+static DEFINE_MUTEX(cpwd_mutex);
 static struct cpwd *cpwd_device;
 
 /* Sun uses Altera PLD EPF8820ATC144-4
@@ -368,7 +369,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
 {
        struct cpwd *p = cpwd_device;
 
-       lock_kernel();
+       mutex_lock(&cpwd_mutex);
        switch (iminor(inode)) {
        case WD0_MINOR:
        case WD1_MINOR:
@@ -376,7 +377,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
                break;
 
        default:
-               unlock_kernel();
+               mutex_unlock(&cpwd_mutex);
                return -ENODEV;
        }
 
@@ -386,13 +387,13 @@ static int cpwd_open(struct inode *inode, struct file *f)
                                IRQF_SHARED, DRIVER_NAME, p)) {
                        printk(KERN_ERR PFX "Cannot register IRQ %d\n",
                                p->irq);
-                       unlock_kernel();
+                       mutex_unlock(&cpwd_mutex);
                        return -EBUSY;
                }
                p->initialized = true;
        }
 
-       unlock_kernel();
+       mutex_unlock(&cpwd_mutex);
 
        return nonseekable_open(inode, f);
 }
@@ -482,9 +483,9 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd,
        case WIOCSTART:
        case WIOCSTOP:
        case WIOCGSTAT:
-               lock_kernel();
+               mutex_lock(&cpwd_mutex);
                rval = cpwd_ioctl(file, cmd, arg);
-               unlock_kernel();
+               mutex_unlock(&cpwd_mutex);
                break;
 
        /* everything else is handled by the generic compat layer */
@@ -524,6 +525,7 @@ static const struct file_operations cpwd_fops = {
        .write =                cpwd_write,
        .read =                 cpwd_read,
        .release =              cpwd_release,
+       .llseek =               no_llseek,
 };
 
 static int __devinit cpwd_probe(struct platform_device *op,
index 59359c9a5e01aafaaa43cba6c8a3fd1ca4842e1c..726b7df61fd08b366a728fb5be0c793235b4d585 100644 (file)
@@ -188,6 +188,7 @@ static const struct file_operations ep93xx_wdt_fops = {
        .unlocked_ioctl = ep93xx_wdt_ioctl,
        .open           = ep93xx_wdt_open,
        .release        = ep93xx_wdt_release,
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice ep93xx_wdt_miscdev = {
index 2a410170eca67c93b5472fdfa4c419c3bba2f58e..909923800a02291bee821038ca3b62f6eb0a1ea8 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/irq.h>
 
 #include <asm/mipsregs.h>
 #include <asm/uasm.h>
index 76b58abf445182d6708e39f7801c77c062004769..81e3d610089439c7f6a168f56c5227781453729f 100644 (file)
@@ -258,6 +258,7 @@ static const struct file_operations omap_wdt_fops = {
        .unlocked_ioctl = omap_wdt_ioctl,
        .open = omap_wdt_open,
        .release = omap_wdt_release,
+       .llseek = no_llseek,
 };
 
 static int __devinit omap_wdt_probe(struct platform_device *pdev)
index 88c83aa5730318b512d86a7a048dc60a9758de46..f31493e65b380cd63fef6d55132dd96e7af32d63 100644 (file)
@@ -305,7 +305,7 @@ static int __init sbwdog_init(void)
        if (ret) {
                printk(KERN_ERR "%s: failed to request irq 1 - %d\n",
                                                ident.identity, ret);
-               return ret;
+               goto out;
        }
 
        ret = misc_register(&sbwdog_miscdev);
@@ -313,14 +313,20 @@ static int __init sbwdog_init(void)
                printk(KERN_INFO "%s: timeout is %ld.%ld secs\n",
                                ident.identity,
                                timeout / 1000000, (timeout / 100000) % 10);
-       } else
-               free_irq(1, (void *)user_dog);
+               return 0;
+       }
+       free_irq(1, (void *)user_dog);
+out:
+       unregister_reboot_notifier(&sbwdog_notifier);
+
        return ret;
 }
 
 static void __exit sbwdog_exit(void)
 {
        misc_deregister(&sbwdog_miscdev);
+       free_irq(1, (void *)user_dog);
+       unregister_reboot_notifier(&sbwdog_notifier);
 }
 
 module_init(sbwdog_init);
index 458c499c1223c6f73aaab93f9a6bdc7c816de5a2..18cdeb4c4258a67ccdba77fc517596eaa71819b9 100644 (file)
@@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
        wdt->pdev = pdev;
        mutex_init(&wdt->lock);
 
+       /* make sure that the watchdog is disabled */
+       ts72xx_wdt_stop(wdt);
+
        error = misc_register(&ts72xx_wdt_miscdev);
        if (error) {
                dev_err(&pdev->dev, "failed to register miscdev\n");
index 72f91bff29c7d836d86844c224225e1353c76648..7d24b0d94ed4756615ef66b3304b270f66707ba4 100644 (file)
@@ -112,6 +112,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
 #define VALID_EVTCHN(chn)      ((chn) != 0)
 
 static struct irq_chip xen_dynamic_chip;
+static struct irq_chip xen_percpu_chip;
 
 /* Constructor for packed IRQ information. */
 static struct irq_info mk_unbound_info(void)
@@ -337,30 +338,29 @@ static void unmask_evtchn(int port)
 
 static int find_unbound_irq(void)
 {
-       int irq;
-       struct irq_desc *desc;
+       struct irq_data *data;
+       int irq, res;
 
        for (irq = 0; irq < nr_irqs; irq++) {
-               desc = irq_to_desc(irq);
+               data = irq_get_irq_data(irq);
                /* only 0->15 have init'd desc; handle irq > 16 */
-               if (desc == NULL)
+               if (!data)
                        break;
-               if (desc->chip == &no_irq_chip)
+               if (data->chip == &no_irq_chip)
                        break;
-               if (desc->chip != &xen_dynamic_chip)
+               if (data->chip != &xen_dynamic_chip)
                        continue;
                if (irq_info[irq].type == IRQT_UNBOUND)
-                       break;
+                       return irq;
        }
 
        if (irq == nr_irqs)
                panic("No available IRQ to bind to: increase nr_irqs!\n");
 
-       desc = irq_to_desc_alloc_node(irq, 0);
-       if (WARN_ON(desc == NULL))
-               return -1;
+       res = irq_alloc_desc_at(irq, 0);
 
-       dynamic_irq_init_keep_chip_data(irq);
+       if (WARN_ON(res != irq))
+               return -1;
 
        return irq;
 }
@@ -377,7 +377,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
                irq = find_unbound_irq();
 
                set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-                                             handle_level_irq, "event");
+                                             handle_edge_irq, "event");
 
                evtchn_to_irq[evtchn] = irq;
                irq_info[irq] = mk_evtchn_info(evtchn);
@@ -403,8 +403,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
                if (irq < 0)
                        goto out;
 
-               set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-                                             handle_level_irq, "ipi");
+               set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
+                                             handle_percpu_irq, "ipi");
 
                bind_ipi.vcpu = cpu;
                if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
@@ -444,8 +444,8 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 
                irq = find_unbound_irq();
 
-               set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-                                             handle_level_irq, "virq");
+               set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
+                                             handle_percpu_irq, "virq");
 
                evtchn_to_irq[evtchn] = irq;
                irq_info[irq] = mk_virq_info(evtchn, virq);
@@ -494,7 +494,7 @@ static void unbind_from_irq(unsigned int irq)
        if (irq_info[irq].type != IRQT_UNBOUND) {
                irq_info[irq] = mk_unbound_info();
 
-               dynamic_irq_cleanup(irq);
+               irq_free_desc(irq);
        }
 
        spin_unlock(&irq_mapping_update_lock);
@@ -964,6 +964,16 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
        .retrigger      = retrigger_dynirq,
 };
 
+static struct irq_chip xen_percpu_chip __read_mostly = {
+       .name           = "xen-percpu",
+
+       .disable        = disable_dynirq,
+       .mask           = disable_dynirq,
+       .unmask         = enable_dynirq,
+
+       .ack            = ack_dynirq,
+};
+
 int xen_set_callback_via(uint64_t via)
 {
        struct xen_hvm_param a;
index 66e185cfe92fa8bb70c29d27de013fed1685c6d2..fec6ba3c08a8e885d663ce3ac9c8b031ff971273 100644 (file)
@@ -467,6 +467,7 @@ static const struct file_operations evtchn_fops = {
        .fasync  = evtchn_fasync,
        .open    = evtchn_open,
        .release = evtchn_release,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice evtchn_miscdev = {
index 1799bd8903151db422bd28cf1173564f0d6872d4..ef9c7db52077c6d58c0d5f036be0a03bd771dffa 100644 (file)
@@ -237,7 +237,7 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
                goto again;
 
        if (sysrq_key != '\0')
-               handle_sysrq(sysrq_key, NULL);
+               handle_sysrq(sysrq_key);
 }
 
 static struct xenbus_watch sysrq_watch = {
index 29bac5118877ef2028a781e6b409e2fe36463a99..d409495876f11b24fabaebc01d57f02224fe459f 100644 (file)
@@ -755,7 +755,10 @@ int register_xenstore_notifier(struct notifier_block *nb)
 {
        int ret = 0;
 
-       blocking_notifier_chain_register(&xenstore_chain, nb);
+       if (xenstored_ready > 0)
+               ret = nb->notifier_call(nb, 0, NULL);
+       else
+               blocking_notifier_chain_register(&xenstore_chain, nb);
 
        return ret;
 }
@@ -769,7 +772,7 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
 
 void xenbus_probe(struct work_struct *unused)
 {
-       BUG_ON((xenstored_ready <= 0));
+       xenstored_ready = 1;
 
        /* Enumerate devices in xenstore and watch for changes. */
        xenbus_probe_devices(&xenbus_frontend);
@@ -835,8 +838,8 @@ static int __init xenbus_init(void)
                        xen_store_evtchn = xen_start_info->store_evtchn;
                        xen_store_mfn = xen_start_info->store_mfn;
                        xen_store_interface = mfn_to_virt(xen_store_mfn);
+                       xenstored_ready = 1;
                }
-               xenstored_ready = 1;
        }
 
        /* Initialize the interface to xenstore. */
index 78bfab0700baf187f8482dcb5a62af1e7507bc31..bd96340063c1d6175f633fa507e8c7e2bf34ba93 100644 (file)
@@ -35,6 +35,7 @@ static ssize_t capabilities_read(struct file *file, char __user *buf,
 
 static const struct file_operations capabilities_file_ops = {
        .read = capabilities_read,
+       .llseek = default_llseek,
 };
 
 static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
index 3b39c3752e21812976f10e393c8d0c6ecd15ea9a..1c1236087f785a20b1351e375b6ea4b9e1d1444e 100644 (file)
@@ -594,4 +594,5 @@ const struct file_operations xenbus_file_ops = {
        .open = xenbus_file_open,
        .release = xenbus_file_release,
        .poll = xenbus_file_poll,
+       .llseek = no_llseek,
 };
index b27f09f05d177fb45cd0dc25f674853656ad3789..9c2d19452d0bf08a4c3642c7596d6056a8456797 100644 (file)
@@ -142,7 +142,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
 fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
 
 # Directories which we _might_ need to create, so we have a rule for them.
-firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all))))
+firmware-dirs := $(sort $(addprefix $(objtree)/$(obj)/,$(dir $(fw-external-y) $(fw-shipped-all))))
 
 quiet_cmd_mkdir = MKDIR   $(patsubst $(objtree)/%,%,$@)
       cmd_mkdir = mkdir -p $@
index 358563689064df61c9b81713ad8bb8911c6518bd..6406f896bf95fe56d404f40cdae7e083d88e3e9c 100644 (file)
@@ -242,7 +242,8 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
        }
        kfree(wnames);
 fid_out:
-       v9fs_fid_add(dentry, fid);
+       if (!IS_ERR(fid))
+               v9fs_fid_add(dentry, fid);
 err_out:
        up_read(&v9ses->rename_sem);
        return fid;
index 16c8a2a98c1bb6b93fbc8634cb1986cf555bad0e..899f168fd19cc4d4aca48e6d26e51aa08b34db59 100644 (file)
@@ -292,9 +292,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
 
        fid = filp->private_data;
        P9_DPRINTK(P9_DEBUG_VFS,
-                       "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid);
+                       "v9fs_dir_release: inode: %p filp: %p fid: %d\n",
+                       inode, filp, fid ? fid->fid : -1);
        filemap_write_and_wait(inode->i_mapping);
-       p9_client_clunk(fid);
+       if (fid)
+               p9_client_clunk(fid);
        return 0;
 }
 
index c7c23eab94403468d161eac3bd254dfde1e27610..9e670d527646fc4abe2be6f0dfc992f4a3178042 100644 (file)
@@ -730,7 +730,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
                P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
                goto error;
        }
-       dentry->d_op = &v9fs_cached_dentry_operations;
+       if (v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        err = v9fs_fid_add(dentry, fid);
        if (err < 0)
@@ -1128,6 +1131,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
                generic_fillattr(dentry->d_inode, stat);
 
+       p9stat_free(st);
        kfree(st);
        return 0;
 }
@@ -1489,6 +1493,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
        retval = strnlen(buffer, buflen);
 done:
+       p9stat_free(st);
        kfree(st);
        return retval;
 }
@@ -1942,7 +1947,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
        .unlink = v9fs_vfs_unlink,
        .mkdir = v9fs_vfs_mkdir,
        .rmdir = v9fs_vfs_rmdir,
-       .mknod = v9fs_vfs_mknod_dotl,
+       .mknod = v9fs_vfs_mknod,
        .rename = v9fs_vfs_rename,
        .getattr = v9fs_vfs_getattr,
        .setattr = v9fs_vfs_setattr,
index f9311077de6842091df9f257e3e6d91c641a0622..1d12ba0ed3db52fa55e2e6ff4aa48ade2cae1a88 100644 (file)
@@ -122,6 +122,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
        fid = v9fs_session_init(v9ses, dev_name, data);
        if (IS_ERR(fid)) {
                retval = PTR_ERR(fid);
+               /*
+                * we need to call session_close to tear down some
+                * of the data structure setup by session_init
+                */
                goto close_session;
        }
 
@@ -144,7 +148,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
                retval = -ENOMEM;
                goto release_sb;
        }
-
        sb->s_root = root;
 
        if (v9fs_proto_dotl(v9ses)) {
@@ -152,7 +155,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
                st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
                if (IS_ERR(st)) {
                        retval = PTR_ERR(st);
-                       goto clunk_fid;
+                       goto release_sb;
                }
 
                v9fs_stat2inode_dotl(st, root->d_inode);
@@ -162,7 +165,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
                st = p9_client_stat(fid);
                if (IS_ERR(st)) {
                        retval = PTR_ERR(st);
-                       goto clunk_fid;
+                       goto release_sb;
                }
 
                root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
@@ -174,19 +177,24 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 
        v9fs_fid_add(root, fid);
 
-P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
+       P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
        simple_set_mnt(mnt, sb);
        return 0;
 
 clunk_fid:
        p9_client_clunk(fid);
-
 close_session:
        v9fs_session_close(v9ses);
        kfree(v9ses);
        return retval;
-
 release_sb:
+       /*
+        * we will do the session_close and root dentry release
+        * in the below call. But we need to clunk fid, because we haven't
+        * attached the fid to dentry so it won't get clunked
+        * automatically.
+        */
+       p9_client_clunk(fid);
        deactivate_locked_super(sb);
        return retval;
 }
index 3d185308ec883bd0c06be0d151385c65e15b3353..65781de44fc0e04998d3daa2bee8b51e215d9844 100644 (file)
@@ -50,6 +50,7 @@ endif # BLOCK
 config FILE_LOCKING
        bool "Enable POSIX file locking API" if EMBEDDED
        default y
+       select BKL # while lockd still uses it.
        help
          This option enables standard file locking support, required
           for filesystems like NFS and for the flock() system
index e55182a7460535a6cd79fbb5f1e709ce069c86d8..1dd5f34b3cf2bbcd885f144495f1ec2d5a799439 100644 (file)
@@ -1,6 +1,7 @@
 config ADFS_FS
        tristate "ADFS file system support (EXPERIMENTAL)"
        depends on BLOCK && EXPERIMENTAL
+       depends on BKL # need to fix
        help
          The Acorn Disc Filing System is the standard file system of the
          RiscOS operating system which runs on Acorn's ARM-based Risc PC
index 4a3af7075c1d09058347ef532edc8c3105a9f9d5..d9803f73236f543fca9764cbe453414f6fe22286 100644 (file)
@@ -352,11 +352,15 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
        struct adfs_sb_info *asb;
        struct inode *root;
 
+       lock_kernel();
+
        sb->s_flags |= MS_NODIRATIME;
 
        asb = kzalloc(sizeof(*asb), GFP_KERNEL);
-       if (!asb)
+       if (!asb) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        sb->s_fs_info = asb;
 
        /* set default options */
@@ -474,6 +478,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                goto error;
        } else
                sb->s_root->d_op = &adfs_dentry_operations;
+       unlock_kernel();
        return 0;
 
 error_free_bh:
@@ -481,6 +486,7 @@ error_free_bh:
 error:
        sb->s_fs_info = NULL;
        kfree(asb);
+       unlock_kernel();
        return -EINVAL;
 }
 
index 33c4e7eef470e995246562b774fd88a82ca7f12b..fa4fbe1e238a344bbe35207e635461f07ac81691 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include "affs.h"
 
@@ -46,8 +45,6 @@ affs_put_super(struct super_block *sb)
        struct affs_sb_info *sbi = AFFS_SB(sb);
        pr_debug("AFFS: put_super()\n");
 
-       lock_kernel();
-
        if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
                affs_commit_super(sb, 1, 1);
 
@@ -56,8 +53,6 @@ affs_put_super(struct super_block *sb)
        affs_brelse(sbi->s_root_bh);
        kfree(sbi);
        sb->s_fs_info = NULL;
-
-       unlock_kernel();
 }
 
 static void
@@ -109,8 +104,8 @@ static void init_once(void *foo)
 {
        struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 
-       init_MUTEX(&ei->i_link_lock);
-       init_MUTEX(&ei->i_ext_lock);
+       sema_init(&ei->i_link_lock, 1);
+       sema_init(&ei->i_ext_lock, 1);
        inode_init_once(&ei->vfs_inode);
 }
 
@@ -302,6 +297,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
+
        sb->s_fs_info = sbi;
        mutex_init(&sbi->s_bmlock);
        spin_lock_init(&sbi->symlink_lock);
@@ -527,7 +523,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
                kfree(new_opts);
                return -EINVAL;
        }
-       lock_kernel();
+
        replace_mount_options(sb, new_opts);
 
        sbi->s_flags = mount_flags;
@@ -543,17 +539,15 @@ affs_remount(struct super_block *sb, int *flags, char *data)
        memcpy(sbi->s_volume, volume, 32);
        spin_unlock(&sbi->symlink_lock);
 
-       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
-               unlock_kernel();
+       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
-       }
+
        if (*flags & MS_RDONLY) {
                affs_write_super(sb);
                affs_free_bitmap(sb);
        } else
                res = affs_init_bitmap(sb, flags);
 
-       unlock_kernel();
        return res;
 }
 
index 0931bc1325ebd26fe38b9b6cd515d82d6d3fc618..757d664575dde8eff7659f471fce43692e992f06 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/smp_lock.h>
 #include "internal.h"
 
 #define AFS_LOCK_GRANTED       0
@@ -274,7 +273,7 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
 
        type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
 
-       lock_kernel();
+       lock_flocks();
 
        /* make sure we've got a callback on this file and that our view of the
         * data version is up to date */
@@ -421,7 +420,7 @@ given_lock:
        afs_vnode_fetch_status(vnode, NULL, key);
 
 error:
-       unlock_kernel();
+       unlock_flocks();
        _leave(" = %d", ret);
        return ret;
 
index 6d552686c498fae427e2b9408bd03e96e1153699..6153417caf57e2b9219bbfdd40970c262b65fdcf 100644 (file)
@@ -29,6 +29,7 @@ static void afs_mntpt_expiry_timed_out(struct work_struct *work);
 
 const struct file_operations afs_mntpt_file_operations = {
        .open           = afs_mntpt_open,
+       .llseek         = noop_llseek,
 };
 
 const struct inode_operations afs_mntpt_inode_operations = {
index 77e1e5a61154c6796d80d709ed31722017d90e18..eacf76d98ae02345d00d62f22f5ab4893a0452e6 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
@@ -453,12 +452,8 @@ static void afs_put_super(struct super_block *sb)
 
        _enter("");
 
-       lock_kernel();
-
        afs_put_volume(as->volume);
 
-       unlock_kernel();
-
        _leave("");
 }
 
index 3006b5bc33d697a2f773b2d81016fda57ee5ff68..250b0a73c8a8ca92b78c3a0282d2425ce7649dcf 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -712,8 +712,16 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
         */
        ret = retry(iocb);
 
-       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED)
+       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
+               /*
+                * There's no easy way to restart the syscall since other AIO's
+                * may be already running. Just fail this IO with EINTR.
+                */
+               if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR ||
+                            ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK))
+                       ret = -EINTR;
                aio_complete(iocb, ret, 0);
+       }
 out:
        spin_lock_irq(&ctx->ctx_lock);
 
@@ -1659,6 +1667,9 @@ long do_io_submit(aio_context_t ctx_id, long nr,
        if (unlikely(nr < 0))
                return -EINVAL;
 
+       if (unlikely(nr > LONG_MAX/sizeof(*iocbpp)))
+               nr = LONG_MAX/sizeof(*iocbpp);
+
        if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
                return -EFAULT;
 
index 5f3bea90911e5a81238bbee7765b6be54dddc996..480e210c83ab1f46ea9ee9a0b326d46132290c78 100644 (file)
@@ -1,5 +1,6 @@
 config AUTOFS_FS
        tristate "Kernel automounter support"
+       depends on BKL # unfixable, just use autofs4
        help
          The automounter is a tool to automatically mount remote file systems
          on demand. This implementation is partially kernel-based to reduce
index 11b1ea786d006472cc93cd0f33e6f787445ef569..0c4ca81aeaebb43e5d34b53626d1b886507cff86 100644 (file)
@@ -27,7 +27,9 @@ static int autofs_root_unlink(struct inode *,struct dentry *);
 static int autofs_root_rmdir(struct inode *,struct dentry *);
 static int autofs_root_mkdir(struct inode *,struct dentry *,int);
 static long autofs_root_ioctl(struct file *,unsigned int,unsigned long);
+#ifdef CONFIG_COMPAT
 static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+#endif
 
 const struct file_operations autofs_root_operations = {
        .llseek         = generic_file_llseek,
index ba4a38b9c22ff63d9897ad59c30c1479a0c54fed..eff9a419469a3d1661f4ad64d674b8db4370ae09 100644 (file)
@@ -724,6 +724,7 @@ static const struct file_operations _dev_ioctl_fops = {
        .unlocked_ioctl  = autofs_dev_ioctl,
        .compat_ioctl = autofs_dev_ioctl_compat,
        .owner   = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice _autofs_dev_ioctl_misc = {
index cb1bd38dc08cb10c47650e1e08c2a8fe13730ab2..d5c1401f00310979b117f9eaaecc0e026fd11c93 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/param.h>
 #include <linux/time.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "autofs_i.h"
 
@@ -28,7 +28,9 @@ static int autofs4_dir_unlink(struct inode *,struct dentry *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
+#ifdef CONFIG_COMPAT
 static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+#endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static void *autofs4_follow_link(struct dentry *, struct nameidata *);
@@ -978,15 +980,17 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
        }
 }
 
+static DEFINE_MUTEX(autofs4_ioctl_mutex);
+
 static long autofs4_root_ioctl(struct file *filp,
                               unsigned int cmd, unsigned long arg)
 {
        long ret;
        struct inode *inode = filp->f_dentry->d_inode;
 
-       lock_kernel();
+       mutex_lock(&autofs4_ioctl_mutex);
        ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&autofs4_ioctl_mutex);
 
        return ret;
 }
@@ -998,13 +1002,13 @@ static long autofs4_root_compat_ioctl(struct file *filp,
        struct inode *inode = filp->f_path.dentry->d_inode;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&autofs4_ioctl_mutex);
        if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
        else
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
                        (unsigned long)compat_ptr(arg));
-       unlock_kernel();
+       mutex_unlock(&autofs4_ioctl_mutex);
 
        return ret;
 }
index c4daf0f5fc021e9b98fa2521b96ee28ea67c9b4c..883e77acd5a8cd8e0c3598cb62e5993e82725d97 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
@@ -215,14 +214,10 @@ static void bfs_put_super(struct super_block *s)
        if (!info)
                return;
 
-       lock_kernel();
-
        mutex_destroy(&info->bfs_lock);
        kfree(info->si_imap);
        kfree(info);
        s->s_fs_info = NULL;
-
-       unlock_kernel();
 }
 
 static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
index f96eff04e11ab4a8b23f7489ee4b0de50e67e152..a6395bdb26aeb13b7b98c74df4f77780c1c95412 100644 (file)
@@ -134,10 +134,6 @@ static int aout_core_dump(struct coredump_params *cprm)
                if (!dump_write(file, dump_start, dump_size))
                        goto end_coredump;
        }
-/* Finally dump the task struct.  Not be used by gdb, but could be useful */
-       set_fs(KERNEL_DS);
-       if (!dump_write(file, current, sizeof(*current)))
-               goto end_coredump;
 end_coredump:
        set_fs(fs);
        return has_dumped;
index 535e763ab1a61e56ef5d25d725dc4f39eb899a49..6884e198e0c70d092192a34089d0b6d828e43f33 100644 (file)
@@ -800,7 +800,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         * default mmap base, as well as whatever program they
                         * might try to exec.  This is because the brk will
                         * follow the loader, and is not movable.  */
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_ARM)
                        load_bias = 0;
 #else
                        load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
index a7528b91393676bb1f1affa72f6b78f38206d4c5..139fc8083f53cbd9351b3c4ebeeedc79f30102b4 100644 (file)
@@ -576,6 +576,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
 static const struct file_operations bm_entry_operations = {
        .read           = bm_entry_read,
        .write          = bm_entry_write,
+       .llseek         = default_llseek,
 };
 
 /* /register */
@@ -643,6 +644,7 @@ out:
 
 static const struct file_operations bm_register_operations = {
        .write          = bm_register_write,
+       .llseek         = noop_llseek,
 };
 
 /* /status */
@@ -680,6 +682,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
 static const struct file_operations bm_status_operations = {
        .read           = bm_status_read,
        .write          = bm_status_write,
+       .llseek         = default_llseek,
 };
 
 /* Superblock handling */
@@ -724,7 +727,7 @@ static int __init init_misc_binfmt(void)
 {
        int err = register_filesystem(&bm_fs_type);
        if (!err) {
-               err = register_binfmt(&misc_format);
+               err = insert_binfmt(&misc_format);
                if (err)
                        unregister_filesystem(&bm_fs_type);
        }
index 612a5c38d3c1a5fc49e0d0990e19550c27217650..4d0ff5ee27b86bef6d377b9211694941939999a9 100644 (file)
@@ -413,10 +413,10 @@ int bio_integrity_prep(struct bio *bio)
 
        /* Allocate kernel buffer for protection data */
        len = sectors * blk_integrity_tuple_size(bi);
-       buf = kmalloc(len, GFP_NOIO | __GFP_NOFAIL | q->bounce_gfp);
+       buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
        if (unlikely(buf == NULL)) {
                printk(KERN_ERR "could not allocate integrity buffer\n");
-               return -EIO;
+               return -ENOMEM;
        }
 
        end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
index 1776dbd8dc9815cfd9af60929b41f773032c1f10..144f8a5730f56991cda69558daadfaf1eb458081 100644 (file)
@@ -815,6 +815,7 @@ static const struct file_operations btrfs_ctl_fops = {
        .unlocked_ioctl  = btrfs_control_ioctl,
        .compat_ioctl = btrfs_control_ioctl,
        .owner   = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
 static struct miscdevice btrfs_misc = {
index 727caedcdd921142323e62eaf56c8cdeee5afed4..0a1467b15516521569110c18e517a64ae07237e1 100644 (file)
@@ -55,6 +55,7 @@ const struct file_operations cachefiles_daemon_fops = {
        .read           = cachefiles_daemon_read,
        .write          = cachefiles_daemon_write,
        .poll           = cachefiles_daemon_poll,
+       .llseek         = noop_llseek,
 };
 
 struct cachefiles_daemon_cmd {
index bc87b9c1d27ea8e253f5a1b9b395a287ede4106e..9eb134ea6eb223a45be745c77f9530b80fcdc082 100644 (file)
@@ -1,8 +1,11 @@
 config CEPH_FS
         tristate "Ceph distributed file system (EXPERIMENTAL)"
        depends on INET && EXPERIMENTAL
+       select CEPH_LIB
        select LIBCRC32C
        select CRYPTO_AES
+       select CRYPTO
+       default n
        help
          Choose Y or M here to include support for mounting the
          experimental Ceph distributed file system.  Ceph is an extremely
@@ -13,15 +16,3 @@ config CEPH_FS
 
          If unsure, say N.
 
-config CEPH_FS_PRETTYDEBUG
-       bool "Include file:line in ceph debug output"
-       depends on CEPH_FS
-       default n
-       help
-         If you say Y here, debug output will include a filename and
-         line to aid debugging.  This icnreases kernel size and slows
-         execution slightly when debug call sites are enabled (e.g.,
-         via CONFIG_DYNAMIC_DEBUG).
-
-         If unsure, say N.
-
index 278e1172600dc3a3d5acba3654c53719d6f38697..9e6c4f2e8ff1f3e2712979d791da9e55fa780982 100644 (file)
@@ -8,15 +8,8 @@ obj-$(CONFIG_CEPH_FS) += ceph.o
 
 ceph-objs := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
        export.o caps.o snap.o xattr.o \
-       messenger.o msgpool.o buffer.o pagelist.o \
-       mds_client.o mdsmap.o \
-       mon_client.o \
-       osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
-       debugfs.o \
-       auth.o auth_none.o \
-       crypto.o armor.o \
-       auth_x.o \
-       ceph_fs.o ceph_strings.o ceph_hash.o ceph_frag.o
+       mds_client.o mdsmap.o strings.o ceph_frag.o \
+       debugfs.o
 
 else
 #Otherwise we were called directly from the command
diff --git a/fs/ceph/README b/fs/ceph/README
deleted file mode 100644 (file)
index 18352fa..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# The following files are shared by (and manually synchronized
-# between) the Ceph userland and kernel client.
-#
-# userland                  kernel
-src/include/ceph_fs.h      fs/ceph/ceph_fs.h
-src/include/ceph_fs.cc     fs/ceph/ceph_fs.c
-src/include/msgr.h         fs/ceph/msgr.h
-src/include/rados.h        fs/ceph/rados.h
-src/include/ceph_strings.cc fs/ceph/ceph_strings.c
-src/include/ceph_frag.h            fs/ceph/ceph_frag.h
-src/include/ceph_frag.cc    fs/ceph/ceph_frag.c
-src/include/ceph_hash.h            fs/ceph/ceph_hash.h
-src/include/ceph_hash.cc    fs/ceph/ceph_hash.c
-src/crush/crush.c          fs/ceph/crush/crush.c
-src/crush/crush.h          fs/ceph/crush/crush.h
-src/crush/mapper.c         fs/ceph/crush/mapper.c
-src/crush/mapper.h         fs/ceph/crush/mapper.h
-src/crush/hash.h           fs/ceph/crush/hash.h
-src/crush/hash.c           fs/ceph/crush/hash.c
index 5598a0d02295d11eaa3646e137497a083910251e..51bcc5ce323024a995d300b4a6035ecf8e72e94b 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/backing-dev.h>
 #include <linux/fs.h>
@@ -10,7 +10,8 @@
 #include <linux/task_io_accounting_ops.h>
 
 #include "super.h"
-#include "osd_client.h"
+#include "mds_client.h"
+#include <linux/ceph/osd_client.h>
 
 /*
  * Ceph address space ops.
@@ -87,7 +88,7 @@ static int ceph_set_page_dirty(struct page *page)
 
        /* dirty the head */
        spin_lock(&inode->i_lock);
-       if (ci->i_wrbuffer_ref_head == 0)
+       if (ci->i_head_snapc == NULL)
                ci->i_head_snapc = ceph_get_snap_context(snapc);
        ++ci->i_wrbuffer_ref_head;
        if (ci->i_wrbuffer_ref == 0)
@@ -105,13 +106,7 @@ static int ceph_set_page_dirty(struct page *page)
        spin_lock_irq(&mapping->tree_lock);
        if (page->mapping) {    /* Race with truncate? */
                WARN_ON_ONCE(!PageUptodate(page));
-
-               if (mapping_cap_account_dirty(mapping)) {
-                       __inc_zone_page_state(page, NR_FILE_DIRTY);
-                       __inc_bdi_stat(mapping->backing_dev_info,
-                                       BDI_RECLAIMABLE);
-                       task_io_account_write(PAGE_CACHE_SIZE);
-               }
+               account_page_dirtied(page, page->mapping);
                radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
 
@@ -199,7 +194,8 @@ static int readpage_nounlock(struct file *filp, struct page *page)
 {
        struct inode *inode = filp->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc;
+       struct ceph_osd_client *osdc = 
+               &ceph_inode_to_client(inode)->client->osdc;
        int err = 0;
        u64 len = PAGE_CACHE_SIZE;
 
@@ -271,7 +267,8 @@ static int ceph_readpages(struct file *file, struct address_space *mapping,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc;
+       struct ceph_osd_client *osdc =
+               &ceph_inode_to_client(inode)->client->osdc;
        int rc = 0;
        struct page **pages;
        loff_t offset;
@@ -352,7 +349,7 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode,
                        break;
                }
        }
-       if (!snapc && ci->i_head_snapc) {
+       if (!snapc && ci->i_wrbuffer_ref_head) {
                snapc = ceph_get_snap_context(ci->i_head_snapc);
                dout(" head snapc %p has %d dirty pages\n",
                     snapc, ci->i_wrbuffer_ref_head);
@@ -371,7 +368,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
 {
        struct inode *inode;
        struct ceph_inode_info *ci;
-       struct ceph_client *client;
+       struct ceph_fs_client *fsc;
        struct ceph_osd_client *osdc;
        loff_t page_off = page->index << PAGE_CACHE_SHIFT;
        int len = PAGE_CACHE_SIZE;
@@ -389,8 +386,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
        }
        inode = page->mapping->host;
        ci = ceph_inode(inode);
-       client = ceph_inode_to_client(inode);
-       osdc = &client->osdc;
+       fsc = ceph_inode_to_client(inode);
+       osdc = &fsc->client->osdc;
 
        /* verify this is a writeable snap context */
        snapc = (void *)page->private;
@@ -417,13 +414,13 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
        if (i_size < page_off + len)
                len = i_size - page_off;
 
-       dout("writepage %p page %p index %lu on %llu~%u\n",
-            inode, page, page->index, page_off, len);
+       dout("writepage %p page %p index %lu on %llu~%u snapc %p\n",
+            inode, page, page->index, page_off, len, snapc);
 
-       writeback_stat = atomic_long_inc_return(&client->writeback_count);
+       writeback_stat = atomic_long_inc_return(&fsc->writeback_count);
        if (writeback_stat >
-           CONGESTION_ON_THRESH(client->mount_args->congestion_kb))
-               set_bdi_congested(&client->backing_dev_info, BLK_RW_ASYNC);
+           CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb))
+               set_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC);
 
        set_page_writeback(page);
        err = ceph_osdc_writepages(osdc, ceph_vino(inode),
@@ -502,7 +499,7 @@ static void writepages_finish(struct ceph_osd_request *req,
        struct address_space *mapping = inode->i_mapping;
        __s32 rc = -EIO;
        u64 bytes = 0;
-       struct ceph_client *client = ceph_inode_to_client(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        long writeback_stat;
        unsigned issued = ceph_caps_issued(ci);
 
@@ -535,10 +532,10 @@ static void writepages_finish(struct ceph_osd_request *req,
                WARN_ON(!PageUptodate(page));
 
                writeback_stat =
-                       atomic_long_dec_return(&client->writeback_count);
+                       atomic_long_dec_return(&fsc->writeback_count);
                if (writeback_stat <
-                   CONGESTION_OFF_THRESH(client->mount_args->congestion_kb))
-                       clear_bdi_congested(&client->backing_dev_info,
+                   CONGESTION_OFF_THRESH(fsc->mount_options->congestion_kb))
+                       clear_bdi_congested(&fsc->backing_dev_info,
                                            BLK_RW_ASYNC);
 
                ceph_put_snap_context((void *)page->private);
@@ -575,13 +572,13 @@ static void writepages_finish(struct ceph_osd_request *req,
  * mempool.  we avoid the mempool if we can because req->r_num_pages
  * may be less than the maximum write size.
  */
-static void alloc_page_vec(struct ceph_client *client,
+static void alloc_page_vec(struct ceph_fs_client *fsc,
                           struct ceph_osd_request *req)
 {
        req->r_pages = kmalloc(sizeof(struct page *) * req->r_num_pages,
                               GFP_NOFS);
        if (!req->r_pages) {
-               req->r_pages = mempool_alloc(client->wb_pagevec_pool, GFP_NOFS);
+               req->r_pages = mempool_alloc(fsc->wb_pagevec_pool, GFP_NOFS);
                req->r_pages_from_pool = 1;
                WARN_ON(!req->r_pages);
        }
@@ -596,7 +593,7 @@ static int ceph_writepages_start(struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct backing_dev_info *bdi = mapping->backing_dev_info;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_client *client;
+       struct ceph_fs_client *fsc;
        pgoff_t index, start, end;
        int range_whole = 0;
        int should_loop = 1;
@@ -623,13 +620,13 @@ static int ceph_writepages_start(struct address_space *mapping,
             wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
             (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
 
-       client = ceph_inode_to_client(inode);
-       if (client->mount_state == CEPH_MOUNT_SHUTDOWN) {
+       fsc = ceph_inode_to_client(inode);
+       if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
                pr_warning("writepage_start %p on forced umount\n", inode);
                return -EIO; /* we're in a forced umount, don't write! */
        }
-       if (client->mount_args->wsize && client->mount_args->wsize < wsize)
-               wsize = client->mount_args->wsize;
+       if (fsc->mount_options->wsize && fsc->mount_options->wsize < wsize)
+               wsize = fsc->mount_options->wsize;
        if (wsize < PAGE_CACHE_SIZE)
                wsize = PAGE_CACHE_SIZE;
        max_pages_ever = wsize >> PAGE_CACHE_SHIFT;
@@ -772,9 +769,10 @@ get_more_pages:
                        /* ok */
                        if (locked_pages == 0) {
                                /* prepare async write request */
-                               offset = page->index << PAGE_CACHE_SHIFT;
+                               offset = (unsigned long long)page->index
+                                       << PAGE_CACHE_SHIFT;
                                len = wsize;
-                               req = ceph_osdc_new_request(&client->osdc,
+                               req = ceph_osdc_new_request(&fsc->client->osdc,
                                            &ci->i_layout,
                                            ceph_vino(inode),
                                            offset, &len,
@@ -787,7 +785,7 @@ get_more_pages:
                                            &inode->i_mtime, true, 1);
                                max_pages = req->r_num_pages;
 
-                               alloc_page_vec(client, req);
+                               alloc_page_vec(fsc, req);
                                req->r_callback = writepages_finish;
                                req->r_inode = inode;
                        }
@@ -799,10 +797,10 @@ get_more_pages:
                             inode, page, page->index);
 
                        writeback_stat =
-                              atomic_long_inc_return(&client->writeback_count);
+                              atomic_long_inc_return(&fsc->writeback_count);
                        if (writeback_stat > CONGESTION_ON_THRESH(
-                                   client->mount_args->congestion_kb)) {
-                               set_bdi_congested(&client->backing_dev_info,
+                                   fsc->mount_options->congestion_kb)) {
+                               set_bdi_congested(&fsc->backing_dev_info,
                                                  BLK_RW_ASYNC);
                        }
 
@@ -851,7 +849,7 @@ get_more_pages:
                op->payload_len = cpu_to_le32(len);
                req->r_request->hdr.data_len = cpu_to_le32(len);
 
-               ceph_osdc_start_request(&client->osdc, req, true);
+               ceph_osdc_start_request(&fsc->client->osdc, req, true);
                req = NULL;
 
                /* continue? */
@@ -920,7 +918,7 @@ static int ceph_update_writeable_page(struct file *file,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
        loff_t page_off = pos & PAGE_CACHE_MASK;
        int pos_in_page = pos & ~PAGE_CACHE_MASK;
        int end_in_page = pos_in_page + len;
@@ -1058,8 +1056,8 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
                          struct page *page, void *fsdata)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct ceph_client *client = ceph_inode_to_client(inode);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        unsigned from = pos & (PAGE_CACHE_SIZE - 1);
        int check_cap = 0;
 
@@ -1128,7 +1126,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct inode *inode = vma->vm_file->f_dentry->d_inode;
        struct page *page = vmf->page;
-       struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
        loff_t off = page->index << PAGE_CACHE_SHIFT;
        loff_t size, len;
        int ret;
index 7bf182b0397396f961151a1c1b59218bc1cb2749..98ab13e2b71d9d8ebcbf1715da112d78cb0bac17 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -9,8 +9,9 @@
 #include <linux/writeback.h>
 
 #include "super.h"
-#include "decode.h"
-#include "messenger.h"
+#include "mds_client.h"
+#include <linux/ceph/decode.h>
+#include <linux/ceph/messenger.h>
 
 /*
  * Capability management
@@ -287,11 +288,11 @@ void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap)
        spin_unlock(&mdsc->caps_list_lock);
 }
 
-void ceph_reservation_status(struct ceph_client *client,
+void ceph_reservation_status(struct ceph_fs_client *fsc,
                             int *total, int *avail, int *used, int *reserved,
                             int *min)
 {
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
 
        if (total)
                *total = mdsc->caps_total_count;
@@ -399,7 +400,7 @@ static void __insert_cap_node(struct ceph_inode_info *ci,
 static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
                               struct ceph_inode_info *ci)
 {
-       struct ceph_mount_args *ma = mdsc->client->mount_args;
+       struct ceph_mount_options *ma = mdsc->fsc->mount_options;
 
        ci->i_hold_caps_min = round_jiffies(jiffies +
                                            ma->caps_wanted_delay_min * HZ);
@@ -515,7 +516,7 @@ int ceph_add_cap(struct inode *inode,
                 unsigned seq, unsigned mseq, u64 realmino, int flags,
                 struct ceph_cap_reservation *caps_reservation)
 {
-       struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_cap *new_cap = NULL;
        struct ceph_cap *cap;
@@ -814,7 +815,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci)
                used |= CEPH_CAP_PIN;
        if (ci->i_rd_ref)
                used |= CEPH_CAP_FILE_RD;
-       if (ci->i_rdcache_ref || ci->i_rdcache_gen)
+       if (ci->i_rdcache_ref || ci->vfs_inode.i_data.nrpages)
                used |= CEPH_CAP_FILE_CACHE;
        if (ci->i_wr_ref)
                used |= CEPH_CAP_FILE_WR;
@@ -873,7 +874,7 @@ void __ceph_remove_cap(struct ceph_cap *cap)
        struct ceph_mds_session *session = cap->session;
        struct ceph_inode_info *ci = cap->ci;
        struct ceph_mds_client *mdsc =
-               &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+               ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
        int removed = 0;
 
        dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
@@ -1082,6 +1083,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        gid_t gid;
        struct ceph_mds_session *session;
        u64 xattr_version = 0;
+       struct ceph_buffer *xattr_blob = NULL;
        int delayed = 0;
        u64 flush_tid = 0;
        int i;
@@ -1142,6 +1144,10 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
                for (i = 0; i < CEPH_CAP_BITS; i++)
                        if (flushing & (1 << i))
                                ci->i_cap_flush_tid[i] = flush_tid;
+
+               follows = ci->i_head_snapc->seq;
+       } else {
+               follows = 0;
        }
 
        keep = cap->implemented;
@@ -1155,14 +1161,14 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        mtime = inode->i_mtime;
        atime = inode->i_atime;
        time_warp_seq = ci->i_time_warp_seq;
-       follows = ci->i_snap_realm->cached_context->seq;
        uid = inode->i_uid;
        gid = inode->i_gid;
        mode = inode->i_mode;
 
-       if (dropping & CEPH_CAP_XATTR_EXCL) {
+       if (flushing & CEPH_CAP_XATTR_EXCL) {
                __ceph_build_xattrs_blob(ci);
-               xattr_version = ci->i_xattrs.version + 1;
+               xattr_blob = ci->i_xattrs.blob;
+               xattr_version = ci->i_xattrs.version;
        }
 
        spin_unlock(&inode->i_lock);
@@ -1170,9 +1176,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        ret = send_cap_msg(session, ceph_vino(inode).ino, cap_id,
                op, keep, want, flushing, seq, flush_tid, issue_seq, mseq,
                size, max_size, &mtime, &atime, time_warp_seq,
-               uid, gid, mode,
-               xattr_version,
-               (flushing & CEPH_CAP_XATTR_EXCL) ? ci->i_xattrs.blob : NULL,
+               uid, gid, mode, xattr_version, xattr_blob,
                follows);
        if (ret < 0) {
                dout("error sending cap msg, must requeue %p\n", inode);
@@ -1192,10 +1196,14 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
  * asynchronously back to the MDS once sync writes complete and dirty
  * data is written out.
  *
+ * Unless @again is true, skip cap_snaps that were already sent to
+ * the MDS (i.e., during this session).
+ *
  * Called under i_lock.  Takes s_mutex as needed.
  */
 void __ceph_flush_snaps(struct ceph_inode_info *ci,
-                       struct ceph_mds_session **psession)
+                       struct ceph_mds_session **psession,
+                       int again)
                __releases(ci->vfs_inode->i_lock)
                __acquires(ci->vfs_inode->i_lock)
 {
@@ -1203,7 +1211,7 @@ void __ceph_flush_snaps(struct ceph_inode_info *ci,
        int mds;
        struct ceph_cap_snap *capsnap;
        u32 mseq;
-       struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
        struct ceph_mds_session *session = NULL; /* if session != NULL, we hold
                                                    session->s_mutex */
        u64 next_follows = 0;  /* keep track of how far we've gotten through the
@@ -1224,7 +1232,7 @@ retry:
                 * pages to be written out.
                 */
                if (capsnap->dirty_pages || capsnap->writing)
-                       continue;
+                       break;
 
                /*
                 * if cap writeback already occurred, we should have dropped
@@ -1237,6 +1245,13 @@ retry:
                        dout("no auth cap (migrating?), doing nothing\n");
                        goto out;
                }
+
+               /* only flush each capsnap once */
+               if (!again && !list_empty(&capsnap->flushing_item)) {
+                       dout("already flushed %p, skipping\n", capsnap);
+                       continue;
+               }
+
                mds = ci->i_auth_cap->session->s_mds;
                mseq = ci->i_auth_cap->mseq;
 
@@ -1273,8 +1288,8 @@ retry:
                              &session->s_cap_snaps_flushing);
                spin_unlock(&inode->i_lock);
 
-               dout("flush_snaps %p cap_snap %p follows %lld size %llu\n",
-                    inode, capsnap, next_follows, capsnap->size);
+               dout("flush_snaps %p cap_snap %p follows %lld tid %llu\n",
+                    inode, capsnap, capsnap->follows, capsnap->flush_tid);
                send_cap_msg(session, ceph_vino(inode).ino, 0,
                             CEPH_CAP_OP_FLUSHSNAP, capsnap->issued, 0,
                             capsnap->dirty, 0, capsnap->flush_tid, 0, mseq,
@@ -1282,7 +1297,7 @@ retry:
                             &capsnap->mtime, &capsnap->atime,
                             capsnap->time_warp_seq,
                             capsnap->uid, capsnap->gid, capsnap->mode,
-                            0, NULL,
+                            capsnap->xattr_version, capsnap->xattr_blob,
                             capsnap->follows);
 
                next_follows = capsnap->follows + 1;
@@ -1311,7 +1326,7 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
        struct inode *inode = &ci->vfs_inode;
 
        spin_lock(&inode->i_lock);
-       __ceph_flush_snaps(ci, NULL);
+       __ceph_flush_snaps(ci, NULL, 0);
        spin_unlock(&inode->i_lock);
 }
 
@@ -1322,7 +1337,7 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
 void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
 {
        struct ceph_mds_client *mdsc =
-               &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+               ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
        struct inode *inode = &ci->vfs_inode;
        int was = ci->i_dirty_caps;
        int dirty = 0;
@@ -1332,7 +1347,11 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
             ceph_cap_string(was | mask));
        ci->i_dirty_caps |= mask;
        if (was == 0) {
-               dout(" inode %p now dirty\n", &ci->vfs_inode);
+               if (!ci->i_head_snapc)
+                       ci->i_head_snapc = ceph_get_snap_context(
+                               ci->i_snap_realm->cached_context);
+               dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode,
+                       ci->i_head_snapc);
                BUG_ON(!list_empty(&ci->i_dirty_item));
                spin_lock(&mdsc->cap_dirty_lock);
                list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
@@ -1360,7 +1379,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
 static int __mark_caps_flushing(struct inode *inode,
                                 struct ceph_mds_session *session)
 {
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int flushing;
 
@@ -1398,17 +1417,6 @@ static int __mark_caps_flushing(struct inode *inode,
 /*
  * try to invalidate mapping pages without blocking.
  */
-static int mapping_is_empty(struct address_space *mapping)
-{
-       struct page *page = find_get_page(mapping, 0);
-
-       if (!page)
-               return 1;
-
-       put_page(page);
-       return 0;
-}
-
 static int try_nonblocking_invalidate(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1418,7 +1426,7 @@ static int try_nonblocking_invalidate(struct inode *inode)
        invalidate_mapping_pages(&inode->i_data, 0, -1);
        spin_lock(&inode->i_lock);
 
-       if (mapping_is_empty(&inode->i_data) &&
+       if (inode->i_data.nrpages == 0 &&
            invalidating_gen == ci->i_rdcache_gen) {
                /* success. */
                dout("try_nonblocking_invalidate %p success\n", inode);
@@ -1444,8 +1452,8 @@ static int try_nonblocking_invalidate(struct inode *inode)
 void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                     struct ceph_mds_session *session)
 {
-       struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(&ci->vfs_inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct inode *inode = &ci->vfs_inode;
        struct ceph_cap *cap;
        int file_wanted, used;
@@ -1470,7 +1478,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
 
        /* flush snaps first time around only */
        if (!list_empty(&ci->i_cap_snaps))
-               __ceph_flush_snaps(ci, &session);
+               __ceph_flush_snaps(ci, &session, 0);
        goto retry_locked;
 retry:
        spin_lock(&inode->i_lock);
@@ -1515,7 +1523,7 @@ retry_locked:
         */
        if ((!is_delayed || mdsc->stopping) &&
            ci->i_wrbuffer_ref == 0 &&               /* no dirty pages... */
-           ci->i_rdcache_gen &&                     /* may have cached pages */
+           inode->i_data.nrpages &&                 /* have cached pages */
            (file_wanted == 0 ||                     /* no open files */
             (revoking & (CEPH_CAP_FILE_CACHE|
                          CEPH_CAP_FILE_LAZYIO))) && /*  or revoking cache */
@@ -1688,7 +1696,7 @@ ack:
 static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session,
                          unsigned *flush_tid)
 {
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int unlock_session = session ? 0 : 1;
        int flushing = 0;
@@ -1854,7 +1862,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
                                       caps_are_flushed(inode, flush_tid));
        } else {
                struct ceph_mds_client *mdsc =
-                       &ceph_sb_to_client(inode->i_sb)->mdsc;
+                       ceph_sb_to_client(inode->i_sb)->mdsc;
 
                spin_lock(&inode->i_lock);
                if (__ceph_caps_dirty(ci))
@@ -1887,7 +1895,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc,
                if (cap && cap->session == session) {
                        dout("kick_flushing_caps %p cap %p capsnap %p\n", inode,
                             cap, capsnap);
-                       __ceph_flush_snaps(ci, &session);
+                       __ceph_flush_snaps(ci, &session, 1);
                } else {
                        pr_err("%p auth cap %p not mds%d ???\n", inode,
                               cap, session->s_mds);
@@ -2190,7 +2198,9 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
 
        if (ci->i_head_snapc == snapc) {
                ci->i_wrbuffer_ref_head -= nr;
-               if (!ci->i_wrbuffer_ref_head) {
+               if (ci->i_wrbuffer_ref_head == 0 &&
+                   ci->i_dirty_caps == 0 && ci->i_flushing_caps == 0) {
+                       BUG_ON(!ci->i_head_snapc);
                        ceph_put_snap_context(ci->i_head_snapc);
                        ci->i_head_snapc = NULL;
                }
@@ -2263,7 +2273,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int mds = session->s_mds;
-       int seq = le32_to_cpu(grant->seq);
+       unsigned seq = le32_to_cpu(grant->seq);
+       unsigned issue_seq = le32_to_cpu(grant->issue_seq);
        int newcaps = le32_to_cpu(grant->caps);
        int issued, implemented, used, wanted, dirty;
        u64 size = le64_to_cpu(grant->size);
@@ -2275,8 +2286,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        int revoked_rdcache = 0;
        int queue_invalidate = 0;
 
-       dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
-            inode, cap, mds, seq, ceph_cap_string(newcaps));
+       dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n",
+            inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps));
        dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
                inode->i_size);
 
@@ -2372,6 +2383,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        }
 
        cap->seq = seq;
+       cap->issue_seq = issue_seq;
 
        /* file layout may have changed */
        ci->i_layout = grant->layout;
@@ -2443,7 +2455,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
        __releases(inode->i_lock)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        unsigned seq = le32_to_cpu(m->seq);
        int dirty = le32_to_cpu(m->dirty);
        int cleaned = 0;
@@ -2483,6 +2495,11 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
                        dout(" inode %p now clean\n", inode);
                        BUG_ON(!list_empty(&ci->i_dirty_item));
                        drop = 1;
+                       if (ci->i_wrbuffer_ref_head == 0) {
+                               BUG_ON(!ci->i_head_snapc);
+                               ceph_put_snap_context(ci->i_head_snapc);
+                               ci->i_head_snapc = NULL;
+                       }
                } else {
                        BUG_ON(list_empty(&ci->i_dirty_item));
                }
@@ -2686,7 +2703,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                      struct ceph_msg *msg)
 {
        struct ceph_mds_client *mdsc = session->s_mdsc;
-       struct super_block *sb = mdsc->client->sb;
+       struct super_block *sb = mdsc->fsc->sb;
        struct inode *inode;
        struct ceph_cap *cap;
        struct ceph_mds_caps *h;
@@ -2749,15 +2766,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                if (op == CEPH_CAP_OP_IMPORT)
                        __queue_cap_release(session, vino.ino, cap_id,
                                            mseq, seq);
-
-               /*
-                * send any full release message to try to move things
-                * along for the mds (who clearly thinks we still have this
-                * cap).
-                */
-               ceph_add_cap_releases(mdsc, session);
-               ceph_send_cap_releases(mdsc, session);
-               goto done;
+               goto flush_cap_releases;
        }
 
        /* these will work even if we don't have a cap yet */
@@ -2785,7 +2794,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                dout(" no cap on %p ino %llx.%llx from mds%d\n",
                     inode, ceph_ino(inode), ceph_snap(inode), mds);
                spin_unlock(&inode->i_lock);
-               goto done;
+               goto flush_cap_releases;
        }
 
        /* note that each of these drops i_lock for us */
@@ -2809,6 +2818,17 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                       ceph_cap_op_name(op));
        }
 
+       goto done;
+
+flush_cap_releases:
+       /*
+        * send any full release message to try to move things
+        * along for the mds (who clearly thinks we still have this
+        * cap).
+        */
+       ceph_add_cap_releases(mdsc, session);
+       ceph_send_cap_releases(mdsc, session);
+
 done:
        mutex_unlock(&session->s_mutex);
 done_unlocked:
index ab6cf35c40919843e40f29137500e45a8170e5ab..bdce8b1fbd06794d9de7be918c9ab8aab97bcbd2 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Ceph 'frag' type
  */
-#include "types.h"
+#include <linux/module.h>
+#include <linux/ceph/types.h>
 
 int ceph_frag_compare(__u32 a, __u32 b)
 {
index 360c4f22718d5e079c2ce99c2484af9376751a76..7ae1b3d55b58a7b70bf55e79a0788f211b90ff3c 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
+
 #include "super.h"
-#include "mds_client.h"
-#include "mon_client.h"
-#include "auth.h"
 
 #ifdef CONFIG_DEBUG_FS
 
-/*
- * Implement /sys/kernel/debug/ceph fun
- *
- * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
- *      .../osdmap      - current osdmap
- *      .../mdsmap      - current mdsmap
- *      .../monmap      - current monmap
- *      .../osdc        - active osd requests
- *      .../mdsc        - active mds requests
- *      .../monc        - mon client state
- *      .../dentry_lru  - dump contents of dentry lru
- *      .../caps        - expose cap (reservation) stats
- *      .../bdi         - symlink to ../../bdi/something
- */
-
-static struct dentry *ceph_debugfs_dir;
-
-static int monmap_show(struct seq_file *s, void *p)
-{
-       int i;
-       struct ceph_client *client = s->private;
-
-       if (client->monc.monmap == NULL)
-               return 0;
-
-       seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
-       for (i = 0; i < client->monc.monmap->num_mon; i++) {
-               struct ceph_entity_inst *inst =
-                       &client->monc.monmap->mon_inst[i];
-
-               seq_printf(s, "\t%s%lld\t%s\n",
-                          ENTITY_NAME(inst->name),
-                          pr_addr(&inst->addr.in_addr));
-       }
-       return 0;
-}
+#include "mds_client.h"
 
 static int mdsmap_show(struct seq_file *s, void *p)
 {
        int i;
-       struct ceph_client *client = s->private;
+       struct ceph_fs_client *fsc = s->private;
 
-       if (client->mdsc.mdsmap == NULL)
+       if (fsc->mdsc == NULL || fsc->mdsc->mdsmap == NULL)
                return 0;
-       seq_printf(s, "epoch %d\n", client->mdsc.mdsmap->m_epoch);
-       seq_printf(s, "root %d\n", client->mdsc.mdsmap->m_root);
+       seq_printf(s, "epoch %d\n", fsc->mdsc->mdsmap->m_epoch);
+       seq_printf(s, "root %d\n", fsc->mdsc->mdsmap->m_root);
        seq_printf(s, "session_timeout %d\n",
-                      client->mdsc.mdsmap->m_session_timeout);
+                      fsc->mdsc->mdsmap->m_session_timeout);
        seq_printf(s, "session_autoclose %d\n",
-                      client->mdsc.mdsmap->m_session_autoclose);
-       for (i = 0; i < client->mdsc.mdsmap->m_max_mds; i++) {
+                      fsc->mdsc->mdsmap->m_session_autoclose);
+       for (i = 0; i < fsc->mdsc->mdsmap->m_max_mds; i++) {
                struct ceph_entity_addr *addr =
-                       &client->mdsc.mdsmap->m_info[i].addr;
-               int state = client->mdsc.mdsmap->m_info[i].state;
+                       &fsc->mdsc->mdsmap->m_info[i].addr;
+               int state = fsc->mdsc->mdsmap->m_info[i].state;
 
-               seq_printf(s, "\tmds%d\t%s\t(%s)\n", i, pr_addr(&addr->in_addr),
+               seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
+                              ceph_pr_addr(&addr->in_addr),
                               ceph_mds_state_name(state));
        }
        return 0;
 }
 
-static int osdmap_show(struct seq_file *s, void *p)
-{
-       int i;
-       struct ceph_client *client = s->private;
-       struct rb_node *n;
-
-       if (client->osdc.osdmap == NULL)
-               return 0;
-       seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch);
-       seq_printf(s, "flags%s%s\n",
-                  (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ?
-                  " NEARFULL" : "",
-                  (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ?
-                  " FULL" : "");
-       for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) {
-               struct ceph_pg_pool_info *pool =
-                       rb_entry(n, struct ceph_pg_pool_info, node);
-               seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n",
-                          pool->id, pool->v.pg_num, pool->pg_num_mask,
-                          pool->v.lpg_num, pool->lpg_num_mask);
-       }
-       for (i = 0; i < client->osdc.osdmap->max_osd; i++) {
-               struct ceph_entity_addr *addr =
-                       &client->osdc.osdmap->osd_addr[i];
-               int state = client->osdc.osdmap->osd_state[i];
-               char sb[64];
-
-               seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n",
-                          i, pr_addr(&addr->in_addr),
-                          ((client->osdc.osdmap->osd_weight[i]*100) >> 16),
-                          ceph_osdmap_state_str(sb, sizeof(sb), state));
-       }
-       return 0;
-}
-
-static int monc_show(struct seq_file *s, void *p)
-{
-       struct ceph_client *client = s->private;
-       struct ceph_mon_generic_request *req;
-       struct ceph_mon_client *monc = &client->monc;
-       struct rb_node *rp;
-
-       mutex_lock(&monc->mutex);
-
-       if (monc->have_mdsmap)
-               seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap);
-       if (monc->have_osdmap)
-               seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap);
-       if (monc->want_next_osdmap)
-               seq_printf(s, "want next osdmap\n");
-
-       for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
-               __u16 op;
-               req = rb_entry(rp, struct ceph_mon_generic_request, node);
-               op = le16_to_cpu(req->request->hdr.type);
-               if (op == CEPH_MSG_STATFS)
-                       seq_printf(s, "%lld statfs\n", req->tid);
-               else
-                       seq_printf(s, "%lld unknown\n", req->tid);
-       }
-
-       mutex_unlock(&monc->mutex);
-       return 0;
-}
-
+/*
+ * mdsc debugfs
+ */
 static int mdsc_show(struct seq_file *s, void *p)
 {
-       struct ceph_client *client = s->private;
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = s->private;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        struct rb_node *rp;
        int pathlen;
@@ -171,6 +77,8 @@ static int mdsc_show(struct seq_file *s, void *p)
                } else if (req->r_dentry) {
                        path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
                                                    &pathbase, 0);
+                       if (IS_ERR(path))
+                               path = NULL;
                        spin_lock(&req->r_dentry->d_lock);
                        seq_printf(s, " #%llx/%.*s (%s)",
                                   ceph_ino(req->r_dentry->d_parent->d_inode),
@@ -187,6 +95,8 @@ static int mdsc_show(struct seq_file *s, void *p)
                if (req->r_old_dentry) {
                        path = ceph_mdsc_build_path(req->r_old_dentry, &pathlen,
                                                    &pathbase, 0);
+                       if (IS_ERR(path))
+                               path = NULL;
                        spin_lock(&req->r_old_dentry->d_lock);
                        seq_printf(s, " #%llx/%.*s (%s)",
                           ceph_ino(req->r_old_dentry->d_parent->d_inode),
@@ -210,61 +120,12 @@ static int mdsc_show(struct seq_file *s, void *p)
        return 0;
 }
 
-static int osdc_show(struct seq_file *s, void *pp)
-{
-       struct ceph_client *client = s->private;
-       struct ceph_osd_client *osdc = &client->osdc;
-       struct rb_node *p;
-
-       mutex_lock(&osdc->request_mutex);
-       for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
-               struct ceph_osd_request *req;
-               struct ceph_osd_request_head *head;
-               struct ceph_osd_op *op;
-               int num_ops;
-               int opcode, olen;
-               int i;
-
-               req = rb_entry(p, struct ceph_osd_request, r_node);
-
-               seq_printf(s, "%lld\tosd%d\t%d.%x\t", req->r_tid,
-                          req->r_osd ? req->r_osd->o_osd : -1,
-                          le32_to_cpu(req->r_pgid.pool),
-                          le16_to_cpu(req->r_pgid.ps));
-
-               head = req->r_request->front.iov_base;
-               op = (void *)(head + 1);
-
-               num_ops = le16_to_cpu(head->num_ops);
-               olen = le32_to_cpu(head->object_len);
-               seq_printf(s, "%.*s", olen,
-                          (const char *)(head->ops + num_ops));
-
-               if (req->r_reassert_version.epoch)
-                       seq_printf(s, "\t%u'%llu",
-                          (unsigned)le32_to_cpu(req->r_reassert_version.epoch),
-                          le64_to_cpu(req->r_reassert_version.version));
-               else
-                       seq_printf(s, "\t");
-
-               for (i = 0; i < num_ops; i++) {
-                       opcode = le16_to_cpu(op->op);
-                       seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
-                       op++;
-               }
-
-               seq_printf(s, "\n");
-       }
-       mutex_unlock(&osdc->request_mutex);
-       return 0;
-}
-
 static int caps_show(struct seq_file *s, void *p)
 {
-       struct ceph_client *client = s->private;
+       struct ceph_fs_client *fsc = s->private;
        int total, avail, used, reserved, min;
 
-       ceph_reservation_status(client, &total, &avail, &used, &reserved, &min);
+       ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
        seq_printf(s, "total\t\t%d\n"
                   "avail\t\t%d\n"
                   "used\t\t%d\n"
@@ -276,8 +137,8 @@ static int caps_show(struct seq_file *s, void *p)
 
 static int dentry_lru_show(struct seq_file *s, void *ptr)
 {
-       struct ceph_client *client = s->private;
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = s->private;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_dentry_info *di;
 
        spin_lock(&mdsc->dentry_lru_lock);
@@ -291,199 +152,124 @@ static int dentry_lru_show(struct seq_file *s, void *ptr)
        return 0;
 }
 
-#define DEFINE_SHOW_FUNC(name)                                         \
-static int name##_open(struct inode *inode, struct file *file)         \
-{                                                                      \
-       struct seq_file *sf;                                            \
-       int ret;                                                        \
-                                                                       \
-       ret = single_open(file, name, NULL);                            \
-       sf = file->private_data;                                        \
-       sf->private = inode->i_private;                                 \
-       return ret;                                                     \
-}                                                                      \
-                                                                       \
-static const struct file_operations name##_fops = {                    \
-       .open           = name##_open,                                  \
-       .read           = seq_read,                                     \
-       .llseek         = seq_lseek,                                    \
-       .release        = single_release,                               \
-};
-
-DEFINE_SHOW_FUNC(monmap_show)
-DEFINE_SHOW_FUNC(mdsmap_show)
-DEFINE_SHOW_FUNC(osdmap_show)
-DEFINE_SHOW_FUNC(monc_show)
-DEFINE_SHOW_FUNC(mdsc_show)
-DEFINE_SHOW_FUNC(osdc_show)
-DEFINE_SHOW_FUNC(dentry_lru_show)
-DEFINE_SHOW_FUNC(caps_show)
+CEPH_DEFINE_SHOW_FUNC(mdsmap_show)
+CEPH_DEFINE_SHOW_FUNC(mdsc_show)
+CEPH_DEFINE_SHOW_FUNC(caps_show)
+CEPH_DEFINE_SHOW_FUNC(dentry_lru_show)
+
 
+/*
+ * debugfs
+ */
 static int congestion_kb_set(void *data, u64 val)
 {
-       struct ceph_client *client = (struct ceph_client *)data;
-
-       if (client)
-               client->mount_args->congestion_kb = (int)val;
+       struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 
+       fsc->mount_options->congestion_kb = (int)val;
        return 0;
 }
 
 static int congestion_kb_get(void *data, u64 *val)
 {
-       struct ceph_client *client = (struct ceph_client *)data;
-
-       if (client)
-               *val = (u64)client->mount_args->congestion_kb;
+       struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 
+       *val = (u64)fsc->mount_options->congestion_kb;
        return 0;
 }
 
-
 DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
                        congestion_kb_set, "%llu\n");
 
-int __init ceph_debugfs_init(void)
-{
-       ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
-       if (!ceph_debugfs_dir)
-               return -ENOMEM;
-       return 0;
-}
 
-void ceph_debugfs_cleanup(void)
+void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 {
-       debugfs_remove(ceph_debugfs_dir);
+       dout("ceph_fs_debugfs_cleanup\n");
+       debugfs_remove(fsc->debugfs_bdi);
+       debugfs_remove(fsc->debugfs_congestion_kb);
+       debugfs_remove(fsc->debugfs_mdsmap);
+       debugfs_remove(fsc->debugfs_caps);
+       debugfs_remove(fsc->debugfs_mdsc);
+       debugfs_remove(fsc->debugfs_dentry_lru);
 }
 
-int ceph_debugfs_client_init(struct ceph_client *client)
+int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 {
-       int ret = 0;
-       char name[80];
-
-       snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
-                client->monc.auth->global_id);
+       char name[100];
+       int err = -ENOMEM;
 
-       client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
-       if (!client->debugfs_dir)
-               goto out;
-
-       client->monc.debugfs_file = debugfs_create_file("monc",
-                                                     0600,
-                                                     client->debugfs_dir,
-                                                     client,
-                                                     &monc_show_fops);
-       if (!client->monc.debugfs_file)
+       dout("ceph_fs_debugfs_init\n");
+       fsc->debugfs_congestion_kb =
+               debugfs_create_file("writeback_congestion_kb",
+                                   0600,
+                                   fsc->client->debugfs_dir,
+                                   fsc,
+                                   &congestion_kb_fops);
+       if (!fsc->debugfs_congestion_kb)
                goto out;
 
-       client->mdsc.debugfs_file = debugfs_create_file("mdsc",
-                                                     0600,
-                                                     client->debugfs_dir,
-                                                     client,
-                                                     &mdsc_show_fops);
-       if (!client->mdsc.debugfs_file)
-               goto out;
+       dout("a\n");
 
-       client->osdc.debugfs_file = debugfs_create_file("osdc",
-                                                     0600,
-                                                     client->debugfs_dir,
-                                                     client,
-                                                     &osdc_show_fops);
-       if (!client->osdc.debugfs_file)
+       snprintf(name, sizeof(name), "../../bdi/%s",
+                dev_name(fsc->backing_dev_info.dev));
+       fsc->debugfs_bdi =
+               debugfs_create_symlink("bdi",
+                                      fsc->client->debugfs_dir,
+                                      name);
+       if (!fsc->debugfs_bdi)
                goto out;
 
-       client->debugfs_monmap = debugfs_create_file("monmap",
+       dout("b\n");
+       fsc->debugfs_mdsmap = debugfs_create_file("mdsmap",
                                        0600,
-                                       client->debugfs_dir,
-                                       client,
-                                       &monmap_show_fops);
-       if (!client->debugfs_monmap)
-               goto out;
-
-       client->debugfs_mdsmap = debugfs_create_file("mdsmap",
-                                       0600,
-                                       client->debugfs_dir,
-                                       client,
+                                       fsc->client->debugfs_dir,
+                                       fsc,
                                        &mdsmap_show_fops);
-       if (!client->debugfs_mdsmap)
-               goto out;
-
-       client->debugfs_osdmap = debugfs_create_file("osdmap",
-                                       0600,
-                                       client->debugfs_dir,
-                                       client,
-                                       &osdmap_show_fops);
-       if (!client->debugfs_osdmap)
+       if (!fsc->debugfs_mdsmap)
                goto out;
 
-       client->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
-                                       0600,
-                                       client->debugfs_dir,
-                                       client,
-                                       &dentry_lru_show_fops);
-       if (!client->debugfs_dentry_lru)
+       dout("ca\n");
+       fsc->debugfs_mdsc = debugfs_create_file("mdsc",
+                                               0600,
+                                               fsc->client->debugfs_dir,
+                                               fsc,
+                                               &mdsc_show_fops);
+       if (!fsc->debugfs_mdsc)
                goto out;
 
-       client->debugfs_caps = debugfs_create_file("caps",
+       dout("da\n");
+       fsc->debugfs_caps = debugfs_create_file("caps",
                                                   0400,
-                                                  client->debugfs_dir,
-                                                  client,
+                                                  fsc->client->debugfs_dir,
+                                                  fsc,
                                                   &caps_show_fops);
-       if (!client->debugfs_caps)
+       if (!fsc->debugfs_caps)
                goto out;
 
-       client->debugfs_congestion_kb =
-               debugfs_create_file("writeback_congestion_kb",
-                                   0600,
-                                   client->debugfs_dir,
-                                   client,
-                                   &congestion_kb_fops);
-       if (!client->debugfs_congestion_kb)
+       dout("ea\n");
+       fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
+                                       0600,
+                                       fsc->client->debugfs_dir,
+                                       fsc,
+                                       &dentry_lru_show_fops);
+       if (!fsc->debugfs_dentry_lru)
                goto out;
 
-       sprintf(name, "../../bdi/%s", dev_name(client->sb->s_bdi->dev));
-       client->debugfs_bdi = debugfs_create_symlink("bdi", client->debugfs_dir,
-                                                    name);
-
        return 0;
 
 out:
-       ceph_debugfs_client_cleanup(client);
-       return ret;
+       ceph_fs_debugfs_cleanup(fsc);
+       return err;
 }
 
-void ceph_debugfs_client_cleanup(struct ceph_client *client)
-{
-       debugfs_remove(client->debugfs_bdi);
-       debugfs_remove(client->debugfs_caps);
-       debugfs_remove(client->debugfs_dentry_lru);
-       debugfs_remove(client->debugfs_osdmap);
-       debugfs_remove(client->debugfs_mdsmap);
-       debugfs_remove(client->debugfs_monmap);
-       debugfs_remove(client->osdc.debugfs_file);
-       debugfs_remove(client->mdsc.debugfs_file);
-       debugfs_remove(client->monc.debugfs_file);
-       debugfs_remove(client->debugfs_congestion_kb);
-       debugfs_remove(client->debugfs_dir);
-}
 
 #else  /* CONFIG_DEBUG_FS */
 
-int __init ceph_debugfs_init(void)
-{
-       return 0;
-}
-
-void ceph_debugfs_cleanup(void)
-{
-}
-
-int ceph_debugfs_client_init(struct ceph_client *client)
+int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 {
        return 0;
 }
 
-void ceph_debugfs_client_cleanup(struct ceph_client *client)
+void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 {
 }
 
index 67bbb41d5526fcbdfb74f48f0e261b59b957ef9c..e0a2dc6fcafcb62266909c5ec71329e58083d1d7 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/spinlock.h>
 #include <linux/fs_struct.h>
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 
 #include "super.h"
+#include "mds_client.h"
 
 /*
  * Directory operations: readdir, lookup, create, link, unlink,
@@ -46,7 +47,7 @@ int ceph_init_dentry(struct dentry *dentry)
        else
                dentry->d_op = &ceph_snap_dentry_ops;
 
-       di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS);
+       di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
        if (!di)
                return -ENOMEM;          /* oh well */
 
@@ -94,10 +95,7 @@ static unsigned fpos_off(loff_t p)
  */
 static int __dcache_readdir(struct file *filp,
                            void *dirent, filldir_t filldir)
-               __releases(inode->i_lock)
-               __acquires(inode->i_lock)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
        struct ceph_file_info *fi = filp->private_data;
        struct dentry *parent = filp->f_dentry;
        struct inode *dir = parent->d_inode;
@@ -153,7 +151,6 @@ more:
 
        atomic_inc(&dentry->d_count);
        spin_unlock(&dcache_lock);
-       spin_unlock(&inode->i_lock);
 
        dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
             dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
@@ -171,35 +168,30 @@ more:
                } else {
                        dput(last);
                }
-               last = NULL;
        }
-
-       spin_lock(&inode->i_lock);
-       spin_lock(&dcache_lock);
-
        last = dentry;
 
        if (err < 0)
-               goto out_unlock;
+               goto out;
 
-       p = p->prev;
        filp->f_pos++;
 
        /* make sure a dentry wasn't dropped while we didn't have dcache_lock */
-       if ((ceph_inode(dir)->i_ceph_flags & CEPH_I_COMPLETE))
-               goto more;
-       dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
-       err = -EAGAIN;
+       if (!ceph_i_test(dir, CEPH_I_COMPLETE)) {
+               dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
+               err = -EAGAIN;
+               goto out;
+       }
+
+       spin_lock(&dcache_lock);
+       p = p->prev;    /* advance to next dentry */
+       goto more;
 
 out_unlock:
        spin_unlock(&dcache_lock);
-
-       if (last) {
-               spin_unlock(&inode->i_lock);
+out:
+       if (last)
                dput(last);
-               spin_lock(&inode->i_lock);
-       }
-
        return err;
 }
 
@@ -227,15 +219,15 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct ceph_file_info *fi = filp->private_data;
        struct inode *inode = filp->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_client *client = ceph_inode_to_client(inode);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        unsigned frag = fpos_frag(filp->f_pos);
        int off = fpos_off(filp->f_pos);
        int err;
        u32 ftype;
        struct ceph_mds_reply_info_parsed *rinfo;
-       const int max_entries = client->mount_args->max_readdir;
-       const int max_bytes = client->mount_args->max_readdir_bytes;
+       const int max_entries = fsc->mount_options->max_readdir;
+       const int max_bytes = fsc->mount_options->max_readdir_bytes;
 
        dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
        if (fi->at_end)
@@ -267,17 +259,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
        /* can we use the dcache? */
        spin_lock(&inode->i_lock);
        if ((filp->f_pos == 2 || fi->dentry) &&
-           !ceph_test_opt(client, NOASYNCREADDIR) &&
+           !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
            ceph_snap(inode) != CEPH_SNAPDIR &&
            (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
            __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
+               spin_unlock(&inode->i_lock);
                err = __dcache_readdir(filp, dirent, filldir);
-               if (err != -EAGAIN) {
-                       spin_unlock(&inode->i_lock);
+               if (err != -EAGAIN)
                        return err;
-               }
+       } else {
+               spin_unlock(&inode->i_lock);
        }
-       spin_unlock(&inode->i_lock);
        if (fi->dentry) {
                err = note_last_dentry(fi, fi->dentry->d_name.name,
                                       fi->dentry->d_name.len);
@@ -487,14 +479,13 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
 struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                                  struct dentry *dentry, int err)
 {
-       struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct inode *parent = dentry->d_parent->d_inode;
 
        /* .snap dir? */
        if (err == -ENOENT &&
-           ceph_vino(parent).ino != CEPH_INO_ROOT && /* no .snap in root dir */
            strcmp(dentry->d_name.name,
-                  client->mount_args->snapdir_name) == 0) {
+                  fsc->mount_options->snapdir_name) == 0) {
                struct inode *inode = ceph_get_snapdir(parent);
                dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n",
                     dentry, dentry->d_name.len, dentry->d_name.name, inode);
@@ -539,8 +530,8 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)
 static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                                  struct nameidata *nd)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int op;
        int err;
@@ -572,7 +563,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                spin_lock(&dir->i_lock);
                dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags);
                if (strncmp(dentry->d_name.name,
-                           client->mount_args->snapdir_name,
+                           fsc->mount_options->snapdir_name,
                            dentry->d_name.len) &&
                    !is_root_ceph_dentry(dir, dentry) &&
                    (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
@@ -629,8 +620,8 @@ int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
 static int ceph_mknod(struct inode *dir, struct dentry *dentry,
                      int mode, dev_t rdev)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err;
 
@@ -685,8 +676,8 @@ static int ceph_create(struct inode *dir, struct dentry *dentry, int mode,
 static int ceph_symlink(struct inode *dir, struct dentry *dentry,
                            const char *dest)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err;
 
@@ -716,8 +707,8 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
 
 static int ceph_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err = -EROFS;
        int op;
@@ -758,8 +749,8 @@ out:
 static int ceph_link(struct dentry *old_dentry, struct inode *dir,
                     struct dentry *dentry)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err;
 
@@ -813,8 +804,8 @@ static int drop_caps_for_unlink(struct inode *inode)
  */
 static int ceph_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct inode *inode = dentry->d_inode;
        struct ceph_mds_request *req;
        int err = -EROFS;
@@ -854,8 +845,8 @@ out:
 static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
                       struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct ceph_client *client = ceph_sb_to_client(old_dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(old_dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err;
 
@@ -1021,11 +1012,15 @@ out_touch:
 static void ceph_dentry_release(struct dentry *dentry)
 {
        struct ceph_dentry_info *di = ceph_dentry(dentry);
-       struct inode *parent_inode = dentry->d_parent->d_inode;
-       u64 snapid = ceph_snap(parent_inode);
+       struct inode *parent_inode = NULL;
+       u64 snapid = CEPH_NOSNAP;
 
+       if (!IS_ROOT(dentry)) {
+               parent_inode = dentry->d_parent->d_inode;
+               if (parent_inode)
+                       snapid = ceph_snap(parent_inode);
+       }
        dout("dentry_release %p parent %p\n", dentry, parent_inode);
-
        if (parent_inode && snapid != CEPH_SNAPDIR) {
                struct ceph_inode_info *ci = ceph_inode(parent_inode);
 
@@ -1072,7 +1067,7 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
        struct ceph_inode_info *ci = ceph_inode(inode);
        int left;
 
-       if (!ceph_test_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
+       if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
                return -EISDIR;
 
        if (!cf->dir_info) {
@@ -1173,7 +1168,7 @@ void ceph_dentry_lru_add(struct dentry *dn)
        dout("dentry_lru_add %p %p '%.*s'\n", di, dn,
             dn->d_name.len, dn->d_name.name);
        if (di) {
-               mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+               mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
                list_add_tail(&di->lru, &mdsc->dentry_lru);
                mdsc->num_dentry++;
@@ -1189,7 +1184,7 @@ void ceph_dentry_lru_touch(struct dentry *dn)
        dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn,
             dn->d_name.len, dn->d_name.name, di->offset);
        if (di) {
-               mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+               mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
                list_move_tail(&di->lru, &mdsc->dentry_lru);
                spin_unlock(&mdsc->dentry_lru_lock);
@@ -1204,7 +1199,7 @@ void ceph_dentry_lru_del(struct dentry *dn)
        dout("dentry_lru_del %p %p '%.*s'\n", di, dn,
             dn->d_name.len, dn->d_name.name);
        if (di) {
-               mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+               mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
                list_del_init(&di->lru);
                mdsc->num_dentry--;
index 4480cb1c63e7c69b107628481388cf1e35f49b8d..2297d9426992b0132b991e0d4e129982c4ab4a01 100644 (file)
@@ -1,10 +1,11 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/exportfs.h>
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
 #include "super.h"
+#include "mds_client.h"
 
 /*
  * NFS export support
@@ -42,32 +43,37 @@ struct ceph_nfs_confh {
 static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
                          int connectable)
 {
+       int type;
        struct ceph_nfs_fh *fh = (void *)rawfh;
        struct ceph_nfs_confh *cfh = (void *)rawfh;
        struct dentry *parent = dentry->d_parent;
        struct inode *inode = dentry->d_inode;
-       int type;
+       int connected_handle_length = sizeof(*cfh)/4;
+       int handle_length = sizeof(*fh)/4;
 
        /* don't re-export snaps */
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EINVAL;
 
-       if (*max_len >= sizeof(*cfh)) {
+       if (*max_len >= connected_handle_length) {
                dout("encode_fh %p connectable\n", dentry);
                cfh->ino = ceph_ino(dentry->d_inode);
                cfh->parent_ino = ceph_ino(parent->d_inode);
                cfh->parent_name_hash = parent->d_name.hash;
-               *max_len = sizeof(*cfh);
+               *max_len = connected_handle_length;
                type = 2;
-       } else if (*max_len > sizeof(*fh)) {
-               if (connectable)
-                       return -ENOSPC;
+       } else if (*max_len >= handle_length) {
+               if (connectable) {
+                       *max_len = connected_handle_length;
+                       return 255;
+               }
                dout("encode_fh %p\n", dentry);
                fh->ino = ceph_ino(dentry->d_inode);
-               *max_len = sizeof(*fh);
+               *max_len = handle_length;
                type = 1;
        } else {
-               return -ENOSPC;
+               *max_len = handle_length;
+               return 255;
        }
        return type;
 }
@@ -115,7 +121,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
 static struct dentry *__cfh_to_dentry(struct super_block *sb,
                                      struct ceph_nfs_confh *cfh)
 {
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
        struct inode *inode;
        struct dentry *dentry;
        struct ceph_vino vino;
index 8c044a4f045751c62420e67664705f981efe238a..e77c28cf369059112dd06ee3b7c78c5146f0ffdc 100644 (file)
@@ -1,5 +1,6 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/file.h>
@@ -38,8 +39,8 @@
 static struct ceph_mds_request *
 prepare_open_request(struct super_block *sb, int flags, int create_mode)
 {
-       struct ceph_client *client = ceph_sb_to_client(sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int want_auth = USE_ANY_MDS;
        int op = (flags & O_CREAT) ? CEPH_MDS_OP_CREATE : CEPH_MDS_OP_OPEN;
@@ -117,8 +118,8 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
 int ceph_open(struct inode *inode, struct file *file)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_client *client = ceph_sb_to_client(inode->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        struct ceph_file_info *cf = file->private_data;
        struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
@@ -216,8 +217,8 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
                                struct nameidata *nd, int mode,
                                int locked_dir)
 {
-       struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct file *file = nd->intent.open.file;
        struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry);
        struct ceph_mds_request *req;
@@ -269,163 +270,6 @@ int ceph_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- * build a vector of user pages
- */
-static struct page **get_direct_page_vector(const char __user *data,
-                                           int num_pages,
-                                           loff_t off, size_t len)
-{
-       struct page **pages;
-       int rc;
-
-       pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);
-       if (!pages)
-               return ERR_PTR(-ENOMEM);
-
-       down_read(&current->mm->mmap_sem);
-       rc = get_user_pages(current, current->mm, (unsigned long)data,
-                           num_pages, 0, 0, pages, NULL);
-       up_read(&current->mm->mmap_sem);
-       if (rc < 0)
-               goto fail;
-       return pages;
-
-fail:
-       kfree(pages);
-       return ERR_PTR(rc);
-}
-
-static void put_page_vector(struct page **pages, int num_pages)
-{
-       int i;
-
-       for (i = 0; i < num_pages; i++)
-               put_page(pages[i]);
-       kfree(pages);
-}
-
-void ceph_release_page_vector(struct page **pages, int num_pages)
-{
-       int i;
-
-       for (i = 0; i < num_pages; i++)
-               __free_pages(pages[i], 0);
-       kfree(pages);
-}
-
-/*
- * allocate a vector new pages
- */
-static struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
-{
-       struct page **pages;
-       int i;
-
-       pages = kmalloc(sizeof(*pages) * num_pages, flags);
-       if (!pages)
-               return ERR_PTR(-ENOMEM);
-       for (i = 0; i < num_pages; i++) {
-               pages[i] = __page_cache_alloc(flags);
-               if (pages[i] == NULL) {
-                       ceph_release_page_vector(pages, i);
-                       return ERR_PTR(-ENOMEM);
-               }
-       }
-       return pages;
-}
-
-/*
- * copy user data into a page vector
- */
-static int copy_user_to_page_vector(struct page **pages,
-                                   const char __user *data,
-                                   loff_t off, size_t len)
-{
-       int i = 0;
-       int po = off & ~PAGE_CACHE_MASK;
-       int left = len;
-       int l, bad;
-
-       while (left > 0) {
-               l = min_t(int, PAGE_CACHE_SIZE-po, left);
-               bad = copy_from_user(page_address(pages[i]) + po, data, l);
-               if (bad == l)
-                       return -EFAULT;
-               data += l - bad;
-               left -= l - bad;
-               po += l - bad;
-               if (po == PAGE_CACHE_SIZE) {
-                       po = 0;
-                       i++;
-               }
-       }
-       return len;
-}
-
-/*
- * copy user data from a page vector into a user pointer
- */
-static int copy_page_vector_to_user(struct page **pages, char __user *data,
-                                   loff_t off, size_t len)
-{
-       int i = 0;
-       int po = off & ~PAGE_CACHE_MASK;
-       int left = len;
-       int l, bad;
-
-       while (left > 0) {
-               l = min_t(int, left, PAGE_CACHE_SIZE-po);
-               bad = copy_to_user(data, page_address(pages[i]) + po, l);
-               if (bad == l)
-                       return -EFAULT;
-               data += l - bad;
-               left -= l - bad;
-               if (po) {
-                       po += l - bad;
-                       if (po == PAGE_CACHE_SIZE)
-                               po = 0;
-               }
-               i++;
-       }
-       return len;
-}
-
-/*
- * Zero an extent within a page vector.  Offset is relative to the
- * start of the first page.
- */
-static void zero_page_vector_range(int off, int len, struct page **pages)
-{
-       int i = off >> PAGE_CACHE_SHIFT;
-
-       off &= ~PAGE_CACHE_MASK;
-
-       dout("zero_page_vector_page %u~%u\n", off, len);
-
-       /* leading partial page? */
-       if (off) {
-               int end = min((int)PAGE_CACHE_SIZE, off + len);
-               dout("zeroing %d %p head from %d\n", i, pages[i],
-                    (int)off);
-               zero_user_segment(pages[i], off, end);
-               len -= (end - off);
-               i++;
-       }
-       while (len >= PAGE_CACHE_SIZE) {
-               dout("zeroing %d %p len=%d\n", i, pages[i], len);
-               zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
-               len -= PAGE_CACHE_SIZE;
-               i++;
-       }
-       /* trailing partial page? */
-       if (len) {
-               dout("zeroing %d %p tail to %d\n", i, pages[i], (int)len);
-               zero_user_segment(pages[i], 0, len);
-       }
-}
-
-
 /*
  * Read a range of bytes striped over one or more objects.  Iterate over
  * objects we stripe over.  (That's not atomic, but good enough for now.)
@@ -438,7 +282,7 @@ static int striped_read(struct inode *inode,
                        struct page **pages, int num_pages,
                        int *checkeof)
 {
-       struct ceph_client *client = ceph_inode_to_client(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_inode_info *ci = ceph_inode(inode);
        u64 pos, this_len;
        int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */
@@ -459,7 +303,7 @@ static int striped_read(struct inode *inode,
 
 more:
        this_len = left;
-       ret = ceph_osdc_readpages(&client->osdc, ceph_vino(inode),
+       ret = ceph_osdc_readpages(&fsc->client->osdc, ceph_vino(inode),
                                  &ci->i_layout, pos, &this_len,
                                  ci->i_truncate_seq,
                                  ci->i_truncate_size,
@@ -477,8 +321,8 @@ more:
 
                if (read < pos - off) {
                        dout(" zero gap %llu to %llu\n", off + read, pos);
-                       zero_page_vector_range(page_off + read,
-                                              pos - off - read, pages);
+                       ceph_zero_page_vector_range(page_off + read,
+                                                   pos - off - read, pages);
                }
                pos += ret;
                read = pos - off;
@@ -495,8 +339,8 @@ more:
                /* was original extent fully inside i_size? */
                if (pos + left <= inode->i_size) {
                        dout("zero tail\n");
-                       zero_page_vector_range(page_off + read, len - read,
-                                              pages);
+                       ceph_zero_page_vector_range(page_off + read, len - read,
+                                                   pages);
                        read = len;
                        goto out;
                }
@@ -531,7 +375,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
 
        if (file->f_flags & O_DIRECT) {
-               pages = get_direct_page_vector(data, num_pages, off, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, off, len);
 
                /*
                 * flush any page cache pages in this range.  this
@@ -552,13 +396,13 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
        ret = striped_read(inode, off, len, pages, num_pages, checkeof);
 
        if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
-               ret = copy_page_vector_to_user(pages, data, off, ret);
+               ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
        if (ret >= 0)
                *poff = off + ret;
 
 done:
        if (file->f_flags & O_DIRECT)
-               put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages);
        else
                ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
@@ -594,7 +438,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_client *client = ceph_inode_to_client(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_osd_request *req;
        struct page **pages;
        int num_pages;
@@ -642,7 +486,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
         */
 more:
        len = left;
-       req = ceph_osdc_new_request(&client->osdc, &ci->i_layout,
+       req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
                                    ceph_vino(inode), pos, &len,
                                    CEPH_OSD_OP_WRITE, flags,
                                    ci->i_snap_realm->cached_context,
@@ -655,7 +499,7 @@ more:
        num_pages = calc_pages_for(pos, len);
 
        if (file->f_flags & O_DIRECT) {
-               pages = get_direct_page_vector(data, num_pages, pos, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, pos, len);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
                        goto out;
@@ -673,7 +517,7 @@ more:
                        ret = PTR_ERR(pages);
                        goto out;
                }
-               ret = copy_user_to_page_vector(pages, data, pos, len);
+               ret = ceph_copy_user_to_page_vector(pages, data, pos, len);
                if (ret < 0) {
                        ceph_release_page_vector(pages, num_pages);
                        goto out;
@@ -689,7 +533,7 @@ more:
        req->r_num_pages = num_pages;
        req->r_inode = inode;
 
-       ret = ceph_osdc_start_request(&client->osdc, req, false);
+       ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
        if (!ret) {
                if (req->r_safe_callback) {
                        /*
@@ -697,15 +541,15 @@ more:
                         * start_request so that a tid has been assigned.
                         */
                        spin_lock(&ci->i_unsafe_lock);
-                       list_add(&ci->i_unsafe_writes, &req->r_unsafe_item);
+                       list_add(&req->r_unsafe_item, &ci->i_unsafe_writes);
                        spin_unlock(&ci->i_unsafe_lock);
                        ceph_get_cap_refs(ci, CEPH_CAP_FILE_WR);
                }
-               ret = ceph_osdc_wait_request(&client->osdc, req);
+               ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
        }
 
        if (file->f_flags & O_DIRECT)
-               put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages);
        else if (file->f_flags & O_SYNC)
                ceph_release_page_vector(pages, num_pages);
 
@@ -814,7 +658,8 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct ceph_file_info *fi = file->private_data;
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc = &ceph_sb_to_client(inode->i_sb)->osdc;
+       struct ceph_osd_client *osdc =
+               &ceph_sb_to_client(inode->i_sb)->client->osdc;
        loff_t endoff = pos + iov->iov_len;
        int want, got = 0;
        int ret, err;
index 5d893d31e399b81f57543ede560dc2258f7400da..1d6a45b5a04c696591879d141165627746d6a476 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -13,7 +13,8 @@
 #include <linux/pagevec.h>
 
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+#include <linux/ceph/decode.h>
 
 /*
  * Ceph inode operations
@@ -384,7 +385,7 @@ void ceph_destroy_inode(struct inode *inode)
         */
        if (ci->i_snap_realm) {
                struct ceph_mds_client *mdsc =
-                       &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+                       ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
                struct ceph_snap_realm *realm = ci->i_snap_realm;
 
                dout(" dropping residual ref to snap realm %p\n", realm);
@@ -677,6 +678,7 @@ static int fill_inode(struct inode *inode,
                if (ci->i_files == 0 && ci->i_subdirs == 0 &&
                    ceph_snap(inode) == CEPH_NOSNAP &&
                    (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
+                   (issued & CEPH_CAP_FILE_EXCL) == 0 &&
                    (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
                        dout(" marking %p complete (empty)\n", inode);
                        ci->i_ceph_flags |= CEPH_I_COMPLETE;
@@ -684,7 +686,7 @@ static int fill_inode(struct inode *inode,
                }
 
                /* it may be better to set st_size in getattr instead? */
-               if (ceph_test_opt(ceph_sb_to_client(inode->i_sb), RBYTES))
+               if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), RBYTES))
                        inode->i_size = ci->i_rbytes;
                break;
        default:
@@ -844,7 +846,7 @@ static void ceph_set_dentry_offset(struct dentry *dn)
  * the caller) if we fail.
  */
 static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
-                                   bool *prehash)
+                                   bool *prehash, bool set_offset)
 {
        struct dentry *realdn;
 
@@ -876,7 +878,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
        }
        if ((!prehash || *prehash) && d_unhashed(dn))
                d_rehash(dn);
-       ceph_set_dentry_offset(dn);
+       if (set_offset)
+               ceph_set_dentry_offset(dn);
 out:
        return dn;
 }
@@ -899,7 +902,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        struct inode *in = NULL;
        struct ceph_mds_reply_inode *ininfo;
        struct ceph_vino vino;
-       struct ceph_client *client = ceph_sb_to_client(sb);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
        int i = 0;
        int err = 0;
 
@@ -963,7 +966,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
         */
        if (rinfo->head->is_dentry && !req->r_aborted &&
            (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,
-                                              client->mount_args->snapdir_name,
+                                              fsc->mount_options->snapdir_name,
                                               req->r_dentry->d_name.len))) {
                /*
                 * lookup link rename   : null -> possibly existing inode
@@ -1061,7 +1064,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                                d_delete(dn);
                                goto done;
                        }
-                       dn = splice_dentry(dn, in, &have_lease);
+                       dn = splice_dentry(dn, in, &have_lease, true);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                goto done;
@@ -1104,7 +1107,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                        goto done;
                }
                dout(" linking snapped dir %p to dn %p\n", in, dn);
-               dn = splice_dentry(dn, in, NULL);
+               dn = splice_dentry(dn, in, NULL, true);
                if (IS_ERR(dn)) {
                        err = PTR_ERR(dn);
                        goto done;
@@ -1229,14 +1232,14 @@ retry_lookup:
                        in = dn->d_inode;
                } else {
                        in = ceph_get_inode(parent->d_sb, vino);
-                       if (in == NULL) {
+                       if (IS_ERR(in)) {
                                dout("new_inode badness\n");
                                d_delete(dn);
                                dput(dn);
-                               err = -ENOMEM;
+                               err = PTR_ERR(in);
                                goto out;
                        }
-                       dn = splice_dentry(dn, in, NULL);
+                       dn = splice_dentry(dn, in, NULL, false);
                        if (IS_ERR(dn))
                                dn = NULL;
                }
@@ -1531,7 +1534,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *parent_inode = dentry->d_parent->d_inode;
        const unsigned int ia_valid = attr->ia_valid;
        struct ceph_mds_request *req;
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(dentry->d_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
        int issued;
        int release = 0, dirtied = 0;
        int mask = 0;
@@ -1726,8 +1729,8 @@ out:
  */
 int ceph_do_getattr(struct inode *inode, int mask)
 {
-       struct ceph_client *client = ceph_sb_to_client(inode->i_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
        int err;
 
index 76e307d2aba16868c9b1e8136496d929e0cd971f..8888c9ba68dbfec194e06f06142547ee2d35c8bc 100644 (file)
@@ -1,8 +1,10 @@
 #include <linux/in.h>
 
-#include "ioctl.h"
 #include "super.h"
-#include "ceph_debug.h"
+#include "mds_client.h"
+#include <linux/ceph/ceph_debug.h>
+
+#include "ioctl.h"
 
 
 /*
@@ -37,7 +39,7 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        struct ceph_ioctl_layout l;
        int err, i;
@@ -89,6 +91,68 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
        return err;
 }
 
+/*
+ * Set a layout policy on a directory inode. All items in the tree
+ * rooted at this inode will inherit this layout on creation,
+ * (It doesn't apply retroactively )
+ * unless a subdirectory has its own layout policy.
+ */
+static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_mds_request *req;
+       struct ceph_ioctl_layout l;
+       int err, i;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+
+       /* copy and validate */
+       if (copy_from_user(&l, arg, sizeof(l)))
+               return -EFAULT;
+
+       if ((l.object_size & ~PAGE_MASK) ||
+           (l.stripe_unit & ~PAGE_MASK) ||
+           !l.stripe_unit ||
+           (l.object_size &&
+               (unsigned)l.object_size % (unsigned)l.stripe_unit))
+               return -EINVAL;
+
+       /* make sure it's a valid data pool */
+       if (l.data_pool > 0) {
+               mutex_lock(&mdsc->mutex);
+               err = -EINVAL;
+               for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++)
+                       if (mdsc->mdsmap->m_data_pg_pools[i] == l.data_pool) {
+                               err = 0;
+                               break;
+                       }
+               mutex_unlock(&mdsc->mutex);
+               if (err)
+                       return err;
+       }
+
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETDIRLAYOUT,
+                                      USE_AUTH_MDS);
+
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+       req->r_inode = igrab(inode);
+
+       req->r_args.setlayout.layout.fl_stripe_unit =
+                       cpu_to_le32(l.stripe_unit);
+       req->r_args.setlayout.layout.fl_stripe_count =
+                       cpu_to_le32(l.stripe_count);
+       req->r_args.setlayout.layout.fl_object_size =
+                       cpu_to_le32(l.object_size);
+       req->r_args.setlayout.layout.fl_pg_pool =
+                       cpu_to_le32(l.data_pool);
+       req->r_args.setlayout.layout.fl_pg_preferred =
+                       cpu_to_le32(l.preferred_osd);
+
+       err = ceph_mdsc_do_request(mdsc, inode, req);
+       ceph_mdsc_put_request(req);
+       return err;
+}
+
 /*
  * Return object name, size/offset information, and location (OSD
  * number, network address) for a given file offset.
@@ -98,7 +162,8 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
        struct ceph_ioctl_dataloc dl;
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc = &ceph_sb_to_client(inode->i_sb)->osdc;
+       struct ceph_osd_client *osdc =
+               &ceph_sb_to_client(inode->i_sb)->client->osdc;
        u64 len = 1, olen;
        u64 tmp;
        struct ceph_object_layout ol;
@@ -174,11 +239,15 @@ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case CEPH_IOC_SET_LAYOUT:
                return ceph_ioctl_set_layout(file, (void __user *)arg);
 
+       case CEPH_IOC_SET_LAYOUT_POLICY:
+               return ceph_ioctl_set_layout_policy(file, (void __user *)arg);
+
        case CEPH_IOC_GET_DATALOC:
                return ceph_ioctl_get_dataloc(file, (void __user *)arg);
 
        case CEPH_IOC_LAZYIO:
                return ceph_ioctl_lazyio(file);
        }
+
        return -ENOTTY;
 }
index 88451a3b6857d14bc7b21f418bcd82e56e9fdc64..a6ce54e94eb5ab435670093cd6ad789e72cc627b 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x97
+#define CEPH_IOCTL_MAGIC 0x98
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
@@ -17,6 +17,8 @@ struct ceph_ioctl_layout {
                                   struct ceph_ioctl_layout)
 #define CEPH_IOC_SET_LAYOUT _IOW(CEPH_IOCTL_MAGIC, 2,          \
                                   struct ceph_ioctl_layout)
+#define CEPH_IOC_SET_LAYOUT_POLICY _IOW(CEPH_IOCTL_MAGIC, 5,   \
+                                  struct ceph_ioctl_layout)
 
 /*
  * Extract identity, address of the OSD and object storing a given
index ae85af06454fd3544840329be8639a0910d2cb3d..40abde93c345d054279fd51cbca998525c4931c7 100644 (file)
@@ -1,11 +1,11 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/file.h>
 #include <linux/namei.h>
 
 #include "super.h"
 #include "mds_client.h"
-#include "pagelist.h"
+#include <linux/ceph/pagelist.h>
 
 /**
  * Implement fcntl and flock locking functions.
@@ -16,7 +16,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_mds_client *mdsc =
-               &ceph_sb_to_client(inode->i_sb)->mdsc;
+               ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        int err;
 
@@ -82,7 +82,8 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
                length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                               (u64)fl->fl_pid, (u64)fl->fl_nspid,
+                               (u64)fl->fl_pid,
+                               (u64)(unsigned long)fl->fl_nspid,
                                lock_cmd, fl->fl_start,
                                length, wait);
        if (!err) {
@@ -92,7 +93,8 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
                        /* undo! This should only happen if the kernel detects
                         * local deadlock. */
                        ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                         (u64)fl->fl_pid, (u64)fl->fl_nspid,
+                                         (u64)fl->fl_pid,
+                                         (u64)(unsigned long)fl->fl_nspid,
                                          CEPH_LOCK_UNLOCK, fl->fl_start,
                                          length, 0);
                        dout("got %d on posix_lock_file, undid lock", err);
@@ -132,7 +134,8 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
-                               file, (u64)fl->fl_pid, (u64)fl->fl_nspid,
+                               file, (u64)fl->fl_pid,
+                               (u64)(unsigned long)fl->fl_nspid,
                                lock_cmd, fl->fl_start,
                                length, wait);
        if (!err) {
@@ -141,7 +144,7 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                        ceph_lock_message(CEPH_LOCK_FLOCK,
                                          CEPH_MDS_OP_SETFILELOCK,
                                          file, (u64)fl->fl_pid,
-                                         (u64)fl->fl_nspid,
+                                         (u64)(unsigned long)fl->fl_nspid,
                                          CEPH_LOCK_UNLOCK, fl->fl_start,
                                          length, 0);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
@@ -178,8 +181,9 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
  * Encode the flock and fcntl locks for the given inode into the pagelist.
  * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
  * sequential flock locks.
- * Must be called with BLK already held, and the lock numbers should have
- * been gathered under the same lock holding window.
+ * Must be called with lock_flocks() already held.
+ * If we encounter more of a specific lock type than expected,
+ * we return the value 1.
  */
 int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
                      int num_fcntl_locks, int num_flock_locks)
@@ -187,6 +191,8 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
        struct file_lock *lock;
        struct ceph_filelock cephlock;
        int err = 0;
+       int seen_fcntl = 0;
+       int seen_flock = 0;
 
        dout("encoding %d flock and %d fcntl locks", num_flock_locks,
             num_fcntl_locks);
@@ -195,6 +201,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
                goto fail;
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_POSIX) {
+                       ++seen_fcntl;
+                       if (seen_fcntl > num_fcntl_locks) {
+                               err = -ENOSPC;
+                               goto fail;
+                       }
                        err = lock_to_ceph_filelock(lock, &cephlock);
                        if (err)
                                goto fail;
@@ -210,6 +221,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
                goto fail;
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_FLOCK) {
+                       ++seen_flock;
+                       if (seen_flock > num_flock_locks) {
+                               err = -ENOSPC;
+                               goto fail;
+                       }
                        err = lock_to_ceph_filelock(lock, &cephlock);
                        if (err)
                                goto fail;
@@ -235,7 +251,8 @@ int lock_to_ceph_filelock(struct file_lock *lock,
        cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1);
        cephlock->client = cpu_to_le64(0);
        cephlock->pid = cpu_to_le64(lock->fl_pid);
-       cephlock->pid_namespace = cpu_to_le64((u64)lock->fl_nspid);
+       cephlock->pid_namespace =
+               cpu_to_le64((u64)(unsigned long)lock->fl_nspid);
 
        switch (lock->fl_type) {
        case F_RDLCK:
index a75ddbf9fe3743973c6fd02724f005b8504c3738..3142b15940c25656a43ec3a5d72af3e1ee1cece9 100644 (file)
@@ -1,17 +1,21 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/fs.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/smp_lock.h>
 
-#include "mds_client.h"
-#include "mon_client.h"
 #include "super.h"
-#include "messenger.h"
-#include "decode.h"
-#include "auth.h"
-#include "pagelist.h"
+#include "mds_client.h"
+
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/pagelist.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
 
 /*
  * A cluster of MDS (metadata server) daemons is responsible for
@@ -286,8 +290,9 @@ void ceph_put_mds_session(struct ceph_mds_session *s)
             atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
        if (atomic_dec_and_test(&s->s_ref)) {
                if (s->s_authorizer)
-                       s->s_mdsc->client->monc.auth->ops->destroy_authorizer(
-                               s->s_mdsc->client->monc.auth, s->s_authorizer);
+                    s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer(
+                            s->s_mdsc->fsc->client->monc.auth,
+                            s->s_authorizer);
                kfree(s);
        }
 }
@@ -344,7 +349,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        s->s_seq = 0;
        mutex_init(&s->s_mutex);
 
-       ceph_con_init(mdsc->client->msgr, &s->s_con);
+       ceph_con_init(mdsc->fsc->client->msgr, &s->s_con);
        s->s_con.private = s;
        s->s_con.ops = &mds_con_ops;
        s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
@@ -560,6 +565,13 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
  *
  * Called under mdsc->mutex.
  */
+struct dentry *get_nonsnap_parent(struct dentry *dentry)
+{
+       while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+               dentry = dentry->d_parent;
+       return dentry;
+}
+
 static int __choose_mds(struct ceph_mds_client *mdsc,
                        struct ceph_mds_request *req)
 {
@@ -590,14 +602,29 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
        if (req->r_inode) {
                inode = req->r_inode;
        } else if (req->r_dentry) {
-               if (req->r_dentry->d_inode) {
+               struct inode *dir = req->r_dentry->d_parent->d_inode;
+
+               if (dir->i_sb != mdsc->fsc->sb) {
+                       /* not this fs! */
+                       inode = req->r_dentry->d_inode;
+               } else if (ceph_snap(dir) != CEPH_NOSNAP) {
+                       /* direct snapped/virtual snapdir requests
+                        * based on parent dir inode */
+                       struct dentry *dn =
+                               get_nonsnap_parent(req->r_dentry->d_parent);
+                       inode = dn->d_inode;
+                       dout("__choose_mds using nonsnap parent %p\n", inode);
+               } else if (req->r_dentry->d_inode) {
+                       /* dentry target */
                        inode = req->r_dentry->d_inode;
                } else {
-                       inode = req->r_dentry->d_parent->d_inode;
+                       /* dir + name */
+                       inode = dir;
                        hash = req->r_dentry->d_name.hash;
                        is_hash = true;
                }
        }
+
        dout("__choose_mds %p is_hash=%d (%d) mode %d\n", inode, (int)is_hash,
             (int)hash, mode);
        if (!inode)
@@ -862,7 +889,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
        __ceph_remove_cap(cap);
        if (!__ceph_is_any_real_caps(ci)) {
                struct ceph_mds_client *mdsc =
-                       &ceph_sb_to_client(inode->i_sb)->mdsc;
+                       ceph_sb_to_client(inode->i_sb)->mdsc;
 
                spin_lock(&mdsc->cap_dirty_lock);
                if (!list_empty(&ci->i_dirty_item)) {
@@ -1124,7 +1151,7 @@ int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
        struct ceph_msg *msg, *partial = NULL;
        struct ceph_mds_cap_release *head;
        int err = -ENOMEM;
-       int extra = mdsc->client->mount_args->cap_release_safety;
+       int extra = mdsc->fsc->mount_options->cap_release_safety;
        int num;
 
        dout("add_cap_releases %p mds%d extra %d\n", session, session->s_mds,
@@ -2063,7 +2090,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        /* insert trace into our cache */
        mutex_lock(&req->r_fill_mutex);
-       err = ceph_fill_trace(mdsc->client->sb, req, req->r_session);
+       err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
                if (result == 0 && rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
@@ -2208,7 +2235,7 @@ static void handle_session(struct ceph_mds_session *session,
                        pr_info("mds%d reconnect denied\n", session->s_mds);
                remove_session_caps(session);
                wake = 1; /* for good measure */
-               complete_all(&mdsc->session_close_waiters);
+               wake_up_all(&mdsc->session_close_wq);
                kick_requests(mdsc, mds);
                break;
 
@@ -2302,7 +2329,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
                path = ceph_mdsc_build_path(dentry, &pathlen, &pathbase, 0);
                if (IS_ERR(path)) {
                        err = PTR_ERR(path);
-                       BUG_ON(err);
+                       goto out_dput;
                }
        } else {
                path = NULL;
@@ -2310,7 +2337,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
        }
        err = ceph_pagelist_encode_string(pagelist, path, pathlen);
        if (err)
-               goto out;
+               goto out_free;
 
        spin_lock(&inode->i_lock);
        cap->seq = 0;        /* reset cap seq */
@@ -2339,23 +2366,42 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
 
        if (recon_state->flock) {
                int num_fcntl_locks, num_flock_locks;
-
-               lock_kernel();
-               ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks);
-               rec.v2.flock_len = (2*sizeof(u32) +
-                                   (num_fcntl_locks+num_flock_locks) *
-                                   sizeof(struct ceph_filelock));
-
+               struct ceph_pagelist_cursor trunc_point;
+
+               ceph_pagelist_set_cursor(pagelist, &trunc_point);
+               do {
+                       lock_flocks();
+                       ceph_count_locks(inode, &num_fcntl_locks,
+                                        &num_flock_locks);
+                       rec.v2.flock_len = (2*sizeof(u32) +
+                                           (num_fcntl_locks+num_flock_locks) *
+                                           sizeof(struct ceph_filelock));
+                       unlock_flocks();
+
+                       /* pre-alloc pagelist */
+                       ceph_pagelist_truncate(pagelist, &trunc_point);
+                       err = ceph_pagelist_append(pagelist, &rec, reclen);
+                       if (!err)
+                               err = ceph_pagelist_reserve(pagelist,
+                                                           rec.v2.flock_len);
+
+                       /* encode locks */
+                       if (!err) {
+                               lock_flocks();
+                               err = ceph_encode_locks(inode,
+                                                       pagelist,
+                                                       num_fcntl_locks,
+                                                       num_flock_locks);
+                               unlock_flocks();
+                       }
+               } while (err == -ENOSPC);
+       } else {
                err = ceph_pagelist_append(pagelist, &rec, reclen);
-               if (!err)
-                       err = ceph_encode_locks(inode, pagelist,
-                                               num_fcntl_locks,
-                                               num_flock_locks);
-               unlock_kernel();
        }
 
-out:
+out_free:
        kfree(path);
+out_dput:
        dput(dentry);
        return err;
 }
@@ -2588,7 +2634,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
                         struct ceph_mds_session *session,
                         struct ceph_msg *msg)
 {
-       struct super_block *sb = mdsc->client->sb;
+       struct super_block *sb = mdsc->fsc->sb;
        struct inode *inode;
        struct ceph_inode_info *ci;
        struct dentry *parent, *dentry;
@@ -2866,17 +2912,23 @@ static void delayed_work(struct work_struct *work)
        schedule_delayed(mdsc);
 }
 
+int ceph_mdsc_init(struct ceph_fs_client *fsc)
 
-int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
 {
-       mdsc->client = client;
+       struct ceph_mds_client *mdsc;
+
+       mdsc = kzalloc(sizeof(struct ceph_mds_client), GFP_NOFS);
+       if (!mdsc)
+               return -ENOMEM;
+       mdsc->fsc = fsc;
+       fsc->mdsc = mdsc;
        mutex_init(&mdsc->mutex);
        mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS);
        if (mdsc->mdsmap == NULL)
                return -ENOMEM;
 
        init_completion(&mdsc->safe_umount_waiters);
-       init_completion(&mdsc->session_close_waiters);
+       init_waitqueue_head(&mdsc->session_close_wq);
        INIT_LIST_HEAD(&mdsc->waiting_for_map);
        mdsc->sessions = NULL;
        mdsc->max_sessions = 0;
@@ -2902,7 +2954,7 @@ int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
        INIT_LIST_HEAD(&mdsc->dentry_lru);
 
        ceph_caps_init(mdsc);
-       ceph_adjust_min_caps(mdsc, client->min_caps);
+       ceph_adjust_min_caps(mdsc, fsc->min_caps);
 
        return 0;
 }
@@ -2914,7 +2966,7 @@ int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
 static void wait_requests(struct ceph_mds_client *mdsc)
 {
        struct ceph_mds_request *req;
-       struct ceph_client *client = mdsc->client;
+       struct ceph_fs_client *fsc = mdsc->fsc;
 
        mutex_lock(&mdsc->mutex);
        if (__get_oldest_req(mdsc)) {
@@ -2922,7 +2974,7 @@ static void wait_requests(struct ceph_mds_client *mdsc)
 
                dout("wait_requests waiting for requests\n");
                wait_for_completion_timeout(&mdsc->safe_umount_waiters,
-                                   client->mount_args->mount_timeout * HZ);
+                                   fsc->client->options->mount_timeout * HZ);
 
                /* tear down remaining requests */
                mutex_lock(&mdsc->mutex);
@@ -3005,7 +3057,7 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
 {
        u64 want_tid, want_flush;
 
-       if (mdsc->client->mount_state == CEPH_MOUNT_SHUTDOWN)
+       if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
                return;
 
        dout("sync\n");
@@ -3021,6 +3073,23 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
        wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush));
 }
 
+/*
+ * true if all sessions are closed, or we force unmount
+ */
+bool done_closing_sessions(struct ceph_mds_client *mdsc)
+{
+       int i, n = 0;
+
+       if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
+               return true;
+
+       mutex_lock(&mdsc->mutex);
+       for (i = 0; i < mdsc->max_sessions; i++)
+               if (mdsc->sessions[i])
+                       n++;
+       mutex_unlock(&mdsc->mutex);
+       return n == 0;
+}
 
 /*
  * called after sb is ro.
@@ -3029,45 +3098,32 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
 {
        struct ceph_mds_session *session;
        int i;
-       int n;
-       struct ceph_client *client = mdsc->client;
-       unsigned long started, timeout = client->mount_args->mount_timeout * HZ;
+       struct ceph_fs_client *fsc = mdsc->fsc;
+       unsigned long timeout = fsc->client->options->mount_timeout * HZ;
 
        dout("close_sessions\n");
 
-       mutex_lock(&mdsc->mutex);
-
        /* close sessions */
-       started = jiffies;
-       while (time_before(jiffies, started + timeout)) {
-               dout("closing sessions\n");
-               n = 0;
-               for (i = 0; i < mdsc->max_sessions; i++) {
-                       session = __ceph_lookup_mds_session(mdsc, i);
-                       if (!session)
-                               continue;
-                       mutex_unlock(&mdsc->mutex);
-                       mutex_lock(&session->s_mutex);
-                       __close_session(mdsc, session);
-                       mutex_unlock(&session->s_mutex);
-                       ceph_put_mds_session(session);
-                       mutex_lock(&mdsc->mutex);
-                       n++;
-               }
-               if (n == 0)
-                       break;
-
-               if (client->mount_state == CEPH_MOUNT_SHUTDOWN)
-                       break;
-
-               dout("waiting for sessions to close\n");
+       mutex_lock(&mdsc->mutex);
+       for (i = 0; i < mdsc->max_sessions; i++) {
+               session = __ceph_lookup_mds_session(mdsc, i);
+               if (!session)
+                       continue;
                mutex_unlock(&mdsc->mutex);
-               wait_for_completion_timeout(&mdsc->session_close_waiters,
-                                           timeout);
+               mutex_lock(&session->s_mutex);
+               __close_session(mdsc, session);
+               mutex_unlock(&session->s_mutex);
+               ceph_put_mds_session(session);
                mutex_lock(&mdsc->mutex);
        }
+       mutex_unlock(&mdsc->mutex);
+
+       dout("waiting for sessions to close\n");
+       wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
+                          timeout);
 
        /* tear down remaining sessions */
+       mutex_lock(&mdsc->mutex);
        for (i = 0; i < mdsc->max_sessions; i++) {
                if (mdsc->sessions[i]) {
                        session = get_session(mdsc->sessions[i]);
@@ -3080,9 +3136,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
                        mutex_lock(&mdsc->mutex);
                }
        }
-
        WARN_ON(!list_empty(&mdsc->cap_delay_list));
-
        mutex_unlock(&mdsc->mutex);
 
        ceph_cleanup_empty_realms(mdsc);
@@ -3092,7 +3146,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        dout("stopped\n");
 }
 
-void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
+static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
 {
        dout("stop\n");
        cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
@@ -3102,6 +3156,15 @@ void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
        ceph_caps_finalize(mdsc);
 }
 
+void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
+{
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+
+       ceph_mdsc_stop(mdsc);
+       fsc->mdsc = NULL;
+       kfree(mdsc);
+}
+
 
 /*
  * handle mds map update.
@@ -3118,14 +3181,14 @@ void ceph_mdsc_handle_map(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
 
        ceph_decode_need(&p, end, sizeof(fsid)+2*sizeof(u32), bad);
        ceph_decode_copy(&p, &fsid, sizeof(fsid));
-       if (ceph_check_fsid(mdsc->client, &fsid) < 0)
+       if (ceph_check_fsid(mdsc->fsc->client, &fsid) < 0)
                return;
        epoch = ceph_decode_32(&p);
        maplen = ceph_decode_32(&p);
        dout("handle_map epoch %u len %d\n", epoch, (int)maplen);
 
        /* do we need it? */
-       ceph_monc_got_mdsmap(&mdsc->client->monc, epoch);
+       ceph_monc_got_mdsmap(&mdsc->fsc->client->monc, epoch);
        mutex_lock(&mdsc->mutex);
        if (mdsc->mdsmap && epoch <= mdsc->mdsmap->m_epoch) {
                dout("handle_map epoch %u <= our %u\n",
@@ -3149,7 +3212,7 @@ void ceph_mdsc_handle_map(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
        } else {
                mdsc->mdsmap = newmap;  /* first mds map */
        }
-       mdsc->client->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
+       mdsc->fsc->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
 
        __wake_requests(mdsc, &mdsc->waiting_for_map);
 
@@ -3250,7 +3313,7 @@ static int get_authorizer(struct ceph_connection *con,
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
-       struct ceph_auth_client *ac = mdsc->client->monc.auth;
+       struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
        int ret = 0;
 
        if (force_new && s->s_authorizer) {
@@ -3284,7 +3347,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
-       struct ceph_auth_client *ac = mdsc->client->monc.auth;
+       struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
        return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
 }
@@ -3293,12 +3356,12 @@ static int invalidate_authorizer(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
-       struct ceph_auth_client *ac = mdsc->client->monc.auth;
+       struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
        if (ac->ops->invalidate_authorizer)
                ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
 
-       return ceph_monc_validate_auth(&mdsc->client->monc);
+       return ceph_monc_validate_auth(&mdsc->fsc->client->monc);
 }
 
 static const struct ceph_connection_operations mds_con_ops = {
@@ -3311,7 +3374,4 @@ static const struct ceph_connection_operations mds_con_ops = {
        .peer_reset = peer_reset,
 };
 
-
-
-
 /* eof */
index ab7e89f5e344b14d44500866625f378a2c849d57..d66d63c7235526ef63d16ff0ea1e9ba3899df586 100644 (file)
@@ -8,9 +8,9 @@
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 
-#include "types.h"
-#include "messenger.h"
-#include "mdsmap.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/mdsmap.h>
 
 /*
  * Some lock dependencies:
@@ -26,7 +26,7 @@
  *
  */
 
-struct ceph_client;
+struct ceph_fs_client;
 struct ceph_cap;
 
 /*
@@ -230,11 +230,12 @@ struct ceph_mds_request {
  * mds client state
  */
 struct ceph_mds_client {
-       struct ceph_client      *client;
+       struct ceph_fs_client  *fsc;
        struct mutex            mutex;         /* all nested structures */
 
        struct ceph_mdsmap      *mdsmap;
-       struct completion       safe_umount_waiters, session_close_waiters;
+       struct completion       safe_umount_waiters;
+       wait_queue_head_t       session_close_wq;
        struct list_head        waiting_for_map;
 
        struct ceph_mds_session **sessions;    /* NULL for mds if no session */
@@ -288,11 +289,6 @@ struct ceph_mds_client {
        int             caps_avail_count;    /* unused, unreserved */
        int             caps_min_count;      /* keep at least this many
                                                (unreserved) */
-
-#ifdef CONFIG_DEBUG_FS
-       struct dentry     *debugfs_file;
-#endif
-
        spinlock_t        dentry_lru_lock;
        struct list_head  dentry_lru;
        int               num_dentry;
@@ -315,10 +311,9 @@ extern void ceph_put_mds_session(struct ceph_mds_session *s);
 extern int ceph_send_msg_mds(struct ceph_mds_client *mdsc,
                             struct ceph_msg *msg, int mds);
 
-extern int ceph_mdsc_init(struct ceph_mds_client *mdsc,
-                          struct ceph_client *client);
+extern int ceph_mdsc_init(struct ceph_fs_client *fsc);
 extern void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc);
-extern void ceph_mdsc_stop(struct ceph_mds_client *mdsc);
+extern void ceph_mdsc_destroy(struct ceph_fs_client *fsc);
 
 extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
 
index 040be6d1150be5ace2be71e955ac3b3525b8fd76..73b7d44e8a354264e3f08f66e8cb788851328029 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/bug.h>
 #include <linux/err.h>
@@ -6,9 +6,9 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#include "mdsmap.h"
-#include "messenger.h"
-#include "decode.h"
+#include <linux/ceph/mdsmap.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
 
 #include "super.h"
 
@@ -117,7 +117,8 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                }
 
                dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
-                    i+1, n, global_id, mds, inc, pr_addr(&addr.in_addr),
+                    i+1, n, global_id, mds, inc,
+                    ceph_pr_addr(&addr.in_addr),
                     ceph_mds_state_name(state));
                if (mds >= 0 && mds < m->m_max_mds && state > 0) {
                        m->m_info[mds].global_id = global_id;
diff --git a/fs/ceph/pagelist.c b/fs/ceph/pagelist.c
deleted file mode 100644 (file)
index b6859f4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-
-#include <linux/gfp.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
-
-#include "pagelist.h"
-
-int ceph_pagelist_release(struct ceph_pagelist *pl)
-{
-       if (pl->mapped_tail)
-               kunmap(pl->mapped_tail);
-       while (!list_empty(&pl->head)) {
-               struct page *page = list_first_entry(&pl->head, struct page,
-                                                    lru);
-               list_del(&page->lru);
-               __free_page(page);
-       }
-       return 0;
-}
-
-static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
-{
-       struct page *page = __page_cache_alloc(GFP_NOFS);
-       if (!page)
-               return -ENOMEM;
-       pl->room += PAGE_SIZE;
-       list_add_tail(&page->lru, &pl->head);
-       if (pl->mapped_tail)
-               kunmap(pl->mapped_tail);
-       pl->mapped_tail = kmap(page);
-       return 0;
-}
-
-int ceph_pagelist_append(struct ceph_pagelist *pl, void *buf, size_t len)
-{
-       while (pl->room < len) {
-               size_t bit = pl->room;
-               int ret;
-
-               memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
-                      buf, bit);
-               pl->length += bit;
-               pl->room -= bit;
-               buf += bit;
-               len -= bit;
-               ret = ceph_pagelist_addpage(pl);
-               if (ret)
-                       return ret;
-       }
-
-       memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
-       pl->length += len;
-       pl->room -= len;
-       return 0;
-}
index c0b26b6badba7f53d0d8b32be33c165fb762922e..39c243acd062c810d33e60da27af51cbcfe058e8 100644 (file)
@@ -1,10 +1,12 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/sort.h>
 #include <linux/slab.h>
 
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
 
 /*
  * Snapshots in ceph are driven in large part by cooperation from the
@@ -119,6 +121,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
        INIT_LIST_HEAD(&realm->children);
        INIT_LIST_HEAD(&realm->child_item);
        INIT_LIST_HEAD(&realm->empty_item);
+       INIT_LIST_HEAD(&realm->dirty_item);
        INIT_LIST_HEAD(&realm->inodes_with_caps);
        spin_lock_init(&realm->inodes_with_caps_lock);
        __insert_snap_realm(&mdsc->snap_realms, realm);
@@ -435,7 +438,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 {
        struct inode *inode = &ci->vfs_inode;
        struct ceph_cap_snap *capsnap;
-       int used;
+       int used, dirty;
 
        capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS);
        if (!capsnap) {
@@ -445,6 +448,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 
        spin_lock(&inode->i_lock);
        used = __ceph_caps_used(ci);
+       dirty = __ceph_caps_dirty(ci);
        if (__ceph_have_pending_cap_snap(ci)) {
                /* there is no point in queuing multiple "pending" cap_snaps,
                   as no new writes are allowed to start when pending, so any
@@ -452,27 +456,37 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
                   cap_snap.  lucky us. */
                dout("queue_cap_snap %p already pending\n", inode);
                kfree(capsnap);
-       } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) {
+       } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR) ||
+                  (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
+                            CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR))) {
                struct ceph_snap_context *snapc = ci->i_head_snapc;
 
+               dout("queue_cap_snap %p cap_snap %p queuing under %p\n", inode,
+                    capsnap, snapc);
                igrab(inode);
-
+               
                atomic_set(&capsnap->nref, 1);
                capsnap->ci = ci;
                INIT_LIST_HEAD(&capsnap->ci_item);
                INIT_LIST_HEAD(&capsnap->flushing_item);
 
-               capsnap->follows = snapc->seq - 1;
+               capsnap->follows = snapc->seq;
                capsnap->issued = __ceph_caps_issued(ci, NULL);
-               capsnap->dirty = __ceph_caps_dirty(ci);
+               capsnap->dirty = dirty;
 
                capsnap->mode = inode->i_mode;
                capsnap->uid = inode->i_uid;
                capsnap->gid = inode->i_gid;
 
-               /* fixme? */
-               capsnap->xattr_blob = NULL;
-               capsnap->xattr_len = 0;
+               if (dirty & CEPH_CAP_XATTR_EXCL) {
+                       __ceph_build_xattrs_blob(ci);
+                       capsnap->xattr_blob =
+                               ceph_buffer_get(ci->i_xattrs.blob);
+                       capsnap->xattr_version = ci->i_xattrs.version;
+               } else {
+                       capsnap->xattr_blob = NULL;
+                       capsnap->xattr_version = 0;
+               }
 
                /* dirty page count moved from _head to this cap_snap;
                   all subsequent writes page dirties occur _after_ this
@@ -480,7 +494,9 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
                capsnap->dirty_pages = ci->i_wrbuffer_ref_head;
                ci->i_wrbuffer_ref_head = 0;
                capsnap->context = snapc;
-               ci->i_head_snapc = NULL;
+               ci->i_head_snapc =
+                       ceph_get_snap_context(ci->i_snap_realm->cached_context);
+               dout(" new snapc is %p\n", ci->i_head_snapc);
                list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps);
 
                if (used & CEPH_CAP_FILE_WR) {
@@ -512,7 +528,7 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
                            struct ceph_cap_snap *capsnap)
 {
        struct inode *inode = &ci->vfs_inode;
-       struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 
        BUG_ON(capsnap->writing);
        capsnap->size = inode->i_size;
@@ -539,6 +555,41 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
        return 1;  /* caller may want to ceph_flush_snaps */
 }
 
+/*
+ * Queue cap_snaps for snap writeback for this realm and its children.
+ * Called under snap_rwsem, so realm topology won't change.
+ */
+static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
+{
+       struct ceph_inode_info *ci;
+       struct inode *lastinode = NULL;
+       struct ceph_snap_realm *child;
+
+       dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
+
+       spin_lock(&realm->inodes_with_caps_lock);
+       list_for_each_entry(ci, &realm->inodes_with_caps,
+                           i_snap_realm_item) {
+               struct inode *inode = igrab(&ci->vfs_inode);
+               if (!inode)
+                       continue;
+               spin_unlock(&realm->inodes_with_caps_lock);
+               if (lastinode)
+                       iput(lastinode);
+               lastinode = inode;
+               ceph_queue_cap_snap(ci);
+               spin_lock(&realm->inodes_with_caps_lock);
+       }
+       spin_unlock(&realm->inodes_with_caps_lock);
+       if (lastinode)
+               iput(lastinode);
+
+       dout("queue_realm_cap_snaps %p %llx children\n", realm, realm->ino);
+       list_for_each_entry(child, &realm->children, child_item)
+               queue_realm_cap_snaps(child);
+
+       dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
+}
 
 /*
  * Parse and apply a snapblob "snap trace" from the MDS.  This specifies
@@ -556,6 +607,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
        struct ceph_snap_realm *realm;
        int invalidate = 0;
        int err = -ENOMEM;
+       LIST_HEAD(dirty_realms);
 
        dout("update_snap_trace deletion=%d\n", deletion);
 more:
@@ -578,45 +630,6 @@ more:
                }
        }
 
-       if (le64_to_cpu(ri->seq) > realm->seq) {
-               dout("update_snap_trace updating %llx %p %lld -> %lld\n",
-                    realm->ino, realm, realm->seq, le64_to_cpu(ri->seq));
-               /*
-                * if the realm seq has changed, queue a cap_snap for every
-                * inode with open caps.  we do this _before_ we update
-                * the realm info so that we prepare for writeback under the
-                * _previous_ snap context.
-                *
-                * ...unless it's a snap deletion!
-                */
-               if (!deletion) {
-                       struct ceph_inode_info *ci;
-                       struct inode *lastinode = NULL;
-
-                       spin_lock(&realm->inodes_with_caps_lock);
-                       list_for_each_entry(ci, &realm->inodes_with_caps,
-                                           i_snap_realm_item) {
-                               struct inode *inode = igrab(&ci->vfs_inode);
-                               if (!inode)
-                                       continue;
-                               spin_unlock(&realm->inodes_with_caps_lock);
-                               if (lastinode)
-                                       iput(lastinode);
-                               lastinode = inode;
-                               ceph_queue_cap_snap(ci);
-                               spin_lock(&realm->inodes_with_caps_lock);
-                       }
-                       spin_unlock(&realm->inodes_with_caps_lock);
-                       if (lastinode)
-                               iput(lastinode);
-                       dout("update_snap_trace cap_snaps queued\n");
-               }
-
-       } else {
-               dout("update_snap_trace %llx %p seq %lld unchanged\n",
-                    realm->ino, realm, realm->seq);
-       }
-
        /* ensure the parent is correct */
        err = adjust_snap_realm_parent(mdsc, realm, le64_to_cpu(ri->parent));
        if (err < 0)
@@ -624,6 +637,8 @@ more:
        invalidate += err;
 
        if (le64_to_cpu(ri->seq) > realm->seq) {
+               dout("update_snap_trace updating %llx %p %lld -> %lld\n",
+                    realm->ino, realm, realm->seq, le64_to_cpu(ri->seq));
                /* update realm parameters, snap lists */
                realm->seq = le64_to_cpu(ri->seq);
                realm->created = le64_to_cpu(ri->created);
@@ -641,9 +656,17 @@ more:
                if (err < 0)
                        goto fail;
 
+               /* queue realm for cap_snap creation */
+               list_add(&realm->dirty_item, &dirty_realms);
+
                invalidate = 1;
        } else if (!realm->cached_context) {
+               dout("update_snap_trace %llx %p seq %lld new\n",
+                    realm->ino, realm, realm->seq);
                invalidate = 1;
+       } else {
+               dout("update_snap_trace %llx %p seq %lld unchanged\n",
+                    realm->ino, realm, realm->seq);
        }
 
        dout("done with %llx %p, invalidated=%d, %p %p\n", realm->ino,
@@ -656,6 +679,14 @@ more:
        if (invalidate)
                rebuild_snap_realms(realm);
 
+       /*
+        * queue cap snaps _after_ we've built the new snap contexts,
+        * so that i_head_snapc can be set appropriately.
+        */
+       list_for_each_entry(realm, &dirty_realms, dirty_item) {
+               queue_realm_cap_snaps(realm);
+       }
+
        __cleanup_empty_realms(mdsc);
        return 0;
 
@@ -688,7 +719,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
                igrab(inode);
                spin_unlock(&mdsc->snap_flush_lock);
                spin_lock(&inode->i_lock);
-               __ceph_flush_snaps(ci, &session);
+               __ceph_flush_snaps(ci, &session, 0);
                spin_unlock(&inode->i_lock);
                iput(inode);
                spin_lock(&mdsc->snap_flush_lock);
@@ -718,7 +749,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                      struct ceph_mds_session *session,
                      struct ceph_msg *msg)
 {
-       struct super_block *sb = mdsc->client->sb;
+       struct super_block *sb = mdsc->fsc->sb;
        int mds = session->s_mds;
        u64 split;
        int op;
@@ -789,6 +820,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        };
                        struct inode *inode = ceph_find_inode(sb, vino);
                        struct ceph_inode_info *ci;
+                       struct ceph_snap_realm *oldrealm;
 
                        if (!inode)
                                continue;
@@ -814,18 +846,19 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        dout(" will move %p to split realm %llx %p\n",
                             inode, realm->ino, realm);
                        /*
-                        * Remove the inode from the realm's inode
-                        * list, but don't add it to the new realm
-                        * yet.  We don't want the cap_snap to be
-                        * queued (again) by ceph_update_snap_trace()
-                        * below.  Queue it _now_, under the old context.
+                        * Move the inode to the new realm
                         */
                        spin_lock(&realm->inodes_with_caps_lock);
                        list_del_init(&ci->i_snap_realm_item);
+                       list_add(&ci->i_snap_realm_item,
+                                &realm->inodes_with_caps);
+                       oldrealm = ci->i_snap_realm;
+                       ci->i_snap_realm = realm;
                        spin_unlock(&realm->inodes_with_caps_lock);
                        spin_unlock(&inode->i_lock);
 
-                       ceph_queue_cap_snap(ci);
+                       ceph_get_snap_realm(mdsc, realm);
+                       ceph_put_snap_realm(mdsc, oldrealm);
 
                        iput(inode);
                        continue;
@@ -853,43 +886,9 @@ skip_inode:
        ceph_update_snap_trace(mdsc, p, e,
                               op == CEPH_SNAP_OP_DESTROY);
 
-       if (op == CEPH_SNAP_OP_SPLIT) {
-               /*
-                * ok, _now_ add the inodes into the new realm.
-                */
-               for (i = 0; i < num_split_inos; i++) {
-                       struct ceph_vino vino = {
-                               .ino = le64_to_cpu(split_inos[i]),
-                               .snap = CEPH_NOSNAP,
-                       };
-                       struct inode *inode = ceph_find_inode(sb, vino);
-                       struct ceph_inode_info *ci;
-
-                       if (!inode)
-                               continue;
-                       ci = ceph_inode(inode);
-                       spin_lock(&inode->i_lock);
-                       if (list_empty(&ci->i_snap_realm_item)) {
-                               struct ceph_snap_realm *oldrealm =
-                                       ci->i_snap_realm;
-
-                               dout(" moving %p to split realm %llx %p\n",
-                                    inode, realm->ino, realm);
-                               spin_lock(&realm->inodes_with_caps_lock);
-                               list_add(&ci->i_snap_realm_item,
-                                        &realm->inodes_with_caps);
-                               ci->i_snap_realm = realm;
-                               spin_unlock(&realm->inodes_with_caps_lock);
-                               ceph_get_snap_realm(mdsc, realm);
-                               ceph_put_snap_realm(mdsc, oldrealm);
-                       }
-                       spin_unlock(&inode->i_lock);
-                       iput(inode);
-               }
-
+       if (op == CEPH_SNAP_OP_SPLIT)
                /* we took a reference when we created the realm, above */
                ceph_put_snap_realm(mdsc, realm);
-       }
 
        __cleanup_empty_realms(mdsc);
 
similarity index 59%
rename from fs/ceph/ceph_strings.c
rename to fs/ceph/strings.c
index c6179d3a26a216cb7b8f6ee0119884162887c778..cd5097d7c804e5897eeed60716c962d1bbd59b5c 100644 (file)
@@ -1,71 +1,9 @@
 /*
- * Ceph string constants
+ * Ceph fs string constants
  */
-#include "types.h"
+#include <linux/module.h>
+#include <linux/ceph/types.h>
 
-const char *ceph_entity_type_name(int type)
-{
-       switch (type) {
-       case CEPH_ENTITY_TYPE_MDS: return "mds";
-       case CEPH_ENTITY_TYPE_OSD: return "osd";
-       case CEPH_ENTITY_TYPE_MON: return "mon";
-       case CEPH_ENTITY_TYPE_CLIENT: return "client";
-       case CEPH_ENTITY_TYPE_AUTH: return "auth";
-       default: return "unknown";
-       }
-}
-
-const char *ceph_osd_op_name(int op)
-{
-       switch (op) {
-       case CEPH_OSD_OP_READ: return "read";
-       case CEPH_OSD_OP_STAT: return "stat";
-
-       case CEPH_OSD_OP_MASKTRUNC: return "masktrunc";
-
-       case CEPH_OSD_OP_WRITE: return "write";
-       case CEPH_OSD_OP_DELETE: return "delete";
-       case CEPH_OSD_OP_TRUNCATE: return "truncate";
-       case CEPH_OSD_OP_ZERO: return "zero";
-       case CEPH_OSD_OP_WRITEFULL: return "writefull";
-       case CEPH_OSD_OP_ROLLBACK: return "rollback";
-
-       case CEPH_OSD_OP_APPEND: return "append";
-       case CEPH_OSD_OP_STARTSYNC: return "startsync";
-       case CEPH_OSD_OP_SETTRUNC: return "settrunc";
-       case CEPH_OSD_OP_TRIMTRUNC: return "trimtrunc";
-
-       case CEPH_OSD_OP_TMAPUP: return "tmapup";
-       case CEPH_OSD_OP_TMAPGET: return "tmapget";
-       case CEPH_OSD_OP_TMAPPUT: return "tmapput";
-
-       case CEPH_OSD_OP_GETXATTR: return "getxattr";
-       case CEPH_OSD_OP_GETXATTRS: return "getxattrs";
-       case CEPH_OSD_OP_SETXATTR: return "setxattr";
-       case CEPH_OSD_OP_SETXATTRS: return "setxattrs";
-       case CEPH_OSD_OP_RESETXATTRS: return "resetxattrs";
-       case CEPH_OSD_OP_RMXATTR: return "rmxattr";
-       case CEPH_OSD_OP_CMPXATTR: return "cmpxattr";
-
-       case CEPH_OSD_OP_PULL: return "pull";
-       case CEPH_OSD_OP_PUSH: return "push";
-       case CEPH_OSD_OP_BALANCEREADS: return "balance-reads";
-       case CEPH_OSD_OP_UNBALANCEREADS: return "unbalance-reads";
-       case CEPH_OSD_OP_SCRUB: return "scrub";
-
-       case CEPH_OSD_OP_WRLOCK: return "wrlock";
-       case CEPH_OSD_OP_WRUNLOCK: return "wrunlock";
-       case CEPH_OSD_OP_RDLOCK: return "rdlock";
-       case CEPH_OSD_OP_RDUNLOCK: return "rdunlock";
-       case CEPH_OSD_OP_UPLOCK: return "uplock";
-       case CEPH_OSD_OP_DNLOCK: return "dnlock";
-
-       case CEPH_OSD_OP_CALL: return "call";
-
-       case CEPH_OSD_OP_PGLS: return "pgls";
-       }
-       return "???";
-}
 
 const char *ceph_mds_state_name(int s)
 {
@@ -177,17 +115,3 @@ const char *ceph_snap_op_name(int o)
        }
        return "???";
 }
-
-const char *ceph_pool_op_name(int op)
-{
-       switch (op) {
-       case POOL_OP_CREATE: return "create";
-       case POOL_OP_DELETE: return "delete";
-       case POOL_OP_AUID_CHANGE: return "auid change";
-       case POOL_OP_CREATE_SNAP: return "create snap";
-       case POOL_OP_DELETE_SNAP: return "delete snap";
-       case POOL_OP_CREATE_UNMANAGED_SNAP: return "create unmanaged snap";
-       case POOL_OP_DELETE_UNMANAGED_SNAP: return "delete unmanaged snap";
-       }
-       return "???";
-}
index 9922628532b2c649dee6761710405adc552ca248..d6e0e042189184183b4ccf82da8787622e7f7d11 100644 (file)
@@ -1,5 +1,5 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/backing-dev.h>
 #include <linux/ctype.h>
 #include <linux/statfs.h>
 #include <linux/string.h>
 
-#include "decode.h"
 #include "super.h"
-#include "mon_client.h"
-#include "auth.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
 
 /*
  * Ceph superblock operations
  * Handle the basics of mounting, unmounting.
  */
 
-
-/*
- * find filename portion of a path (/foo/bar/baz -> baz)
- */
-const char *ceph_file_part(const char *s, int len)
-{
-       const char *e = s + len;
-
-       while (e != s && *(e-1) != '/')
-               e--;
-       return e;
-}
-
-
 /*
  * super ops
  */
 static void ceph_put_super(struct super_block *s)
 {
-       struct ceph_client *client = ceph_sb_to_client(s);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(s);
 
        dout("put_super\n");
-       ceph_mdsc_close_sessions(&client->mdsc);
+       ceph_mdsc_close_sessions(fsc->mdsc);
 
        /*
         * ensure we release the bdi before put_anon_super releases
         * the device name.
         */
-       if (s->s_bdi == &client->backing_dev_info) {
-               bdi_unregister(&client->backing_dev_info);
+       if (s->s_bdi == &fsc->backing_dev_info) {
+               bdi_unregister(&fsc->backing_dev_info);
                s->s_bdi = NULL;
        }
 
@@ -64,14 +53,14 @@ static void ceph_put_super(struct super_block *s)
 
 static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct ceph_client *client = ceph_inode_to_client(dentry->d_inode);
-       struct ceph_monmap *monmap = client->monc.monmap;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
+       struct ceph_monmap *monmap = fsc->client->monc.monmap;
        struct ceph_statfs st;
        u64 fsid;
        int err;
 
        dout("statfs\n");
-       err = ceph_monc_do_statfs(&client->monc, &st);
+       err = ceph_monc_do_statfs(&fsc->client->monc, &st);
        if (err < 0)
                return err;
 
@@ -104,238 +93,28 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 static int ceph_sync_fs(struct super_block *sb, int wait)
 {
-       struct ceph_client *client = ceph_sb_to_client(sb);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
 
        if (!wait) {
                dout("sync_fs (non-blocking)\n");
-               ceph_flush_dirty_caps(&client->mdsc);
+               ceph_flush_dirty_caps(fsc->mdsc);
                dout("sync_fs (non-blocking) done\n");
                return 0;
        }
 
        dout("sync_fs (blocking)\n");
-       ceph_osdc_sync(&ceph_sb_to_client(sb)->osdc);
-       ceph_mdsc_sync(&ceph_sb_to_client(sb)->mdsc);
+       ceph_osdc_sync(&fsc->client->osdc);
+       ceph_mdsc_sync(fsc->mdsc);
        dout("sync_fs (blocking) done\n");
        return 0;
 }
 
-static int default_congestion_kb(void)
-{
-       int congestion_kb;
-
-       /*
-        * Copied from NFS
-        *
-        * congestion size, scale with available memory.
-        *
-        *  64MB:    8192k
-        * 128MB:   11585k
-        * 256MB:   16384k
-        * 512MB:   23170k
-        *   1GB:   32768k
-        *   2GB:   46340k
-        *   4GB:   65536k
-        *   8GB:   92681k
-        *  16GB:  131072k
-        *
-        * This allows larger machines to have larger/more transfers.
-        * Limit the default to 256M
-        */
-       congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
-       if (congestion_kb > 256*1024)
-               congestion_kb = 256*1024;
-
-       return congestion_kb;
-}
-
-/**
- * ceph_show_options - Show mount options in /proc/mounts
- * @m: seq_file to write to
- * @mnt: mount descriptor
- */
-static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
-{
-       struct ceph_client *client = ceph_sb_to_client(mnt->mnt_sb);
-       struct ceph_mount_args *args = client->mount_args;
-
-       if (args->flags & CEPH_OPT_FSID)
-               seq_printf(m, ",fsid=%pU", &args->fsid);
-       if (args->flags & CEPH_OPT_NOSHARE)
-               seq_puts(m, ",noshare");
-       if (args->flags & CEPH_OPT_DIRSTAT)
-               seq_puts(m, ",dirstat");
-       if ((args->flags & CEPH_OPT_RBYTES) == 0)
-               seq_puts(m, ",norbytes");
-       if (args->flags & CEPH_OPT_NOCRC)
-               seq_puts(m, ",nocrc");
-       if (args->flags & CEPH_OPT_NOASYNCREADDIR)
-               seq_puts(m, ",noasyncreaddir");
-
-       if (args->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
-               seq_printf(m, ",mount_timeout=%d", args->mount_timeout);
-       if (args->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
-               seq_printf(m, ",osd_idle_ttl=%d", args->osd_idle_ttl);
-       if (args->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
-               seq_printf(m, ",osdtimeout=%d", args->osd_timeout);
-       if (args->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
-               seq_printf(m, ",osdkeepalivetimeout=%d",
-                        args->osd_keepalive_timeout);
-       if (args->wsize)
-               seq_printf(m, ",wsize=%d", args->wsize);
-       if (args->rsize != CEPH_MOUNT_RSIZE_DEFAULT)
-               seq_printf(m, ",rsize=%d", args->rsize);
-       if (args->congestion_kb != default_congestion_kb())
-               seq_printf(m, ",write_congestion_kb=%d", args->congestion_kb);
-       if (args->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_min=%d",
-                        args->caps_wanted_delay_min);
-       if (args->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_max=%d",
-                          args->caps_wanted_delay_max);
-       if (args->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
-               seq_printf(m, ",cap_release_safety=%d",
-                          args->cap_release_safety);
-       if (args->max_readdir != CEPH_MAX_READDIR_DEFAULT)
-               seq_printf(m, ",readdir_max_entries=%d", args->max_readdir);
-       if (args->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
-               seq_printf(m, ",readdir_max_bytes=%d", args->max_readdir_bytes);
-       if (strcmp(args->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
-               seq_printf(m, ",snapdirname=%s", args->snapdir_name);
-       if (args->name)
-               seq_printf(m, ",name=%s", args->name);
-       if (args->secret)
-               seq_puts(m, ",secret=<hidden>");
-       return 0;
-}
-
-/*
- * caches
- */
-struct kmem_cache *ceph_inode_cachep;
-struct kmem_cache *ceph_cap_cachep;
-struct kmem_cache *ceph_dentry_cachep;
-struct kmem_cache *ceph_file_cachep;
-
-static void ceph_inode_init_once(void *foo)
-{
-       struct ceph_inode_info *ci = foo;
-       inode_init_once(&ci->vfs_inode);
-}
-
-static int __init init_caches(void)
-{
-       ceph_inode_cachep = kmem_cache_create("ceph_inode_info",
-                                     sizeof(struct ceph_inode_info),
-                                     __alignof__(struct ceph_inode_info),
-                                     (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
-                                     ceph_inode_init_once);
-       if (ceph_inode_cachep == NULL)
-               return -ENOMEM;
-
-       ceph_cap_cachep = KMEM_CACHE(ceph_cap,
-                                    SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
-       if (ceph_cap_cachep == NULL)
-               goto bad_cap;
-
-       ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info,
-                                       SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
-       if (ceph_dentry_cachep == NULL)
-               goto bad_dentry;
-
-       ceph_file_cachep = KMEM_CACHE(ceph_file_info,
-                                     SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
-       if (ceph_file_cachep == NULL)
-               goto bad_file;
-
-       return 0;
-
-bad_file:
-       kmem_cache_destroy(ceph_dentry_cachep);
-bad_dentry:
-       kmem_cache_destroy(ceph_cap_cachep);
-bad_cap:
-       kmem_cache_destroy(ceph_inode_cachep);
-       return -ENOMEM;
-}
-
-static void destroy_caches(void)
-{
-       kmem_cache_destroy(ceph_inode_cachep);
-       kmem_cache_destroy(ceph_cap_cachep);
-       kmem_cache_destroy(ceph_dentry_cachep);
-       kmem_cache_destroy(ceph_file_cachep);
-}
-
-
-/*
- * ceph_umount_begin - initiate forced umount.  Tear down down the
- * mount, skipping steps that may hang while waiting for server(s).
- */
-static void ceph_umount_begin(struct super_block *sb)
-{
-       struct ceph_client *client = ceph_sb_to_client(sb);
-
-       dout("ceph_umount_begin - starting forced umount\n");
-       if (!client)
-               return;
-       client->mount_state = CEPH_MOUNT_SHUTDOWN;
-       return;
-}
-
-static const struct super_operations ceph_super_ops = {
-       .alloc_inode    = ceph_alloc_inode,
-       .destroy_inode  = ceph_destroy_inode,
-       .write_inode    = ceph_write_inode,
-       .sync_fs        = ceph_sync_fs,
-       .put_super      = ceph_put_super,
-       .show_options   = ceph_show_options,
-       .statfs         = ceph_statfs,
-       .umount_begin   = ceph_umount_begin,
-};
-
-
-const char *ceph_msg_type_name(int type)
-{
-       switch (type) {
-       case CEPH_MSG_SHUTDOWN: return "shutdown";
-       case CEPH_MSG_PING: return "ping";
-       case CEPH_MSG_AUTH: return "auth";
-       case CEPH_MSG_AUTH_REPLY: return "auth_reply";
-       case CEPH_MSG_MON_MAP: return "mon_map";
-       case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
-       case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
-       case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
-       case CEPH_MSG_STATFS: return "statfs";
-       case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
-       case CEPH_MSG_MDS_MAP: return "mds_map";
-       case CEPH_MSG_CLIENT_SESSION: return "client_session";
-       case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
-       case CEPH_MSG_CLIENT_REQUEST: return "client_request";
-       case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
-       case CEPH_MSG_CLIENT_REPLY: return "client_reply";
-       case CEPH_MSG_CLIENT_CAPS: return "client_caps";
-       case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
-       case CEPH_MSG_CLIENT_SNAP: return "client_snap";
-       case CEPH_MSG_CLIENT_LEASE: return "client_lease";
-       case CEPH_MSG_OSD_MAP: return "osd_map";
-       case CEPH_MSG_OSD_OP: return "osd_op";
-       case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
-       default: return "unknown";
-       }
-}
-
-
 /*
  * mount options
  */
 enum {
        Opt_wsize,
        Opt_rsize,
-       Opt_osdtimeout,
-       Opt_osdkeepalivetimeout,
-       Opt_mount_timeout,
-       Opt_osd_idle_ttl,
        Opt_caps_wanted_delay_min,
        Opt_caps_wanted_delay_max,
        Opt_cap_release_safety,
@@ -344,29 +123,19 @@ enum {
        Opt_congestion_kb,
        Opt_last_int,
        /* int args above */
-       Opt_fsid,
        Opt_snapdirname,
-       Opt_name,
-       Opt_secret,
        Opt_last_string,
        /* string args above */
-       Opt_ip,
-       Opt_noshare,
        Opt_dirstat,
        Opt_nodirstat,
        Opt_rbytes,
        Opt_norbytes,
-       Opt_nocrc,
        Opt_noasyncreaddir,
 };
 
-static match_table_t arg_tokens = {
+static match_table_t fsopt_tokens = {
        {Opt_wsize, "wsize=%d"},
        {Opt_rsize, "rsize=%d"},
-       {Opt_osdtimeout, "osdtimeout=%d"},
-       {Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
-       {Opt_mount_timeout, "mount_timeout=%d"},
-       {Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
        {Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
        {Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
        {Opt_cap_release_safety, "cap_release_safety=%d"},
@@ -374,403 +143,459 @@ static match_table_t arg_tokens = {
        {Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
        {Opt_congestion_kb, "write_congestion_kb=%d"},
        /* int args above */
-       {Opt_fsid, "fsid=%s"},
        {Opt_snapdirname, "snapdirname=%s"},
-       {Opt_name, "name=%s"},
-       {Opt_secret, "secret=%s"},
        /* string args above */
-       {Opt_ip, "ip=%s"},
-       {Opt_noshare, "noshare"},
        {Opt_dirstat, "dirstat"},
        {Opt_nodirstat, "nodirstat"},
        {Opt_rbytes, "rbytes"},
        {Opt_norbytes, "norbytes"},
-       {Opt_nocrc, "nocrc"},
        {Opt_noasyncreaddir, "noasyncreaddir"},
        {-1, NULL}
 };
 
-static int parse_fsid(const char *str, struct ceph_fsid *fsid)
+static int parse_fsopt_token(char *c, void *private)
 {
-       int i = 0;
-       char tmp[3];
-       int err = -EINVAL;
-       int d;
-
-       dout("parse_fsid '%s'\n", str);
-       tmp[2] = 0;
-       while (*str && i < 16) {
-               if (ispunct(*str)) {
-                       str++;
-                       continue;
+       struct ceph_mount_options *fsopt = private;
+       substring_t argstr[MAX_OPT_ARGS];
+       int token, intval, ret;
+
+       token = match_token((char *)c, fsopt_tokens, argstr);
+       if (token < 0)
+               return -EINVAL;
+
+       if (token < Opt_last_int) {
+               ret = match_int(&argstr[0], &intval);
+               if (ret < 0) {
+                       pr_err("bad mount option arg (not int) "
+                              "at '%s'\n", c);
+                       return ret;
                }
-               if (!isxdigit(str[0]) || !isxdigit(str[1]))
-                       break;
-               tmp[0] = str[0];
-               tmp[1] = str[1];
-               if (sscanf(tmp, "%x", &d) < 1)
-                       break;
-               fsid->fsid[i] = d & 0xff;
-               i++;
-               str += 2;
+               dout("got int token %d val %d\n", token, intval);
+       } else if (token > Opt_last_int && token < Opt_last_string) {
+               dout("got string token %d val %s\n", token,
+                    argstr[0].from);
+       } else {
+               dout("got token %d\n", token);
        }
 
-       if (i == 16)
-               err = 0;
-       dout("parse_fsid ret %d got fsid %pU", err, fsid);
-       return err;
+       switch (token) {
+       case Opt_snapdirname:
+               kfree(fsopt->snapdir_name);
+               fsopt->snapdir_name = kstrndup(argstr[0].from,
+                                              argstr[0].to-argstr[0].from,
+                                              GFP_KERNEL);
+               if (!fsopt->snapdir_name)
+                       return -ENOMEM;
+               break;
+
+               /* misc */
+       case Opt_wsize:
+               fsopt->wsize = intval;
+               break;
+       case Opt_rsize:
+               fsopt->rsize = intval;
+               break;
+       case Opt_caps_wanted_delay_min:
+               fsopt->caps_wanted_delay_min = intval;
+               break;
+       case Opt_caps_wanted_delay_max:
+               fsopt->caps_wanted_delay_max = intval;
+               break;
+       case Opt_readdir_max_entries:
+               fsopt->max_readdir = intval;
+               break;
+       case Opt_readdir_max_bytes:
+               fsopt->max_readdir_bytes = intval;
+               break;
+       case Opt_congestion_kb:
+               fsopt->congestion_kb = intval;
+               break;
+       case Opt_dirstat:
+               fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
+               break;
+       case Opt_nodirstat:
+               fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
+               break;
+       case Opt_rbytes:
+               fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
+               break;
+       case Opt_norbytes:
+               fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
+               break;
+       case Opt_noasyncreaddir:
+               fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
+               break;
+       default:
+               BUG_ON(token);
+       }
+       return 0;
 }
 
-static struct ceph_mount_args *parse_mount_args(int flags, char *options,
-                                               const char *dev_name,
-                                               const char **path)
+static void destroy_mount_options(struct ceph_mount_options *args)
 {
-       struct ceph_mount_args *args;
-       const char *c;
-       int err = -ENOMEM;
-       substring_t argstr[MAX_OPT_ARGS];
+       dout("destroy_mount_options %p\n", args);
+       kfree(args->snapdir_name);
+       kfree(args);
+}
 
-       args = kzalloc(sizeof(*args), GFP_KERNEL);
-       if (!args)
-               return ERR_PTR(-ENOMEM);
-       args->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*args->mon_addr),
-                                GFP_KERNEL);
-       if (!args->mon_addr)
-               goto out;
+static int strcmp_null(const char *s1, const char *s2)
+{
+       if (!s1 && !s2)
+               return 0;
+       if (s1 && !s2)
+               return -1;
+       if (!s1 && s2)
+               return 1;
+       return strcmp(s1, s2);
+}
 
-       dout("parse_mount_args %p, dev_name '%s'\n", args, dev_name);
-
-       /* start with defaults */
-       args->sb_flags = flags;
-       args->flags = CEPH_OPT_DEFAULT;
-       args->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
-       args->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
-       args->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
-       args->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
-       args->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
-       args->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
-       args->rsize = CEPH_MOUNT_RSIZE_DEFAULT;
-       args->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
-       args->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
-       args->max_readdir = CEPH_MAX_READDIR_DEFAULT;
-       args->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
-       args->congestion_kb = default_congestion_kb();
-
-       /* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
-       err = -EINVAL;
-       if (!dev_name)
-               goto out;
-       *path = strstr(dev_name, ":/");
-       if (*path == NULL) {
-               pr_err("device name is missing path (no :/ in %s)\n",
-                      dev_name);
-               goto out;
-       }
+static int compare_mount_options(struct ceph_mount_options *new_fsopt,
+                                struct ceph_options *new_opt,
+                                struct ceph_fs_client *fsc)
+{
+       struct ceph_mount_options *fsopt1 = new_fsopt;
+       struct ceph_mount_options *fsopt2 = fsc->mount_options;
+       int ofs = offsetof(struct ceph_mount_options, snapdir_name);
+       int ret;
 
-       /* get mon ip(s) */
-       err = ceph_parse_ips(dev_name, *path, args->mon_addr,
-                            CEPH_MAX_MON, &args->num_mon);
-       if (err < 0)
-               goto out;
+       ret = memcmp(fsopt1, fsopt2, ofs);
+       if (ret)
+               return ret;
+
+       ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
+       if (ret)
+               return ret;
+
+       return ceph_compare_options(new_opt, fsc->client);
+}
+
+static int parse_mount_options(struct ceph_mount_options **pfsopt,
+                              struct ceph_options **popt,
+                              int flags, char *options,
+                              const char *dev_name,
+                              const char **path)
+{
+       struct ceph_mount_options *fsopt;
+       const char *dev_name_end;
+       int err = -ENOMEM;
+
+       fsopt = kzalloc(sizeof(*fsopt), GFP_KERNEL);
+       if (!fsopt)
+               return -ENOMEM;
+
+       dout("parse_mount_options %p, dev_name '%s'\n", fsopt, dev_name);
+
+        fsopt->sb_flags = flags;
+        fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
+
+        fsopt->rsize = CEPH_MOUNT_RSIZE_DEFAULT;
+        fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
+        fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
+        fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT;
+        fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
+        fsopt->congestion_kb = default_congestion_kb();
+       
+        /* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
+        err = -EINVAL;
+        if (!dev_name)
+                goto out;
+        *path = strstr(dev_name, ":/");
+        if (*path == NULL) {
+                pr_err("device name is missing path (no :/ in %s)\n",
+                       dev_name);
+                goto out;
+        }
+       dev_name_end = *path;
+       dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
 
        /* path on server */
        *path += 2;
        dout("server path '%s'\n", *path);
 
-       /* parse mount options */
-       while ((c = strsep(&options, ",")) != NULL) {
-               int token, intval, ret;
-               if (!*c)
-                       continue;
-               err = -EINVAL;
-               token = match_token((char *)c, arg_tokens, argstr);
-               if (token < 0) {
-                       pr_err("bad mount option at '%s'\n", c);
-                       goto out;
-               }
-               if (token < Opt_last_int) {
-                       ret = match_int(&argstr[0], &intval);
-                       if (ret < 0) {
-                               pr_err("bad mount option arg (not int) "
-                                      "at '%s'\n", c);
-                               continue;
-                       }
-                       dout("got int token %d val %d\n", token, intval);
-               } else if (token > Opt_last_int && token < Opt_last_string) {
-                       dout("got string token %d val %s\n", token,
-                            argstr[0].from);
-               } else {
-                       dout("got token %d\n", token);
-               }
-               switch (token) {
-               case Opt_ip:
-                       err = ceph_parse_ips(argstr[0].from,
-                                            argstr[0].to,
-                                            &args->my_addr,
-                                            1, NULL);
-                       if (err < 0)
-                               goto out;
-                       args->flags |= CEPH_OPT_MYIP;
-                       break;
-
-               case Opt_fsid:
-                       err = parse_fsid(argstr[0].from, &args->fsid);
-                       if (err == 0)
-                               args->flags |= CEPH_OPT_FSID;
-                       break;
-               case Opt_snapdirname:
-                       kfree(args->snapdir_name);
-                       args->snapdir_name = kstrndup(argstr[0].from,
-                                             argstr[0].to-argstr[0].from,
-                                             GFP_KERNEL);
-                       break;
-               case Opt_name:
-                       args->name = kstrndup(argstr[0].from,
-                                             argstr[0].to-argstr[0].from,
-                                             GFP_KERNEL);
-                       break;
-               case Opt_secret:
-                       args->secret = kstrndup(argstr[0].from,
-                                               argstr[0].to-argstr[0].from,
-                                               GFP_KERNEL);
-                       break;
-
-                       /* misc */
-               case Opt_wsize:
-                       args->wsize = intval;
-                       break;
-               case Opt_rsize:
-                       args->rsize = intval;
-                       break;
-               case Opt_osdtimeout:
-                       args->osd_timeout = intval;
-                       break;
-               case Opt_osdkeepalivetimeout:
-                       args->osd_keepalive_timeout = intval;
-                       break;
-               case Opt_osd_idle_ttl:
-                       args->osd_idle_ttl = intval;
-                       break;
-               case Opt_mount_timeout:
-                       args->mount_timeout = intval;
-                       break;
-               case Opt_caps_wanted_delay_min:
-                       args->caps_wanted_delay_min = intval;
-                       break;
-               case Opt_caps_wanted_delay_max:
-                       args->caps_wanted_delay_max = intval;
-                       break;
-               case Opt_readdir_max_entries:
-                       args->max_readdir = intval;
-                       break;
-               case Opt_readdir_max_bytes:
-                       args->max_readdir_bytes = intval;
-                       break;
-               case Opt_congestion_kb:
-                       args->congestion_kb = intval;
-                       break;
-
-               case Opt_noshare:
-                       args->flags |= CEPH_OPT_NOSHARE;
-                       break;
-
-               case Opt_dirstat:
-                       args->flags |= CEPH_OPT_DIRSTAT;
-                       break;
-               case Opt_nodirstat:
-                       args->flags &= ~CEPH_OPT_DIRSTAT;
-                       break;
-               case Opt_rbytes:
-                       args->flags |= CEPH_OPT_RBYTES;
-                       break;
-               case Opt_norbytes:
-                       args->flags &= ~CEPH_OPT_RBYTES;
-                       break;
-               case Opt_nocrc:
-                       args->flags |= CEPH_OPT_NOCRC;
-                       break;
-               case Opt_noasyncreaddir:
-                       args->flags |= CEPH_OPT_NOASYNCREADDIR;
-                       break;
-
-               default:
-                       BUG_ON(token);
-               }
-       }
-       return args;
+       err = ceph_parse_options(popt, options, dev_name, dev_name_end,
+                                parse_fsopt_token, (void *)fsopt);
+       if (err)
+               goto out;
+
+       /* success */
+       *pfsopt = fsopt;
+       return 0;
 
 out:
-       kfree(args->mon_addr);
-       kfree(args);
-       return ERR_PTR(err);
+       destroy_mount_options(fsopt);
+       return err;
 }
 
-static void destroy_mount_args(struct ceph_mount_args *args)
+/**
+ * ceph_show_options - Show mount options in /proc/mounts
+ * @m: seq_file to write to
+ * @mnt: mount descriptor
+ */
+static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
 {
-       dout("destroy_mount_args %p\n", args);
-       kfree(args->snapdir_name);
-       args->snapdir_name = NULL;
-       kfree(args->name);
-       args->name = NULL;
-       kfree(args->secret);
-       args->secret = NULL;
-       kfree(args);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(mnt->mnt_sb);
+       struct ceph_mount_options *fsopt = fsc->mount_options;
+       struct ceph_options *opt = fsc->client->options;
+
+       if (opt->flags & CEPH_OPT_FSID)
+               seq_printf(m, ",fsid=%pU", &opt->fsid);
+       if (opt->flags & CEPH_OPT_NOSHARE)
+               seq_puts(m, ",noshare");
+       if (opt->flags & CEPH_OPT_NOCRC)
+               seq_puts(m, ",nocrc");
+
+       if (opt->name)
+               seq_printf(m, ",name=%s", opt->name);
+       if (opt->secret)
+               seq_puts(m, ",secret=<hidden>");
+
+       if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
+               seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
+       if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
+               seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
+       if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
+               seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
+       if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
+               seq_printf(m, ",osdkeepalivetimeout=%d",
+                          opt->osd_keepalive_timeout);
+
+       if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
+               seq_puts(m, ",dirstat");
+       if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES) == 0)
+               seq_puts(m, ",norbytes");
+       if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
+               seq_puts(m, ",noasyncreaddir");
+
+       if (fsopt->wsize)
+               seq_printf(m, ",wsize=%d", fsopt->wsize);
+       if (fsopt->rsize != CEPH_MOUNT_RSIZE_DEFAULT)
+               seq_printf(m, ",rsize=%d", fsopt->rsize);
+       if (fsopt->congestion_kb != default_congestion_kb())
+               seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
+       if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
+               seq_printf(m, ",caps_wanted_delay_min=%d",
+                        fsopt->caps_wanted_delay_min);
+       if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
+               seq_printf(m, ",caps_wanted_delay_max=%d",
+                          fsopt->caps_wanted_delay_max);
+       if (fsopt->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
+               seq_printf(m, ",cap_release_safety=%d",
+                          fsopt->cap_release_safety);
+       if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
+               seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
+       if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
+               seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
+       if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
+               seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
+       return 0;
 }
 
 /*
- * create a fresh client instance
+ * handle any mon messages the standard library doesn't understand.
+ * return error if we don't either.
  */
-static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
+static int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg)
 {
-       struct ceph_client *client;
+       struct ceph_fs_client *fsc = client->private;
+       int type = le16_to_cpu(msg->hdr.type);
+
+       switch (type) {
+       case CEPH_MSG_MDS_MAP:
+               ceph_mdsc_handle_map(fsc->mdsc, msg);
+               return 0;
+
+       default:
+               return -1;
+       }
+}
+
+/*
+ * create a new fs client
+ */
+struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
+                                       struct ceph_options *opt)
+{
+       struct ceph_fs_client *fsc;
        int err = -ENOMEM;
 
-       client = kzalloc(sizeof(*client), GFP_KERNEL);
-       if (client == NULL)
+       fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
+       if (!fsc)
                return ERR_PTR(-ENOMEM);
 
-       mutex_init(&client->mount_mutex);
-
-       init_waitqueue_head(&client->auth_wq);
+       fsc->client = ceph_create_client(opt, fsc);
+       if (IS_ERR(fsc->client)) {
+               err = PTR_ERR(fsc->client);
+               goto fail;
+       }
+       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
+       fsc->client->supported_features |= CEPH_FEATURE_FLOCK;
+       fsc->client->monc.want_mdsmap = 1;
 
-       client->sb = NULL;
-       client->mount_state = CEPH_MOUNT_MOUNTING;
-       client->mount_args = args;
+       fsc->mount_options = fsopt;
 
-       client->msgr = NULL;
+       fsc->sb = NULL;
+       fsc->mount_state = CEPH_MOUNT_MOUNTING;
 
-       client->auth_err = 0;
-       atomic_long_set(&client->writeback_count, 0);
+       atomic_long_set(&fsc->writeback_count, 0);
 
-       err = bdi_init(&client->backing_dev_info);
+       err = bdi_init(&fsc->backing_dev_info);
        if (err < 0)
-               goto fail;
+               goto fail_client;
 
        err = -ENOMEM;
-       client->wb_wq = create_workqueue("ceph-writeback");
-       if (client->wb_wq == NULL)
+       fsc->wb_wq = create_workqueue("ceph-writeback");
+       if (fsc->wb_wq == NULL)
                goto fail_bdi;
-       client->pg_inv_wq = create_singlethread_workqueue("ceph-pg-invalid");
-       if (client->pg_inv_wq == NULL)
+       fsc->pg_inv_wq = create_singlethread_workqueue("ceph-pg-invalid");
+       if (fsc->pg_inv_wq == NULL)
                goto fail_wb_wq;
-       client->trunc_wq = create_singlethread_workqueue("ceph-trunc");
-       if (client->trunc_wq == NULL)
+       fsc->trunc_wq = create_singlethread_workqueue("ceph-trunc");
+       if (fsc->trunc_wq == NULL)
                goto fail_pg_inv_wq;
 
        /* set up mempools */
        err = -ENOMEM;
-       client->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
-                             client->mount_args->wsize >> PAGE_CACHE_SHIFT);
-       if (!client->wb_pagevec_pool)
+       fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
+                             fsc->mount_options->wsize >> PAGE_CACHE_SHIFT);
+       if (!fsc->wb_pagevec_pool)
                goto fail_trunc_wq;
 
        /* caps */
-       client->min_caps = args->max_readdir;
+       fsc->min_caps = fsopt->max_readdir;
+
+       return fsc;
 
-       /* subsystems */
-       err = ceph_monc_init(&client->monc, client);
-       if (err < 0)
-               goto fail_mempool;
-       err = ceph_osdc_init(&client->osdc, client);
-       if (err < 0)
-               goto fail_monc;
-       err = ceph_mdsc_init(&client->mdsc, client);
-       if (err < 0)
-               goto fail_osdc;
-       return client;
-
-fail_osdc:
-       ceph_osdc_stop(&client->osdc);
-fail_monc:
-       ceph_monc_stop(&client->monc);
-fail_mempool:
-       mempool_destroy(client->wb_pagevec_pool);
 fail_trunc_wq:
-       destroy_workqueue(client->trunc_wq);
+       destroy_workqueue(fsc->trunc_wq);
 fail_pg_inv_wq:
-       destroy_workqueue(client->pg_inv_wq);
+       destroy_workqueue(fsc->pg_inv_wq);
 fail_wb_wq:
-       destroy_workqueue(client->wb_wq);
+       destroy_workqueue(fsc->wb_wq);
 fail_bdi:
-       bdi_destroy(&client->backing_dev_info);
+       bdi_destroy(&fsc->backing_dev_info);
+fail_client:
+       ceph_destroy_client(fsc->client);
 fail:
-       kfree(client);
+       kfree(fsc);
        return ERR_PTR(err);
 }
 
-static void ceph_destroy_client(struct ceph_client *client)
+void destroy_fs_client(struct ceph_fs_client *fsc)
 {
-       dout("destroy_client %p\n", client);
+       dout("destroy_fs_client %p\n", fsc);
 
-       /* unmount */
-       ceph_mdsc_stop(&client->mdsc);
-       ceph_osdc_stop(&client->osdc);
+       destroy_workqueue(fsc->wb_wq);
+       destroy_workqueue(fsc->pg_inv_wq);
+       destroy_workqueue(fsc->trunc_wq);
 
-       /*
-        * make sure mds and osd connections close out before destroying
-        * the auth module, which is needed to free those connections'
-        * ceph_authorizers.
-        */
-       ceph_msgr_flush();
-
-       ceph_monc_stop(&client->monc);
+       bdi_destroy(&fsc->backing_dev_info);
 
-       ceph_debugfs_client_cleanup(client);
-       destroy_workqueue(client->wb_wq);
-       destroy_workqueue(client->pg_inv_wq);
-       destroy_workqueue(client->trunc_wq);
+       mempool_destroy(fsc->wb_pagevec_pool);
 
-       bdi_destroy(&client->backing_dev_info);
+       destroy_mount_options(fsc->mount_options);
 
-       if (client->msgr)
-               ceph_messenger_destroy(client->msgr);
-       mempool_destroy(client->wb_pagevec_pool);
+       ceph_fs_debugfs_cleanup(fsc);
 
-       destroy_mount_args(client->mount_args);
+       ceph_destroy_client(fsc->client);
 
-       kfree(client);
-       dout("destroy_client %p done\n", client);
+       kfree(fsc);
+       dout("destroy_fs_client %p done\n", fsc);
 }
 
 /*
- * Initially learn our fsid, or verify an fsid matches.
+ * caches
  */
-int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
+struct kmem_cache *ceph_inode_cachep;
+struct kmem_cache *ceph_cap_cachep;
+struct kmem_cache *ceph_dentry_cachep;
+struct kmem_cache *ceph_file_cachep;
+
+static void ceph_inode_init_once(void *foo)
 {
-       if (client->have_fsid) {
-               if (ceph_fsid_compare(&client->fsid, fsid)) {
-                       pr_err("bad fsid, had %pU got %pU",
-                              &client->fsid, fsid);
-                       return -1;
-               }
-       } else {
-               pr_info("client%lld fsid %pU\n", client->monc.auth->global_id,
-                       fsid);
-               memcpy(&client->fsid, fsid, sizeof(*fsid));
-               ceph_debugfs_client_init(client);
-               client->have_fsid = true;
-       }
+       struct ceph_inode_info *ci = foo;
+       inode_init_once(&ci->vfs_inode);
+}
+
+static int __init init_caches(void)
+{
+       ceph_inode_cachep = kmem_cache_create("ceph_inode_info",
+                                     sizeof(struct ceph_inode_info),
+                                     __alignof__(struct ceph_inode_info),
+                                     (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
+                                     ceph_inode_init_once);
+       if (ceph_inode_cachep == NULL)
+               return -ENOMEM;
+
+       ceph_cap_cachep = KMEM_CACHE(ceph_cap,
+                                    SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
+       if (ceph_cap_cachep == NULL)
+               goto bad_cap;
+
+       ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info,
+                                       SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
+       if (ceph_dentry_cachep == NULL)
+               goto bad_dentry;
+
+       ceph_file_cachep = KMEM_CACHE(ceph_file_info,
+                                     SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
+       if (ceph_file_cachep == NULL)
+               goto bad_file;
+
        return 0;
+
+bad_file:
+       kmem_cache_destroy(ceph_dentry_cachep);
+bad_dentry:
+       kmem_cache_destroy(ceph_cap_cachep);
+bad_cap:
+       kmem_cache_destroy(ceph_inode_cachep);
+       return -ENOMEM;
 }
 
+static void destroy_caches(void)
+{
+       kmem_cache_destroy(ceph_inode_cachep);
+       kmem_cache_destroy(ceph_cap_cachep);
+       kmem_cache_destroy(ceph_dentry_cachep);
+       kmem_cache_destroy(ceph_file_cachep);
+}
+
+
 /*
- * true if we have the mon map (and have thus joined the cluster)
+ * ceph_umount_begin - initiate forced umount.  Tear down down the
+ * mount, skipping steps that may hang while waiting for server(s).
  */
-static int have_mon_and_osd_map(struct ceph_client *client)
+static void ceph_umount_begin(struct super_block *sb)
 {
-       return client->monc.monmap && client->monc.monmap->epoch &&
-              client->osdc.osdmap && client->osdc.osdmap->epoch;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+
+       dout("ceph_umount_begin - starting forced umount\n");
+       if (!fsc)
+               return;
+       fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
+       return;
 }
 
+static const struct super_operations ceph_super_ops = {
+       .alloc_inode    = ceph_alloc_inode,
+       .destroy_inode  = ceph_destroy_inode,
+       .write_inode    = ceph_write_inode,
+       .sync_fs        = ceph_sync_fs,
+       .put_super      = ceph_put_super,
+       .show_options   = ceph_show_options,
+       .statfs         = ceph_statfs,
+       .umount_begin   = ceph_umount_begin,
+};
+
 /*
  * Bootstrap mount by opening the root directory.  Note the mount
  * @started time from caller, and time out if this takes too long.
  */
-static struct dentry *open_root_dentry(struct ceph_client *client,
+static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
                                       const char *path,
                                       unsigned long started)
 {
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req = NULL;
        int err;
        struct dentry *root;
@@ -784,14 +609,14 @@ static struct dentry *open_root_dentry(struct ceph_client *client,
        req->r_ino1.ino = CEPH_INO_ROOT;
        req->r_ino1.snap = CEPH_NOSNAP;
        req->r_started = started;
-       req->r_timeout = client->mount_args->mount_timeout * HZ;
+       req->r_timeout = fsc->client->options->mount_timeout * HZ;
        req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
        req->r_num_caps = 2;
        err = ceph_mdsc_do_request(mdsc, NULL, req);
        if (err == 0) {
                dout("open_root_inode success\n");
                if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT &&
-                   client->sb->s_root == NULL)
+                   fsc->sb->s_root == NULL)
                        root = d_alloc_root(req->r_target_inode);
                else
                        root = d_obtain_alias(req->r_target_inode);
@@ -804,105 +629,86 @@ static struct dentry *open_root_dentry(struct ceph_client *client,
        return root;
 }
 
+
+
+
 /*
  * mount: join the ceph cluster, and open root directory.
  */
-static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
+static int ceph_mount(struct ceph_fs_client *fsc, struct vfsmount *mnt,
                      const char *path)
 {
-       struct ceph_entity_addr *myaddr = NULL;
        int err;
-       unsigned long timeout = client->mount_args->mount_timeout * HZ;
        unsigned long started = jiffies;  /* note the start time */
        struct dentry *root;
+       int first = 0;   /* first vfsmount for this super_block */
 
        dout("mount start\n");
-       mutex_lock(&client->mount_mutex);
-
-       /* initialize the messenger */
-       if (client->msgr == NULL) {
-               if (ceph_test_opt(client, MYIP))
-                       myaddr = &client->mount_args->my_addr;
-               client->msgr = ceph_messenger_create(myaddr);
-               if (IS_ERR(client->msgr)) {
-                       err = PTR_ERR(client->msgr);
-                       client->msgr = NULL;
-                       goto out;
-               }
-               client->msgr->nocrc = ceph_test_opt(client, NOCRC);
-       }
+       mutex_lock(&fsc->client->mount_mutex);
 
-       /* open session, and wait for mon, mds, and osd maps */
-       err = ceph_monc_open_session(&client->monc);
+       err = __ceph_open_session(fsc->client, started);
        if (err < 0)
                goto out;
 
-       while (!have_mon_and_osd_map(client)) {
-               err = -EIO;
-               if (timeout && time_after_eq(jiffies, started + timeout))
-                       goto out;
-
-               /* wait */
-               dout("mount waiting for mon_map\n");
-               err = wait_event_interruptible_timeout(client->auth_wq,
-                      have_mon_and_osd_map(client) || (client->auth_err < 0),
-                      timeout);
-               if (err == -EINTR || err == -ERESTARTSYS)
-                       goto out;
-               if (client->auth_err < 0) {
-                       err = client->auth_err;
-                       goto out;
-               }
-       }
-
        dout("mount opening root\n");
-       root = open_root_dentry(client, "", started);
+       root = open_root_dentry(fsc, "", started);
        if (IS_ERR(root)) {
                err = PTR_ERR(root);
                goto out;
        }
-       if (client->sb->s_root)
+       if (fsc->sb->s_root) {
                dput(root);
-       else
-               client->sb->s_root = root;
+       } else {
+               fsc->sb->s_root = root;
+               first = 1;
+
+               err = ceph_fs_debugfs_init(fsc);
+               if (err < 0)
+                       goto fail;
+       }
 
        if (path[0] == 0) {
                dget(root);
        } else {
                dout("mount opening base mountpoint\n");
-               root = open_root_dentry(client, path, started);
+               root = open_root_dentry(fsc, path, started);
                if (IS_ERR(root)) {
                        err = PTR_ERR(root);
-                       dput(client->sb->s_root);
-                       client->sb->s_root = NULL;
-                       goto out;
+                       goto fail;
                }
        }
 
        mnt->mnt_root = root;
-       mnt->mnt_sb = client->sb;
+       mnt->mnt_sb = fsc->sb;
 
-       client->mount_state = CEPH_MOUNT_MOUNTED;
+       fsc->mount_state = CEPH_MOUNT_MOUNTED;
        dout("mount success\n");
        err = 0;
 
 out:
-       mutex_unlock(&client->mount_mutex);
+       mutex_unlock(&fsc->client->mount_mutex);
        return err;
+
+fail:
+       if (first) {
+               dput(fsc->sb->s_root);
+               fsc->sb->s_root = NULL;
+       }
+       goto out;
 }
 
 static int ceph_set_super(struct super_block *s, void *data)
 {
-       struct ceph_client *client = data;
+       struct ceph_fs_client *fsc = data;
        int ret;
 
        dout("set_super %p data %p\n", s, data);
 
-       s->s_flags = client->mount_args->sb_flags;
+       s->s_flags = fsc->mount_options->sb_flags;
        s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
 
-       s->s_fs_info = client;
-       client->sb = s;
+       s->s_fs_info = fsc;
+       fsc->sb = s;
 
        s->s_op = &ceph_super_ops;
        s->s_export_op = &ceph_export_ops;
@@ -917,7 +723,7 @@ static int ceph_set_super(struct super_block *s, void *data)
 
 fail:
        s->s_fs_info = NULL;
-       client->sb = NULL;
+       fsc->sb = NULL;
        return ret;
 }
 
@@ -926,30 +732,23 @@ fail:
  */
 static int ceph_compare_super(struct super_block *sb, void *data)
 {
-       struct ceph_client *new = data;
-       struct ceph_mount_args *args = new->mount_args;
-       struct ceph_client *other = ceph_sb_to_client(sb);
-       int i;
+       struct ceph_fs_client *new = data;
+       struct ceph_mount_options *fsopt = new->mount_options;
+       struct ceph_options *opt = new->client->options;
+       struct ceph_fs_client *other = ceph_sb_to_client(sb);
 
        dout("ceph_compare_super %p\n", sb);
-       if (args->flags & CEPH_OPT_FSID) {
-               if (ceph_fsid_compare(&args->fsid, &other->fsid)) {
-                       dout("fsid doesn't match\n");
-                       return 0;
-               }
-       } else {
-               /* do we share (a) monitor? */
-               for (i = 0; i < new->monc.monmap->num_mon; i++)
-                       if (ceph_monmap_contains(other->monc.monmap,
-                                        &new->monc.monmap->mon_inst[i].addr))
-                               break;
-               if (i == new->monc.monmap->num_mon) {
-                       dout("mon ip not part of monmap\n");
-                       return 0;
-               }
-               dout("mon ip matches existing sb %p\n", sb);
+
+       if (compare_mount_options(fsopt, opt, other)) {
+               dout("monitor(s)/mount options don't match\n");
+               return 0;
        }
-       if (args->sb_flags != other->mount_args->sb_flags) {
+       if ((opt->flags & CEPH_OPT_FSID) &&
+           ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
+               dout("fsid doesn't match\n");
+               return 0;
+       }
+       if (fsopt->sb_flags != other->mount_options->sb_flags) {
                dout("flags differ\n");
                return 0;
        }
@@ -961,19 +760,20 @@ static int ceph_compare_super(struct super_block *sb, void *data)
  */
 static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
 
-static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
+static int ceph_register_bdi(struct super_block *sb,
+                            struct ceph_fs_client *fsc)
 {
        int err;
 
        /* set ra_pages based on rsize mount option? */
-       if (client->mount_args->rsize >= PAGE_CACHE_SIZE)
-               client->backing_dev_info.ra_pages =
-                       (client->mount_args->rsize + PAGE_CACHE_SIZE - 1)
+       if (fsc->mount_options->rsize >= PAGE_CACHE_SIZE)
+               fsc->backing_dev_info.ra_pages =
+                       (fsc->mount_options->rsize + PAGE_CACHE_SIZE - 1)
                        >> PAGE_SHIFT;
-       err = bdi_register(&client->backing_dev_info, NULL, "ceph-%d",
+       err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
                           atomic_long_inc_return(&bdi_seq));
        if (!err)
-               sb->s_bdi = &client->backing_dev_info;
+               sb->s_bdi = &fsc->backing_dev_info;
        return err;
 }
 
@@ -982,46 +782,52 @@ static int ceph_get_sb(struct file_system_type *fs_type,
                       struct vfsmount *mnt)
 {
        struct super_block *sb;
-       struct ceph_client *client;
+       struct ceph_fs_client *fsc;
        int err;
        int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
        const char *path = NULL;
-       struct ceph_mount_args *args;
+       struct ceph_mount_options *fsopt = NULL;
+       struct ceph_options *opt = NULL;
 
        dout("ceph_get_sb\n");
-       args = parse_mount_args(flags, data, dev_name, &path);
-       if (IS_ERR(args)) {
-               err = PTR_ERR(args);
+       err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
+       if (err < 0)
                goto out_final;
-       }
 
        /* create client (which we may/may not use) */
-       client = ceph_create_client(args);
-       if (IS_ERR(client)) {
-               err = PTR_ERR(client);
+       fsc = create_fs_client(fsopt, opt);
+       if (IS_ERR(fsc)) {
+               err = PTR_ERR(fsc);
+               kfree(fsopt);
+               kfree(opt);
                goto out_final;
        }
 
-       if (client->mount_args->flags & CEPH_OPT_NOSHARE)
+       err = ceph_mdsc_init(fsc);
+       if (err < 0)
+               goto out;
+
+       if (ceph_test_opt(fsc->client, NOSHARE))
                compare_super = NULL;
-       sb = sget(fs_type, compare_super, ceph_set_super, client);
+       sb = sget(fs_type, compare_super, ceph_set_super, fsc);
        if (IS_ERR(sb)) {
                err = PTR_ERR(sb);
                goto out;
        }
 
-       if (ceph_sb_to_client(sb) != client) {
-               ceph_destroy_client(client);
-               client = ceph_sb_to_client(sb);
-               dout("get_sb got existing client %p\n", client);
+       if (ceph_sb_to_client(sb) != fsc) {
+               ceph_mdsc_destroy(fsc);
+               destroy_fs_client(fsc);
+               fsc = ceph_sb_to_client(sb);
+               dout("get_sb got existing client %p\n", fsc);
        } else {
-               dout("get_sb using new client %p\n", client);
-               err = ceph_register_bdi(sb, client);
+               dout("get_sb using new client %p\n", fsc);
+               err = ceph_register_bdi(sb, fsc);
                if (err < 0)
                        goto out_splat;
        }
 
-       err = ceph_mount(client, mnt, path);
+       err = ceph_mount(fsc, mnt, path);
        if (err < 0)
                goto out_splat;
        dout("root %p inode %p ino %llx.%llx\n", mnt->mnt_root,
@@ -1029,12 +835,13 @@ static int ceph_get_sb(struct file_system_type *fs_type,
        return 0;
 
 out_splat:
-       ceph_mdsc_close_sessions(&client->mdsc);
+       ceph_mdsc_close_sessions(fsc->mdsc);
        deactivate_locked_super(sb);
        goto out_final;
 
 out:
-       ceph_destroy_client(client);
+       ceph_mdsc_destroy(fsc);
+       destroy_fs_client(fsc);
 out_final:
        dout("ceph_get_sb fail %d\n", err);
        return err;
@@ -1042,11 +849,12 @@ out_final:
 
 static void ceph_kill_sb(struct super_block *s)
 {
-       struct ceph_client *client = ceph_sb_to_client(s);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(s);
        dout("kill_sb %p\n", s);
-       ceph_mdsc_pre_umount(&client->mdsc);
+       ceph_mdsc_pre_umount(fsc->mdsc);
        kill_anon_super(s);    /* will call put_super after sb is r/o */
-       ceph_destroy_client(client);
+       ceph_mdsc_destroy(fsc);
+       destroy_fs_client(fsc);
 }
 
 static struct file_system_type ceph_fs_type = {
@@ -1062,36 +870,20 @@ static struct file_system_type ceph_fs_type = {
 
 static int __init init_ceph(void)
 {
-       int ret = 0;
-
-       ret = ceph_debugfs_init();
-       if (ret < 0)
-               goto out;
-
-       ret = ceph_msgr_init();
-       if (ret < 0)
-               goto out_debugfs;
-
-       ret = init_caches();
+       int ret = init_caches();
        if (ret)
-               goto out_msgr;
+               goto out;
 
        ret = register_filesystem(&ceph_fs_type);
        if (ret)
                goto out_icache;
 
-       pr_info("loaded (mon/mds/osd proto %d/%d/%d, osdmap %d/%d %d/%d)\n",
-               CEPH_MONC_PROTOCOL, CEPH_MDSC_PROTOCOL, CEPH_OSDC_PROTOCOL,
-               CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT,
-               CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT);
+       pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL);
+
        return 0;
 
 out_icache:
        destroy_caches();
-out_msgr:
-       ceph_msgr_exit();
-out_debugfs:
-       ceph_debugfs_cleanup();
 out:
        return ret;
 }
@@ -1101,8 +893,6 @@ static void __exit exit_ceph(void)
        dout("exit_ceph\n");
        unregister_filesystem(&ceph_fs_type);
        destroy_caches();
-       ceph_msgr_exit();
-       ceph_debugfs_cleanup();
 }
 
 module_init(init_ceph);
index 2482d696f0de17f2fcccdedfc79d2ad4a14c6664..1886294e12f7a3106c00f3376d92e43330514081 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _FS_CEPH_SUPER_H
 #define _FS_CEPH_SUPER_H
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <asm/unaligned.h>
 #include <linux/backing-dev.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
 
-#include "types.h"
-#include "messenger.h"
-#include "msgpool.h"
-#include "mon_client.h"
-#include "mds_client.h"
-#include "osd_client.h"
-#include "ceph_fs.h"
+#include <linux/ceph/libceph.h>
 
 /* f_type in struct statfs */
 #define CEPH_SUPER_MAGIC 0x00c36400
 #define CEPH_BLOCK_SHIFT   20  /* 1 MB */
 #define CEPH_BLOCK         (1 << CEPH_BLOCK_SHIFT)
 
-/*
- * Supported features
- */
-#define CEPH_FEATURE_SUPPORTED CEPH_FEATURE_NOSRCADDR | CEPH_FEATURE_FLOCK
-#define CEPH_FEATURE_REQUIRED  CEPH_FEATURE_NOSRCADDR
+#define CEPH_MOUNT_OPT_DIRSTAT         (1<<4) /* `cat dirname` for stats */
+#define CEPH_MOUNT_OPT_RBYTES          (1<<5) /* dir st_bytes = rbytes */
+#define CEPH_MOUNT_OPT_NOASYNCREADDIR  (1<<7) /* no dcache readdir */
 
-/*
- * mount options
- */
-#define CEPH_OPT_FSID             (1<<0)
-#define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
-#define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
-#define CEPH_OPT_DIRSTAT          (1<<4) /* funky `cat dirname` for stats */
-#define CEPH_OPT_RBYTES           (1<<5) /* dir st_bytes = rbytes */
-#define CEPH_OPT_NOCRC            (1<<6) /* no data crc on writes */
-#define CEPH_OPT_NOASYNCREADDIR   (1<<7) /* no dcache readdir */
+#define CEPH_MOUNT_OPT_DEFAULT    (CEPH_MOUNT_OPT_RBYTES)
 
-#define CEPH_OPT_DEFAULT   (CEPH_OPT_RBYTES)
+#define ceph_set_mount_opt(fsc, opt) \
+       (fsc)->mount_options->flags |= CEPH_MOUNT_OPT_##opt;
+#define ceph_test_mount_opt(fsc, opt) \
+       (!!((fsc)->mount_options->flags & CEPH_MOUNT_OPT_##opt))
 
-#define ceph_set_opt(client, opt) \
-       (client)->mount_args->flags |= CEPH_OPT_##opt;
-#define ceph_test_opt(client, opt) \
-       (!!((client)->mount_args->flags & CEPH_OPT_##opt))
+#define CEPH_MAX_READDIR_DEFAULT        1024
+#define CEPH_MAX_READDIR_BYTES_DEFAULT  (512*1024)
+#define CEPH_SNAPDIRNAME_DEFAULT        ".snap"
 
-
-struct ceph_mount_args {
-       int sb_flags;
+struct ceph_mount_options {
        int flags;
-       struct ceph_fsid fsid;
-       struct ceph_entity_addr my_addr;
-       int num_mon;
-       struct ceph_entity_addr *mon_addr;
-       int mount_timeout;
-       int osd_idle_ttl;
-       int osd_timeout;
-       int osd_keepalive_timeout;
+       int sb_flags;
+
        int wsize;
        int rsize;            /* max readahead */
        int congestion_kb;    /* max writeback in flight */
@@ -73,82 +50,25 @@ struct ceph_mount_args {
        int cap_release_safety;
        int max_readdir;       /* max readdir result (entires) */
        int max_readdir_bytes; /* max readdir result (bytes) */
-       char *snapdir_name;   /* default ".snap" */
-       char *name;
-       char *secret;
-};
 
-/*
- * defaults
- */
-#define CEPH_MOUNT_TIMEOUT_DEFAULT  60
-#define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
-#define CEPH_OSD_KEEPALIVE_DEFAULT  5
-#define CEPH_OSD_IDLE_TTL_DEFAULT    60
-#define CEPH_MOUNT_RSIZE_DEFAULT    (512*1024) /* readahead */
-#define CEPH_MAX_READDIR_DEFAULT    1024
-#define CEPH_MAX_READDIR_BYTES_DEFAULT    (512*1024)
-
-#define CEPH_MSG_MAX_FRONT_LEN (16*1024*1024)
-#define CEPH_MSG_MAX_DATA_LEN  (16*1024*1024)
-
-#define CEPH_SNAPDIRNAME_DEFAULT ".snap"
-#define CEPH_AUTH_NAME_DEFAULT   "guest"
-/*
- * Delay telling the MDS we no longer want caps, in case we reopen
- * the file.  Delay a minimum amount of time, even if we send a cap
- * message for some other reason.  Otherwise, take the oppotunity to
- * update the mds to avoid sending another message later.
- */
-#define CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT      5  /* cap release delay */
-#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
-
-#define CEPH_CAP_RELEASE_SAFETY_DEFAULT        (CEPH_CAPS_PER_RELEASE * 4)
-
-/* mount state */
-enum {
-       CEPH_MOUNT_MOUNTING,
-       CEPH_MOUNT_MOUNTED,
-       CEPH_MOUNT_UNMOUNTING,
-       CEPH_MOUNT_UNMOUNTED,
-       CEPH_MOUNT_SHUTDOWN,
-};
-
-/*
- * subtract jiffies
- */
-static inline unsigned long time_sub(unsigned long a, unsigned long b)
-{
-       BUG_ON(time_after(b, a));
-       return (long)a - (long)b;
-}
-
-/*
- * per-filesystem client state
- *
- * possibly shared by multiple mount points, if they are
- * mounting the same ceph filesystem/cluster.
- */
-struct ceph_client {
-       struct ceph_fsid fsid;
-       bool have_fsid;
+       /*
+        * everything above this point can be memcmp'd; everything below
+        * is handled in compare_mount_options()
+        */
 
-       struct mutex mount_mutex;       /* serialize mount attempts */
-       struct ceph_mount_args *mount_args;
+       char *snapdir_name;   /* default ".snap" */
+};
 
+struct ceph_fs_client {
        struct super_block *sb;
 
-       unsigned long mount_state;
-       wait_queue_head_t auth_wq;
-
-       int auth_err;
+       struct ceph_mount_options *mount_options;
+       struct ceph_client *client;
 
+       unsigned long mount_state;
        int min_caps;                  /* min caps i added */
 
-       struct ceph_messenger *msgr;   /* messenger instance */
-       struct ceph_mon_client monc;
-       struct ceph_mds_client mdsc;
-       struct ceph_osd_client osdc;
+       struct ceph_mds_client *mdsc;
 
        /* writeback */
        mempool_t *wb_pagevec_pool;
@@ -160,14 +80,14 @@ struct ceph_client {
        struct backing_dev_info backing_dev_info;
 
 #ifdef CONFIG_DEBUG_FS
-       struct dentry *debugfs_monmap;
-       struct dentry *debugfs_mdsmap, *debugfs_osdmap;
-       struct dentry *debugfs_dir, *debugfs_dentry_lru, *debugfs_caps;
+       struct dentry *debugfs_dentry_lru, *debugfs_caps;
        struct dentry *debugfs_congestion_kb;
        struct dentry *debugfs_bdi;
+       struct dentry *debugfs_mdsc, *debugfs_mdsmap;
 #endif
 };
 
+
 /*
  * File i/o capability.  This tracks shared state with the metadata
  * server that allows us to cache or writeback attributes or to read
@@ -216,8 +136,7 @@ struct ceph_cap_snap {
        uid_t uid;
        gid_t gid;
 
-       void *xattr_blob;
-       int xattr_len;
+       struct ceph_buffer *xattr_blob;
        u64 xattr_version;
 
        u64 size;
@@ -229,8 +148,11 @@ struct ceph_cap_snap {
 
 static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
 {
-       if (atomic_dec_and_test(&capsnap->nref))
+       if (atomic_dec_and_test(&capsnap->nref)) {
+               if (capsnap->xattr_blob)
+                       ceph_buffer_put(capsnap->xattr_blob);
                kfree(capsnap);
+       }
 }
 
 /*
@@ -273,6 +195,20 @@ struct ceph_inode_xattr {
        int should_free_val;
 };
 
+/*
+ * Ceph dentry state
+ */
+struct ceph_dentry_info {
+       struct ceph_mds_session *lease_session;
+       u32 lease_gen, lease_shared_gen;
+       u32 lease_seq;
+       unsigned long lease_renew_after, lease_renew_from;
+       struct list_head lru;
+       struct dentry *dentry;
+       u64 time;
+       u64 offset;
+};
+
 struct ceph_inode_xattrs_info {
        /*
         * (still encoded) xattr blob. we avoid the overhead of parsing
@@ -294,11 +230,6 @@ struct ceph_inode_xattrs_info {
 /*
  * Ceph inode.
  */
-#define CEPH_I_COMPLETE  1  /* we have complete directory cached */
-#define CEPH_I_NODELAY   4  /* do not delay cap release */
-#define CEPH_I_FLUSH     8  /* do not delay flush of dirty metadata */
-#define CEPH_I_NOFLUSH  16  /* do not flush dirty caps */
-
 struct ceph_inode_info {
        struct ceph_vino i_vino;   /* ceph ino + snap */
 
@@ -342,7 +273,8 @@ struct ceph_inode_info {
        unsigned i_cap_exporting_issued;
        struct ceph_cap_reservation i_cap_migration_resv;
        struct list_head i_cap_snaps;   /* snapped state pending flush to mds */
-       struct ceph_snap_context *i_head_snapc;  /* set if wr_buffer_head > 0 */
+       struct ceph_snap_context *i_head_snapc;  /* set if wr_buffer_head > 0 or
+                                                   dirty|flushing caps */
        unsigned i_snap_caps;           /* cap bits for snapped files */
 
        int i_nr_by_mode[CEPH_FILE_MODE_NUM];  /* open file counts */
@@ -388,6 +320,63 @@ static inline struct ceph_inode_info *ceph_inode(struct inode *inode)
        return container_of(inode, struct ceph_inode_info, vfs_inode);
 }
 
+static inline struct ceph_vino ceph_vino(struct inode *inode)
+{
+       return ceph_inode(inode)->i_vino;
+}
+
+/*
+ * ino_t is <64 bits on many architectures, blech.
+ *
+ * don't include snap in ino hash, at least for now.
+ */
+static inline ino_t ceph_vino_to_ino(struct ceph_vino vino)
+{
+       ino_t ino = (ino_t)vino.ino;  /* ^ (vino.snap << 20); */
+#if BITS_PER_LONG == 32
+       ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8;
+       if (!ino)
+               ino = 1;
+#endif
+       return ino;
+}
+
+/* for printf-style formatting */
+#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
+
+static inline u64 ceph_ino(struct inode *inode)
+{
+       return ceph_inode(inode)->i_vino.ino;
+}
+static inline u64 ceph_snap(struct inode *inode)
+{
+       return ceph_inode(inode)->i_vino.snap;
+}
+
+static inline int ceph_ino_compare(struct inode *inode, void *data)
+{
+       struct ceph_vino *pvino = (struct ceph_vino *)data;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       return ci->i_vino.ino == pvino->ino &&
+               ci->i_vino.snap == pvino->snap;
+}
+
+static inline struct inode *ceph_find_inode(struct super_block *sb,
+                                           struct ceph_vino vino)
+{
+       ino_t t = ceph_vino_to_ino(vino);
+       return ilookup5(sb, t, ceph_ino_compare, &vino);
+}
+
+
+/*
+ * Ceph inode.
+ */
+#define CEPH_I_COMPLETE  1  /* we have complete directory cached */
+#define CEPH_I_NODELAY   4  /* do not delay cap release */
+#define CEPH_I_FLUSH     8  /* do not delay flush of dirty metadata */
+#define CEPH_I_NOFLUSH  16  /* do not flush dirty caps */
+
 static inline void ceph_i_clear(struct inode *inode, unsigned mask)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -411,8 +400,9 @@ static inline bool ceph_i_test(struct inode *inode, unsigned mask)
        struct ceph_inode_info *ci = ceph_inode(inode);
        bool r;
 
-       smp_mb();
+       spin_lock(&inode->i_lock);
        r = (ci->i_ceph_flags & mask) == mask;
+       spin_unlock(&inode->i_lock);
        return r;
 }
 
@@ -429,20 +419,6 @@ extern u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
                            struct ceph_inode_frag *pfrag,
                            int *found);
 
-/*
- * Ceph dentry state
- */
-struct ceph_dentry_info {
-       struct ceph_mds_session *lease_session;
-       u32 lease_gen, lease_shared_gen;
-       u32 lease_seq;
-       unsigned long lease_renew_after, lease_renew_from;
-       struct list_head lru;
-       struct dentry *dentry;
-       u64 time;
-       u64 offset;
-};
-
 static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
 {
        return (struct ceph_dentry_info *)dentry->d_fsdata;
@@ -453,22 +429,6 @@ static inline loff_t ceph_make_fpos(unsigned frag, unsigned off)
        return ((loff_t)frag << 32) | (loff_t)off;
 }
 
-/*
- * ino_t is <64 bits on many architectures, blech.
- *
- * don't include snap in ino hash, at least for now.
- */
-static inline ino_t ceph_vino_to_ino(struct ceph_vino vino)
-{
-       ino_t ino = (ino_t)vino.ino;  /* ^ (vino.snap << 20); */
-#if BITS_PER_LONG == 32
-       ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8;
-       if (!ino)
-               ino = 1;
-#endif
-       return ino;
-}
-
 static inline int ceph_set_ino_cb(struct inode *inode, void *data)
 {
        ceph_inode(inode)->i_vino = *(struct ceph_vino *)data;
@@ -476,39 +436,6 @@ static inline int ceph_set_ino_cb(struct inode *inode, void *data)
        return 0;
 }
 
-static inline struct ceph_vino ceph_vino(struct inode *inode)
-{
-       return ceph_inode(inode)->i_vino;
-}
-
-/* for printf-style formatting */
-#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
-
-static inline u64 ceph_ino(struct inode *inode)
-{
-       return ceph_inode(inode)->i_vino.ino;
-}
-static inline u64 ceph_snap(struct inode *inode)
-{
-       return ceph_inode(inode)->i_vino.snap;
-}
-
-static inline int ceph_ino_compare(struct inode *inode, void *data)
-{
-       struct ceph_vino *pvino = (struct ceph_vino *)data;
-       struct ceph_inode_info *ci = ceph_inode(inode);
-       return ci->i_vino.ino == pvino->ino &&
-               ci->i_vino.snap == pvino->snap;
-}
-
-static inline struct inode *ceph_find_inode(struct super_block *sb,
-                                           struct ceph_vino vino)
-{
-       ino_t t = ceph_vino_to_ino(vino);
-       return ilookup5(sb, t, ceph_ino_compare, &vino);
-}
-
-
 /*
  * caps helpers
  */
@@ -573,18 +500,18 @@ extern int ceph_reserve_caps(struct ceph_mds_client *mdsc,
                             struct ceph_cap_reservation *ctx, int need);
 extern int ceph_unreserve_caps(struct ceph_mds_client *mdsc,
                               struct ceph_cap_reservation *ctx);
-extern void ceph_reservation_status(struct ceph_client *client,
+extern void ceph_reservation_status(struct ceph_fs_client *client,
                                    int *total, int *avail, int *used,
                                    int *reserved, int *min);
 
-static inline struct ceph_client *ceph_inode_to_client(struct inode *inode)
+static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
 {
-       return (struct ceph_client *)inode->i_sb->s_fs_info;
+       return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
 }
 
-static inline struct ceph_client *ceph_sb_to_client(struct super_block *sb)
+static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
 {
-       return (struct ceph_client *)sb->s_fs_info;
+       return (struct ceph_fs_client *)sb->s_fs_info;
 }
 
 
@@ -613,51 +540,6 @@ struct ceph_file_info {
 
 
 
-/*
- * snapshots
- */
-
-/*
- * A "snap context" is the set of existing snapshots when we
- * write data.  It is used by the OSD to guide its COW behavior.
- *
- * The ceph_snap_context is refcounted, and attached to each dirty
- * page, indicating which context the dirty data belonged when it was
- * dirtied.
- */
-struct ceph_snap_context {
-       atomic_t nref;
-       u64 seq;
-       int num_snaps;
-       u64 snaps[];
-};
-
-static inline struct ceph_snap_context *
-ceph_get_snap_context(struct ceph_snap_context *sc)
-{
-       /*
-       printk("get_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
-              atomic_read(&sc->nref)+1);
-       */
-       if (sc)
-               atomic_inc(&sc->nref);
-       return sc;
-}
-
-static inline void ceph_put_snap_context(struct ceph_snap_context *sc)
-{
-       if (!sc)
-               return;
-       /*
-       printk("put_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
-              atomic_read(&sc->nref)-1);
-       */
-       if (atomic_dec_and_test(&sc->nref)) {
-               /*printk(" deleting snap_context %p\n", sc);*/
-               kfree(sc);
-       }
-}
-
 /*
  * A "snap realm" describes a subset of the file hierarchy sharing
  * the same set of snapshots that apply to it.  The realms themselves
@@ -687,6 +569,8 @@ struct ceph_snap_realm {
 
        struct list_head empty_item;     /* if i have ref==0 */
 
+       struct list_head dirty_item;     /* if realm needs new context */
+
        /* the current set of snaps for this realm */
        struct ceph_snap_context *cached_context;
 
@@ -694,16 +578,33 @@ struct ceph_snap_realm {
        spinlock_t inodes_with_caps_lock;
 };
 
-
-
-/*
- * calculate the number of pages a given length and offset map onto,
- * if we align the data.
- */
-static inline int calc_pages_for(u64 off, u64 len)
+static inline int default_congestion_kb(void)
 {
-       return ((off+len+PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT) -
-               (off >> PAGE_CACHE_SHIFT);
+       int congestion_kb;
+
+       /*
+        * Copied from NFS
+        *
+        * congestion size, scale with available memory.
+        *
+        *  64MB:    8192k
+        * 128MB:   11585k
+        * 256MB:   16384k
+        * 512MB:   23170k
+        *   1GB:   32768k
+        *   2GB:   46340k
+        *   4GB:   65536k
+        *   8GB:   92681k
+        *  16GB:  131072k
+        *
+        * This allows larger machines to have larger/more transfers.
+        * Limit the default to 256M
+        */
+       congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
+       if (congestion_kb > 256*1024)
+               congestion_kb = 256*1024;
+
+       return congestion_kb;
 }
 
 
@@ -736,16 +637,6 @@ static inline bool __ceph_have_pending_cap_snap(struct ceph_inode_info *ci)
                           ci_item)->writing;
 }
 
-
-/* super.c */
-extern struct kmem_cache *ceph_inode_cachep;
-extern struct kmem_cache *ceph_cap_cachep;
-extern struct kmem_cache *ceph_dentry_cachep;
-extern struct kmem_cache *ceph_file_cachep;
-
-extern const char *ceph_msg_type_name(int type);
-extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
-
 /* inode.c */
 extern const struct inode_operations ceph_file_iops;
 
@@ -823,7 +714,8 @@ extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
 extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
                                       struct ceph_snap_context *snapc);
 extern void __ceph_flush_snaps(struct ceph_inode_info *ci,
-                              struct ceph_mds_session **psession);
+                              struct ceph_mds_session **psession,
+                              int again);
 extern void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                            struct ceph_mds_session *session);
 extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
@@ -851,12 +743,18 @@ extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
 /* file.c */
 extern const struct file_operations ceph_file_fops;
 extern const struct address_space_operations ceph_aops;
+extern int ceph_copy_to_page_vector(struct page **pages,
+                                   const char *data,
+                                   loff_t off, size_t len);
+extern int ceph_copy_from_page_vector(struct page **pages,
+                                   char *data,
+                                   loff_t off, size_t len);
+extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_open(struct inode *inode, struct file *file);
 extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
                                       struct nameidata *nd, int mode,
                                       int locked_dir);
 extern int ceph_release(struct inode *inode, struct file *filp);
-extern void ceph_release_page_vector(struct page **pages, int num_pages);
 
 /* dir.c */
 extern const struct file_operations ceph_dir_fops;
@@ -886,12 +784,6 @@ extern long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 /* export.c */
 extern const struct export_operations ceph_export_ops;
 
-/* debugfs.c */
-extern int ceph_debugfs_init(void);
-extern void ceph_debugfs_cleanup(void);
-extern int ceph_debugfs_client_init(struct ceph_client *client);
-extern void ceph_debugfs_client_cleanup(struct ceph_client *client);
-
 /* locks.c */
 extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl);
 extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl);
@@ -908,4 +800,8 @@ static inline struct inode *get_dentry_parent_inode(struct dentry *dentry)
        return NULL;
 }
 
+/* debugfs.c */
+extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
+extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
+
 #endif /* _FS_CEPH_SUPER_H */
index 097a2654c00f517c004ef429b3c0046664f205c3..6e12a6ba5f79daabc1bc455a3a4db464b240c00a 100644 (file)
@@ -1,6 +1,9 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
+
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
 
 #include <linux/xattr.h>
 #include <linux/slab.h>
@@ -485,6 +488,7 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
                ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
                ci->i_xattrs.prealloc_blob = NULL;
                ci->i_xattrs.dirty = false;
+               ci->i_xattrs.version++;
        }
 }
 
@@ -619,12 +623,12 @@ out:
 static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
                              const char *value, size_t size, int flags)
 {
-       struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct inode *inode = dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct inode *parent_inode = dentry->d_parent->d_inode;
        struct ceph_mds_request *req;
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        int err;
        int i, nr_pages;
        struct page **pages = NULL;
@@ -712,10 +716,9 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
 
        /* preallocate memory for xattr name, value, index node */
        err = -ENOMEM;
-       newname = kmalloc(name_len + 1, GFP_NOFS);
+       newname = kmemdup(name, name_len + 1, GFP_NOFS);
        if (!newname)
                goto out;
-       memcpy(newname, name, name_len + 1);
 
        if (val_len) {
                newval = kmalloc(val_len + 1, GFP_NOFS);
@@ -776,8 +779,8 @@ out:
 
 static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 {
-       struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
-       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct inode *inode = dentry->d_inode;
        struct inode *parent_inode = dentry->d_parent->d_inode;
        struct ceph_mds_request *req;
index f80a4f25123c3fa912daa1eb4080e69dab3d58fb..e5b9df993b934f0876666f7c50153a467ef7c939 100644 (file)
@@ -40,7 +40,9 @@ struct backing_dev_info directly_mappable_cdev_bdi = {
 #endif
                /* permit direct mmap, for read, write or exec */
                BDI_CAP_MAP_DIRECT |
-               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP),
+               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP |
+               /* no writeback happens */
+               BDI_CAP_NO_ACCT_AND_WRITEBACK),
 };
 
 static struct kobj_map *cdev_map;
@@ -454,6 +456,7 @@ static void cdev_purge(struct cdev *cdev)
  */
 const struct file_operations def_chr_fops = {
        .open = chrdev_open,
+       .llseek = noop_llseek,
 };
 
 static struct kobject *exact_match(dev_t dev, int *part, void *data)
index 650638275a6feed35d31fdbc183e57092b872f33..7fe6b52df5076a2eb14a7ec563403795e2e4c041 100644 (file)
@@ -30,6 +30,8 @@
  *     This is a compressed table of upper and lower case conversion.
  *
  */
+#ifndef _CIFS_UNICODE_H
+#define _CIFS_UNICODE_H
 
 #include <asm/byteorder.h>
 #include <linux/types.h>
@@ -67,8 +69,8 @@ extern const struct UniCaseRange CifsUniUpperRange[];
 #endif                         /* UNIUPR_NOUPPER */
 
 #ifndef UNIUPR_NOLOWER
-extern signed char UniLowerTable[512];
-extern struct UniCaseRange UniLowerRange[];
+extern signed char CifsUniLowerTable[512];
+extern const struct UniCaseRange CifsUniLowerRange[];
 #endif                         /* UNIUPR_NOLOWER */
 
 #ifdef __KERNEL__
@@ -337,15 +339,15 @@ UniStrupr(register wchar_t *upin)
  * UniTolower:  Convert a unicode character to lower case
  */
 static inline wchar_t
-UniTolower(wchar_t uc)
+UniTolower(register wchar_t uc)
 {
-       register struct UniCaseRange *rp;
+       register const struct UniCaseRange *rp;
 
-       if (uc < sizeof(UniLowerTable)) {
+       if (uc < sizeof(CifsUniLowerTable)) {
                /* Latin characters */
-               return uc + UniLowerTable[uc];  /* Use base tables */
+               return uc + CifsUniLowerTable[uc];      /* Use base tables */
        } else {
-               rp = UniLowerRange;     /* Use range tables */
+               rp = CifsUniLowerRange; /* Use range tables */
                while (rp->start) {
                        if (uc < rp->start)     /* Before start of range */
                                return uc;      /* Uppercase = input */
@@ -374,3 +376,5 @@ UniStrlwr(register wchar_t *upin)
 }
 
 #endif
+
+#endif /* _CIFS_UNICODE_H */
index 18a9d978e5190dfc9e3974fdf46f193d0c29d8b6..0ac7c5a8633a777dd1d804138ea82aff9f957521 100644 (file)
@@ -140,7 +140,7 @@ const struct UniCaseRange CifsUniUpperRange[] = {
 /*
  * Latin lower case
  */
-static signed char CifsUniLowerTable[512] = {
+signed char CifsUniLowerTable[512] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
@@ -242,12 +242,12 @@ static signed char UniCaseRangeLff20[27] = {
 /*
  * Lower Case Range
  */
-static const struct UniCaseRange CifsUniLowerRange[] = {
-       0x0380, 0x03ab, UniCaseRangeL0380,
-       0x0400, 0x042f, UniCaseRangeL0400,
-       0x0490, 0x04cb, UniCaseRangeL0490,
-       0x1e00, 0x1ff7, UniCaseRangeL1e00,
-       0xff20, 0xff3a, UniCaseRangeLff20,
-       0, 0, 0
+const struct UniCaseRange CifsUniLowerRange[] = {
+       {0x0380, 0x03ab, UniCaseRangeL0380},
+       {0x0400, 0x042f, UniCaseRangeL0400},
+       {0x0490, 0x04cb, UniCaseRangeL0490},
+       {0x1e00, 0x1ff7, UniCaseRangeL1e00},
+       {0xff20, 0xff3a, UniCaseRangeLff20},
+       {0}
 };
 #endif
index 847628dfdc44fa95c5c0ea232b8b28ccb03347e3..35042d8f733865c77b31ee8d10dd097d4f0a16d8 100644 (file)
@@ -223,63 +223,6 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
        return 0;
 }
 
-int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
-                              const struct nls_table *nls_info)
-{
-       char temp_hash[16];
-       struct HMACMD5Context ctx;
-       char *ucase_buf;
-       __le16 *unicode_buf;
-       unsigned int i, user_name_len, dom_name_len;
-
-       if (ses == NULL)
-               return -EINVAL;
-
-       E_md4hash(ses->password, temp_hash);
-
-       hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
-       user_name_len = strlen(ses->userName);
-       if (user_name_len > MAX_USERNAME_SIZE)
-               return -EINVAL;
-       if (ses->domainName == NULL)
-               return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
-       dom_name_len = strlen(ses->domainName);
-       if (dom_name_len > MAX_USERNAME_SIZE)
-               return -EINVAL;
-
-       ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
-       if (ucase_buf == NULL)
-               return -ENOMEM;
-       unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
-       if (unicode_buf == NULL) {
-               kfree(ucase_buf);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < user_name_len; i++)
-               ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
-       ucase_buf[i] = 0;
-       user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
-                                     MAX_USERNAME_SIZE*2, nls_info);
-       unicode_buf[user_name_len] = 0;
-       user_name_len++;
-
-       for (i = 0; i < dom_name_len; i++)
-               ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
-       ucase_buf[i] = 0;
-       dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
-                                    MAX_USERNAME_SIZE*2, nls_info);
-
-       unicode_buf[user_name_len + dom_name_len] = 0;
-       hmac_md5_update((const unsigned char *) unicode_buf,
-               (user_name_len+dom_name_len)*2, &ctx);
-
-       hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
-       kfree(ucase_buf);
-       kfree(unicode_buf);
-       return 0;
-}
-
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
                        char *lnm_session_key)
index b7431afdd76d57fb17ef70385428dd5c132020f2..50208c15309a7321b15e0d0adc417c34e1994143 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -200,8 +199,6 @@ cifs_put_super(struct super_block *sb)
                return;
        }
 
-       lock_kernel();
-
        rc = cifs_umount(sb, cifs_sb);
        if (rc)
                cERROR(1, "cifs_umount failed with return code %d", rc);
@@ -215,8 +212,6 @@ cifs_put_super(struct super_block *sb)
        unload_nls(cifs_sb->local_nls);
        bdi_destroy(&cifs_sb->bdi);
        kfree(cifs_sb);
-
-       unlock_kernel();
 }
 
 static int
@@ -514,7 +509,9 @@ cifs_get_sb(struct file_system_type *fs_type,
            int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
        int rc;
-       struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
+       struct super_block *sb;
+
+       sb = sget(fs_type, NULL, set_anon_super, NULL);
 
        cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
 
@@ -565,8 +562,8 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 
 static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
 {
-       /* note that this is called by vfs setlease with the BKL held
-          although I doubt that BKL is needed here in cifs */
+       /* note that this is called by vfs setlease with lock_flocks held
+          to protect *lease from going away */
        struct inode *inode = file->f_path.dentry->d_inode;
 
        if (!(S_ISREG(inode->i_mode)))
index 1f5450814087bed34651f0c2ac4834d8251d63e6..1d60c655e3e0b70fc54ab5a48c2b6f3ffd01477c 100644 (file)
@@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
                        struct TCP_Server_Info *server);
 extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
+extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
 extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
-                               unsigned short int port);
+                               const unsigned short int port);
 extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
                            const struct cifsTconInfo *, int /* length of
@@ -365,8 +366,6 @@ extern int cifs_verify_signature(struct smb_hdr *,
                                __u32 expected_sequence_number);
 extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
                                 const char *pass);
-extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
-                       const struct nls_table *);
 extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
 extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
                             const struct nls_table *);
index c65c3419dd3703f12bb4994e9333c085c907ecfa..7e83b356cc9e3a93c2bc1b0e915d118884170474 100644 (file)
@@ -232,7 +232,7 @@ static int
 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                void **request_buf)
 {
-       int rc = 0;
+       int rc;
 
        rc = cifs_reconnect_tcon(tcon, smb_command);
        if (rc)
@@ -250,7 +250,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
 
-       return rc;
+       return 0;
 }
 
 int
@@ -281,16 +281,9 @@ small_smb_init_no_tc(const int smb_command, const int wct,
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
-smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
-        void **request_buf /* returned */ ,
-        void **response_buf /* returned */ )
+__smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+                       void **request_buf, void **response_buf)
 {
-       int rc = 0;
-
-       rc = cifs_reconnect_tcon(tcon, smb_command);
-       if (rc)
-               return rc;
-
        *request_buf = cifs_buf_get();
        if (*request_buf == NULL) {
                /* BB should we add a retry in here if not a writepage? */
@@ -309,7 +302,31 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
 
-       return rc;
+       return 0;
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+        void **request_buf, void **response_buf)
+{
+       int rc;
+
+       rc = cifs_reconnect_tcon(tcon, smb_command);
+       if (rc)
+               return rc;
+
+       return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
+}
+
+static int
+smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
+                       void **request_buf, void **response_buf)
+{
+       if (tcon->ses->need_reconnect || tcon->need_reconnect)
+               return -EHOSTDOWN;
+
+       return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 }
 
 static int validate_t2(struct smb_t2_rsp *pSMB)
@@ -4534,8 +4551,8 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
 
        cFYI(1, "In QFSUnixInfo");
 QFSUnixRetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+                                  (void **) &pSMB, (void **) &pSMBr);
        if (rc)
                return rc;
 
@@ -4604,8 +4621,8 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
        cFYI(1, "In SETFSUnixInfo");
 SETFSUnixRetry:
        /* BB switch to small buf init to save memory */
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+                                       (void **) &pSMB, (void **) &pSMBr);
        if (rc)
                return rc;
 
index 95c2ea67edfb8f240d286885caddd51031aa82fc..88c84a38bccb182c313316a172bbae39ba2ee38f 100644 (file)
@@ -400,7 +400,9 @@ incomplete_rcv:
                        cFYI(1, "call to reconnect done");
                        csocket = server->ssocket;
                        continue;
-               } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
+               } else if (length == -ERESTARTSYS ||
+                          length == -EAGAIN ||
+                          length == -EINTR) {
                        msleep(1); /* minimum sleep to prevent looping
                                allowing socket to clear and app threads to set
                                tcpStatus CifsNeedReconnect if server hung */
@@ -414,18 +416,6 @@ incomplete_rcv:
                        } else
                                continue;
                } else if (length <= 0) {
-                       if (server->tcpStatus == CifsNew) {
-                               cFYI(1, "tcp session abend after SMBnegprot");
-                               /* some servers kill the TCP session rather than
-                                  returning an SMB negprot error, in which
-                                  case reconnecting here is not going to help,
-                                  and so simply return error to mount */
-                               break;
-                       }
-                       if (!try_to_freeze() && (length == -EINTR)) {
-                               cFYI(1, "cifsd thread killed");
-                               break;
-                       }
                        cFYI(1, "Reconnect after unexpected peek error %d",
                                length);
                        cifs_reconnect(server);
@@ -466,27 +456,19 @@ incomplete_rcv:
                           an error on SMB negprot response */
                        cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
                                pdu_length);
-                       if (server->tcpStatus == CifsNew) {
-                               /* if nack on negprot (rather than
-                               ret of smb negprot error) reconnecting
-                               not going to help, ret error to mount */
-                               break;
-                       } else {
-                               /* give server a second to
-                               clean up before reconnect attempt */
-                               msleep(1000);
-                               /* always try 445 first on reconnect
-                               since we get NACK on some if we ever
-                               connected to port 139 (the NACK is
-                               since we do not begin with RFC1001
-                               session initialize frame) */
-                               server->addr.sockAddr.sin_port =
-                                       htons(CIFS_PORT);
-                               cifs_reconnect(server);
-                               csocket = server->ssocket;
-                               wake_up(&server->response_q);
-                               continue;
-                       }
+                       /* give server a second to clean up  */
+                       msleep(1000);
+                       /* always try 445 first on reconnect since we get NACK
+                        * on some if we ever connected to port 139 (the NACK
+                        * is since we do not begin with RFC1001 session
+                        * initialize frame)
+                        */
+                       cifs_set_port((struct sockaddr *)
+                                       &server->addr.sockAddr, CIFS_PORT);
+                       cifs_reconnect(server);
+                       csocket = server->ssocket;
+                       wake_up(&server->response_q);
+                       continue;
                } else if (temp != (char) 0) {
                        cERROR(1, "Unknown RFC 1002 frame");
                        cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
@@ -522,8 +504,7 @@ incomplete_rcv:
                     total_read += length) {
                        length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
                                                pdu_length - total_read, 0);
-                       if ((server->tcpStatus == CifsExiting) ||
-                           (length == -EINTR)) {
+                       if (server->tcpStatus == CifsExiting) {
                                /* then will exit */
                                reconnect = 2;
                                break;
@@ -534,8 +515,9 @@ incomplete_rcv:
                                /* Now we will reread sock */
                                reconnect = 1;
                                break;
-                       } else if ((length == -ERESTARTSYS) ||
-                                  (length == -EAGAIN)) {
+                       } else if (length == -ERESTARTSYS ||
+                                  length == -EAGAIN ||
+                                  length == -EINTR) {
                                msleep(1); /* minimum sleep to prevent looping,
                                              allowing socket to clear and app
                                              threads to set tcpStatus
@@ -1673,7 +1655,9 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
                                    MAX_USERNAME_SIZE))
                                continue;
                        if (strlen(vol->username) != 0 &&
-                           strncmp(ses->password, vol->password,
+                           ses->password != NULL &&
+                           strncmp(ses->password,
+                                   vol->password ? vol->password : "",
                                    MAX_PASSWORD_SIZE))
                                continue;
                }
@@ -1722,9 +1706,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
        if (ses) {
                cFYI(1, "Existing smb sess found (status=%d)", ses->status);
 
-               /* existing SMB ses has a server reference already */
-               cifs_put_tcp_session(server);
-
                mutex_lock(&ses->session_mutex);
                rc = cifs_negotiate_protocol(xid, ses);
                if (rc) {
@@ -1747,6 +1728,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
                        }
                }
                mutex_unlock(&ses->session_mutex);
+
+               /* existing SMB ses has a server reference already */
+               cifs_put_tcp_session(server);
                FreeXid(xid);
                return ses;
        }
index 578d88c5b46e7eae539fb04aede8f59b7c9dac53..f9ed0751cc12cb6f93e498b526c07e215bb91138 100644 (file)
@@ -305,8 +305,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-               FreeXid(xid);
-               return rc;
+               goto cifs_create_out;
        }
 
        if (oplockEnabled)
@@ -365,9 +364,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 
        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
        if (buf == NULL) {
-               kfree(full_path);
-               FreeXid(xid);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto cifs_create_out;
        }
 
        /*
@@ -496,6 +494,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
        struct cifsTconInfo *pTcon;
        char *full_path = NULL;
        struct inode *newinode = NULL;
+       int oplock = 0;
+       u16 fileHandle;
+       FILE_ALL_INFO *buf = NULL;
+       unsigned int bytes_written;
+       struct win_dev *pdev;
 
        if (!old_valid_dev(device_number))
                return -EINVAL;
@@ -506,9 +509,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
        pTcon = cifs_sb->tcon;
 
        full_path = build_path_from_dentry(direntry);
-       if (full_path == NULL)
+       if (full_path == NULL) {
                rc = -ENOMEM;
-       else if (pTcon->unix_ext) {
+               goto mknod_out;
+       }
+
+       if (pTcon->unix_ext) {
                struct cifs_unix_set_info_args args = {
                        .mode   = mode & ~current_umask(),
                        .ctime  = NO_CHANGE_64,
@@ -527,87 +533,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
                                            cifs_sb->local_nls,
                                            cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (rc)
+                       goto mknod_out;
 
-               if (!rc) {
-                       rc = cifs_get_inode_info_unix(&newinode, full_path,
+               rc = cifs_get_inode_info_unix(&newinode, full_path,
                                                inode->i_sb, xid);
-                       if (pTcon->nocase)
-                               direntry->d_op = &cifs_ci_dentry_ops;
-                       else
-                               direntry->d_op = &cifs_dentry_ops;
-                       if (rc == 0)
-                               d_instantiate(direntry, newinode);
-               }
-       } else {
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
-                       int oplock = 0;
-                       u16 fileHandle;
-                       FILE_ALL_INFO *buf;
+               if (pTcon->nocase)
+                       direntry->d_op = &cifs_ci_dentry_ops;
+               else
+                       direntry->d_op = &cifs_dentry_ops;
 
-                       cFYI(1, "sfu compat create special file");
+               if (rc == 0)
+                       d_instantiate(direntry, newinode);
+               goto mknod_out;
+       }
 
-                       buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-                       if (buf == NULL) {
-                               kfree(full_path);
-                               rc = -ENOMEM;
-                               FreeXid(xid);
-                               return rc;
-                       }
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+               goto mknod_out;
 
-                       rc = CIFSSMBOpen(xid, pTcon, full_path,
-                                        FILE_CREATE, /* fail if exists */
-                                        GENERIC_WRITE /* BB would
-                                         WRITE_OWNER | WRITE_DAC be better? */,
-                                        /* Create a file and set the
-                                           file attribute to SYSTEM */
-                                        CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
-                                        &fileHandle, &oplock, buf,
-                                        cifs_sb->local_nls,
-                                        cifs_sb->mnt_cifs_flags &
-                                           CIFS_MOUNT_MAP_SPECIAL_CHR);
-
-                       /* BB FIXME - add handling for backlevel servers
-                          which need legacy open and check for all
-                          calls to SMBOpen for fallback to SMBLeagcyOpen */
-                       if (!rc) {
-                               /* BB Do not bother to decode buf since no
-                                  local inode yet to put timestamps in,
-                                  but we can reuse it safely */
-                               unsigned int bytes_written;
-                               struct win_dev *pdev;
-                               pdev = (struct win_dev *)buf;
-                               if (S_ISCHR(mode)) {
-                                       memcpy(pdev->type, "IntxCHR", 8);
-                                       pdev->major =
-                                             cpu_to_le64(MAJOR(device_number));
-                                       pdev->minor =
-                                             cpu_to_le64(MINOR(device_number));
-                                       rc = CIFSSMBWrite(xid, pTcon,
-                                               fileHandle,
-                                               sizeof(struct win_dev),
-                                               0, &bytes_written, (char *)pdev,
-                                               NULL, 0);
-                               } else if (S_ISBLK(mode)) {
-                                       memcpy(pdev->type, "IntxBLK", 8);
-                                       pdev->major =
-                                             cpu_to_le64(MAJOR(device_number));
-                                       pdev->minor =
-                                             cpu_to_le64(MINOR(device_number));
-                                       rc = CIFSSMBWrite(xid, pTcon,
-                                               fileHandle,
-                                               sizeof(struct win_dev),
-                                               0, &bytes_written, (char *)pdev,
-                                               NULL, 0);
-                               } /* else if(S_ISFIFO */
-                               CIFSSMBClose(xid, pTcon, fileHandle);
-                               d_drop(direntry);
-                       }
-                       kfree(buf);
-                       /* add code here to set EAs */
-               }
+
+       cFYI(1, "sfu compat create special file");
+
+       buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+       if (buf == NULL) {
+               kfree(full_path);
+               rc = -ENOMEM;
+               FreeXid(xid);
+               return rc;
        }
 
+       /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
+       rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
+                        GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
+                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
+                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if (rc)
+               goto mknod_out;
+
+       /* BB Do not bother to decode buf since no local inode yet to put
+        * timestamps in, but we can reuse it safely */
+
+       pdev = (struct win_dev *)buf;
+       if (S_ISCHR(mode)) {
+               memcpy(pdev->type, "IntxCHR", 8);
+               pdev->major =
+                     cpu_to_le64(MAJOR(device_number));
+               pdev->minor =
+                     cpu_to_le64(MINOR(device_number));
+               rc = CIFSSMBWrite(xid, pTcon,
+                       fileHandle,
+                       sizeof(struct win_dev),
+                       0, &bytes_written, (char *)pdev,
+                       NULL, 0);
+       } else if (S_ISBLK(mode)) {
+               memcpy(pdev->type, "IntxBLK", 8);
+               pdev->major =
+                     cpu_to_le64(MAJOR(device_number));
+               pdev->minor =
+                     cpu_to_le64(MINOR(device_number));
+               rc = CIFSSMBWrite(xid, pTcon,
+                       fileHandle,
+                       sizeof(struct win_dev),
+                       0, &bytes_written, (char *)pdev,
+                       NULL, 0);
+       } /* else if (S_ISFIFO) */
+       CIFSSMBClose(xid, pTcon, fileHandle);
+       d_drop(direntry);
+
+       /* FIXME: add code here to set EAs */
+
+mknod_out:
        kfree(full_path);
+       kfree(buf);
        FreeXid(xid);
        return rc;
 }
index db11fdef0e92b1ca52a75fb033f03dda24e8f6a5..de748c652d11f4fca214b2aed62c8ad1639ae2dc 100644 (file)
@@ -242,8 +242,7 @@ int cifs_open(struct inode *inode, struct file *file)
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-               FreeXid(xid);
-               return rc;
+               goto out;
        }
 
        cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
index 4bc47e5b5f29af38d601f699face0e1f16b31a9f..53cce8cc2224f4abe4754d2cc320a05a6f36d215 100644 (file)
@@ -801,6 +801,8 @@ retry_iget5_locked:
                        inode->i_flags |= S_NOATIME | S_NOCMTIME;
                if (inode->i_state & I_NEW) {
                        inode->i_ino = hash;
+                       if (S_ISREG(inode->i_mode))
+                               inode->i_data.backing_dev_info = sb->s_bdi;
 #ifdef CONFIG_CIFS_FSCACHE
                        /* initialize per-inode cache cookie pointer */
                        CIFS_I(inode)->fscache = NULL;
@@ -834,7 +836,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
                                                xid, NULL);
 
        if (!inode)
-               return ERR_PTR(-ENOMEM);
+               return ERR_PTR(rc);
 
 #ifdef CONFIG_CIFS_FSCACHE
        /* populate tcon->resource_id */
@@ -1462,28 +1464,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 {
        char *fromName = NULL;
        char *toName = NULL;
-       struct cifs_sb_info *cifs_sb_source;
-       struct cifs_sb_info *cifs_sb_target;
+       struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *tcon;
        FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
        FILE_UNIX_BASIC_INFO *info_buf_target;
        int xid, rc, tmprc;
 
-       cifs_sb_target = CIFS_SB(target_dir->i_sb);
-       cifs_sb_source = CIFS_SB(source_dir->i_sb);
-       tcon = cifs_sb_source->tcon;
+       cifs_sb = CIFS_SB(source_dir->i_sb);
+       tcon = cifs_sb->tcon;
 
        xid = GetXid();
 
-       /*
-        * BB: this might be allowed if same server, but different share.
-        * Consider adding support for this
-        */
-       if (tcon != cifs_sb_target->tcon) {
-               rc = -EXDEV;
-               goto cifs_rename_exit;
-       }
-
        /*
         * we already have the rename sem so we do not need to
         * grab it again here to protect the path integrity
@@ -1519,17 +1510,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
                info_buf_target = info_buf_source + 1;
                tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
                                        info_buf_source,
-                                       cifs_sb_source->local_nls,
-                                       cifs_sb_source->mnt_cifs_flags &
+                                       cifs_sb->local_nls,
+                                       cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
                if (tmprc != 0)
                        goto unlink_target;
 
-               tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
-                                       toName, info_buf_target,
-                                       cifs_sb_target->local_nls,
-                                       /* remap based on source sb */
-                                       cifs_sb_source->mnt_cifs_flags &
+               tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
+                                       info_buf_target,
+                                       cifs_sb->local_nls,
+                                       cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 
                if (tmprc == 0 && (info_buf_source->UniqueId ==
index f97851119e6c1b965530f57062b3ae97b53f4e00..9aad47a2d62f6d861035e1ce0b8b6876804aed61 100644 (file)
@@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len)
 }
 
 int
-cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
-                  const unsigned short int port)
+cifs_set_port(struct sockaddr *addr, const unsigned short int port)
 {
-       if (!cifs_convert_address(dst, src, len))
-               return 0;
-
-       switch (dst->sa_family) {
+       switch (addr->sa_family) {
        case AF_INET:
-               ((struct sockaddr_in *)dst)->sin_port = htons(port);
+               ((struct sockaddr_in *)addr)->sin_port = htons(port);
                break;
        case AF_INET6:
-               ((struct sockaddr_in6 *)dst)->sin6_port = htons(port);
+               ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
                break;
        default:
                return 0;
        }
-
        return 1;
 }
 
+int
+cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
+                  const unsigned short int port)
+{
+       if (!cifs_convert_address(dst, src, len))
+               return 0;
+       return cifs_set_port(dst, port);
+}
+
 /*****************************************************************************
 convert a NT status code to a dos class/code
  *****************************************************************************/
index 6526e6f21ecfb22f23a5b19efb5b9d82287cef49..bfe8179b1295e76ea4433fce9d2533e240eed840 100644 (file)
@@ -148,6 +148,8 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        int error;
        int idx;
 
+       lock_kernel();
+
        idx = get_device_index((struct coda_mount_data *) data);
 
        /* Ignore errors in data, for backward compatibility */
@@ -159,11 +161,13 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        vc = &coda_comms[idx];
        if (!vc->vc_inuse) {
                printk("coda_read_super: No pseudo device\n");
+               unlock_kernel();
                return -EINVAL;
        }
 
         if ( vc->vc_sb ) {
                printk("coda_read_super: Device already mounted\n");
+               unlock_kernel();
                return -EBUSY;
        }
 
@@ -202,7 +206,8 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_root = d_alloc_root(root);
        if (!sb->s_root)
                goto error;
-        return 0;
+       unlock_kernel();
+       return 0;
 
  error:
        bdi_destroy(&vc->bdi);
@@ -212,6 +217,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        if (vc)
                vc->vc_sb = NULL;
 
+       unlock_kernel();
        return -EINVAL;
 }
 
index ca25d96d45c9a51caa6d63d33f6670eaa769fcbc..028a9a0f588b2664cee7ab65a3a7f8ccc88af61c 100644 (file)
@@ -39,6 +39,7 @@ const struct inode_operations coda_ioctl_inode_operations = {
 const struct file_operations coda_ioctl_operations = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = coda_pioctl,
+       .llseek         = noop_llseek,
 };
 
 /* the coda pioctl inode ops */
index de89645777c7c2b06cb62b3657cd72b26a9c4f9e..fdc2f3ef7ecd6768d856511fb1cf12e7689282a5 100644 (file)
@@ -184,8 +184,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
        }
 
        /* adjust outsize. is this useful ?? */
-        req->uc_outSize = nbytes;      
-        req->uc_flags |= REQ_WRITE;
+       req->uc_outSize = nbytes;
+       req->uc_flags |= CODA_REQ_WRITE;
        count = nbytes;
 
        /* Convert filedescriptor into a file handle */
@@ -346,6 +346,7 @@ static const struct file_operations coda_psdev_fops = {
        .unlocked_ioctl = coda_psdev_ioctl,
        .open           = coda_psdev_open,
        .release        = coda_psdev_release,
+       .llseek         = noop_llseek,
 };
 
 static int init_coda_psdev(void)
index 718c7062aec129844cda361e2f4b8a143aa31861..0644a154672b93012a4d7a7f864ba7f505b43213 100644 (file)
@@ -1153,7 +1153,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
 {
        compat_ssize_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov;
+       struct iovec *iov = iovstack;
        ssize_t ret;
        io_fn_t fn;
        iov_fn_t fnv;
index 03e59aa318eb0a2c9801857a9d343fa008fdc7a2..d0ad09d57789c2e72b4f6eeda2c09535651bfe8e 100644 (file)
@@ -599,69 +599,6 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd,
 #define HIDPGETCONNLIST        _IOR('H', 210, int)
 #define HIDPGETCONNINFO        _IOR('H', 211, int)
 
-#ifdef CONFIG_BLOCK
-struct raw32_config_request
-{
-        compat_int_t    raw_minor;
-        __u64   block_major;
-        __u64   block_minor;
-} __attribute__((packed));
-
-static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __get_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __get_user(req->block_major, &user_req->block_major);
-        ret |= __get_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-       int ret;
-
-        if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __put_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __put_user(req->block_major, &user_req->block_major);
-        ret |= __put_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int raw_ioctl(unsigned fd, unsigned cmd,
-               struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        switch (cmd) {
-        case RAW_SETBIND:
-       default: {      /* RAW_GETBIND */
-                struct raw_config_request req;
-                mm_segment_t oldfs = get_fs();
-
-                if ((ret = get_raw32_request(&req, user_req)))
-                        return ret;
-
-                set_fs(KERNEL_DS);
-                ret = sys_ioctl(fd,cmd,(unsigned long)&req);
-                set_fs(oldfs);
-
-                if ((!ret) && (cmd == RAW_GETBIND)) {
-                        ret = set_raw32_request(&req, user_req);
-                }
-                break;
-        }
-        }
-        return ret;
-}
-#endif /* CONFIG_BLOCK */
 
 struct serial_struct32 {
         compat_int_t    type;
@@ -1262,9 +1199,6 @@ COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
 COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
 COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
 COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* Raw devices */
-COMPATIBLE_IOCTL(RAW_SETBIND)
-COMPATIBLE_IOCTL(RAW_GETBIND)
 /* SMB ioctls which do not need any translations */
 COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
 /* Watchdog */
@@ -1523,10 +1457,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
        case MTIOCGET32:
        case MTIOCPOS32:
                return mt_ioctl_trans(fd, cmd, argp);
-       /* Raw devices */
-       case RAW_SETBIND:
-       case RAW_GETBIND:
-               return raw_ioctl(fd, cmd, argp);
 #endif
        /* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
index 0210898458b27286e403266e705ec1cd3396218b..89d394d8fe24c5b35fbdf71cfbef4bade56415b3 100644 (file)
@@ -43,6 +43,7 @@ const struct file_operations debugfs_file_operations = {
        .read =         default_read_file,
        .write =        default_write_file,
        .open =         default_open,
+       .llseek =       noop_llseek,
 };
 
 static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -454,6 +455,7 @@ static const struct file_operations fops_bool = {
        .read =         read_file_bool,
        .write =        write_file_bool,
        .open =         default_open,
+       .llseek =       default_llseek,
 };
 
 /**
@@ -498,6 +500,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf,
 static const struct file_operations fops_blob = {
        .read =         read_file_blob,
        .open =         default_open,
+       .llseek =       default_llseek,
 };
 
 /**
index 51f270b479b6938a4a730ea56f9011c30f99563f..48d74c7391d13f4f07393c45d19825e937ecbcd1 100644 (file)
@@ -634,7 +634,7 @@ static int dio_send_cur_page(struct dio *dio)
        int ret = 0;
 
        if (dio->bio) {
-               loff_t cur_offset = dio->block_in_file << dio->blkbits;
+               loff_t cur_offset = dio->cur_page_fs_offset;
                loff_t bio_next_offset = dio->logical_offset_in_bio +
                        dio->bio->bi_size;
 
@@ -659,7 +659,7 @@ static int dio_send_cur_page(struct dio *dio)
                 * Submit now if the underlying fs is about to perform a
                 * metadata read
                 */
-               if (dio->boundary)
+               else if (dio->boundary)
                        dio_bio_submit(dio);
        }
 
index c6cf251587467dc9af1c12c7391c6e529fa4249a..6b42ba807dfda1747f7cae9fa0ecf7a3c400b5f2 100644 (file)
@@ -643,7 +643,8 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
 static const struct file_operations waiters_fops = {
        .owner   = THIS_MODULE,
        .open    = waiters_open,
-       .read    = waiters_read
+       .read    = waiters_read,
+       .llseek  = default_llseek,
 };
 
 void dlm_delete_debug_file(struct dlm_ls *ls)
index d45c02db694393a1989119ec510709b653dd76e9..30d8b85febbf1eb413333bddac0b365b29b676d3 100644 (file)
@@ -412,7 +412,8 @@ static const struct file_operations dev_fops = {
        .read    = dev_read,
        .write   = dev_write,
        .poll    = dev_poll,
-       .owner   = THIS_MODULE
+       .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice plock_dev_misc = {
index b6272853130c5c04b6562bc185170324155cc2e9..66d6c16bf440b480c57b11ca8cf4ada22f7c65fc 100644 (file)
@@ -1009,6 +1009,7 @@ static const struct file_operations device_fops = {
        .write   = device_write,
        .poll    = device_poll,
        .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static const struct file_operations ctl_device_fops = {
@@ -1017,6 +1018,7 @@ static const struct file_operations ctl_device_fops = {
        .read    = device_read,
        .write   = device_write,
        .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice ctl_device = {
@@ -1029,6 +1031,7 @@ static const struct file_operations monitor_device_fops = {
        .open    = monitor_device_open,
        .release = monitor_device_close,
        .owner   = THIS_MODULE,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice monitor_device = {
index a2e3b562e65d996f62d1ef15eaa9c6e5a7a2293f..cbadc1bee6e7ecceeefa5131143e08783d006297 100644 (file)
@@ -1793,7 +1793,7 @@ struct kmem_cache *ecryptfs_key_tfm_cache;
 static struct list_head key_tfm_list;
 struct mutex key_tfm_list_mutex;
 
-int ecryptfs_init_crypto(void)
+int __init ecryptfs_init_crypto(void)
 {
        mutex_init(&key_tfm_list_mutex);
        INIT_LIST_HEAD(&key_tfm_list);
@@ -2169,7 +2169,6 @@ int ecryptfs_encrypt_and_encode_filename(
                                (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE
                                 + encoded_name_no_prefix_size);
                        (*encoded_name)[(*encoded_name_size)] = '\0';
-                       (*encoded_name_size)++;
                } else {
                        rc = -EOPNOTSUPP;
                }
index 622c95140802c33d18713e16eb29b7f23c498104..91da02987bffef3aa07638d9dd9a8587a7b5a5b2 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
-#include <linux/smp_lock.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -284,11 +283,9 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
        int rc = 0;
        struct file *lower_file = NULL;
 
-       lock_kernel();
        lower_file = ecryptfs_file_to_lower(file);
        if (lower_file->f_op && lower_file->f_op->fasync)
                rc = lower_file->f_op->fasync(fd, lower_file, flag);
-       unlock_kernel();
        return rc;
 }
 
@@ -332,6 +329,7 @@ const struct file_operations ecryptfs_dir_fops = {
        .fsync = ecryptfs_fsync,
        .fasync = ecryptfs_fasync,
        .splice_read = generic_file_splice_read,
+       .llseek = default_llseek,
 };
 
 const struct file_operations ecryptfs_main_fops = {
index 6c55113e72222cf473f92b16277056561ebbf55d..3fbc94203380acf8e6095627ee610ff058df5f38 100644 (file)
@@ -349,7 +349,7 @@ out:
 
 /**
  * ecryptfs_new_lower_dentry
- * @ename: The name of the new dentry.
+ * @name: The name of the new dentry.
  * @lower_dir_dentry: Parent directory of the new dentry.
  * @nd: nameidata from last lookup.
  *
@@ -386,20 +386,19 @@ ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry,
  * ecryptfs_lookup_one_lower
  * @ecryptfs_dentry: The eCryptfs dentry that we are looking up
  * @lower_dir_dentry: lower parent directory
+ * @name: lower file name
  *
  * Get the lower dentry from vfs. If lower dentry does not exist yet,
  * create it.
  */
 static struct dentry *
 ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry,
-                         struct dentry *lower_dir_dentry)
+                         struct dentry *lower_dir_dentry, struct qstr *name)
 {
        struct nameidata nd;
        struct vfsmount *lower_mnt;
-       struct qstr *name;
        int err;
 
-       name = &ecryptfs_dentry->d_name;
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
                                    ecryptfs_dentry->d_parent));
        err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd);
@@ -434,6 +433,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
        size_t encrypted_and_encoded_name_size;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
        struct dentry *lower_dir_dentry, *lower_dentry;
+       struct qstr lower_name;
        int rc = 0;
 
        ecryptfs_dentry->d_op = &ecryptfs_dops;
@@ -444,9 +444,17 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                goto out_d_drop;
        }
        lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
-
+       lower_name.name = ecryptfs_dentry->d_name.name;
+       lower_name.len = ecryptfs_dentry->d_name.len;
+       lower_name.hash = ecryptfs_dentry->d_name.hash;
+       if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
+               rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
+                                                   &lower_name);
+               if (rc < 0)
+                       goto out_d_drop;
+       }
        lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry,
-                                                lower_dir_dentry);
+                                                lower_dir_dentry, &lower_name);
        if (IS_ERR(lower_dentry)) {
                rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned "
@@ -471,8 +479,17 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                       "filename; rc = [%d]\n", __func__, rc);
                goto out_d_drop;
        }
+       lower_name.name = encrypted_and_encoded_name;
+       lower_name.len = encrypted_and_encoded_name_size;
+       lower_name.hash = full_name_hash(lower_name.name, lower_name.len);
+       if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
+               rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
+                                                   &lower_name);
+               if (rc < 0)
+                       goto out_d_drop;
+       }
        lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry,
-                                                lower_dir_dentry);
+                                                lower_dir_dentry, &lower_name);
        if (IS_ERR(lower_dentry)) {
                rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned "
index 89c5476506ef36c8c3de7520565b8360d70eb83b..73811cfa2ea4369766a99a251c614ddb091bc8f4 100644 (file)
@@ -515,6 +515,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
        if (!s) {
                printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc "
                       "[%zd] bytes of kernel memory\n", __func__, sizeof(*s));
+               rc = -ENOMEM;
                goto out;
        }
        s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -806,6 +807,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
        if (!s) {
                printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc "
                       "[%zd] bytes of kernel memory\n", __func__, sizeof(*s));
+               rc = -ENOMEM;
                goto out;
        }
        s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
index d8c3a373aafa40547090427c0ae1e96b73f49dbe..0851ab6980f54038b8f0ed9239712fea573622c5 100644 (file)
@@ -86,7 +86,7 @@ out:
        return 0;
 }
 
-int ecryptfs_init_kthread(void)
+int __init ecryptfs_init_kthread(void)
 {
        int rc = 0;
 
index bcb68c0cb1f0fed8ac5300c804b304879b08ae22..ab2248090515534dfd47b940b83aef63c696b545 100644 (file)
@@ -473,7 +473,7 @@ sleep:
        return rc;
 }
 
-int ecryptfs_init_messaging(void)
+int __init ecryptfs_init_messaging(void)
 {
        int i;
        int rc = 0;
index 3745f612bcd438cb477f8bb245afeb5f47495f89..940a82e63dc3fcdc52797f9176842fdbf391d272 100644 (file)
@@ -482,6 +482,7 @@ static const struct file_operations ecryptfs_miscdev_fops = {
        .read    = ecryptfs_miscdev_read,
        .write   = ecryptfs_miscdev_write,
        .release = ecryptfs_miscdev_release,
+       .llseek  = noop_llseek,
 };
 
 static struct miscdevice ecryptfs_miscdev = {
@@ -500,7 +501,7 @@ static struct miscdevice ecryptfs_miscdev = {
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_init_ecryptfs_miscdev(void)
+int __init ecryptfs_init_ecryptfs_miscdev(void)
 {
        int rc;
 
index 6bd3f76fdf881ffc4973bc2d7a0d8346a3464bba..e0194b3e14d6ba28d42d0ae7352923d7102760cb 100644 (file)
@@ -293,6 +293,7 @@ static const struct file_operations eventfd_fops = {
        .poll           = eventfd_poll,
        .read           = eventfd_read,
        .write          = eventfd_write,
+       .llseek         = noop_llseek,
 };
 
 /**
index 3817149919cb81fa298686f183f67e0c86fe1c50..256bb7bb102a0d2221fe4b9b8d2b533949d069c1 100644 (file)
@@ -674,7 +674,8 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
 /* File callbacks that implement the eventpoll file behaviour */
 static const struct file_operations eventpoll_fops = {
        .release        = ep_eventpoll_release,
-       .poll           = ep_eventpoll_poll
+       .poll           = ep_eventpoll_poll,
+       .llseek         = noop_llseek,
 };
 
 /* Fast test to see if the file is an evenpoll file */
index 2d9455282744bce582e48e0ecec4f4a6d332a28c..6d2b6f93685813ba2b2119dc71c14a941061cf46 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -376,6 +376,9 @@ static int count(const char __user * const __user * argv, int max)
                        argv++;
                        if (i++ >= max)
                                return -E2BIG;
+
+                       if (fatal_signal_pending(current))
+                               return -ERESTARTNOHAND;
                        cond_resched();
                }
        }
@@ -419,6 +422,12 @@ static int copy_strings(int argc, const char __user *const __user *argv,
                while (len > 0) {
                        int offset, bytes_to_copy;
 
+                       if (fatal_signal_pending(current)) {
+                               ret = -ERESTARTNOHAND;
+                               goto out;
+                       }
+                       cond_resched();
+
                        offset = pos % PAGE_SIZE;
                        if (offset == 0)
                                offset = PAGE_SIZE;
@@ -594,6 +603,11 @@ int setup_arg_pages(struct linux_binprm *bprm,
 #else
        stack_top = arch_align_stack(stack_top);
        stack_top = PAGE_ALIGN(stack_top);
+
+       if (unlikely(stack_top < mmap_min_addr) ||
+           unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
+               return -ENOMEM;
+
        stack_shift = vma->vm_end - stack_top;
 
        bprm->p -= stack_shift;
@@ -2000,3 +2014,43 @@ fail_creds:
 fail:
        return;
 }
+
+/*
+ * Core dumping helper functions.  These are the only things you should
+ * do on a core-file: use only these functions to write out all the
+ * necessary info.
+ */
+int dump_write(struct file *file, const void *addr, int nr)
+{
+       return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+EXPORT_SYMBOL(dump_write);
+
+int dump_seek(struct file *file, loff_t off)
+{
+       int ret = 1;
+
+       if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+               if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+                       return 0;
+       } else {
+               char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+
+               if (!buf)
+                       return 0;
+               while (off > 0) {
+                       unsigned long n = off;
+
+                       if (n > PAGE_SIZE)
+                               n = PAGE_SIZE;
+                       if (!dump_write(file, buf, n)) {
+                               ret = 0;
+                               break;
+                       }
+                       off -= n;
+               }
+               free_page((unsigned long)buf);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(dump_seek);
index eb7368ebd8cdc294c7ec4b2d1ad0d4953f699981..3eadd97324b140e679f269480b3737823fd008cb 100644 (file)
@@ -54,6 +54,9 @@ struct page_collect {
        unsigned nr_pages;
        unsigned long length;
        loff_t pg_first; /* keep 64bit also in 32-arches */
+       bool read_4_write; /* This means two things: that the read is sync
+                           * And the pages should not be unlocked.
+                           */
 };
 
 static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
@@ -71,6 +74,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
        pcol->nr_pages = 0;
        pcol->length = 0;
        pcol->pg_first = -1;
+       pcol->read_4_write = false;
 }
 
 static void _pcol_reset(struct page_collect *pcol)
@@ -347,7 +351,8 @@ static int readpage_strip(void *data, struct page *page)
                if (PageError(page))
                        ClearPageError(page);
 
-               unlock_page(page);
+               if (!pcol->read_4_write)
+                       unlock_page(page);
                EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
                             " splitting\n", inode->i_ino, page->index);
 
@@ -428,6 +433,7 @@ static int _readpage(struct page *page, bool is_sync)
        /* readpage_strip might call read_exec(,is_sync==false) at several
         * places but not if we have a single page.
         */
+       pcol.read_4_write = is_sync;
        ret = readpage_strip(&pcol, page);
        if (ret) {
                EXOFS_ERR("_readpage => %d\n", ret);
index 1ec602673ea8d37c3ddd72c7016ca1783ca8cf74..85df87d0f7b70a01dde7b39826f6d9abbeb08799 100644 (file)
@@ -747,15 +747,16 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        __le32 features;
        int err;
 
+       err = -ENOMEM;
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
-               return -ENOMEM;
+               goto failed_unlock;
 
        sbi->s_blockgroup_lock =
                kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
        if (!sbi->s_blockgroup_lock) {
                kfree(sbi);
-               return -ENOMEM;
+               goto failed_unlock;
        }
        sb->s_fs_info = sbi;
        sbi->s_sb_block = sb_block;
@@ -1107,6 +1108,7 @@ failed_sbi:
        sb->s_fs_info = NULL;
        kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
+failed_unlock:
        return ret;
 }
 
index 5dbf4dba03c4d99240edd76de5e9a0a2bba4bd04..37776800910670e2a675e4fd11378f3d8eb35446 100644 (file)
@@ -411,9 +411,6 @@ static void ext3_put_super (struct super_block * sb)
        int i, err;
 
        dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
-
-       lock_kernel();
-
        ext3_xattr_put_super(sb);
        err = journal_destroy(sbi->s_journal);
        sbi->s_journal = NULL;
@@ -462,8 +459,6 @@ static void ext3_put_super (struct super_block * sb)
        sb->s_fs_info = NULL;
        kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
-
-       unlock_kernel();
 }
 
 static struct kmem_cache *ext3_inode_cachep;
@@ -1627,8 +1622,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_resgid = EXT3_DEF_RESGID;
        sbi->s_sb_block = sb_block;
 
-       unlock_kernel();
-
        blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
        if (!blocksize) {
                ext3_msg(sb, KERN_ERR, "error: unable to set blocksize");
@@ -1849,8 +1842,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       if (le32_to_cpu(es->s_blocks_count) >
-                   (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+       if (generic_check_addressable(sb->s_blocksize_bits,
+                                     le32_to_cpu(es->s_blocks_count))) {
                ext3_msg(sb, KERN_ERR,
                        "error: filesystem is too large to mount safely");
                if (sizeof(sector_t) < 8)
@@ -2025,7 +2018,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
                "writeback");
 
-       lock_kernel();
        return 0;
 
 cantfind_ext3:
@@ -2055,7 +2047,6 @@ out_fail:
        sb->s_fs_info = NULL;
        kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
-       lock_kernel();
        return ret;
 }
 
@@ -2538,8 +2529,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
        int i;
 #endif
 
-       lock_kernel();
-
        /* Store the original options */
        lock_super(sb);
        old_sb_flags = sb->s_flags;
@@ -2648,7 +2637,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                        kfree(old_opts.s_qf_names[i]);
 #endif
        unlock_super(sb);
-       unlock_kernel();
 
        if (enable_quota)
                dquot_resume(sb, -1);
@@ -2669,7 +2657,6 @@ restore_opts:
        }
 #endif
        unlock_super(sb);
-       unlock_kernel();
        return err;
 }
 
index 26147746c272c2112b7067aa6415800434586b50..8ecc1e590303841b0c5f13d07568082230acdf4d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/parser.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
 #include <linux/vfs.h>
@@ -708,7 +707,6 @@ static void ext4_put_super(struct super_block *sb)
        destroy_workqueue(sbi->dio_unwritten_wq);
 
        lock_super(sb);
-       lock_kernel();
        if (sb->s_dirt)
                ext4_commit_super(sb, 1);
 
@@ -775,7 +773,6 @@ static void ext4_put_super(struct super_block *sb)
         * Now that we are completely done shutting down the
         * superblock, we need to actually destroy the kobject.
         */
-       unlock_kernel();
        unlock_super(sb);
        kobject_put(&sbi->s_kobj);
        wait_for_completion(&sbi->s_kobj_unregister);
@@ -2588,8 +2585,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                sbi->s_sectors_written_start =
                        part_stat_read(sb->s_bdev->bd_part, sectors[1]);
 
-       unlock_kernel();
-
        /* Cleanup superblock name */
        for (cp = sb->s_id; (cp = strchr(cp, '/'));)
                *cp = '!';
@@ -2831,15 +2826,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         * Test whether we have more sectors than will fit in sector_t,
         * and whether the max offset is addressable by the page cache.
         */
-       if ((ext4_blocks_count(es) >
-            (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) ||
-           (ext4_blocks_count(es) >
-            (pgoff_t)(~0ULL) >> (PAGE_CACHE_SHIFT - sb->s_blocksize_bits))) {
+       ret = generic_check_addressable(sb->s_blocksize_bits,
+                                       ext4_blocks_count(es));
+       if (ret) {
                ext4_msg(sb, KERN_ERR, "filesystem"
                         " too large to mount safely on this system");
                if (sizeof(sector_t) < 8)
                        ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled");
-               ret = -EFBIG;
                goto failed_mount;
        }
 
@@ -3166,7 +3159,6 @@ no_journal:
        if (es->s_error_count)
                mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
 
-       lock_kernel();
        kfree(orig_data);
        return 0;
 
@@ -3213,7 +3205,6 @@ out_fail:
        sb->s_fs_info = NULL;
        kfree(sbi->s_blockgroup_lock);
        kfree(sbi);
-       lock_kernel();
 out_free_orig:
        kfree(orig_data);
        return ret;
@@ -3722,8 +3713,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
 #endif
        char *orig_data = kstrdup(data, GFP_KERNEL);
 
-       lock_kernel();
-
        /* Store the original options */
        lock_super(sb);
        old_sb_flags = sb->s_flags;
@@ -3858,7 +3847,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                        kfree(old_opts.s_qf_names[i]);
 #endif
        unlock_super(sb);
-       unlock_kernel();
        if (enable_quota)
                dquot_resume(sb, -1);
 
@@ -3884,7 +3872,6 @@ restore_opts:
        }
 #endif
        unlock_super(sb);
-       unlock_kernel();
        kfree(orig_data);
        return err;
 }
index 830058057d333d547effdbc969d8a9d89464854f..ad6998a92c30d4a90336bcb295743ffb9547ec3f 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
@@ -489,8 +488,6 @@ static void fat_put_super(struct super_block *sb)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-       lock_kernel();
-
        if (sb->s_dirt)
                fat_write_super(sb);
 
@@ -504,8 +501,6 @@ static void fat_put_super(struct super_block *sb)
 
        sb->s_fs_info = NULL;
        kfree(sbi);
-
-       unlock_kernel();
 }
 
 static struct kmem_cache *fat_inode_cachep;
index bbc94ae4fd77150203435058b79e46a03bfb40bc..bbca5c186ae7654d69025a2cbb214c1fc1f96a3d 100644 (file)
@@ -662,12 +662,16 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent)
 {
        int res;
 
+       lock_super(sb);
        res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
-       if (res)
+       if (res) {
+               unlock_super(sb);
                return res;
+       }
 
        sb->s_flags |= MS_NOATIME;
        sb->s_root->d_op = &msdos_dentry_operations;
+       unlock_super(sb);
        return 0;
 }
 
index 6fcc7e71fbaaf0c8f1d21b3cf50fab86d67f50ee..6f0f6c9a0152263d61081e436641fb9a0300db6c 100644 (file)
@@ -1055,15 +1055,19 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent)
 {
        int res;
 
+       lock_super(sb);
        res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
-       if (res)
+       if (res) {
+               unlock_super(sb);
                return res;
+       }
 
        if (MSDOS_SB(sb)->options.name_check != 's')
                sb->s_root->d_op = &vfat_ci_dentry_ops;
        else
                sb->s_root->d_op = &vfat_dentry_ops;
 
+       unlock_super(sb);
        return 0;
 }
 
index 6769fd0f35b88373fdb8d0b265668a976a7ab251..f8cc34f542c3a1cc8b4f53309ffae317ecdddf15 100644 (file)
@@ -769,11 +769,15 @@ EXPORT_SYMBOL(kill_fasync);
 
 static int __init fcntl_init(void)
 {
-       /* please add new bits here to ensure allocation uniqueness */
-       BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
+       /*
+        * Please add new bits here to ensure allocation uniqueness.
+        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
+        * is defined as O_NONBLOCK on some platforms and not on others.
+        */
+       BUILD_BUG_ON(18 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
                O_RDONLY        | O_WRONLY      | O_RDWR        |
                O_CREAT         | O_EXCL        | O_NOCTTY      |
-               O_TRUNC         | O_APPEND      | O_NONBLOCK    |
+               O_TRUNC         | O_APPEND      | /* O_NONBLOCK | */
                __O_SYNC        | O_DSYNC       | FASYNC        |
                O_DIRECT        | O_LARGEFILE   | O_DIRECTORY   |
                O_NOFOLLOW      | O_NOATIME     | O_CLOEXEC     |
index 5d6606ffc2d28de7b94c4dc3bb04367ac6a57f93..4e303c22d5ee53613682530bd1705a0a3cec8382 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -151,4 +151,5 @@ err_nocleanup:
  */
 const struct file_operations def_fifo_fops = {
        .open           = fifo_open,    /* will set read_ or write_pipefifo_fops */
+       .llseek         = noop_llseek,
 };
index 0ec7bb2c95c6afd035a9484b0a39347f9f8f61c1..6c5131d592f0ae2fbeba8b4c2d227c603bb544c3 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/highmem.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "vxfs.h"
 #include "vxfs_dir.h"
@@ -212,16 +211,12 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
        if (dp->d_name.len > VXFS_NAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
                                 
-       lock_kernel();
        ino = vxfs_inode_by_name(dip, dp);
        if (ino) {
                ip = vxfs_iget(dip->i_sb, ino);
-               if (IS_ERR(ip)) {
-                       unlock_kernel();
+               if (IS_ERR(ip))
                        return ERR_CAST(ip);
-               }
        }
-       unlock_kernel();
        d_add(dp, ip);
        return NULL;
 }
@@ -248,8 +243,6 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
        u_long                  page, npages, block, pblocks, nblocks, offset;
        loff_t                  pos;
 
-       lock_kernel();
-
        switch ((long)fp->f_pos) {
        case 0:
                if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
@@ -265,10 +258,8 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
 
        pos = fp->f_pos - 2;
        
-       if (pos > VXFS_DIRROUND(ip->i_size)) {
-               unlock_kernel();
+       if (pos > VXFS_DIRROUND(ip->i_size))
                return 0;
-       }
 
        npages = dir_pages(ip);
        nblocks = dir_blocks(ip);
@@ -327,6 +318,5 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
 done:
        fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
 out:
-       unlock_kernel();
        return 0;
 }
index dc0c041e85cbcd5c14b04c0e5b09eda611605aef..71b0148b878415795d984528c02679d45ee218e4 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
@@ -81,16 +80,12 @@ vxfs_put_super(struct super_block *sbp)
 {
        struct vxfs_sb_info     *infp = VXFS_SBI(sbp);
 
-       lock_kernel();
-
        vxfs_put_fake_inode(infp->vsi_fship);
        vxfs_put_fake_inode(infp->vsi_ilist);
        vxfs_put_fake_inode(infp->vsi_stilist);
 
        brelse(infp->vsi_bp);
        kfree(infp);
-
-       unlock_kernel();
 }
 
 /**
@@ -148,7 +143,7 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
  *   The superblock on success, else %NULL.
  *
  * Locking:
- *   We are under the bkl and @sbp->s_lock.
+ *   We are under @sbp->s_lock.
  */
 static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
index 7d9d06ba184b409e2ae90050ce82ca365cf3ce82..ab38fef1c9a1a52eab7128fa6a7dad217d4ad744 100644 (file)
@@ -52,8 +52,6 @@ struct wb_writeback_work {
 #define CREATE_TRACE_POINTS
 #include <trace/events/writeback.h>
 
-#define inode_to_bdi(inode)    ((inode)->i_mapping->backing_dev_info)
-
 /*
  * We don't actually have pdflush, but this one is exported though /proc...
  */
@@ -71,6 +69,16 @@ int writeback_in_progress(struct backing_dev_info *bdi)
        return test_bit(BDI_writeback_running, &bdi->state);
 }
 
+static inline struct backing_dev_info *inode_to_bdi(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+
+       if (strcmp(sb->s_type->name, "bdev") == 0)
+               return inode->i_mapping->backing_dev_info;
+
+       return sb->s_bdi;
+}
+
 static void bdi_queue_work(struct backing_dev_info *bdi,
                struct wb_writeback_work *work)
 {
@@ -808,7 +816,7 @@ int bdi_writeback_thread(void *data)
                        wb->last_active = jiffies;
 
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!list_empty(&bdi->work_list)) {
+               if (!list_empty(&bdi->work_list) || kthread_should_stop()) {
                        __set_current_state(TASK_RUNNING);
                        continue;
                }
index 3773fd63d2f9f66ebf4b5424211f9879ee05a360..7367e177186f4b0efb96d1281134860058050e6d 100644 (file)
@@ -179,23 +179,27 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
 static const struct file_operations fuse_ctl_abort_ops = {
        .open = nonseekable_open,
        .write = fuse_conn_abort_write,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations fuse_ctl_waiting_ops = {
        .open = nonseekable_open,
        .read = fuse_conn_waiting_read,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_max_background_ops = {
        .open = nonseekable_open,
        .read = fuse_conn_max_background_read,
        .write = fuse_conn_max_background_write,
+       .llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_congestion_threshold_ops = {
        .open = nonseekable_open,
        .read = fuse_conn_congestion_threshold_read,
        .write = fuse_conn_congestion_threshold_write,
+       .llseek = no_llseek,
 };
 
 static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
index e1f8171278bdeac8b5ba7f5b71abfe1d9984c307..3e87cce5837d6df9f0db0f476a9ca58c3a269231 100644 (file)
@@ -182,6 +182,7 @@ static const struct file_operations cuse_frontend_fops = {
        .unlocked_ioctl         = cuse_file_ioctl,
        .compat_ioctl           = cuse_file_compat_ioctl,
        .poll                   = fuse_file_poll,
+       .llseek         = noop_llseek,
 };
 
 
index 69ad053ffd78cb0f2669516b5327571f37d65254..cde755cca5642d41fb9cbbe05ac2d01f70f53c69 100644 (file)
@@ -276,7 +276,7 @@ static void flush_bg_queue(struct fuse_conn *fc)
  * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
-__releases(&fc->lock)
+__releases(fc->lock)
 {
        void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
        req->end = NULL;
@@ -306,8 +306,8 @@ __releases(&fc->lock)
 
 static void wait_answer_interruptible(struct fuse_conn *fc,
                                      struct fuse_req *req)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        if (signal_pending(current))
                return;
@@ -325,8 +325,8 @@ static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
 }
 
 static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        if (!fc->no_interrupt) {
                /* Any signal may interrupt this */
@@ -905,8 +905,8 @@ static int request_pending(struct fuse_conn *fc)
 
 /* Wait until a request is available on the pending list */
 static void request_wait(struct fuse_conn *fc)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        DECLARE_WAITQUEUE(wait, current);
 
@@ -934,7 +934,7 @@ __acquires(&fc->lock)
  */
 static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_copy_state *cs,
                               size_t nbytes, struct fuse_req *req)
-__releases(&fc->lock)
+__releases(fc->lock)
 {
        struct fuse_in_header ih;
        struct fuse_interrupt_in arg;
@@ -1354,7 +1354,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        loff_t file_size;
        unsigned int num;
        unsigned int offset;
-       size_t total_len;
+       size_t total_len = 0;
 
        req = fuse_get_req(fc);
        if (IS_ERR(req))
@@ -1720,8 +1720,8 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
  * This function releases and reacquires fc->lock
  */
 static void end_requests(struct fuse_conn *fc, struct list_head *head)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        while (!list_empty(head)) {
                struct fuse_req *req;
@@ -1744,8 +1744,8 @@ __acquires(&fc->lock)
  * locked).
  */
 static void end_io_requests(struct fuse_conn *fc)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        while (!list_empty(&fc->io)) {
                struct fuse_req *req =
@@ -1769,6 +1769,16 @@ __acquires(&fc->lock)
        }
 }
 
+static void end_queued_requests(struct fuse_conn *fc)
+__releases(fc->lock)
+__acquires(fc->lock)
+{
+       fc->max_background = UINT_MAX;
+       flush_bg_queue(fc);
+       end_requests(fc, &fc->pending);
+       end_requests(fc, &fc->processing);
+}
+
 /*
  * Abort all requests.
  *
@@ -1795,8 +1805,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
                fc->connected = 0;
                fc->blocked = 0;
                end_io_requests(fc);
-               end_requests(fc, &fc->pending);
-               end_requests(fc, &fc->processing);
+               end_queued_requests(fc);
                wake_up_all(&fc->waitq);
                wake_up_all(&fc->blocked_waitq);
                kill_fasync(&fc->fasync, SIGIO, POLL_IN);
@@ -1811,8 +1820,9 @@ int fuse_dev_release(struct inode *inode, struct file *file)
        if (fc) {
                spin_lock(&fc->lock);
                fc->connected = 0;
-               end_requests(fc, &fc->pending);
-               end_requests(fc, &fc->processing);
+               fc->blocked = 0;
+               end_queued_requests(fc);
+               wake_up_all(&fc->blocked_waitq);
                spin_unlock(&fc->lock);
                fuse_conn_put(fc);
        }
index 147c1f71bdb9f0213307fd3e63f6e3b30fc3f403..c8224587123f6e2ff84c8933f8d56a50ffd06c80 100644 (file)
@@ -1144,8 +1144,8 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
 
 /* Called under fc->lock, may release and reacquire it */
 static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        struct fuse_inode *fi = get_fuse_inode(req->inode);
        loff_t size = i_size_read(req->inode);
@@ -1183,8 +1183,8 @@ __acquires(&fc->lock)
  * Called with fc->lock
  */
 void fuse_flush_writepages(struct inode *inode)
-__releases(&fc->lock)
-__acquires(&fc->lock)
+__releases(fc->lock)
+__acquires(fc->lock)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
index cc9665522148a730b010953596cc24edefc00ed6..c465ae066c62c6392ee22047d2be0ec650b89c98 100644 (file)
@@ -1,6 +1,6 @@
 config GFS2_FS
        tristate "GFS2 file system support"
-       depends on EXPERIMENTAL && (64BIT || LBDAF)
+       depends on (64BIT || LBDAF)
        select DLM if GFS2_FS_LOCKING_DLM
        select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
        select SYSFS if GFS2_FS_LOCKING_DLM
index 194fe16d8418a332a274a74769b15277ff2d6858..6b24afb96aaedade304b48bb427e664eae8e6e53 100644 (file)
@@ -36,8 +36,8 @@
 #include "glops.h"
 
 
-static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
-                                  unsigned int from, unsigned int to)
+void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
+                           unsigned int from, unsigned int to)
 {
        struct buffer_head *head = page_buffers(page);
        unsigned int bsize = head->b_size;
@@ -615,7 +615,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
        int alloc_required;
        int error = 0;
-       struct gfs2_alloc *al;
+       struct gfs2_alloc *al = NULL;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        unsigned from = pos & (PAGE_CACHE_SIZE - 1);
        unsigned to = from + len;
@@ -663,6 +663,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
                rblocks += RES_STATFS + RES_QUOTA;
        if (&ip->i_inode == sdp->sd_rindex)
                rblocks += 2 * RES_STATFS;
+       if (alloc_required)
+               rblocks += gfs2_rg_blocks(al);
 
        error = gfs2_trans_begin(sdp, rblocks,
                                 PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
@@ -696,13 +698,11 @@ out:
 
        page_cache_release(page);
 
-       /*
-        * XXX(truncate): the call below should probably be replaced with
-        * a call to the gfs2-specific truncate blocks helper to actually
-        * release disk blocks..
-        */
+       gfs2_trans_end(sdp);
        if (pos + len > ip->i_inode.i_size)
-               truncate_setsize(&ip->i_inode, ip->i_inode.i_size);
+               gfs2_trim_blocks(&ip->i_inode);
+       goto out_trans_fail;
+
 out_endtrans:
        gfs2_trans_end(sdp);
 out_trans_fail:
@@ -802,10 +802,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
        page_cache_release(page);
 
        if (copied) {
-               if (inode->i_size < to) {
+               if (inode->i_size < to)
                        i_size_write(inode, to);
-                       ip->i_disksize = inode->i_size;
-               }
                gfs2_dinode_out(ip, di);
                mark_inode_dirty(inode);
        }
@@ -876,8 +874,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
 
        ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
        if (ret > 0) {
-               if (inode->i_size > ip->i_disksize)
-                       ip->i_disksize = inode->i_size;
                gfs2_dinode_out(ip, dibh->b_data);
                mark_inode_dirty(inode);
        }
index 6f482809d1a35b4787e9cb62357958d532aeaa30..5476c066d4ee336733445eda2f804561179ecb41 100644 (file)
@@ -50,7 +50,7 @@ struct strip_mine {
  * @ip: the inode
  * @dibh: the dinode buffer
  * @block: the block number that was allocated
- * @private: any locked page held by the caller process
+ * @page: The (optional) page. This is looked up if @page is NULL
  *
  * Returns: errno
  */
@@ -109,8 +109,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
 /**
  * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
  * @ip: The GFS2 inode to unstuff
- * @unstuffer: the routine that handles unstuffing a non-zero length file
- * @private: private data for the unstuffer
+ * @page: The (optional) page. This is looked up if the @page is NULL
  *
  * This routine unstuffs a dinode and returns it to a "normal" state such
  * that the height can be grown in the traditional way.
@@ -132,7 +131,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
        if (error)
                goto out;
 
-       if (ip->i_disksize) {
+       if (i_size_read(&ip->i_inode)) {
                /* Get a free block, fill it with the stuffed data,
                   and write it out to disk */
 
@@ -161,7 +160,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
        di = (struct gfs2_dinode *)dibh->b_data;
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
-       if (ip->i_disksize) {
+       if (i_size_read(&ip->i_inode)) {
                *(__be64 *)(di + 1) = cpu_to_be64(block);
                gfs2_add_inode_blocks(&ip->i_inode, 1);
                di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -884,84 +883,15 @@ out:
        return error;
 }
 
-/**
- * do_grow - Make a file look bigger than it is
- * @ip: the inode
- * @size: the size to set the file to
- *
- * Called with an exclusive lock on @ip.
- *
- * Returns: errno
- */
-
-static int do_grow(struct gfs2_inode *ip, u64 size)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_alloc *al;
-       struct buffer_head *dibh;
-       int error;
-
-       al = gfs2_alloc_get(ip);
-       if (!al)
-               return -ENOMEM;
-
-       error = gfs2_quota_lock_check(ip);
-       if (error)
-               goto out;
-
-       al->al_requested = sdp->sd_max_height + RES_DATA;
-
-       error = gfs2_inplace_reserve(ip);
-       if (error)
-               goto out_gunlock_q;
-
-       error = gfs2_trans_begin(sdp,
-                       sdp->sd_max_height + al->al_rgd->rd_length +
-                       RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
-       if (error)
-               goto out_ipres;
-
-       error = gfs2_meta_inode_buffer(ip, &dibh);
-       if (error)
-               goto out_end_trans;
-
-       if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
-               if (gfs2_is_stuffed(ip)) {
-                       error = gfs2_unstuff_dinode(ip, NULL);
-                       if (error)
-                               goto out_brelse;
-               }
-       }
-
-       ip->i_disksize = size;
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(ip, dibh->b_data);
-
-out_brelse:
-       brelse(dibh);
-out_end_trans:
-       gfs2_trans_end(sdp);
-out_ipres:
-       gfs2_inplace_release(ip);
-out_gunlock_q:
-       gfs2_quota_unlock(ip);
-out:
-       gfs2_alloc_put(ip);
-       return error;
-}
-
-
 /**
  * gfs2_block_truncate_page - Deal with zeroing out data for truncate
  *
  * This is partly borrowed from ext3.
  */
-static int gfs2_block_truncate_page(struct address_space *mapping)
+static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
 {
        struct inode *inode = mapping->host;
        struct gfs2_inode *ip = GFS2_I(inode);
-       loff_t from = inode->i_size;
        unsigned long index = from >> PAGE_CACHE_SHIFT;
        unsigned offset = from & (PAGE_CACHE_SIZE-1);
        unsigned blocksize, iblock, length, pos;
@@ -1023,9 +953,11 @@ unlock:
        return err;
 }
 
-static int trunc_start(struct gfs2_inode *ip, u64 size)
+static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 {
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct address_space *mapping = inode->i_mapping;
        struct buffer_head *dibh;
        int journaled = gfs2_is_jdata(ip);
        int error;
@@ -1039,31 +971,26 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
        if (error)
                goto out;
 
+       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+
        if (gfs2_is_stuffed(ip)) {
-               u64 dsize = size + sizeof(struct gfs2_dinode);
-               ip->i_disksize = size;
-               ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(ip, dibh->b_data);
-               if (dsize > dibh->b_size)
-                       dsize = dibh->b_size;
-               gfs2_buffer_clear_tail(dibh, dsize);
-               error = 1;
+               gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
        } else {
-               if (size & (u64)(sdp->sd_sb.sb_bsize - 1))
-                       error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
-
-               if (!error) {
-                       ip->i_disksize = size;
-                       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-                       ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
-                       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-                       gfs2_dinode_out(ip, dibh->b_data);
+               if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) {
+                       error = gfs2_block_truncate_page(mapping, newsize);
+                       if (error)
+                               goto out_brelse;
                }
+               ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
        }
 
-       brelse(dibh);
+       i_size_write(inode, newsize);
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+       gfs2_dinode_out(ip, dibh->b_data);
 
+       truncate_pagecache(inode, oldsize, newsize);
+out_brelse:
+       brelse(dibh);
 out:
        gfs2_trans_end(sdp);
        return error;
@@ -1123,7 +1050,7 @@ static int trunc_end(struct gfs2_inode *ip)
        if (error)
                goto out;
 
-       if (!ip->i_disksize) {
+       if (!i_size_read(&ip->i_inode)) {
                ip->i_height = 0;
                ip->i_goal = ip->i_no_addr;
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
@@ -1143,92 +1070,154 @@ out:
 
 /**
  * do_shrink - make a file smaller
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
+ * @inode: the inode
+ * @oldsize: the current inode size
+ * @newsize: the size to make the file
  *
- * Called with an exclusive lock on @ip.
+ * Called with an exclusive lock on @inode. The @size must
+ * be equal to or smaller than the current inode size.
  *
  * Returns: errno
  */
 
-static int do_shrink(struct gfs2_inode *ip, u64 size)
+static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize)
 {
+       struct gfs2_inode *ip = GFS2_I(inode);
        int error;
 
-       error = trunc_start(ip, size);
+       error = trunc_start(inode, oldsize, newsize);
        if (error < 0)
                return error;
-       if (error > 0)
+       if (gfs2_is_stuffed(ip))
                return 0;
 
-       error = trunc_dealloc(ip, size);
-       if (!error)
+       error = trunc_dealloc(ip, newsize);
+       if (error == 0)
                error = trunc_end(ip);
 
        return error;
 }
 
-static int do_touch(struct gfs2_inode *ip, u64 size)
+void gfs2_trim_blocks(struct inode *inode)
 {
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       u64 size = inode->i_size;
+       int ret;
+
+       ret = do_shrink(inode, size, size);
+       WARN_ON(ret != 0);
+}
+
+/**
+ * do_grow - Touch and update inode size
+ * @inode: The inode
+ * @size: The new size
+ *
+ * This function updates the timestamps on the inode and
+ * may also increase the size of the inode. This function
+ * must not be called with @size any smaller than the current
+ * inode size.
+ *
+ * Although it is not strictly required to unstuff files here,
+ * earlier versions of GFS2 have a bug in the stuffed file reading
+ * code which will result in a buffer overrun if the size is larger
+ * than the max stuffed file size. In order to prevent this from
+ * occuring, such files are unstuffed, but in other cases we can
+ * just update the inode size directly.
+ *
+ * Returns: 0 on success, or -ve on error
+ */
+
+static int do_grow(struct inode *inode, u64 size)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *dibh;
+       struct gfs2_alloc *al = NULL;
        int error;
 
-       error = gfs2_trans_begin(sdp, RES_DINODE, 0);
+       if (gfs2_is_stuffed(ip) &&
+           (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
+               al = gfs2_alloc_get(ip);
+               if (al == NULL)
+                       return -ENOMEM;
+
+               error = gfs2_quota_lock_check(ip);
+               if (error)
+                       goto do_grow_alloc_put;
+
+               al->al_requested = 1;
+               error = gfs2_inplace_reserve(ip);
+               if (error)
+                       goto do_grow_qunlock;
+       }
+
+       error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
        if (error)
-               return error;
+               goto do_grow_release;
 
-       down_write(&ip->i_rw_mutex);
+       if (al) {
+               error = gfs2_unstuff_dinode(ip, NULL);
+               if (error)
+                       goto do_end_trans;
+       }
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
-               goto do_touch_out;
+               goto do_end_trans;
 
+       i_size_write(inode, size);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
-do_touch_out:
-       up_write(&ip->i_rw_mutex);
+do_end_trans:
        gfs2_trans_end(sdp);
+do_grow_release:
+       if (al) {
+               gfs2_inplace_release(ip);
+do_grow_qunlock:
+               gfs2_quota_unlock(ip);
+do_grow_alloc_put:
+               gfs2_alloc_put(ip);
+       }
        return error;
 }
 
 /**
- * gfs2_truncatei - make a file a given size
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
+ * gfs2_setattr_size - make a file a given size
+ * @inode: the inode
+ * @newsize: the size to make the file
  *
- * The file size can grow, shrink, or stay the same size.
+ * The file size can grow, shrink, or stay the same size. This
+ * is called holding i_mutex and an exclusive glock on the inode
+ * in question.
  *
  * Returns: errno
  */
 
-int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
+int gfs2_setattr_size(struct inode *inode, u64 newsize)
 {
-       int error;
+       int ret;
+       u64 oldsize;
 
-       if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
-               return -EINVAL;
+       BUG_ON(!S_ISREG(inode->i_mode));
 
-       if (size > ip->i_disksize)
-               error = do_grow(ip, size);
-       else if (size < ip->i_disksize)
-               error = do_shrink(ip, size);
-       else
-               /* update time stamps */
-               error = do_touch(ip, size);
+       ret = inode_newsize_ok(inode, newsize);
+       if (ret)
+               return ret;
 
-       return error;
+       oldsize = inode->i_size;
+       if (newsize >= oldsize)
+               return do_grow(inode, newsize);
+
+       return do_shrink(inode, oldsize, newsize);
 }
 
 int gfs2_truncatei_resume(struct gfs2_inode *ip)
 {
        int error;
-       error = trunc_dealloc(ip, ip->i_disksize);
+       error = trunc_dealloc(ip, i_size_read(&ip->i_inode));
        if (!error)
                error = trunc_end(ip);
        return error;
@@ -1269,7 +1258,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
 
        shift = sdp->sd_sb.sb_bsize_shift;
        BUG_ON(gfs2_is_dir(ip));
-       end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
+       end_of_file = (i_size_read(&ip->i_inode) + sdp->sd_sb.sb_bsize - 1) >> shift;
        lblock = offset >> shift;
        lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
        if (lblock_stop > end_of_file)
index a20a5213135a50ae9293da676eb533e9c04063db..42fea03e2bd962b6674747967ac00499009d923f 100644 (file)
@@ -44,14 +44,16 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
        }
 }
 
-int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
-int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create);
-int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
-
-int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
-int gfs2_truncatei_resume(struct gfs2_inode *ip);
-int gfs2_file_dealloc(struct gfs2_inode *ip);
-int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
-                             unsigned int len);
+extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
+extern int gfs2_block_map(struct inode *inode, sector_t lblock,
+                         struct buffer_head *bh, int create);
+extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
+                          u64 *dblock, unsigned *extlen);
+extern int gfs2_setattr_size(struct inode *inode, u64 size);
+extern void gfs2_trim_blocks(struct inode *inode);
+extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
+extern int gfs2_file_dealloc(struct gfs2_inode *ip);
+extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+                                    unsigned int len);
 
 #endif /* __BMAP_DOT_H__ */
index bb7907bde3d81b63b6ae5b198283a52db36e97b0..6798755b3858685b611da5e439393bcffb332563 100644 (file)
@@ -49,7 +49,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
                ip = GFS2_I(inode);
        }
 
-       if (sdp->sd_args.ar_localcaching)
+       if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
                goto valid;
 
        had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
index b9dd88a78dd47073e3af1645a1e0fa3bcb94d1bb..5c356d09c321c10133afc7cf93aba2eddd1cb3c1 100644 (file)
@@ -79,6 +79,9 @@
 #define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
 #define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
 
+struct qstr gfs2_qdot __read_mostly;
+struct qstr gfs2_qdotdot __read_mostly;
+
 typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
                            u64 leaf_no, void *data);
 typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
@@ -127,8 +130,8 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
-       if (ip->i_disksize < offset + size)
-               ip->i_disksize = offset + size;
+       if (ip->i_inode.i_size < offset + size)
+               i_size_write(&ip->i_inode, offset + size);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_dinode_out(ip, dibh->b_data);
 
@@ -225,8 +228,8 @@ out:
        if (error)
                return error;
 
-       if (ip->i_disksize < offset + copied)
-               ip->i_disksize = offset + copied;
+       if (ip->i_inode.i_size < offset + copied)
+               i_size_write(&ip->i_inode, offset + copied);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
@@ -275,12 +278,13 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
        unsigned int o;
        int copied = 0;
        int error = 0;
+       u64 disksize = i_size_read(&ip->i_inode);
 
-       if (offset >= ip->i_disksize)
+       if (offset >= disksize)
                return 0;
 
-       if (offset + size > ip->i_disksize)
-               size = ip->i_disksize - offset;
+       if (offset + size > disksize)
+               size = disksize - offset;
 
        if (!size)
                return 0;
@@ -727,7 +731,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
                unsigned hsize = 1 << ip->i_depth;
                unsigned index;
                u64 ln;
-               if (hsize * sizeof(u64) != ip->i_disksize) {
+               if (hsize * sizeof(u64) != i_size_read(inode)) {
                        gfs2_consist_inode(ip);
                        return ERR_PTR(-EIO);
                }
@@ -879,7 +883,7 @@ static int dir_make_exhash(struct inode *inode)
        for (x = sdp->sd_hash_ptrs; x--; lp++)
                *lp = cpu_to_be64(bn);
 
-       dip->i_disksize = sdp->sd_sb.sb_bsize / 2;
+       i_size_write(inode, sdp->sd_sb.sb_bsize / 2);
        gfs2_add_inode_blocks(&dip->i_inode, 1);
        dip->i_diskflags |= GFS2_DIF_EXHASH;
 
@@ -1057,11 +1061,12 @@ static int dir_double_exhash(struct gfs2_inode *dip)
        u64 *buf;
        u64 *from, *to;
        u64 block;
+       u64 disksize = i_size_read(&dip->i_inode);
        int x;
        int error = 0;
 
        hsize = 1 << dip->i_depth;
-       if (hsize * sizeof(u64) != dip->i_disksize) {
+       if (hsize * sizeof(u64) != disksize) {
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -1072,7 +1077,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
        if (!buf)
                return -ENOMEM;
 
-       for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) {
+       for (block = disksize >> sdp->sd_hash_bsize_shift; block--;) {
                error = gfs2_dir_read_data(dip, (char *)buf,
                                            block * sdp->sd_hash_bsize,
                                            sdp->sd_hash_bsize, 1);
@@ -1370,7 +1375,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
        unsigned depth = 0;
 
        hsize = 1 << dip->i_depth;
-       if (hsize * sizeof(u64) != dip->i_disksize) {
+       if (hsize * sizeof(u64) != i_size_read(inode)) {
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -1784,7 +1789,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
        int error = 0;
 
        hsize = 1 << dip->i_depth;
-       if (hsize * sizeof(u64) != dip->i_disksize) {
+       if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
                gfs2_consist_inode(dip);
                return -EIO;
        }
index 4f919440c3be3e20ed49c2acb742db6758096bea..a98f644bd3df33596cf2382767b89ca0cdd08161 100644 (file)
@@ -17,23 +17,24 @@ struct inode;
 struct gfs2_inode;
 struct gfs2_inum;
 
-struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
-int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
-                  const struct gfs2_inode *ip);
-int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
-                const struct gfs2_inode *ip, unsigned int type);
-int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
-int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
-                 filldir_t filldir);
-int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-                  const struct gfs2_inode *nip, unsigned int new_type);
+extern struct inode *gfs2_dir_search(struct inode *dir,
+                                    const struct qstr *filename);
+extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+                         const struct gfs2_inode *ip);
+extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
+                       const struct gfs2_inode *ip, unsigned int type);
+extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
+extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+                        filldir_t filldir);
+extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
+                         const struct gfs2_inode *nip, unsigned int new_type);
 
-int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
+extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
 
-int gfs2_diradd_alloc_required(struct inode *dir,
-                              const struct qstr *filename);
-int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
-                           struct buffer_head **bhp);
+extern int gfs2_diradd_alloc_required(struct inode *dir,
+                                     const struct qstr *filename);
+extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
+                                  struct buffer_head **bhp);
 
 static inline u32 gfs2_disk_hash(const char *data, int len)
 {
@@ -61,4 +62,7 @@ static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct
        memcpy(dent + 1, name->name, name->len);
 }
 
+extern struct qstr gfs2_qdot;
+extern struct qstr gfs2_qdotdot;
+
 #endif /* __DIR_DOT_H__ */
index dfe237a3f8ad9e2a0f11bae403ff1f1d8687cbd0..06d582732d3427a058864d03ca6cb667c5063481 100644 (file)
@@ -126,16 +126,9 @@ static int gfs2_get_name(struct dentry *parent, char *name,
 
 static struct dentry *gfs2_get_parent(struct dentry *child)
 {
-       struct qstr dotdot;
        struct dentry *dentry;
 
-       /*
-        * XXX(hch): it would be a good idea to keep this around as a
-        *           static variable.
-        */
-       gfs2_str2qstr(&dotdot, "..");
-
-       dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &dotdot, 1));
+       dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
        if (!IS_ERR(dentry))
                dentry->d_op = &gfs2_dops;
        return dentry;
index 4edd662c8232b2c24d1f1767b937f258071f8211..aa996471ec5c961d7d94c62c10a20d29ac8e1bbb 100644 (file)
@@ -382,8 +382,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        rblocks = RES_DINODE + ind_blocks;
        if (gfs2_is_jdata(ip))
                rblocks += data_blocks ? data_blocks : 1;
-       if (ind_blocks || data_blocks)
+       if (ind_blocks || data_blocks) {
                rblocks += RES_STATFS + RES_QUOTA;
+               rblocks += gfs2_rg_blocks(al);
+       }
        ret = gfs2_trans_begin(sdp, rblocks, 0);
        if (ret)
                goto out_trans_fail;
@@ -491,7 +493,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
                        goto fail;
 
                if (!(file->f_flags & O_LARGEFILE) &&
-                   ip->i_disksize > MAX_NON_LFS) {
+                   i_size_read(inode) > MAX_NON_LFS) {
                        error = -EOVERFLOW;
                        goto fail_gunlock;
                }
@@ -620,6 +622,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
  * cluster; until we do, disable leases (by just returning -EINVAL),
  * unless the administrator has requested purely local locking.
  *
+ * Locking: called under lock_flocks
+ *
  * Returns: errno
  */
 
@@ -771,6 +775,7 @@ const struct file_operations gfs2_dir_fops = {
        .fsync          = gfs2_fsync,
        .lock           = gfs2_lock,
        .flock          = gfs2_flock,
+       .llseek         = default_llseek,
 };
 
 #endif /* CONFIG_GFS2_FS_LOCKING_DLM */
@@ -797,5 +802,6 @@ const struct file_operations gfs2_dir_fops_nolock = {
        .open           = gfs2_open,
        .release        = gfs2_close,
        .fsync          = gfs2_fsync,
+       .llseek         = default_llseek,
 };
 
index 9adf8f924e08991c32d12938702e570f163c3215..87778857f0994fa504224d93c7c5611d10bc1e8c 100644 (file)
@@ -441,6 +441,8 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
                else
                        gfs2_glock_put_nolock(gl);
        }
+       if (held1 && held2 && list_empty(&gl->gl_holders))
+               clear_bit(GLF_QUEUED, &gl->gl_flags);
 
        gl->gl_state = new_state;
        gl->gl_tchange = jiffies;
@@ -1012,6 +1014,7 @@ fail:
                if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt))
                        insert_pt = &gh2->gh_list;
        }
+       set_bit(GLF_QUEUED, &gl->gl_flags);
        if (likely(insert_pt == NULL)) {
                list_add_tail(&gh->gh_list, &gl->gl_holders);
                if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
@@ -1310,10 +1313,12 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
 
        gfs2_glock_hold(gl);
        holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
-       if (time_before(now, holdtime))
-               delay = holdtime - now;
-       if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
-               delay = gl->gl_ops->go_min_hold_time;
+       if (test_bit(GLF_QUEUED, &gl->gl_flags)) {
+               if (time_before(now, holdtime))
+                       delay = holdtime - now;
+               if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
+                       delay = gl->gl_ops->go_min_hold_time;
+       }
 
        spin_lock(&gl->gl_spin);
        handle_callback(gl, state, delay);
@@ -1512,7 +1517,7 @@ static void clear_glock(struct gfs2_glock *gl)
        spin_unlock(&lru_lock);
 
        spin_lock(&gl->gl_spin);
-       if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED)
+       if (gl->gl_state != LM_ST_UNLOCKED)
                handle_callback(gl, LM_ST_UNLOCKED, 0);
        spin_unlock(&gl->gl_spin);
        gfs2_glock_hold(gl);
@@ -1660,6 +1665,8 @@ static const char *gflags2str(char *buf, const unsigned long *gflags)
                *p++ = 'I';
        if (test_bit(GLF_FROZEN, gflags))
                *p++ = 'F';
+       if (test_bit(GLF_QUEUED, gflags))
+               *p++ = 'q';
        *p = 0;
        return buf;
 }
@@ -1776,10 +1783,12 @@ int __init gfs2_glock_init(void)
        }
 #endif
 
-       glock_workqueue = create_workqueue("glock_workqueue");
+       glock_workqueue = alloc_workqueue("glock_workqueue", WQ_RESCUER |
+                                         WQ_HIGHPRI | WQ_FREEZEABLE, 0);
        if (IS_ERR(glock_workqueue))
                return PTR_ERR(glock_workqueue);
-       gfs2_delete_workqueue = create_workqueue("delete_workqueue");
+       gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", WQ_RESCUER |
+                                               WQ_FREEZEABLE, 0);
        if (IS_ERR(gfs2_delete_workqueue)) {
                destroy_workqueue(glock_workqueue);
                return PTR_ERR(gfs2_delete_workqueue);
index 2bda1911b1563347b52d4d2da7892768d93bd947..db1c26d6d2206c8f9e9b68396380ed8791f3c720 100644 (file)
@@ -215,7 +215,7 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
- * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
+ * gfs2_glock_nq_init - initialize a holder and enqueue it on a glock
  * @gl: the glock
  * @state: the state we're requesting
  * @flags: the modifier flags
index 49f97d3bb690c512cb0f338d85938e622d501a49..0d149dcc04e515adfaaeb632a6677e5e3b555f45 100644 (file)
@@ -262,13 +262,12 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
        const struct gfs2_inode *ip = gl->gl_object;
        if (ip == NULL)
                return 0;
-       gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu/%llu\n",
+       gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu\n",
                  (unsigned long long)ip->i_no_formal_ino,
                  (unsigned long long)ip->i_no_addr,
                  IF2DT(ip->i_inode.i_mode), ip->i_flags,
                  (unsigned int)ip->i_diskflags,
-                 (unsigned long long)ip->i_inode.i_size,
-                 (unsigned long long)ip->i_disksize);
+                 (unsigned long long)i_size_read(&ip->i_inode));
        return 0;
 }
 
@@ -453,7 +452,6 @@ const struct gfs2_glock_operations *gfs2_glops_list[] = {
        [LM_TYPE_META] = &gfs2_meta_glops,
        [LM_TYPE_INODE] = &gfs2_inode_glops,
        [LM_TYPE_RGRP] = &gfs2_rgrp_glops,
-       [LM_TYPE_NONDISK] = &gfs2_trans_glops,
        [LM_TYPE_IOPEN] = &gfs2_iopen_glops,
        [LM_TYPE_FLOCK] = &gfs2_flock_glops,
        [LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
index fdbf4b366fa540d295dcbd73b298099b50418f8c..764fbb49efc8e3adbdeda7f83f178b0fd6ea70f8 100644 (file)
@@ -196,6 +196,7 @@ enum {
        GLF_REPLY_PENDING               = 9,
        GLF_INITIAL                     = 10,
        GLF_FROZEN                      = 11,
+       GLF_QUEUED                      = 12,
 };
 
 struct gfs2_glock {
@@ -267,7 +268,6 @@ struct gfs2_inode {
        u64 i_no_formal_ino;
        u64 i_generation;
        u64 i_eattr;
-       loff_t i_disksize;
        unsigned long i_flags;          /* GIF_... */
        struct gfs2_glock *i_gl; /* Move into i_gh? */
        struct gfs2_holder i_iopen_gh;
@@ -416,11 +416,8 @@ struct gfs2_args {
        char ar_locktable[GFS2_LOCKNAME_LEN];   /* Name of the Lock Table */
        char ar_hostdata[GFS2_LOCKNAME_LEN];    /* Host specific data */
        unsigned int ar_spectator:1;            /* Don't get a journal */
-       unsigned int ar_ignore_local_fs:1;      /* Ignore optimisations */
        unsigned int ar_localflocks:1;          /* Let the VFS do flock|fcntl */
-       unsigned int ar_localcaching:1;         /* Local caching */
        unsigned int ar_debug:1;                /* Oops on errors */
-       unsigned int ar_upgrade:1;              /* Upgrade ondisk format */
        unsigned int ar_posix_acl:1;            /* Enable posix acls */
        unsigned int ar_quota:2;                /* off/account/on */
        unsigned int ar_suiddir:1;              /* suiddir support */
@@ -497,7 +494,7 @@ struct gfs2_sb_host {
  */
 
 struct lm_lockstruct {
-       unsigned int ls_jid;
+       int ls_jid;
        unsigned int ls_first;
        unsigned int ls_first_done;
        unsigned int ls_nodir;
@@ -572,6 +569,7 @@ struct gfs2_sbd {
        struct list_head sd_rindex_mru_list;
        struct gfs2_rgrpd *sd_rindex_forward;
        unsigned int sd_rgrps;
+       unsigned int sd_max_rg_data;
 
        /* Journal index stuff */
 
index 08140f185a3792153e23bab24f03ac3107d04757..06370f8bd8cf4aafa95fd4df64e93ec8d657328d 100644 (file)
@@ -359,8 +359,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
         * to do that.
         */
        ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
-       ip->i_disksize = be64_to_cpu(str->di_size);
-       i_size_write(&ip->i_inode, ip->i_disksize);
+       i_size_write(&ip->i_inode, be64_to_cpu(str->di_size));
        gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
        atime.tv_sec = be64_to_cpu(str->di_atime);
        atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
@@ -1055,7 +1054,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
        str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
        str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
        str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
-       str->di_size = cpu_to_be64(ip->i_disksize);
+       str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
        str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
        str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
        str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
@@ -1085,8 +1084,8 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
               (unsigned long long)ip->i_no_formal_ino);
        printk(KERN_INFO "  no_addr = %llu\n",
               (unsigned long long)ip->i_no_addr);
-       printk(KERN_INFO "  i_disksize = %llu\n",
-              (unsigned long long)ip->i_disksize);
+       printk(KERN_INFO "  i_size = %llu\n",
+              (unsigned long long)i_size_read(&ip->i_inode));
        printk(KERN_INFO "  blocks = %llu\n",
               (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
        printk(KERN_INFO "  i_goal = %llu\n",
index 300ada3f21de0cf5fc22677283343a76caf8200e..6720d7d5fbc6aac91083b399b95ba6c978922c67 100644 (file)
@@ -19,6 +19,8 @@ extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
 extern int gfs2_internal_read(struct gfs2_inode *ip,
                              struct file_ra_state *ra_state,
                              char *buf, loff_t *pos, unsigned size);
+extern void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
+                                  unsigned int from, unsigned int to);
 extern void gfs2_set_aops(struct inode *inode);
 
 static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
@@ -80,6 +82,19 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
        dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
 }
 
+static inline int gfs2_check_internal_file_size(struct inode *inode,
+                                               u64 minsize, u64 maxsize)
+{
+       u64 size = i_size_read(inode);
+       if (size < minsize || size > maxsize)
+               goto err;
+       if (size & ((1 << inode->i_blkbits) - 1))
+               goto err;
+       return 0;
+err:
+       gfs2_consist_inode(GFS2_I(inode));
+       return -EIO;
+}
 
 extern void gfs2_set_iop(struct inode *inode);
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
index 0e0470ed34c273a341aed5860191bfadf42b41e5..1c09425b45fd728ba52c1f5f49c3feac187640a2 100644 (file)
@@ -42,9 +42,9 @@ static void gdlm_ast(void *arg)
                ret |= LM_OUT_CANCELED;
                goto out;
        case -EAGAIN: /* Try lock fails */
+       case -EDEADLK: /* Deadlock detected */
                goto out;
-       case -EINVAL: /* Invalid */
-       case -ENOMEM: /* Out of memory */
+       case -ETIMEDOUT: /* Canceled due to timeout */
                ret |= LM_OUT_ERROR;
                goto out;
        case 0: /* Success */
index cde1248a62255ae9bdb03b4c2757a71e973fa089..ac750bd31a6f311e8a3dfc859a257c6f85b2f79d 100644 (file)
@@ -932,7 +932,7 @@ int gfs2_logd(void *data)
 
                do {
                        prepare_to_wait(&sdp->sd_logd_waitq, &wait,
-                                       TASK_UNINTERRUPTIBLE);
+                                       TASK_INTERRUPTIBLE);
                        if (!gfs2_ail_flush_reqd(sdp) &&
                            !gfs2_jrnl_flush_reqd(sdp) &&
                            !kthread_should_stop())
index b1e9630eb46a8d0338fef57ffa15caf23ab1cf0f..d7eb1e209aa899561f7168a6d2964460ae73a89f 100644 (file)
@@ -24,6 +24,7 @@
 #include "glock.h"
 #include "quota.h"
 #include "recovery.h"
+#include "dir.h"
 
 static struct shrinker qd_shrinker = {
        .shrink = gfs2_shrink_qd_memory,
@@ -78,6 +79,9 @@ static int __init init_gfs2_fs(void)
 {
        int error;
 
+       gfs2_str2qstr(&gfs2_qdot, ".");
+       gfs2_str2qstr(&gfs2_qdotdot, "..");
+
        error = gfs2_sys_init();
        if (error)
                return error;
@@ -140,7 +144,7 @@ static int __init init_gfs2_fs(void)
 
        error = -ENOMEM;
        gfs_recovery_wq = alloc_workqueue("gfs_recovery",
-                                         WQ_NON_REENTRANT | WQ_RESCUER, 0);
+                                         WQ_RESCUER | WQ_FREEZEABLE, 0);
        if (!gfs_recovery_wq)
                goto fail_wq;
 
index 4d4b1e8ac64c02ef64ffd216a71ec801e2fdb625..aeafc233dc897fdb102df29bf052fc040b61faef 100644 (file)
 #define DO 0
 #define UNDO 1
 
-static const u32 gfs2_old_fs_formats[] = {
-        0
-};
-
-static const u32 gfs2_old_multihost_formats[] = {
-        0
-};
-
 /**
  * gfs2_tune_init - Fill a gfs2_tune structure with default values
  * @gt: tune
@@ -135,8 +127,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
 static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
 {
-       unsigned int x;
-
        if (sb->sb_magic != GFS2_MAGIC ||
            sb->sb_type != GFS2_METATYPE_SB) {
                if (!silent)
@@ -150,55 +140,9 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int sile
            sb->sb_multihost_format == GFS2_FORMAT_MULTI)
                return 0;
 
-       if (sb->sb_fs_format != GFS2_FORMAT_FS) {
-               for (x = 0; gfs2_old_fs_formats[x]; x++)
-                       if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
-                               break;
+       fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
 
-               if (!gfs2_old_fs_formats[x]) {
-                       printk(KERN_WARNING
-                              "GFS2: code version (%u, %u) is incompatible "
-                              "with ondisk format (%u, %u)\n",
-                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                              sb->sb_fs_format, sb->sb_multihost_format);
-                       printk(KERN_WARNING
-                              "GFS2: I don't know how to upgrade this FS\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
-               for (x = 0; gfs2_old_multihost_formats[x]; x++)
-                       if (gfs2_old_multihost_formats[x] ==
-                           sb->sb_multihost_format)
-                               break;
-
-               if (!gfs2_old_multihost_formats[x]) {
-                       printk(KERN_WARNING
-                              "GFS2: code version (%u, %u) is incompatible "
-                              "with ondisk format (%u, %u)\n",
-                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                              sb->sb_fs_format, sb->sb_multihost_format);
-                       printk(KERN_WARNING
-                              "GFS2: I don't know how to upgrade this FS\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (!sdp->sd_args.ar_upgrade) {
-               printk(KERN_WARNING
-                      "GFS2: code version (%u, %u) is incompatible "
-                      "with ondisk format (%u, %u)\n",
-                      GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                      sb->sb_fs_format, sb->sb_multihost_format);
-               printk(KERN_INFO
-                      "GFS2: Use the \"upgrade\" mount option to upgrade "
-                      "the FS\n");
-               printk(KERN_INFO "GFS2: See the manual for more details\n");
-               return -EINVAL;
-       }
-
-       return 0;
+       return -EINVAL;
 }
 
 static void end_bio_io_page(struct bio *bio, int error)
@@ -586,7 +530,7 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
 
        prev_db = 0;
 
-       for (lb = 0; lb < ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; lb++) {
+       for (lb = 0; lb < i_size_read(jd->jd_inode) >> sdp->sd_sb.sb_bsize_shift; lb++) {
                bh.b_state = 0;
                bh.b_blocknr = 0;
                bh.b_size = 1 << ip->i_inode.i_blkbits;
@@ -1022,7 +966,6 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
        if (!strcmp("lock_nolock", proto)) {
                lm = &nolock_ops;
                sdp->sd_args.ar_localflocks = 1;
-               sdp->sd_args.ar_localcaching = 1;
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
        } else if (!strcmp("lock_dlm", proto)) {
                lm = &gfs2_dlm_ops;
@@ -1113,8 +1056,6 @@ static int gfs2_journalid_wait(void *word)
 
 static int wait_on_journal(struct gfs2_sbd *sdp)
 {
-       if (sdp->sd_args.ar_spectator)
-               return 0;
        if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
                return 0;
 
@@ -1217,6 +1158,20 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
        if (error)
                goto fail_sb;
 
+       /*
+        * If user space has failed to join the cluster or some similar
+        * failure has occurred, then the journal id will contain a
+        * negative (error) number. This will then be returned to the
+        * caller (of the mount syscall). We do this even for spectator
+        * mounts (which just write a jid of 0 to indicate "ok" even though
+        * the jid is unused in the spectator case)
+        */
+       if (sdp->sd_lockstruct.ls_jid < 0) {
+               error = sdp->sd_lockstruct.ls_jid;
+               sdp->sd_lockstruct.ls_jid = 0;
+               goto fail_sb;
+       }
+
        error = init_inodes(sdp, DO);
        if (error)
                goto fail_sb;
index 1009be2c9737687cdee8b48668a5f5d09752abeb..0534510200d5961887d3ee957d799e3b4669e76b 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/fiemap.h>
+#include <linux/swap.h>
+#include <linux/falloc.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -217,7 +219,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
                        goto out_gunlock_q;
 
                error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-                                        al->al_rgd->rd_length +
+                                        gfs2_rg_blocks(al) +
                                         2 * RES_DINODE + RES_STATFS +
                                         RES_QUOTA, 0);
                if (error)
@@ -406,7 +408,6 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
 
        ip = ghs[1].gh_gl->gl_object;
 
-       ip->i_disksize = size;
        i_size_write(inode, size);
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -461,7 +462,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        ip = ghs[1].gh_gl->gl_object;
 
        ip->i_inode.i_nlink = 2;
-       ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
+       i_size_write(inode, sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
        ip->i_diskflags |= GFS2_DIF_JDATA;
        ip->i_entries = 2;
 
@@ -470,18 +471,15 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (!gfs2_assert_withdraw(sdp, !error)) {
                struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
                struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
-               struct qstr str;
 
-               gfs2_str2qstr(&str, ".");
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
+               gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent);
                dent->de_inum = di->di_num; /* already GFS2 endian */
                dent->de_type = cpu_to_be16(DT_DIR);
                di->di_entries = cpu_to_be32(1);
 
-               gfs2_str2qstr(&str, "..");
                dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
-               gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
+               gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
 
                gfs2_inum_out(dip, dent);
                dent->de_type = cpu_to_be16(DT_DIR);
@@ -522,7 +520,6 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
                       struct gfs2_inode *ip)
 {
-       struct qstr dotname;
        int error;
 
        if (ip->i_entries != 2) {
@@ -539,13 +536,11 @@ static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
        if (error)
                return error;
 
-       gfs2_str2qstr(&dotname, ".");
-       error = gfs2_dir_del(ip, &dotname);
+       error = gfs2_dir_del(ip, &gfs2_qdot);
        if (error)
                return error;
 
-       gfs2_str2qstr(&dotname, "..");
-       error = gfs2_dir_del(ip, &dotname);
+       error = gfs2_dir_del(ip, &gfs2_qdotdot);
        if (error)
                return error;
 
@@ -694,11 +689,8 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
        struct inode *dir = &to->i_inode;
        struct super_block *sb = dir->i_sb;
        struct inode *tmp;
-       struct qstr dotdot;
        int error = 0;
 
-       gfs2_str2qstr(&dotdot, "..");
-
        igrab(dir);
 
        for (;;) {
@@ -711,7 +703,7 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
                        break;
                }
 
-               tmp = gfs2_lookupi(dir, &dotdot, 1);
+               tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1);
                if (IS_ERR(tmp)) {
                        error = PTR_ERR(tmp);
                        break;
@@ -744,7 +736,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
        struct gfs2_inode *nip = NULL;
        struct gfs2_sbd *sdp = GFS2_SB(odir);
-       struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
+       struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh;
        struct gfs2_rgrpd *nrgd;
        unsigned int num_gh;
        int dir_rename = 0;
@@ -758,6 +750,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        return 0;
        }
 
+       error = gfs2_rindex_hold(sdp, &ri_gh);
+       if (error)
+               return error;
 
        if (odip != ndip) {
                error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
@@ -887,12 +882,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 
                al->al_requested = sdp->sd_max_dirres;
 
-               error = gfs2_inplace_reserve(ndip);
+               error = gfs2_inplace_reserve_ri(ndip);
                if (error)
                        goto out_gunlock_q;
 
                error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-                                        al->al_rgd->rd_length +
+                                        gfs2_rg_blocks(al) +
                                         4 * RES_DINODE + 4 * RES_LEAF +
                                         RES_STATFS + RES_QUOTA + 4, 0);
                if (error)
@@ -920,9 +915,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        }
 
        if (dir_rename) {
-               struct qstr name;
-               gfs2_str2qstr(&name, "..");
-
                error = gfs2_change_nlink(ndip, +1);
                if (error)
                        goto out_end_trans;
@@ -930,7 +922,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                if (error)
                        goto out_end_trans;
 
-               error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
+               error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
                if (error)
                        goto out_end_trans;
        } else {
@@ -972,6 +964,7 @@ out_gunlock_r:
        if (r_gh.gh_gl)
                gfs2_glock_dq_uninit(&r_gh);
 out:
+       gfs2_glock_dq_uninit(&ri_gh);
        return error;
 }
 
@@ -990,7 +983,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
-       unsigned int x;
+       unsigned int x, size;
        char *buf;
        int error;
 
@@ -1002,7 +995,8 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
                return NULL;
        }
 
-       if (!ip->i_disksize) {
+       size = (unsigned int)i_size_read(&ip->i_inode);
+       if (size == 0) {
                gfs2_consist_inode(ip);
                buf = ERR_PTR(-EIO);
                goto out;
@@ -1014,7 +1008,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
                goto out;
        }
 
-       x = ip->i_disksize + 1;
+       x = size + 1;
        buf = kmalloc(x, GFP_NOFS);
        if (!buf)
                buf = ERR_PTR(-ENOMEM);
@@ -1071,30 +1065,6 @@ int gfs2_permission(struct inode *inode, int mask)
        return error;
 }
 
-/*
- * XXX(truncate): the truncate_setsize calls should be moved to the end.
- */
-static int setattr_size(struct inode *inode, struct iattr *attr)
-{
-       struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
-       int error;
-
-       if (attr->ia_size != ip->i_disksize) {
-               error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
-               if (error)
-                       return error;
-               truncate_setsize(inode, attr->ia_size);
-               gfs2_trans_end(sdp);
-       }
-
-       error = gfs2_truncatei(ip, attr->ia_size);
-       if (error && (inode->i_size != ip->i_disksize))
-               i_size_write(inode, ip->i_disksize);
-
-       return error;
-}
-
 static int setattr_chown(struct inode *inode, struct iattr *attr)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -1195,7 +1165,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
                goto out;
 
        if (attr->ia_valid & ATTR_SIZE)
-               error = setattr_size(inode, attr);
+               error = gfs2_setattr_size(inode, attr->ia_size);
        else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
                error = setattr_chown(inode, attr);
        else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
@@ -1301,6 +1271,257 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
        return ret;
 }
 
+static void empty_write_end(struct page *page, unsigned from,
+                          unsigned to)
+{
+       struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+
+       page_zero_new_buffers(page, from, to);
+       flush_dcache_page(page);
+       mark_page_accessed(page);
+
+       if (!gfs2_is_writeback(ip))
+               gfs2_page_add_databufs(ip, page, from, to);
+
+       block_commit_write(page, from, to);
+}
+
+
+static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+{
+       unsigned start, end, next;
+       struct buffer_head *bh, *head;
+       int error;
+
+       if (!page_has_buffers(page)) {
+               error = block_prepare_write(page, from, to, gfs2_block_map);
+               if (unlikely(error))
+                       return error;
+
+               empty_write_end(page, from, to);
+               return 0;
+       }
+
+       bh = head = page_buffers(page);
+       next = end = 0;
+       while (next < from) {
+               next += bh->b_size;
+               bh = bh->b_this_page;
+       }
+       start = next;
+       do {
+               next += bh->b_size;
+               if (buffer_mapped(bh)) {
+                       if (end) {
+                               error = block_prepare_write(page, start, end,
+                                                           gfs2_block_map);
+                               if (unlikely(error))
+                                       return error;
+                               empty_write_end(page, start, end);
+                               end = 0;
+                       }
+                       start = next;
+               }
+               else
+                       end = next;
+               bh = bh->b_this_page;
+       } while (next < to);
+
+       if (end) {
+               error = block_prepare_write(page, start, end, gfs2_block_map);
+               if (unlikely(error))
+                       return error;
+               empty_write_end(page, start, end);
+       }
+
+       return 0;
+}
+
+static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
+                          int mode)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct buffer_head *dibh;
+       int error;
+       u64 start = offset >> PAGE_CACHE_SHIFT;
+       unsigned int start_offset = offset & ~PAGE_CACHE_MASK;
+       u64 end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
+       pgoff_t curr;
+       struct page *page;
+       unsigned int end_offset = (offset + len) & ~PAGE_CACHE_MASK;
+       unsigned int from, to;
+
+       if (!end_offset)
+               end_offset = PAGE_CACHE_SIZE;
+
+       error = gfs2_meta_inode_buffer(ip, &dibh);
+       if (unlikely(error))
+               goto out;
+
+       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+
+       if (gfs2_is_stuffed(ip)) {
+               error = gfs2_unstuff_dinode(ip, NULL);
+               if (unlikely(error))
+                       goto out;
+       }
+
+       curr = start;
+       offset = start << PAGE_CACHE_SHIFT;
+       from = start_offset;
+       to = PAGE_CACHE_SIZE;
+       while (curr <= end) {
+               page = grab_cache_page_write_begin(inode->i_mapping, curr,
+                                                  AOP_FLAG_NOFS);
+               if (unlikely(!page)) {
+                       error = -ENOMEM;
+                       goto out;
+               }
+
+               if (curr == end)
+                       to = end_offset;
+               error = write_empty_blocks(page, from, to);
+               if (!error && offset + to > inode->i_size &&
+                   !(mode & FALLOC_FL_KEEP_SIZE)) {
+                       i_size_write(inode, offset + to);
+               }
+               unlock_page(page);
+               page_cache_release(page);
+               if (error)
+                       goto out;
+               curr++;
+               offset += PAGE_CACHE_SIZE;
+               from = 0;
+       }
+
+       gfs2_dinode_out(ip, dibh->b_data);
+       mark_inode_dirty(inode);
+
+       brelse(dibh);
+
+out:
+       return error;
+}
+
+static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
+                           unsigned int *data_blocks, unsigned int *ind_blocks)
+{
+       const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       unsigned int max_blocks = ip->i_alloc->al_rgd->rd_free_clone;
+       unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1);
+
+       for (tmp = max_data; tmp > sdp->sd_diptrs;) {
+               tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
+               max_data -= tmp;
+       }
+       /* This calculation isn't the exact reverse of gfs2_write_calc_reserve,
+          so it might end up with fewer data blocks */
+       if (max_data <= *data_blocks)
+               return;
+       *data_blocks = max_data;
+       *ind_blocks = max_blocks - max_data;
+       *len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift;
+       if (*len > max) {
+               *len = max;
+               gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks);
+       }
+}
+
+static long gfs2_fallocate(struct inode *inode, int mode, loff_t offset,
+                          loff_t len)
+{
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
+       loff_t bytes, max_bytes;
+       struct gfs2_alloc *al;
+       int error;
+       loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
+       next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
+
+       offset = (offset >> sdp->sd_sb.sb_bsize_shift) <<
+                sdp->sd_sb.sb_bsize_shift;
+
+       len = next - offset;
+       bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2;
+       if (!bytes)
+               bytes = UINT_MAX;
+
+       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
+       error = gfs2_glock_nq(&ip->i_gh);
+       if (unlikely(error))
+               goto out_uninit;
+
+       if (!gfs2_write_alloc_required(ip, offset, len))
+               goto out_unlock;
+
+       while (len > 0) {
+               if (len < bytes)
+                       bytes = len;
+               al = gfs2_alloc_get(ip);
+               if (!al) {
+                       error = -ENOMEM;
+                       goto out_unlock;
+               }
+
+               error = gfs2_quota_lock_check(ip);
+               if (error)
+                       goto out_alloc_put;
+
+retry:
+               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+
+               al->al_requested = data_blocks + ind_blocks;
+               error = gfs2_inplace_reserve(ip);
+               if (error) {
+                       if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
+                               bytes >>= 1;
+                               goto retry;
+                       }
+                       goto out_qunlock;
+               }
+               max_bytes = bytes;
+               calc_max_reserv(ip, len, &max_bytes, &data_blocks, &ind_blocks);
+               al->al_requested = data_blocks + ind_blocks;
+
+               rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
+                         RES_RG_HDR + gfs2_rg_blocks(al);
+               if (gfs2_is_jdata(ip))
+                       rblocks += data_blocks ? data_blocks : 1;
+
+               error = gfs2_trans_begin(sdp, rblocks,
+                                        PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
+               if (error)
+                       goto out_trans_fail;
+
+               error = fallocate_chunk(inode, offset, max_bytes, mode);
+               gfs2_trans_end(sdp);
+
+               if (error)
+                       goto out_trans_fail;
+
+               len -= max_bytes;
+               offset += max_bytes;
+               gfs2_inplace_release(ip);
+               gfs2_quota_unlock(ip);
+               gfs2_alloc_put(ip);
+       }
+       goto out_unlock;
+
+out_trans_fail:
+       gfs2_inplace_release(ip);
+out_qunlock:
+       gfs2_quota_unlock(ip);
+out_alloc_put:
+       gfs2_alloc_put(ip);
+out_unlock:
+       gfs2_glock_dq(&ip->i_gh);
+out_uninit:
+       gfs2_holder_uninit(&ip->i_gh);
+       return error;
+}
+
+
 static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                       u64 start, u64 len)
 {
@@ -1351,6 +1572,7 @@ const struct inode_operations gfs2_file_iops = {
        .getxattr = gfs2_getxattr,
        .listxattr = gfs2_listxattr,
        .removexattr = gfs2_removexattr,
+       .fallocate = gfs2_fallocate,
        .fiemap = gfs2_fiemap,
 };
 
index 1bc6b5695e6dfb34870810b87bd09c819f25c93f..58a9b9998b42d0d9603c7a49ffc746ab4a22ef87 100644 (file)
@@ -735,10 +735,8 @@ get_a_page:
                goto out;
 
        size = loc + sizeof(struct gfs2_quota);
-       if (size > inode->i_size) {
-               ip->i_disksize = size;
+       if (size > inode->i_size)
                i_size_write(inode, size);
-       }
        inode->i_mtime = inode->i_atime = CURRENT_TIME;
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
@@ -817,7 +815,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
                goto out_alloc;
 
        if (nalloc)
-               blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
+               blocks += gfs2_rg_blocks(al) + nalloc * ind_blocks + RES_STATFS;
 
        error = gfs2_trans_begin(sdp, blocks, 0);
        if (error)
@@ -1190,18 +1188,17 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *
 int gfs2_quota_init(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
-       unsigned int blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
+       u64 size = i_size_read(sdp->sd_qc_inode);
+       unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift;
        unsigned int x, slot = 0;
        unsigned int found = 0;
        u64 dblock;
        u32 extlen = 0;
        int error;
 
-       if (!ip->i_disksize || ip->i_disksize > (64 << 20) ||
-           ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
-               gfs2_consist_inode(ip);
+       if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
                return -EIO;
-       }
+
        sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
        sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE);
 
@@ -1589,6 +1586,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
                error = gfs2_inplace_reserve(ip);
                if (error)
                        goto out_alloc;
+               blocks += gfs2_rg_blocks(al);
        }
 
        error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
index f7f89a94a5a4598a4b532016a0c16846a62cef2b..f2a02edcac8f43e9de1dd22fd4c72ac7347f39a5 100644 (file)
@@ -455,11 +455,13 @@ void gfs2_recover_func(struct work_struct *work)
        int ro = 0;
        unsigned int pass;
        int error;
+       int jlocked = 0;
 
-       if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
+       if (sdp->sd_args.ar_spectator ||
+           (jd->jd_jid != sdp->sd_lockstruct.ls_jid)) {
                fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
                        jd->jd_jid);
-
+               jlocked = 1;
                /* Acquire the journal lock so we can do recovery */
 
                error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
@@ -554,13 +556,12 @@ void gfs2_recover_func(struct work_struct *work)
                        jd->jd_jid, t);
        }
 
-       if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
-               gfs2_glock_dq_uninit(&ji_gh);
-
        gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
 
-       if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
+       if (jlocked) {
+               gfs2_glock_dq_uninit(&ji_gh);
                gfs2_glock_dq_uninit(&j_gh);
+       }
 
        fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
        goto done;
@@ -568,7 +569,7 @@ void gfs2_recover_func(struct work_struct *work)
 fail_gunlock_tr:
        gfs2_glock_dq_uninit(&t_gh);
 fail_gunlock_ji:
-       if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
+       if (jlocked) {
                gfs2_glock_dq_uninit(&ji_gh);
 fail_gunlock_j:
                gfs2_glock_dq_uninit(&j_gh);
index 171a744f8e45d172f4e43eb793ae4e08dba8ba23..fb67f593f40856b213f03887642c44a3e4c7ccc5 100644 (file)
@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
        for (rgrps = 0;; rgrps++) {
                loff_t pos = rgrps * sizeof(struct gfs2_rindex);
 
-               if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize)
+               if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode))
                        break;
                error = gfs2_internal_read(ip, &ra_state, buf, &pos,
                                           sizeof(struct gfs2_rindex));
@@ -588,7 +588,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct inode *inode = &ip->i_inode;
        struct file_ra_state ra_state;
-       u64 rgrp_count = ip->i_disksize;
+       u64 rgrp_count = i_size_read(inode);
+       struct gfs2_rgrpd *rgd;
+       unsigned int max_data = 0;
        int error;
 
        do_div(rgrp_count, sizeof(struct gfs2_rindex));
@@ -603,6 +605,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
                }
        }
 
+       list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
+               if (rgd->rd_data > max_data)
+                       max_data = rgd->rd_data;
+       sdp->sd_max_rg_data = max_data;
        sdp->sd_rindex_uptodate = 1;
        return 0;
 }
@@ -622,13 +628,15 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct inode *inode = &ip->i_inode;
        struct file_ra_state ra_state;
+       struct gfs2_rgrpd *rgd;
+       unsigned int max_data = 0;
        int error;
 
        file_ra_state_init(&ra_state, inode->i_mapping);
        for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
                /* Ignore partials */
                if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
-                   ip->i_disksize)
+                   i_size_read(inode))
                        break;
                error = read_rindex_entry(ip, &ra_state);
                if (error) {
@@ -636,6 +644,10 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
                        return error;
                }
        }
+       list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
+               if (rgd->rd_data > max_data)
+                       max_data = rgd->rd_data;
+       sdp->sd_max_rg_data = max_data;
 
        sdp->sd_rindex_uptodate = 1;
        return 0;
@@ -1188,7 +1200,8 @@ out:
  * Returns: errno
  */
 
-int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
+int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
+                          char *file, unsigned int line)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = ip->i_alloc;
@@ -1199,12 +1212,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
                return -EINVAL;
 
 try_again:
-       /* We need to hold the rindex unless the inode we're using is
-          the rindex itself, in which case it's already held. */
-       if (ip != GFS2_I(sdp->sd_rindex))
-               error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
-       else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
-               error = gfs2_ri_update_special(ip);
+       if (hold_rindex) {
+               /* We need to hold the rindex unless the inode we're using is
+                  the rindex itself, in which case it's already held. */
+               if (ip != GFS2_I(sdp->sd_rindex))
+                       error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+               else if (!sdp->sd_rgrps) /* We may not have the rindex read
+                                           in, so: */
+                       error = gfs2_ri_update_special(ip);
+       }
 
        if (error)
                return error;
@@ -1215,7 +1231,7 @@ try_again:
           try to free it, and try the allocation again. */
        error = get_local_rgrp(ip, &unlinked, &last_unlinked);
        if (error) {
-               if (ip != GFS2_I(sdp->sd_rindex))
+               if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
                        gfs2_glock_dq_uninit(&al->al_ri_gh);
                if (error != -EAGAIN)
                        return error;
@@ -1257,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
        al->al_rgd = NULL;
        if (al->al_rgd_gh.gh_gl)
                gfs2_glock_dq_uninit(&al->al_rgd_gh);
-       if (ip != GFS2_I(sdp->sd_rindex))
+       if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl)
                gfs2_glock_dq_uninit(&al->al_ri_gh);
 }
 
@@ -1496,11 +1512,19 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct buffer_head *dibh;
        struct gfs2_alloc *al = ip->i_alloc;
-       struct gfs2_rgrpd *rgd = al->al_rgd;
+       struct gfs2_rgrpd *rgd;
        u32 goal, blk;
        u64 block;
        int error;
 
+       /* Only happens if there is a bug in gfs2, return something distinctive
+        * to ensure that it is noticed.
+        */
+       if (al == NULL)
+               return -ECANCELED;
+
+       rgd = al->al_rgd;
+
        if (rgrp_contains_block(rgd, ip->i_goal))
                goal = ip->i_goal - rgd->rd_data0;
        else
index f07119d89557855fc9a8673b32e9119cad921570..0e35c0466f9a6c5979a3fe8c339def323bc37fad 100644 (file)
@@ -39,10 +39,12 @@ static inline void gfs2_alloc_put(struct gfs2_inode *ip)
        ip->i_alloc = NULL;
 }
 
-extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file,
-                                 unsigned int line);
+extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
+                                 char *file, unsigned int line);
 #define gfs2_inplace_reserve(ip) \
-gfs2_inplace_reserve_i((ip), __FILE__, __LINE__)
+       gfs2_inplace_reserve_i((ip), 1, __FILE__, __LINE__)
+#define gfs2_inplace_reserve_ri(ip) \
+       gfs2_inplace_reserve_i((ip), 0, __FILE__, __LINE__)
 
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
index 77cb9f830ee47eb51520bd8581ebc700b426455e..047d1176096c79d6f0ce50227b8c098755fb0150 100644 (file)
@@ -85,6 +85,7 @@ static const match_table_t tokens = {
        {Opt_locktable, "locktable=%s"},
        {Opt_hostdata, "hostdata=%s"},
        {Opt_spectator, "spectator"},
+       {Opt_spectator, "norecovery"},
        {Opt_ignore_local_fs, "ignore_local_fs"},
        {Opt_localflocks, "localflocks"},
        {Opt_localcaching, "localcaching"},
@@ -159,13 +160,13 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
                        args->ar_spectator = 1;
                        break;
                case Opt_ignore_local_fs:
-                       args->ar_ignore_local_fs = 1;
+                       /* Retained for backwards compat only */
                        break;
                case Opt_localflocks:
                        args->ar_localflocks = 1;
                        break;
                case Opt_localcaching:
-                       args->ar_localcaching = 1;
+                       /* Retained for backwards compat only */
                        break;
                case Opt_debug:
                        if (args->ar_errors == GFS2_ERRORS_PANIC) {
@@ -179,7 +180,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
                        args->ar_debug = 0;
                        break;
                case Opt_upgrade:
-                       args->ar_upgrade = 1;
+                       /* Retained for backwards compat only */
                        break;
                case Opt_acl:
                        args->ar_posix_acl = 1;
@@ -342,15 +343,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
 {
        struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
+       u64 size = i_size_read(jd->jd_inode);
 
-       if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) ||
-           (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
-               gfs2_consist_inode(ip);
+       if (gfs2_check_internal_file_size(jd->jd_inode, 8 << 20, 1 << 30))
                return -EIO;
-       }
-       jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
 
-       if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) {
+       jd->jd_blocks = size >> sdp->sd_sb.sb_bsize_shift;
+
+       if (gfs2_write_alloc_required(ip, 0, size)) {
                gfs2_consist_inode(ip);
                return -EIO;
        }
@@ -1129,9 +1129,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
 
        /* Some flags must not be changed */
        if (args_neq(&args, &sdp->sd_args, spectator) ||
-           args_neq(&args, &sdp->sd_args, ignore_local_fs) ||
            args_neq(&args, &sdp->sd_args, localflocks) ||
-           args_neq(&args, &sdp->sd_args, localcaching) ||
            args_neq(&args, &sdp->sd_args, meta))
                return -EINVAL;
 
@@ -1234,16 +1232,10 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
                seq_printf(s, ",hostdata=%s", args->ar_hostdata);
        if (args->ar_spectator)
                seq_printf(s, ",spectator");
-       if (args->ar_ignore_local_fs)
-               seq_printf(s, ",ignore_local_fs");
        if (args->ar_localflocks)
                seq_printf(s, ",localflocks");
-       if (args->ar_localcaching)
-               seq_printf(s, ",localcaching");
        if (args->ar_debug)
                seq_printf(s, ",debug");
-       if (args->ar_upgrade)
-               seq_printf(s, ",upgrade");
        if (args->ar_posix_acl)
                seq_printf(s, ",acl");
        if (args->ar_quota != GFS2_QUOTA_DEFAULT) {
index ccacffd2faaa6d65d1f116b9b2788ee732786f3f..748ccb557c18fc504c28951f13d634fe9f05fa0a 100644 (file)
@@ -230,7 +230,10 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len
 
        if (gltype > LM_TYPE_JOURNAL)
                return -EINVAL;
-       glops = gfs2_glops_list[gltype];
+       if (gltype == LM_TYPE_NONDISK && glnum == GFS2_TRANS_LOCK)
+               glops = &gfs2_trans_glops;
+       else
+               glops = gfs2_glops_list[gltype];
        if (glops == NULL)
                return -EINVAL;
        if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
@@ -399,31 +402,32 @@ static ssize_t recover_status_show(struct gfs2_sbd *sdp, char *buf)
 
 static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
 {
-       return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid);
+       return sprintf(buf, "%d\n", sdp->sd_lockstruct.ls_jid);
 }
 
 static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 {
-        unsigned jid;
+        int jid;
        int rv;
 
-       rv = sscanf(buf, "%u", &jid);
+       rv = sscanf(buf, "%d", &jid);
        if (rv != 1)
                return -EINVAL;
 
        spin_lock(&sdp->sd_jindex_spin);
        rv = -EINVAL;
-       if (sdp->sd_args.ar_spectator)
-               goto out;
        if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
                goto out;
        rv = -EBUSY;
-       if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
+       if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
                goto out;
+       rv = 0;
+       if (sdp->sd_args.ar_spectator && jid > 0)
+               rv = jid = -EINVAL;
        sdp->sd_lockstruct.ls_jid = jid;
+       clear_bit(SDF_NOJOURNALID, &sdp->sd_flags);
        smp_mb__after_clear_bit();
        wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
-       rv = 0;
 out:
        spin_unlock(&sdp->sd_jindex_spin);
        return rv ? rv : len;
@@ -617,7 +621,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
        add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
        add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
        if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags))
-               add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid);
+               add_uevent_var(env, "JOURNALID=%d", sdp->sd_lockstruct.ls_jid);
        if (gfs2_uuid_valid(uuid))
                add_uevent_var(env, "UUID=%pUB", uuid);
        return 0;
index 148d55c14171dee39435c83d56c906c09dcd0cf8..cedb0bb96d968414d14e6eca3e5b934b68ee606e 100644 (file)
@@ -39,7 +39,8 @@
        {(1UL << GLF_INVALIDATE_IN_PROGRESS),   "i" },          \
        {(1UL << GLF_REPLY_PENDING),            "r" },          \
        {(1UL << GLF_INITIAL),                  "I" },          \
-       {(1UL << GLF_FROZEN),                   "F" })
+       {(1UL << GLF_FROZEN),                   "F" },          \
+       {(1UL << GLF_QUEUED),                   "q" })
 
 #ifndef NUMPTY
 #define NUMPTY
index edf9d4bd908ee2726991f12ac869bfeb60971381..fb56b783e028c8ce61b0b663e67e2df14e408b07 100644 (file)
@@ -20,11 +20,20 @@ struct gfs2_glock;
 #define RES_JDATA      1
 #define RES_DATA       1
 #define RES_LEAF       1
+#define RES_RG_HDR     1
 #define RES_RG_BIT     2
 #define RES_EATTR      1
 #define RES_STATFS     1
 #define RES_QUOTA      2
 
+/* reserve either the number of blocks to be allocated plus the rg header
+ * block, or all of the blocks in the rg, whichever is smaller */
+static inline unsigned int gfs2_rg_blocks(const struct gfs2_alloc *al)
+{
+       return (al->al_requested < al->al_rgd->rd_length)?
+              al->al_requested + 1 : al->al_rgd->rd_length;
+}
+
 int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
                     unsigned int revokes);
 
index 776af6eb4bcb1b193ecf5ef858ac09cb0535b95f..30b58f07c8a6b219fc964efe101ce5f861397885 100644 (file)
@@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                goto out_gunlock_q;
 
        error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
-                                blks + al->al_rgd->rd_length +
+                                blks + gfs2_rg_blocks(al) +
                                 RES_DINODE + RES_STATFS + RES_QUOTA, 0);
        if (error)
                goto out_ipres;
index 4129cdb3f0d8fbf80c4b161d877d9e922666f9ea..571abe97b42a2919caf381238eec6e58c57d0eaf 100644 (file)
@@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
        fd->search_key = ptr;
        fd->key = ptr + tree->max_key_len + 2;
        dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
-       down(&tree->tree_lock);
+       mutex_lock(&tree->tree_lock);
        return 0;
 }
 
@@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd)
        hfs_bnode_put(fd->bnode);
        kfree(fd->search_key);
        dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
-       up(&fd->tree->tree_lock);
+       mutex_unlock(&fd->tree->tree_lock);
        fd->tree = NULL;
 }
 
index 38a0a9917d7f3a67b0eaad49a75246430eef7d76..3ebc437736febb4e0ef37a3612ea6501c7eac59a 100644 (file)
@@ -27,7 +27,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        if (!tree)
                return NULL;
 
-       init_MUTEX(&tree->tree_lock);
+       mutex_init(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
        /* Set the correct compare function */
        tree->sb = sb;
index cc51905ac21de4f110929dedd9160152d76a0f26..2a1d712f85dccfb5bb2983615e84278a1c4923e7 100644 (file)
@@ -33,7 +33,7 @@ struct hfs_btree {
        unsigned int depth;
 
        //unsigned int map1_size, map_size;
-       struct semaphore tree_lock;
+       struct mutex tree_lock;
 
        unsigned int pages_per_bnode;
        spinlock_t hash_lock;
index 34235d4bf08bb5921768b1105b37bfff4277cd7a..33254160f650e22da90ff1b0b153df229c81f0df 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 
 #include "hfs_fs.h"
@@ -79,15 +78,11 @@ static int hfs_sync_fs(struct super_block *sb, int wait)
  */
 static void hfs_put_super(struct super_block *sb)
 {
-       lock_kernel();
-
        if (sb->s_dirt)
                hfs_write_super(sb);
        hfs_mdb_close(sb);
        /* release the MDB's resources */
        hfs_mdb_put(sb);
-
-       unlock_kernel();
 }
 
 /*
@@ -385,6 +380,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
+
        sb->s_fs_info = sbi;
        INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
index 5007a41f1be9d345ff11dd7420285ee6a79c08e2..d182438c7ae4bea8b4ae108ad910ee795417410a 100644 (file)
@@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
        fd->search_key = ptr;
        fd->key = ptr + tree->max_key_len + 2;
        dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
-       down(&tree->tree_lock);
+       mutex_lock(&tree->tree_lock);
        return 0;
 }
 
@@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd)
        hfs_bnode_put(fd->bnode);
        kfree(fd->search_key);
        dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
-       up(&fd->tree->tree_lock);
+       mutex_unlock(&fd->tree->tree_lock);
        fd->tree = NULL;
 }
 
@@ -52,6 +52,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
                rec = (e + b) / 2;
                len = hfs_brec_lenoff(bnode, rec, &off);
                keylen = hfs_brec_keylen(bnode, rec);
+               if (keylen == 0) {
+                       res = -EINVAL;
+                       goto fail;
+               }
                hfs_bnode_read(bnode, fd->key, off, keylen);
                cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
                if (!cmpval) {
@@ -67,6 +71,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
        if (rec != e && e >= 0) {
                len = hfs_brec_lenoff(bnode, e, &off);
                keylen = hfs_brec_keylen(bnode, e);
+               if (keylen == 0) {
+                       res = -EINVAL;
+                       goto fail;
+               }
                hfs_bnode_read(bnode, fd->key, off, keylen);
        }
 done:
@@ -75,6 +83,7 @@ done:
        fd->keylength = keylen;
        fd->entryoffset = off + keylen;
        fd->entrylength = len - keylen;
+fail:
        return res;
 }
 
@@ -198,6 +207,10 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
 
        len = hfs_brec_lenoff(bnode, fd->record, &off);
        keylen = hfs_brec_keylen(bnode, fd->record);
+       if (keylen == 0) {
+               res = -EINVAL;
+               goto out;
+       }
        fd->keyoffset = off;
        fd->keylength = keylen;
        fd->entryoffset = off + keylen;
index ea30afc2a03c774221cc17341c446d30a0cb341b..ad57f5991eb1f14e3ac24dafa207e440d6d74be3 100644 (file)
@@ -17,6 +17,7 @@
 
 int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct page *page;
        struct address_space *mapping;
        __be32 *pptr, *curr, *end;
@@ -29,8 +30,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
                return size;
 
        dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
-       mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
-       mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+       mutex_lock(&sbi->alloc_mutex);
+       mapping = sbi->alloc_file->i_mapping;
        page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
        if (IS_ERR(page)) {
                start = size;
@@ -150,16 +151,17 @@ done:
        set_page_dirty(page);
        kunmap(page);
        *max = offset + (curr - pptr) * 32 + i - start;
-       HFSPLUS_SB(sb).free_blocks -= *max;
+       sbi->free_blocks -= *max;
        sb->s_dirt = 1;
        dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
 out:
-       mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
+       mutex_unlock(&sbi->alloc_mutex);
        return start;
 }
 
 int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct page *page;
        struct address_space *mapping;
        __be32 *pptr, *curr, *end;
@@ -172,11 +174,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 
        dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
        /* are all of the bits in range? */
-       if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
+       if ((offset + count) > sbi->total_blocks)
                return -2;
 
-       mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
-       mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+       mutex_lock(&sbi->alloc_mutex);
+       mapping = sbi->alloc_file->i_mapping;
        pnr = offset / PAGE_CACHE_BITS;
        page = read_mapping_page(mapping, pnr, NULL);
        pptr = kmap(page);
@@ -224,9 +226,9 @@ done:
 out:
        set_page_dirty(page);
        kunmap(page);
-       HFSPLUS_SB(sb).free_blocks += len;
+       sbi->free_blocks += len;
        sb->s_dirt = 1;
-       mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
+       mutex_unlock(&sbi->alloc_mutex);
 
        return 0;
 }
index c88e5d72a402ae2d29a8905cdccf7b59ccd4337d..2f39d05443e1a374b197359f70d20337562aa9e8 100644 (file)
@@ -42,10 +42,13 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
                recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
                if (!recoff)
                        return 0;
-               if (node->tree->attributes & HFS_TREE_BIGKEYS)
-                       retval = hfs_bnode_read_u16(node, recoff) + 2;
-               else
-                       retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
+
+               retval = hfs_bnode_read_u16(node, recoff) + 2;
+               if (retval > node->tree->max_key_len + 2) {
+                       printk(KERN_ERR "hfs: keylen %d too large\n",
+                               retval);
+                       retval = 0;
+               }
        }
        return retval;
 }
@@ -216,7 +219,7 @@ skip:
 static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
 {
        struct hfs_btree *tree;
-       struct hfs_bnode *node, *new_node;
+       struct hfs_bnode *node, *new_node, *next_node;
        struct hfs_bnode_desc node_desc;
        int num_recs, new_rec_off, new_off, old_rec_off;
        int data_start, data_end, size;
@@ -235,6 +238,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
        new_node->type = node->type;
        new_node->height = node->height;
 
+       if (node->next)
+               next_node = hfs_bnode_find(tree, node->next);
+       else
+               next_node = NULL;
+
+       if (IS_ERR(next_node)) {
+               hfs_bnode_put(node);
+               hfs_bnode_put(new_node);
+               return next_node;
+       }
+
        size = tree->node_size / 2 - node->num_recs * 2 - 14;
        old_rec_off = tree->node_size - 4;
        num_recs = 1;
@@ -248,6 +262,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
                /* panic? */
                hfs_bnode_put(node);
                hfs_bnode_put(new_node);
+               if (next_node)
+                       hfs_bnode_put(next_node);
                return ERR_PTR(-ENOSPC);
        }
 
@@ -302,8 +318,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
        hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
 
        /* update next bnode header */
-       if (new_node->next) {
-               struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
+       if (next_node) {
                next_node->prev = new_node->this;
                hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
                node_desc.prev = cpu_to_be32(next_node->prev);
index e49fcee1e293f725786e84ea6126e408e5eda7c8..22e4d4e329999c3ba9848036a3639bc194598f74 100644 (file)
@@ -30,7 +30,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        if (!tree)
                return NULL;
 
-       init_MUTEX(&tree->tree_lock);
+       mutex_init(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
        tree->sb = sb;
        tree->cnid = id;
@@ -39,10 +39,16 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
                goto free_tree;
        tree->inode = inode;
 
+       if (!HFSPLUS_I(tree->inode)->first_blocks) {
+               printk(KERN_ERR
+                      "hfs: invalid btree extent records (0 size).\n");
+               goto free_inode;
+       }
+
        mapping = tree->inode->i_mapping;
        page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
-               goto free_tree;
+               goto free_inode;
 
        /* Load the header */
        head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
@@ -57,27 +63,56 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        tree->max_key_len = be16_to_cpu(head->max_key_len);
        tree->depth = be16_to_cpu(head->depth);
 
-       /* Set the correct compare function */
-       if (id == HFSPLUS_EXT_CNID) {
+       /* Verify the tree and set the correct compare function */
+       switch (id) {
+       case HFSPLUS_EXT_CNID:
+               if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) {
+                       printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
+                               tree->max_key_len);
+                       goto fail_page;
+               }
+               if (tree->attributes & HFS_TREE_VARIDXKEYS) {
+                       printk(KERN_ERR "hfs: invalid extent btree flag\n");
+                       goto fail_page;
+               }
+
                tree->keycmp = hfsplus_ext_cmp_key;
-       } else if (id == HFSPLUS_CAT_CNID) {
-               if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
+               break;
+       case HFSPLUS_CAT_CNID:
+               if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) {
+                       printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
+                               tree->max_key_len);
+                       goto fail_page;
+               }
+               if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
+                       printk(KERN_ERR "hfs: invalid catalog btree flag\n");
+                       goto fail_page;
+               }
+
+               if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) &&
                    (head->key_type == HFSPLUS_KEY_BINARY))
                        tree->keycmp = hfsplus_cat_bin_cmp_key;
                else {
                        tree->keycmp = hfsplus_cat_case_cmp_key;
-                       HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
+                       set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
                }
-       } else {
+               break;
+       default:
                printk(KERN_ERR "hfs: unknown B*Tree requested\n");
                goto fail_page;
        }
 
+       if (!(tree->attributes & HFS_TREE_BIGKEYS)) {
+               printk(KERN_ERR "hfs: invalid btree flag\n");
+               goto fail_page;
+       }
+
        size = tree->node_size;
        if (!is_power_of_2(size))
                goto fail_page;
        if (!tree->node_count)
                goto fail_page;
+
        tree->node_size_shift = ffs(size) - 1;
 
        tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -87,10 +122,11 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        return tree;
 
  fail_page:
-       tree->inode->i_mapping->a_ops = &hfsplus_aops;
        page_cache_release(page);
- free_tree:
+ free_inode:
+       tree->inode->i_mapping->a_ops = &hfsplus_aops;
        iput(tree->inode);
+ free_tree:
        kfree(tree);
        return NULL;
 }
@@ -192,17 +228,18 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
 
        while (!tree->free_nodes) {
                struct inode *inode = tree->inode;
+               struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
                u32 count;
                int res;
 
                res = hfsplus_file_extend(inode);
                if (res)
                        return ERR_PTR(res);
-               HFSPLUS_I(inode).phys_size = inode->i_size =
-                               (loff_t)HFSPLUS_I(inode).alloc_blocks <<
-                               HFSPLUS_SB(tree->sb).alloc_blksz_shift;
-               HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks <<
-                                            HFSPLUS_SB(tree->sb).fs_shift;
+               hip->phys_size = inode->i_size =
+                       (loff_t)hip->alloc_blocks <<
+                               HFSPLUS_SB(tree->sb)->alloc_blksz_shift;
+               hip->fs_blocks =
+                       hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift;
                inode_set_bytes(inode, inode->i_size);
                count = inode->i_size >> tree->node_size_shift;
                tree->free_nodes = count - tree->node_count;
index f6874acb2cf2a3a81a242f1983600eb912b9f607..8af45fc5b051abb3353501441fa9ea9030d9395a 100644 (file)
@@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent,
        key->key_len = cpu_to_be16(6 + ustrlen);
 }
 
-static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
+void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms)
 {
        if (inode->i_flags & S_IMMUTABLE)
                perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
@@ -77,15 +77,24 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
                perms->rootflags |= HFSPLUS_FLG_APPEND;
        else
                perms->rootflags &= ~HFSPLUS_FLG_APPEND;
-       HFSPLUS_I(inode).rootflags = perms->rootflags;
-       HFSPLUS_I(inode).userflags = perms->userflags;
+
+       perms->userflags = HFSPLUS_I(inode)->userflags;
        perms->mode = cpu_to_be16(inode->i_mode);
        perms->owner = cpu_to_be32(inode->i_uid);
        perms->group = cpu_to_be32(inode->i_gid);
+
+       if (S_ISREG(inode->i_mode))
+               perms->dev = cpu_to_be32(inode->i_nlink);
+       else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
+               perms->dev = cpu_to_be32(inode->i_rdev);
+       else
+               perms->dev = 0;
 }
 
 static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+
        if (S_ISDIR(inode->i_mode)) {
                struct hfsplus_cat_folder *folder;
 
@@ -93,13 +102,13 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
                memset(folder, 0, sizeof(*folder));
                folder->type = cpu_to_be16(HFSPLUS_FOLDER);
                folder->id = cpu_to_be32(inode->i_ino);
-               HFSPLUS_I(inode).create_date =
+               HFSPLUS_I(inode)->create_date =
                        folder->create_date =
                        folder->content_mod_date =
                        folder->attribute_mod_date =
                        folder->access_date = hfsp_now2mt();
-               hfsplus_set_perms(inode, &folder->permissions);
-               if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
+               hfsplus_cat_set_perms(inode, &folder->permissions);
+               if (inode == sbi->hidden_dir)
                        /* invisible and namelocked */
                        folder->user_info.frFlags = cpu_to_be16(0x5000);
                return sizeof(*folder);
@@ -111,19 +120,19 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
                file->type = cpu_to_be16(HFSPLUS_FILE);
                file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
                file->id = cpu_to_be32(cnid);
-               HFSPLUS_I(inode).create_date =
+               HFSPLUS_I(inode)->create_date =
                        file->create_date =
                        file->content_mod_date =
                        file->attribute_mod_date =
                        file->access_date = hfsp_now2mt();
                if (cnid == inode->i_ino) {
-                       hfsplus_set_perms(inode, &file->permissions);
+                       hfsplus_cat_set_perms(inode, &file->permissions);
                        if (S_ISLNK(inode->i_mode)) {
                                file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
                                file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
                        } else {
-                               file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
-                               file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+                               file->user_info.fdType = cpu_to_be32(sbi->type);
+                               file->user_info.fdCreator = cpu_to_be32(sbi->creator);
                        }
                        if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
                                file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
@@ -131,8 +140,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
                        file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
                        file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
                        file->user_info.fdFlags = cpu_to_be16(0x100);
-                       file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
-                       file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
+                       file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date;
+                       file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid);
                }
                return sizeof(*file);
        }
@@ -180,15 +189,14 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 
 int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
 {
+       struct super_block *sb = dir->i_sb;
        struct hfs_find_data fd;
-       struct super_block *sb;
        hfsplus_cat_entry entry;
        int entry_size;
        int err;
 
        dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
-       sb = dir->i_sb;
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
        hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
        entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
@@ -234,7 +242,7 @@ err2:
 
 int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 {
-       struct super_block *sb;
+       struct super_block *sb = dir->i_sb;
        struct hfs_find_data fd;
        struct hfsplus_fork_raw fork;
        struct list_head *pos;
@@ -242,8 +250,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
        u16 type;
 
        dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
-       sb = dir->i_sb;
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
        if (!str) {
                int len;
@@ -279,7 +286,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
                hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
        }
 
-       list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) {
+       list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) {
                struct hfsplus_readdir_data *rd =
                        list_entry(pos, struct hfsplus_readdir_data, list);
                if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
@@ -312,7 +319,7 @@ int hfsplus_rename_cat(u32 cnid,
                       struct inode *src_dir, struct qstr *src_name,
                       struct inode *dst_dir, struct qstr *dst_name)
 {
-       struct super_block *sb;
+       struct super_block *sb = src_dir->i_sb;
        struct hfs_find_data src_fd, dst_fd;
        hfsplus_cat_entry entry;
        int entry_size, type;
@@ -320,8 +327,7 @@ int hfsplus_rename_cat(u32 cnid,
 
        dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
                dst_dir->i_ino, dst_name->name);
-       sb = src_dir->i_sb;
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
        dst_fd = src_fd;
 
        /* find the old dir entry and read the data */
index 764fd1bdca882da08028e34b133930d9d155a364..d236d85ec9d73f703384ecaa9d6522fe7433c775 100644 (file)
@@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 
        dentry->d_op = &hfsplus_dentry_operations;
        dentry->d_fsdata = NULL;
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
        hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
 again:
        err = hfs_brec_read(&fd, &entry, sizeof(entry));
@@ -68,9 +68,9 @@ again:
                cnid = be32_to_cpu(entry.file.id);
                if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
                    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
-                   (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
-                    entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
-                   HFSPLUS_SB(sb).hidden_dir) {
+                   (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date ||
+                    entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) &&
+                   HFSPLUS_SB(sb)->hidden_dir) {
                        struct qstr str;
                        char name[32];
 
@@ -86,7 +86,8 @@ again:
                                linkid = be32_to_cpu(entry.file.permissions.dev);
                                str.len = sprintf(name, "iNode%d", linkid);
                                str.name = name;
-                               hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+                               hfsplus_cat_build_key(sb, fd.search_key,
+                                       HFSPLUS_SB(sb)->hidden_dir->i_ino, &str);
                                goto again;
                        }
                } else if (!dentry->d_fsdata)
@@ -101,7 +102,7 @@ again:
        if (IS_ERR(inode))
                return ERR_CAST(inode);
        if (S_ISREG(inode->i_mode))
-               HFSPLUS_I(inode).dev = linkid;
+               HFSPLUS_I(inode)->linkid = linkid;
 out:
        d_add(dentry, inode);
        return NULL;
@@ -124,7 +125,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (filp->f_pos >= inode->i_size)
                return 0;
 
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
        hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
        err = hfs_brec_find(&fd);
        if (err)
@@ -180,8 +181,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                err = -EIO;
                                goto out;
                        }
-                       if (HFSPLUS_SB(sb).hidden_dir &&
-                           HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id))
+                       if (HFSPLUS_SB(sb)->hidden_dir &&
+                           HFSPLUS_SB(sb)->hidden_dir->i_ino ==
+                                       be32_to_cpu(entry.folder.id))
                                goto next;
                        if (filldir(dirent, strbuf, len, filp->f_pos,
                                    be32_to_cpu(entry.folder.id), DT_DIR))
@@ -217,7 +219,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                filp->private_data = rd;
                rd->file = filp;
-               list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list);
+               list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list);
        }
        memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
 out:
@@ -229,38 +231,18 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file)
 {
        struct hfsplus_readdir_data *rd = file->private_data;
        if (rd) {
+               mutex_lock(&inode->i_mutex);
                list_del(&rd->list);
+               mutex_unlock(&inode->i_mutex);
                kfree(rd);
        }
        return 0;
 }
 
-static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
-                         struct nameidata *nd)
-{
-       struct inode *inode;
-       int res;
-
-       inode = hfsplus_new_inode(dir->i_sb, mode);
-       if (!inode)
-               return -ENOSPC;
-
-       res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-       if (res) {
-               inode->i_nlink = 0;
-               hfsplus_delete_inode(inode);
-               iput(inode);
-               return res;
-       }
-       hfsplus_instantiate(dentry, inode, inode->i_ino);
-       mark_inode_dirty(inode);
-       return 0;
-}
-
 static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
                        struct dentry *dst_dentry)
 {
-       struct super_block *sb = dst_dir->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb);
        struct inode *inode = src_dentry->d_inode;
        struct inode *src_dir = src_dentry->d_parent->d_inode;
        struct qstr str;
@@ -270,7 +252,10 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
 
        if (HFSPLUS_IS_RSRC(inode))
                return -EPERM;
+       if (!S_ISREG(inode->i_mode))
+               return -EPERM;
 
+       mutex_lock(&sbi->vh_mutex);
        if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) {
                for (;;) {
                        get_random_bytes(&id, sizeof(cnid));
@@ -279,40 +264,41 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
                        str.len = sprintf(name, "iNode%d", id);
                        res = hfsplus_rename_cat(inode->i_ino,
                                                 src_dir, &src_dentry->d_name,
-                                                HFSPLUS_SB(sb).hidden_dir, &str);
+                                                sbi->hidden_dir, &str);
                        if (!res)
                                break;
                        if (res != -EEXIST)
-                               return res;
+                               goto out;
                }
-               HFSPLUS_I(inode).dev = id;
-               cnid = HFSPLUS_SB(sb).next_cnid++;
+               HFSPLUS_I(inode)->linkid = id;
+               cnid = sbi->next_cnid++;
                src_dentry->d_fsdata = (void *)(unsigned long)cnid;
                res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
                if (res)
                        /* panic? */
-                       return res;
-               HFSPLUS_SB(sb).file_count++;
+                       goto out;
+               sbi->file_count++;
        }
-       cnid = HFSPLUS_SB(sb).next_cnid++;
+       cnid = sbi->next_cnid++;
        res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode);
        if (res)
-               return res;
+               goto out;
 
        inc_nlink(inode);
        hfsplus_instantiate(dst_dentry, inode, cnid);
        atomic_inc(&inode->i_count);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
-       HFSPLUS_SB(sb).file_count++;
-       sb->s_dirt = 1;
-
-       return 0;
+       sbi->file_count++;
+       dst_dir->i_sb->s_dirt = 1;
+out:
+       mutex_unlock(&sbi->vh_mutex);
+       return res;
 }
 
 static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct super_block *sb = dir->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
        struct inode *inode = dentry->d_inode;
        struct qstr str;
        char name[32];
@@ -322,21 +308,22 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
        if (HFSPLUS_IS_RSRC(inode))
                return -EPERM;
 
+       mutex_lock(&sbi->vh_mutex);
        cnid = (u32)(unsigned long)dentry->d_fsdata;
        if (inode->i_ino == cnid &&
-           atomic_read(&HFSPLUS_I(inode).opencnt)) {
+           atomic_read(&HFSPLUS_I(inode)->opencnt)) {
                str.name = name;
                str.len = sprintf(name, "temp%lu", inode->i_ino);
                res = hfsplus_rename_cat(inode->i_ino,
                                         dir, &dentry->d_name,
-                                        HFSPLUS_SB(sb).hidden_dir, &str);
+                                        sbi->hidden_dir, &str);
                if (!res)
                        inode->i_flags |= S_DEAD;
-               return res;
+               goto out;
        }
        res = hfsplus_delete_cat(cnid, dir, &dentry->d_name);
        if (res)
-               return res;
+               goto out;
 
        if (inode->i_nlink > 0)
                drop_nlink(inode);
@@ -344,10 +331,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
                clear_nlink(inode);
        if (!inode->i_nlink) {
                if (inode->i_ino != cnid) {
-                       HFSPLUS_SB(sb).file_count--;
-                       if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
+                       sbi->file_count--;
+                       if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) {
                                res = hfsplus_delete_cat(inode->i_ino,
-                                                        HFSPLUS_SB(sb).hidden_dir,
+                                                        sbi->hidden_dir,
                                                         NULL);
                                if (!res)
                                        hfsplus_delete_inode(inode);
@@ -356,107 +343,108 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
                } else
                        hfsplus_delete_inode(inode);
        } else
-               HFSPLUS_SB(sb).file_count--;
+               sbi->file_count--;
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
-
+out:
+       mutex_unlock(&sbi->vh_mutex);
        return res;
 }
 
-static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-       struct inode *inode;
-       int res;
-
-       inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode);
-       if (!inode)
-               return -ENOSPC;
-
-       res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-       if (res) {
-               inode->i_nlink = 0;
-               hfsplus_delete_inode(inode);
-               iput(inode);
-               return res;
-       }
-       hfsplus_instantiate(dentry, inode, inode->i_ino);
-       mark_inode_dirty(inode);
-       return 0;
-}
-
 static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+       struct inode *inode = dentry->d_inode;
        int res;
 
-       inode = dentry->d_inode;
        if (inode->i_size != 2)
                return -ENOTEMPTY;
+
+       mutex_lock(&sbi->vh_mutex);
        res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
        if (res)
-               return res;
+               goto out;
        clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        hfsplus_delete_inode(inode);
        mark_inode_dirty(inode);
-       return 0;
+out:
+       mutex_unlock(&sbi->vh_mutex);
+       return res;
 }
 
 static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
                           const char *symname)
 {
-       struct super_block *sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
        struct inode *inode;
-       int res;
+       int res = -ENOSPC;
 
-       sb = dir->i_sb;
-       inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO);
+       mutex_lock(&sbi->vh_mutex);
+       inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO);
        if (!inode)
-               return -ENOSPC;
+               goto out;
 
        res = page_symlink(inode, symname, strlen(symname) + 1);
-       if (res) {
-               inode->i_nlink = 0;
-               hfsplus_delete_inode(inode);
-               iput(inode);
-               return res;
-       }
+       if (res)
+               goto out_err;
 
-       mark_inode_dirty(inode);
        res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+       if (res)
+               goto out_err;
 
-       if (!res) {
-               hfsplus_instantiate(dentry, inode, inode->i_ino);
-               mark_inode_dirty(inode);
-       }
+       hfsplus_instantiate(dentry, inode, inode->i_ino);
+       mark_inode_dirty(inode);
+       goto out;
 
+out_err:
+       inode->i_nlink = 0;
+       hfsplus_delete_inode(inode);
+       iput(inode);
+out:
+       mutex_unlock(&sbi->vh_mutex);
        return res;
 }
 
 static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
                         int mode, dev_t rdev)
 {
-       struct super_block *sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
        struct inode *inode;
-       int res;
+       int res = -ENOSPC;
 
-       sb = dir->i_sb;
-       inode = hfsplus_new_inode(sb, mode);
+       mutex_lock(&sbi->vh_mutex);
+       inode = hfsplus_new_inode(dir->i_sb, mode);
        if (!inode)
-               return -ENOSPC;
+               goto out;
+
+       if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
+               init_special_inode(inode, mode, rdev);
 
        res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
        if (res) {
                inode->i_nlink = 0;
                hfsplus_delete_inode(inode);
                iput(inode);
-               return res;
+               goto out;
        }
-       init_special_inode(inode, mode, rdev);
+
        hfsplus_instantiate(dentry, inode, inode->i_ino);
        mark_inode_dirty(inode);
+out:
+       mutex_unlock(&sbi->vh_mutex);
+       return res;
+}
 
-       return 0;
+static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
+                         struct nameidata *nd)
+{
+       return hfsplus_mknod(dir, dentry, mode, 0);
+}
+
+static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+       return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0);
 }
 
 static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -466,7 +454,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        /* Unlink destination if it already exists */
        if (new_dentry->d_inode) {
-               res = hfsplus_unlink(new_dir, new_dentry);
+               if (S_ISDIR(new_dentry->d_inode->i_mode))
+                       res = hfsplus_rmdir(new_dir, new_dentry);
+               else
+                       res = hfsplus_unlink(new_dir, new_dentry);
                if (res)
                        return res;
        }
index 0022eec63cdacd97c2a438b8d9f623ff6be88dd4..0c9cb1820a523fae02c6bf2f37e6fbdc5c5dceeb 100644 (file)
@@ -85,35 +85,49 @@ static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext)
 
 static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
 {
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        int res;
 
-       hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start,
-                             HFSPLUS_IS_RSRC(inode) ?  HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+       WARN_ON(!mutex_is_locked(&hip->extents_lock));
+
+       hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
+                             HFSPLUS_IS_RSRC(inode) ?
+                               HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+
        res = hfs_brec_find(fd);
-       if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) {
+       if (hip->flags & HFSPLUS_FLG_EXT_NEW) {
                if (res != -ENOENT)
                        return;
-               hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec));
-               HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+               hfs_brec_insert(fd, hip->cached_extents,
+                               sizeof(hfsplus_extent_rec));
+               hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
        } else {
                if (res)
                        return;
-               hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength);
-               HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY;
+               hfs_bnode_write(fd->bnode, hip->cached_extents,
+                               fd->entryoffset, fd->entrylength);
+               hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY;
        }
 }
 
-void hfsplus_ext_write_extent(struct inode *inode)
+static void hfsplus_ext_write_extent_locked(struct inode *inode)
 {
-       if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) {
+       if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
                struct hfs_find_data fd;
 
-               hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
+               hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
                __hfsplus_ext_write_extent(inode, &fd);
                hfs_find_exit(&fd);
        }
 }
 
+void hfsplus_ext_write_extent(struct inode *inode)
+{
+       mutex_lock(&HFSPLUS_I(inode)->extents_lock);
+       hfsplus_ext_write_extent_locked(inode);
+       mutex_unlock(&HFSPLUS_I(inode)->extents_lock);
+}
+
 static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
                                            struct hfsplus_extent *extent,
                                            u32 cnid, u32 block, u8 type)
@@ -136,33 +150,39 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
 
 static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
 {
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        int res;
 
-       if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY)
+       WARN_ON(!mutex_is_locked(&hip->extents_lock));
+
+       if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
                __hfsplus_ext_write_extent(inode, fd);
 
-       res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino,
-                                       block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+       res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino,
+                                       block, HFSPLUS_IS_RSRC(inode) ?
+                                               HFSPLUS_TYPE_RSRC :
+                                               HFSPLUS_TYPE_DATA);
        if (!res) {
-               HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block);
-               HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents);
+               hip->cached_start = be32_to_cpu(fd->key->ext.start_block);
+               hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents);
        } else {
-               HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
-               HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+               hip->cached_start = hip->cached_blocks = 0;
+               hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
        }
        return res;
 }
 
 static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
 {
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        struct hfs_find_data fd;
        int res;
 
-       if (block >= HFSPLUS_I(inode).cached_start &&
-           block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks)
+       if (block >= hip->cached_start &&
+           block < hip->cached_start + hip->cached_blocks)
                return 0;
 
-       hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
        res = __hfsplus_ext_cache_extent(&fd, inode, block);
        hfs_find_exit(&fd);
        return res;
@@ -172,21 +192,21 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
 int hfsplus_get_block(struct inode *inode, sector_t iblock,
                      struct buffer_head *bh_result, int create)
 {
-       struct super_block *sb;
+       struct super_block *sb = inode->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        int res = -EIO;
        u32 ablock, dblock, mask;
        int shift;
 
-       sb = inode->i_sb;
-
        /* Convert inode block to disk allocation block */
-       shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits;
-       ablock = iblock >> HFSPLUS_SB(sb).fs_shift;
+       shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
+       ablock = iblock >> sbi->fs_shift;
 
-       if (iblock >= HFSPLUS_I(inode).fs_blocks) {
-               if (iblock > HFSPLUS_I(inode).fs_blocks || !create)
+       if (iblock >= hip->fs_blocks) {
+               if (iblock > hip->fs_blocks || !create)
                        return -EIO;
-               if (ablock >= HFSPLUS_I(inode).alloc_blocks) {
+               if (ablock >= hip->alloc_blocks) {
                        res = hfsplus_file_extend(inode);
                        if (res)
                                return res;
@@ -194,33 +214,33 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
        } else
                create = 0;
 
-       if (ablock < HFSPLUS_I(inode).first_blocks) {
-               dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock);
+       if (ablock < hip->first_blocks) {
+               dblock = hfsplus_ext_find_block(hip->first_extents, ablock);
                goto done;
        }
 
        if (inode->i_ino == HFSPLUS_EXT_CNID)
                return -EIO;
 
-       mutex_lock(&HFSPLUS_I(inode).extents_lock);
+       mutex_lock(&hip->extents_lock);
        res = hfsplus_ext_read_extent(inode, ablock);
        if (!res) {
-               dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock -
-                                            HFSPLUS_I(inode).cached_start);
+               dblock = hfsplus_ext_find_block(hip->cached_extents,
+                                               ablock - hip->cached_start);
        } else {
-               mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+               mutex_unlock(&hip->extents_lock);
                return -EIO;
        }
-       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&hip->extents_lock);
 
 done:
        dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
-       mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1;
-       map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask));
+       mask = (1 << sbi->fs_shift) - 1;
+       map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask));
        if (create) {
                set_buffer_new(bh_result);
-               HFSPLUS_I(inode).phys_size += sb->s_blocksize;
-               HFSPLUS_I(inode).fs_blocks++;
+               hip->phys_size += sb->s_blocksize;
+               hip->fs_blocks++;
                inode_add_bytes(inode, sb->s_blocksize);
                mark_inode_dirty(inode);
        }
@@ -327,7 +347,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw
        if (total_blocks == blocks)
                return 0;
 
-       hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
        do {
                res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid,
                                                total_blocks, type);
@@ -348,29 +368,33 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw
 int hfsplus_file_extend(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        u32 start, len, goal;
        int res;
 
-       if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
+       if (sbi->alloc_file->i_size * 8 <
+           sbi->total_blocks - sbi->free_blocks + 8) {
                // extend alloc file
-               printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
-                       HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
+               printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n",
+                               sbi->alloc_file->i_size * 8,
+                               sbi->total_blocks, sbi->free_blocks);
                return -ENOSPC;
        }
 
-       mutex_lock(&HFSPLUS_I(inode).extents_lock);
-       if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks)
-               goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents);
+       mutex_lock(&hip->extents_lock);
+       if (hip->alloc_blocks == hip->first_blocks)
+               goal = hfsplus_ext_lastblock(hip->first_extents);
        else {
-               res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks);
+               res = hfsplus_ext_read_extent(inode, hip->alloc_blocks);
                if (res)
                        goto out;
-               goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents);
+               goal = hfsplus_ext_lastblock(hip->cached_extents);
        }
 
-       len = HFSPLUS_I(inode).clump_blocks;
-       start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len);
-       if (start >= HFSPLUS_SB(sb).total_blocks) {
+       len = hip->clump_blocks;
+       start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len);
+       if (start >= sbi->total_blocks) {
                start = hfsplus_block_allocate(sb, goal, 0, &len);
                if (start >= goal) {
                        res = -ENOSPC;
@@ -379,56 +403,56 @@ int hfsplus_file_extend(struct inode *inode)
        }
 
        dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
-       if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) {
-               if (!HFSPLUS_I(inode).first_blocks) {
+
+       if (hip->alloc_blocks <= hip->first_blocks) {
+               if (!hip->first_blocks) {
                        dprint(DBG_EXTENT, "first extents\n");
                        /* no extents yet */
-                       HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start);
-                       HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len);
+                       hip->first_extents[0].start_block = cpu_to_be32(start);
+                       hip->first_extents[0].block_count = cpu_to_be32(len);
                        res = 0;
                } else {
                        /* try to append to extents in inode */
-                       res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents,
-                                                HFSPLUS_I(inode).alloc_blocks,
+                       res = hfsplus_add_extent(hip->first_extents,
+                                                hip->alloc_blocks,
                                                 start, len);
                        if (res == -ENOSPC)
                                goto insert_extent;
                }
                if (!res) {
-                       hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
-                       HFSPLUS_I(inode).first_blocks += len;
+                       hfsplus_dump_extent(hip->first_extents);
+                       hip->first_blocks += len;
                }
        } else {
-               res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents,
-                                        HFSPLUS_I(inode).alloc_blocks -
-                                        HFSPLUS_I(inode).cached_start,
+               res = hfsplus_add_extent(hip->cached_extents,
+                                        hip->alloc_blocks - hip->cached_start,
                                         start, len);
                if (!res) {
-                       hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
-                       HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
-                       HFSPLUS_I(inode).cached_blocks += len;
+                       hfsplus_dump_extent(hip->cached_extents);
+                       hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
+                       hip->cached_blocks += len;
                } else if (res == -ENOSPC)
                        goto insert_extent;
        }
 out:
-       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&hip->extents_lock);
        if (!res) {
-               HFSPLUS_I(inode).alloc_blocks += len;
+               hip->alloc_blocks += len;
                mark_inode_dirty(inode);
        }
        return res;
 
 insert_extent:
        dprint(DBG_EXTENT, "insert new extent\n");
-       hfsplus_ext_write_extent(inode);
+       hfsplus_ext_write_extent_locked(inode);
 
-       memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-       HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start);
-       HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len);
-       hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
-       HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
-       HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks;
-       HFSPLUS_I(inode).cached_blocks = len;
+       memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+       hip->cached_extents[0].start_block = cpu_to_be32(start);
+       hip->cached_extents[0].block_count = cpu_to_be32(len);
+       hfsplus_dump_extent(hip->cached_extents);
+       hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
+       hip->cached_start = hip->alloc_blocks;
+       hip->cached_blocks = len;
 
        res = 0;
        goto out;
@@ -437,13 +461,15 @@ insert_extent:
 void hfsplus_file_truncate(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        struct hfs_find_data fd;
        u32 alloc_cnt, blk_cnt, start;
        int res;
 
-       dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino,
-              (long long)HFSPLUS_I(inode).phys_size, inode->i_size);
-       if (inode->i_size > HFSPLUS_I(inode).phys_size) {
+       dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n",
+               inode->i_ino, (long long)hip->phys_size, inode->i_size);
+
+       if (inode->i_size > hip->phys_size) {
                struct address_space *mapping = inode->i_mapping;
                struct page *page;
                void *fsdata;
@@ -460,47 +486,48 @@ void hfsplus_file_truncate(struct inode *inode)
                        return;
                mark_inode_dirty(inode);
                return;
-       } else if (inode->i_size == HFSPLUS_I(inode).phys_size)
+       } else if (inode->i_size == hip->phys_size)
                return;
 
-       blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-       alloc_cnt = HFSPLUS_I(inode).alloc_blocks;
+       blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >>
+                       HFSPLUS_SB(sb)->alloc_blksz_shift;
+       alloc_cnt = hip->alloc_blocks;
        if (blk_cnt == alloc_cnt)
                goto out;
 
-       mutex_lock(&HFSPLUS_I(inode).extents_lock);
-       hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+       mutex_lock(&hip->extents_lock);
+       hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
        while (1) {
-               if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
-                       hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents,
+               if (alloc_cnt == hip->first_blocks) {
+                       hfsplus_free_extents(sb, hip->first_extents,
                                             alloc_cnt, alloc_cnt - blk_cnt);
-                       hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
-                       HFSPLUS_I(inode).first_blocks = blk_cnt;
+                       hfsplus_dump_extent(hip->first_extents);
+                       hip->first_blocks = blk_cnt;
                        break;
                }
                res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
                if (res)
                        break;
-               start = HFSPLUS_I(inode).cached_start;
-               hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents,
+               start = hip->cached_start;
+               hfsplus_free_extents(sb, hip->cached_extents,
                                     alloc_cnt - start, alloc_cnt - blk_cnt);
-               hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
+               hfsplus_dump_extent(hip->cached_extents);
                if (blk_cnt > start) {
-                       HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
+                       hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
                        break;
                }
                alloc_cnt = start;
-               HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
-               HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+               hip->cached_start = hip->cached_blocks = 0;
+               hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
                hfs_brec_remove(&fd);
        }
        hfs_find_exit(&fd);
-       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&hip->extents_lock);
 
-       HFSPLUS_I(inode).alloc_blocks = blk_cnt;
+       hip->alloc_blocks = blk_cnt;
 out:
-       HFSPLUS_I(inode).phys_size = inode->i_size;
-       HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-       inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
+       hip->phys_size = inode->i_size;
+       hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
        mark_inode_dirty(inode);
 }
index dc856be3c2b010854c78da1049b86d2f7ce48147..cb3653efb57a2dcf2285a19fcb7262cb7a1ba509 100644 (file)
@@ -62,7 +62,7 @@ struct hfs_btree {
        unsigned int depth;
 
        //unsigned int map1_size, map_size;
-       struct semaphore tree_lock;
+       struct mutex tree_lock;
 
        unsigned int pages_per_bnode;
        spinlock_t hash_lock;
@@ -121,16 +121,21 @@ struct hfsplus_sb_info {
        u32 sect_count;
        int fs_shift;
 
-       /* Stuff in host order from Vol Header */
+       /* immutable data from the volume header */
        u32 alloc_blksz;
        int alloc_blksz_shift;
        u32 total_blocks;
+       u32 data_clump_blocks, rsrc_clump_blocks;
+
+       /* mutable data from the volume header, protected by alloc_mutex */
        u32 free_blocks;
-       u32 next_alloc;
+       struct mutex alloc_mutex;
+
+       /* mutable data from the volume header, protected by vh_mutex */
        u32 next_cnid;
        u32 file_count;
        u32 folder_count;
-       u32 data_clump_blocks, rsrc_clump_blocks;
+       struct mutex vh_mutex;
 
        /* Config options */
        u32 creator;
@@ -143,40 +148,50 @@ struct hfsplus_sb_info {
        int part, session;
 
        unsigned long flags;
-
-       struct hlist_head rsrc_inodes;
 };
 
-#define HFSPLUS_SB_WRITEBACKUP 0x0001
-#define HFSPLUS_SB_NODECOMPOSE 0x0002
-#define HFSPLUS_SB_FORCE       0x0004
-#define HFSPLUS_SB_HFSX                0x0008
-#define HFSPLUS_SB_CASEFOLD    0x0010
+#define HFSPLUS_SB_WRITEBACKUP 0
+#define HFSPLUS_SB_NODECOMPOSE 1
+#define HFSPLUS_SB_FORCE       2
+#define HFSPLUS_SB_HFSX                3
+#define HFSPLUS_SB_CASEFOLD    4
 
 
 struct hfsplus_inode_info {
-       struct mutex extents_lock;
-       u32 clump_blocks, alloc_blocks;
-       sector_t fs_blocks;
-       /* Allocation extents from catalog record or volume header */
-       hfsplus_extent_rec first_extents;
-       u32 first_blocks;
-       hfsplus_extent_rec cached_extents;
-       u32 cached_start, cached_blocks;
        atomic_t opencnt;
 
-       struct inode *rsrc_inode;
+       /*
+        * Extent allocation information, protected by extents_lock.
+        */
+       u32 first_blocks;
+       u32 clump_blocks;
+       u32 alloc_blocks;
+       u32 cached_start;
+       u32 cached_blocks;
+       hfsplus_extent_rec first_extents;
+       hfsplus_extent_rec cached_extents;
        unsigned long flags;
+       struct mutex extents_lock;
 
+       /*
+        * Immutable data.
+        */
+       struct inode *rsrc_inode;
        __be32 create_date;
-       /* Device number in hfsplus_permissions in catalog */
-       u32 dev;
-       /* BSD system and user file flags */
-       u8 rootflags;
-       u8 userflags;
 
+       /*
+        * Protected by sbi->vh_mutex.
+        */
+       u32 linkid;
+
+       /*
+        * Protected by i_mutex.
+        */
+       sector_t fs_blocks;
+       u8 userflags;           /* BSD user file flags */
        struct list_head open_dir_list;
        loff_t phys_size;
+
        struct inode vfs_inode;
 };
 
@@ -184,8 +199,8 @@ struct hfsplus_inode_info {
 #define HFSPLUS_FLG_EXT_DIRTY  0x0002
 #define HFSPLUS_FLG_EXT_NEW    0x0004
 
-#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
-#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
+#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC))
+#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)
 
 struct hfs_find_data {
        /* filled by caller */
@@ -311,6 +326,7 @@ int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
 int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
 int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
                       struct inode *, struct qstr *);
+void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms);
 
 /* dir.c */
 extern const struct inode_operations hfsplus_dir_inode_operations;
@@ -372,26 +388,15 @@ int hfsplus_read_wrapper(struct super_block *);
 int hfs_part_find(struct super_block *, sector_t *, sector_t *);
 
 /* access macros */
-/*
 static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
 }
+
 static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
 {
        return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
 }
-*/
-#define HFSPLUS_SB(super)      (*(struct hfsplus_sb_info *)(super)->s_fs_info)
-#define HFSPLUS_I(inode)       (*list_entry(inode, struct hfsplus_inode_info, vfs_inode))
-
-#if 1
-#define hfsplus_kmap(p)                ({ struct page *__p = (p); kmap(__p); })
-#define hfsplus_kunmap(p)      ({ struct page *__p = (p); kunmap(__p); __p; })
-#else
-#define hfsplus_kmap(p)                kmap(p)
-#define hfsplus_kunmap(p)      kunmap(p)
-#endif
 
 #define sb_bread512(sb, sec, data) ({                  \
        struct buffer_head *__bh;                       \
@@ -419,6 +424,4 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
 #define hfsp_ut2mt(t)          __hfsp_ut2mt((t).tv_sec)
 #define hfsp_now2mt()          __hfsp_ut2mt(get_seconds())
 
-#define kdev_t_to_nr(x)                (x)
-
 #endif
index fe99fe8db61a3cb279885cee2c73cf5743704604..6892899fd6fbbabce55d3fe1f2c8915fe3f33d89 100644 (file)
@@ -200,6 +200,7 @@ struct hfsplus_cat_key {
        struct hfsplus_unistr name;
 } __packed;
 
+#define HFSPLUS_CAT_KEYLEN     (sizeof(struct hfsplus_cat_key))
 
 /* Structs from hfs.h */
 struct hfsp_point {
@@ -323,7 +324,7 @@ struct hfsplus_ext_key {
        __be32 start_block;
 } __packed;
 
-#define HFSPLUS_EXT_KEYLEN 12
+#define HFSPLUS_EXT_KEYLEN     sizeof(struct hfsplus_ext_key)
 
 /* HFS+ generic BTree key */
 typedef union {
index c5a979d62c657a866685dac4743fa01515b1653a..78449280dae08471958a328afca7f225fe9d744f 100644 (file)
@@ -36,7 +36,7 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
        *pagep = NULL;
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                hfsplus_get_block,
-                               &HFSPLUS_I(mapping->host).phys_size);
+                               &HFSPLUS_I(mapping->host)->phys_size);
        if (unlikely(ret)) {
                loff_t isize = mapping->host->i_size;
                if (pos + len > isize)
@@ -62,13 +62,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 
        switch (inode->i_ino) {
        case HFSPLUS_EXT_CNID:
-               tree = HFSPLUS_SB(sb).ext_tree;
+               tree = HFSPLUS_SB(sb)->ext_tree;
                break;
        case HFSPLUS_CAT_CNID:
-               tree = HFSPLUS_SB(sb).cat_tree;
+               tree = HFSPLUS_SB(sb)->cat_tree;
                break;
        case HFSPLUS_ATTR_CNID:
-               tree = HFSPLUS_SB(sb).attr_tree;
+               tree = HFSPLUS_SB(sb)->attr_tree;
                break;
        default:
                BUG();
@@ -172,12 +172,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
        struct hfs_find_data fd;
        struct super_block *sb = dir->i_sb;
        struct inode *inode = NULL;
+       struct hfsplus_inode_info *hip;
        int err;
 
        if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
                goto out;
 
-       inode = HFSPLUS_I(dir).rsrc_inode;
+       inode = HFSPLUS_I(dir)->rsrc_inode;
        if (inode)
                goto out;
 
@@ -185,12 +186,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
        if (!inode)
                return ERR_PTR(-ENOMEM);
 
+       hip = HFSPLUS_I(inode);
        inode->i_ino = dir->i_ino;
-       INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       mutex_init(&HFSPLUS_I(inode).extents_lock);
-       HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC;
+       INIT_LIST_HEAD(&hip->open_dir_list);
+       mutex_init(&hip->extents_lock);
+       hip->flags = HFSPLUS_FLG_RSRC;
 
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
        err = hfsplus_find_cat(sb, dir->i_ino, &fd);
        if (!err)
                err = hfsplus_cat_read_inode(inode, &fd);
@@ -199,10 +201,18 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
                iput(inode);
                return ERR_PTR(err);
        }
-       HFSPLUS_I(inode).rsrc_inode = dir;
-       HFSPLUS_I(dir).rsrc_inode = inode;
+       hip->rsrc_inode = dir;
+       HFSPLUS_I(dir)->rsrc_inode = inode;
        igrab(dir);
-       hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
+
+       /*
+        * __mark_inode_dirty expects inodes to be hashed.  Since we don't
+        * want resource fork inodes in the regular inode space, we make them
+        * appear hashed, but do not put on any lists.  hlist_del()
+        * will work fine and require no locking.
+        */
+       inode->i_hash.pprev = &inode->i_hash.next;
+
        mark_inode_dirty(inode);
 out:
        d_add(dentry, inode);
@@ -211,30 +221,27 @@ out:
 
 static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir)
 {
-       struct super_block *sb = inode->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
        u16 mode;
 
        mode = be16_to_cpu(perms->mode);
 
        inode->i_uid = be32_to_cpu(perms->owner);
        if (!inode->i_uid && !mode)
-               inode->i_uid = HFSPLUS_SB(sb).uid;
+               inode->i_uid = sbi->uid;
 
        inode->i_gid = be32_to_cpu(perms->group);
        if (!inode->i_gid && !mode)
-               inode->i_gid = HFSPLUS_SB(sb).gid;
+               inode->i_gid = sbi->gid;
 
        if (dir) {
-               mode = mode ? (mode & S_IALLUGO) :
-                       (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask));
+               mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask));
                mode |= S_IFDIR;
        } else if (!mode)
-               mode = S_IFREG | ((S_IRUGO|S_IWUGO) &
-                       ~(HFSPLUS_SB(sb).umask));
+               mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask));
        inode->i_mode = mode;
 
-       HFSPLUS_I(inode).rootflags = perms->rootflags;
-       HFSPLUS_I(inode).userflags = perms->userflags;
+       HFSPLUS_I(inode)->userflags = perms->userflags;
        if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
                inode->i_flags |= S_IMMUTABLE;
        else
@@ -245,30 +252,13 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i
                inode->i_flags &= ~S_APPEND;
 }
 
-static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
-{
-       if (inode->i_flags & S_IMMUTABLE)
-               perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
-       else
-               perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
-       if (inode->i_flags & S_APPEND)
-               perms->rootflags |= HFSPLUS_FLG_APPEND;
-       else
-               perms->rootflags &= ~HFSPLUS_FLG_APPEND;
-       perms->userflags = HFSPLUS_I(inode).userflags;
-       perms->mode = cpu_to_be16(inode->i_mode);
-       perms->owner = cpu_to_be32(inode->i_uid);
-       perms->group = cpu_to_be32(inode->i_gid);
-       perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
-}
-
 static int hfsplus_file_open(struct inode *inode, struct file *file)
 {
        if (HFSPLUS_IS_RSRC(inode))
-               inode = HFSPLUS_I(inode).rsrc_inode;
+               inode = HFSPLUS_I(inode)->rsrc_inode;
        if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
                return -EOVERFLOW;
-       atomic_inc(&HFSPLUS_I(inode).opencnt);
+       atomic_inc(&HFSPLUS_I(inode)->opencnt);
        return 0;
 }
 
@@ -277,12 +267,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
        struct super_block *sb = inode->i_sb;
 
        if (HFSPLUS_IS_RSRC(inode))
-               inode = HFSPLUS_I(inode).rsrc_inode;
-       if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
+               inode = HFSPLUS_I(inode)->rsrc_inode;
+       if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
                mutex_lock(&inode->i_mutex);
                hfsplus_file_truncate(inode);
                if (inode->i_flags & S_DEAD) {
-                       hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
+                       hfsplus_delete_cat(inode->i_ino,
+                                          HFSPLUS_SB(sb)->hidden_dir, NULL);
                        hfsplus_delete_inode(inode);
                }
                mutex_unlock(&inode->i_mutex);
@@ -361,47 +352,52 @@ static const struct file_operations hfsplus_file_operations = {
 
 struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct inode *inode = new_inode(sb);
+       struct hfsplus_inode_info *hip;
+
        if (!inode)
                return NULL;
 
-       inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
+       inode->i_ino = sbi->next_cnid++;
        inode->i_mode = mode;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       mutex_init(&HFSPLUS_I(inode).extents_lock);
-       atomic_set(&HFSPLUS_I(inode).opencnt, 0);
-       HFSPLUS_I(inode).flags = 0;
-       memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec));
-       memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-       HFSPLUS_I(inode).alloc_blocks = 0;
-       HFSPLUS_I(inode).first_blocks = 0;
-       HFSPLUS_I(inode).cached_start = 0;
-       HFSPLUS_I(inode).cached_blocks = 0;
-       HFSPLUS_I(inode).phys_size = 0;
-       HFSPLUS_I(inode).fs_blocks = 0;
-       HFSPLUS_I(inode).rsrc_inode = NULL;
+
+       hip = HFSPLUS_I(inode);
+       INIT_LIST_HEAD(&hip->open_dir_list);
+       mutex_init(&hip->extents_lock);
+       atomic_set(&hip->opencnt, 0);
+       hip->flags = 0;
+       memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
+       memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+       hip->alloc_blocks = 0;
+       hip->first_blocks = 0;
+       hip->cached_start = 0;
+       hip->cached_blocks = 0;
+       hip->phys_size = 0;
+       hip->fs_blocks = 0;
+       hip->rsrc_inode = NULL;
        if (S_ISDIR(inode->i_mode)) {
                inode->i_size = 2;
-               HFSPLUS_SB(sb).folder_count++;
+               sbi->folder_count++;
                inode->i_op = &hfsplus_dir_inode_operations;
                inode->i_fop = &hfsplus_dir_operations;
        } else if (S_ISREG(inode->i_mode)) {
-               HFSPLUS_SB(sb).file_count++;
+               sbi->file_count++;
                inode->i_op = &hfsplus_file_inode_operations;
                inode->i_fop = &hfsplus_file_operations;
                inode->i_mapping->a_ops = &hfsplus_aops;
-               HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks;
+               hip->clump_blocks = sbi->data_clump_blocks;
        } else if (S_ISLNK(inode->i_mode)) {
-               HFSPLUS_SB(sb).file_count++;
+               sbi->file_count++;
                inode->i_op = &page_symlink_inode_operations;
                inode->i_mapping->a_ops = &hfsplus_aops;
-               HFSPLUS_I(inode).clump_blocks = 1;
+               hip->clump_blocks = 1;
        } else
-               HFSPLUS_SB(sb).file_count++;
+               sbi->file_count++;
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
        sb->s_dirt = 1;
@@ -414,11 +410,11 @@ void hfsplus_delete_inode(struct inode *inode)
        struct super_block *sb = inode->i_sb;
 
        if (S_ISDIR(inode->i_mode)) {
-               HFSPLUS_SB(sb).folder_count--;
+               HFSPLUS_SB(sb)->folder_count--;
                sb->s_dirt = 1;
                return;
        }
-       HFSPLUS_SB(sb).file_count--;
+       HFSPLUS_SB(sb)->file_count--;
        if (S_ISREG(inode->i_mode)) {
                if (!inode->i_nlink) {
                        inode->i_size = 0;
@@ -434,34 +430,39 @@ void hfsplus_delete_inode(struct inode *inode)
 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
 {
        struct super_block *sb = inode->i_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        u32 count;
        int i;
 
-       memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents,
-              sizeof(hfsplus_extent_rec));
+       memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec));
        for (count = 0, i = 0; i < 8; i++)
                count += be32_to_cpu(fork->extents[i].block_count);
-       HFSPLUS_I(inode).first_blocks = count;
-       memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-       HFSPLUS_I(inode).cached_start = 0;
-       HFSPLUS_I(inode).cached_blocks = 0;
-
-       HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks);
-       inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size);
-       HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-       inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
-       HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-       if (!HFSPLUS_I(inode).clump_blocks)
-               HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks :
-                               HFSPLUS_SB(sb).data_clump_blocks;
+       hip->first_blocks = count;
+       memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+       hip->cached_start = 0;
+       hip->cached_blocks = 0;
+
+       hip->alloc_blocks = be32_to_cpu(fork->total_blocks);
+       hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size);
+       hip->fs_blocks =
+               (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
+       hip->clump_blocks =
+               be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift;
+       if (!hip->clump_blocks) {
+               hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ?
+                       sbi->rsrc_clump_blocks :
+                       sbi->data_clump_blocks;
+       }
 }
 
 void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
 {
-       memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents,
+       memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
               sizeof(hfsplus_extent_rec));
        fork->total_size = cpu_to_be64(inode->i_size);
-       fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks);
+       fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks);
 }
 
 int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
@@ -472,7 +473,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 
        type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
-       HFSPLUS_I(inode).dev = 0;
+       HFSPLUS_I(inode)->linkid = 0;
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
@@ -486,8 +487,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                inode->i_atime = hfsp_mt2ut(folder->access_date);
                inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
                inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
-               HFSPLUS_I(inode).create_date = folder->create_date;
-               HFSPLUS_I(inode).fs_blocks = 0;
+               HFSPLUS_I(inode)->create_date = folder->create_date;
+               HFSPLUS_I(inode)->fs_blocks = 0;
                inode->i_op = &hfsplus_dir_inode_operations;
                inode->i_fop = &hfsplus_dir_operations;
        } else if (type == HFSPLUS_FILE) {
@@ -518,7 +519,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                inode->i_atime = hfsp_mt2ut(file->access_date);
                inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
                inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
-               HFSPLUS_I(inode).create_date = file->create_date;
+               HFSPLUS_I(inode)->create_date = file->create_date;
        } else {
                printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
                res = -EIO;
@@ -533,12 +534,12 @@ int hfsplus_cat_write_inode(struct inode *inode)
        hfsplus_cat_entry entry;
 
        if (HFSPLUS_IS_RSRC(inode))
-               main_inode = HFSPLUS_I(inode).rsrc_inode;
+               main_inode = HFSPLUS_I(inode)->rsrc_inode;
 
        if (!main_inode->i_nlink)
                return 0;
 
-       if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd))
+       if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd))
                /* panic? */
                return -EIO;
 
@@ -554,7 +555,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_folder));
                /* simple node checks? */
-               hfsplus_set_perms(inode, &folder->permissions);
+               hfsplus_cat_set_perms(inode, &folder->permissions);
                folder->access_date = hfsp_ut2mt(inode->i_atime);
                folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
                folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
@@ -576,11 +577,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_file));
                hfsplus_inode_write_fork(inode, &file->data_fork);
-               if (S_ISREG(inode->i_mode))
-                       HFSPLUS_I(inode).dev = inode->i_nlink;
-               if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-                       HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev);
-               hfsplus_set_perms(inode, &file->permissions);
+               hfsplus_cat_set_perms(inode, &file->permissions);
                if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
                        file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
                else
index ac405f09902651838979e322931ba7a1f1441633..5b4667e08ef7789e49c274758a28d11ef86d5fde 100644 (file)
 #include <linux/mount.h>
 #include <linux/sched.h>
 #include <linux/xattr.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include "hfsplus_fs.h"
 
-long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
 {
-       struct inode *inode = filp->f_path.dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+       unsigned int flags = 0;
+
+       if (inode->i_flags & S_IMMUTABLE)
+               flags |= FS_IMMUTABLE_FL;
+       if (inode->i_flags |= S_APPEND)
+               flags |= FS_APPEND_FL;
+       if (hip->userflags & HFSPLUS_FLG_NODUMP)
+               flags |= FS_NODUMP_FL;
+
+       return put_user(flags, user_flags);
+}
+
+static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        unsigned int flags;
+       int err = 0;
 
-       lock_kernel();
-       switch (cmd) {
-       case HFSPLUS_IOC_EXT2_GETFLAGS:
-               flags = 0;
-               if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE)
-                       flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */
-               if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND)
-                       flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */
-               if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP)
-                       flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
-               return put_user(flags, (int __user *)arg);
-       case HFSPLUS_IOC_EXT2_SETFLAGS: {
-               int err = 0;
-               err = mnt_want_write(filp->f_path.mnt);
-               if (err) {
-                       unlock_kernel();
-                       return err;
-               }
+       err = mnt_want_write(file->f_path.mnt);
+       if (err)
+               goto out;
 
-               if (!is_owner_or_cap(inode)) {
-                       err = -EACCES;
-                       goto setflags_out;
-               }
-               if (get_user(flags, (int __user *)arg)) {
-                       err = -EFAULT;
-                       goto setflags_out;
-               }
-               if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) ||
-                   HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
-                       if (!capable(CAP_LINUX_IMMUTABLE)) {
-                               err = -EPERM;
-                               goto setflags_out;
-                       }
-               }
+       if (!is_owner_or_cap(inode)) {
+               err = -EACCES;
+               goto out_drop_write;
+       }
 
-               /* don't silently ignore unsupported ext2 flags */
-               if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
-                       err = -EOPNOTSUPP;
-                       goto setflags_out;
-               }
-               if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */
-                       inode->i_flags |= S_IMMUTABLE;
-                       HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
-               } else {
-                       inode->i_flags &= ~S_IMMUTABLE;
-                       HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
-               }
-               if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */
-                       inode->i_flags |= S_APPEND;
-                       HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND;
-               } else {
-                       inode->i_flags &= ~S_APPEND;
-                       HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND;
+       if (get_user(flags, user_flags)) {
+               err = -EFAULT;
+               goto out_drop_write;
+       }
+
+       mutex_lock(&inode->i_mutex);
+
+       if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
+           inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+               if (!capable(CAP_LINUX_IMMUTABLE)) {
+                       err = -EPERM;
+                       goto out_unlock_inode;
                }
-               if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */
-                       HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP;
-               else
-                       HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP;
-
-               inode->i_ctime = CURRENT_TIME_SEC;
-               mark_inode_dirty(inode);
-setflags_out:
-               mnt_drop_write(filp->f_path.mnt);
-               unlock_kernel();
-               return err;
        }
+
+       /* don't silently ignore unsupported ext2 flags */
+       if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
+               err = -EOPNOTSUPP;
+               goto out_unlock_inode;
+       }
+
+       if (flags & FS_IMMUTABLE_FL)
+               inode->i_flags |= S_IMMUTABLE;
+       else
+               inode->i_flags &= ~S_IMMUTABLE;
+
+       if (flags & FS_APPEND_FL)
+               inode->i_flags |= S_APPEND;
+       else
+               inode->i_flags &= ~S_APPEND;
+
+       if (flags & FS_NODUMP_FL)
+               hip->userflags |= HFSPLUS_FLG_NODUMP;
+       else
+               hip->userflags &= ~HFSPLUS_FLG_NODUMP;
+
+       inode->i_ctime = CURRENT_TIME_SEC;
+       mark_inode_dirty(inode);
+
+out_unlock_inode:
+       mutex_lock(&inode->i_mutex);
+out_drop_write:
+       mnt_drop_write(file->f_path.mnt);
+out:
+       return err;
+}
+
+long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+
+       switch (cmd) {
+       case HFSPLUS_IOC_EXT2_GETFLAGS:
+               return hfsplus_ioctl_getflags(file, argp);
+       case HFSPLUS_IOC_EXT2_SETFLAGS:
+               return hfsplus_ioctl_setflags(file, argp);
        default:
-               unlock_kernel();
                return -ENOTTY;
        }
 }
@@ -110,7 +125,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
        if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
                return -EOPNOTSUPP;
 
-       res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+       res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
        if (res)
                return res;
        res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
@@ -153,7 +168,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
                return -EOPNOTSUPP;
 
        if (size) {
-               res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+               res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
                if (res)
                        return res;
                res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
@@ -177,7 +192,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
                } else
                        res = size ? -ERANGE : 4;
        } else
-               res = -ENODATA;
+               res = -EOPNOTSUPP;
 out:
        if (size)
                hfs_find_exit(&fd);
index 572628b4b07d23af08f98ca7b757c85acfbcbc0c..f9ab276a4d8de9e15d2acf49a358da1a9ff10fe6 100644 (file)
@@ -143,13 +143,13 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
                        kfree(p);
                        break;
                case opt_decompose:
-                       sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE;
+                       clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
                        break;
                case opt_nodecompose:
-                       sbi->flags |= HFSPLUS_SB_NODECOMPOSE;
+                       set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
                        break;
                case opt_force:
-                       sbi->flags |= HFSPLUS_SB_FORCE;
+                       set_bit(HFSPLUS_SB_FORCE, &sbi->flags);
                        break;
                default:
                        return 0;
@@ -171,7 +171,7 @@ done:
 
 int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
 {
-       struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb);
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb);
 
        if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
                seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
@@ -184,7 +184,7 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
                seq_printf(seq, ",session=%u", sbi->session);
        if (sbi->nls)
                seq_printf(seq, ",nls=%s", sbi->nls->charset);
-       if (sbi->flags & HFSPLUS_SB_NODECOMPOSE)
+       if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags))
                seq_printf(seq, ",nodecompose");
        return 0;
 }
index 1528a6fd02992f1858ee254fe01039520da77bd4..208b16c645cc234c6f5ce1b15fbd5b49ba802ee8 100644 (file)
@@ -74,6 +74,7 @@ struct old_pmap {
 int hfs_part_find(struct super_block *sb,
                  sector_t *part_start, sector_t *part_size)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct buffer_head *bh;
        __be16 *data;
        int i, size, res;
@@ -95,7 +96,7 @@ int hfs_part_find(struct super_block *sb,
                for (i = 0; i < size; p++, i++) {
                        if (p->pdStart && p->pdSize &&
                            p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
-                           (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+                           (sbi->part < 0 || sbi->part == i)) {
                                *part_start += be32_to_cpu(p->pdStart);
                                *part_size = be32_to_cpu(p->pdSize);
                                res = 0;
@@ -111,7 +112,7 @@ int hfs_part_find(struct super_block *sb,
                size = be32_to_cpu(pm->pmMapBlkCnt);
                for (i = 0; i < size;) {
                        if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
-                           (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+                           (sbi->part < 0 || sbi->part == i)) {
                                *part_start += be32_to_cpu(pm->pmPyPartStart);
                                *part_size = be32_to_cpu(pm->pmPartBlkCnt);
                                res = 0;
index 3b55c050c74274710fa95cad827edf6abd6b8316..9a88d7536103e2c1c70f3824b42d367d3eac848f 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/nls.h>
 
@@ -21,40 +20,11 @@ static void hfsplus_destroy_inode(struct inode *inode);
 
 #include "hfsplus_fs.h"
 
-struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
+static int hfsplus_system_read_inode(struct inode *inode)
 {
-       struct hfs_find_data fd;
-       struct hfsplus_vh *vhdr;
-       struct inode *inode;
-       long err = -EIO;
-
-       inode = iget_locked(sb, ino);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
+       struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr;
 
-       INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       mutex_init(&HFSPLUS_I(inode).extents_lock);
-       HFSPLUS_I(inode).flags = 0;
-       HFSPLUS_I(inode).rsrc_inode = NULL;
-       atomic_set(&HFSPLUS_I(inode).opencnt, 0);
-
-       if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-       read_inode:
-               hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
-               err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-               if (!err)
-                       err = hfsplus_cat_read_inode(inode, &fd);
-               hfs_find_exit(&fd);
-               if (err)
-                       goto bad_inode;
-               goto done;
-       }
-       vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
-       switch(inode->i_ino) {
-       case HFSPLUS_ROOT_CNID:
-               goto read_inode;
+       switch (inode->i_ino) {
        case HFSPLUS_EXT_CNID:
                hfsplus_inode_read_fork(inode, &vhdr->ext_file);
                inode->i_mapping->a_ops = &hfsplus_btree_aops;
@@ -75,74 +45,101 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
                inode->i_mapping->a_ops = &hfsplus_btree_aops;
                break;
        default:
-               goto bad_inode;
+               return -EIO;
+       }
+
+       return 0;
+}
+
+struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
+{
+       struct hfs_find_data fd;
+       struct inode *inode;
+       int err;
+
+       inode = iget_locked(sb, ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+       if (!(inode->i_state & I_NEW))
+               return inode;
+
+       INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list);
+       mutex_init(&HFSPLUS_I(inode)->extents_lock);
+       HFSPLUS_I(inode)->flags = 0;
+       HFSPLUS_I(inode)->rsrc_inode = NULL;
+       atomic_set(&HFSPLUS_I(inode)->opencnt, 0);
+
+       if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
+           inode->i_ino == HFSPLUS_ROOT_CNID) {
+               hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+               err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+               if (!err)
+                       err = hfsplus_cat_read_inode(inode, &fd);
+               hfs_find_exit(&fd);
+       } else {
+               err = hfsplus_system_read_inode(inode);
+       }
+
+       if (err) {
+               iget_failed(inode);
+               return ERR_PTR(err);
        }
 
-done:
        unlock_new_inode(inode);
        return inode;
-
-bad_inode:
-       iget_failed(inode);
-       return ERR_PTR(err);
 }
 
-static int hfsplus_write_inode(struct inode *inode,
-               struct writeback_control *wbc)
+static int hfsplus_system_write_inode(struct inode *inode)
 {
-       struct hfsplus_vh *vhdr;
-       int ret = 0;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+       struct hfsplus_vh *vhdr = sbi->s_vhdr;
+       struct hfsplus_fork_raw *fork;
+       struct hfs_btree *tree = NULL;
 
-       dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
-       hfsplus_ext_write_extent(inode);
-       if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-               return hfsplus_cat_write_inode(inode);
-       }
-       vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
        switch (inode->i_ino) {
-       case HFSPLUS_ROOT_CNID:
-               ret = hfsplus_cat_write_inode(inode);
-               break;
        case HFSPLUS_EXT_CNID:
-               if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
-                       HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-                       inode->i_sb->s_dirt = 1;
-               }
-               hfsplus_inode_write_fork(inode, &vhdr->ext_file);
-               hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree);
+               fork = &vhdr->ext_file;
+               tree = sbi->ext_tree;
                break;
        case HFSPLUS_CAT_CNID:
-               if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) {
-                       HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-                       inode->i_sb->s_dirt = 1;
-               }
-               hfsplus_inode_write_fork(inode, &vhdr->cat_file);
-               hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree);
+               fork = &vhdr->cat_file;
+               tree = sbi->cat_tree;
                break;
        case HFSPLUS_ALLOC_CNID:
-               if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) {
-                       HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-                       inode->i_sb->s_dirt = 1;
-               }
-               hfsplus_inode_write_fork(inode, &vhdr->alloc_file);
+               fork = &vhdr->alloc_file;
                break;
        case HFSPLUS_START_CNID:
-               if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) {
-                       HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-                       inode->i_sb->s_dirt = 1;
-               }
-               hfsplus_inode_write_fork(inode, &vhdr->start_file);
+               fork = &vhdr->start_file;
                break;
        case HFSPLUS_ATTR_CNID:
-               if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) {
-                       HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-                       inode->i_sb->s_dirt = 1;
-               }
-               hfsplus_inode_write_fork(inode, &vhdr->attr_file);
-               hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
-               break;
+               fork = &vhdr->attr_file;
+               tree = sbi->attr_tree;
+       default:
+               return -EIO;
+       }
+
+       if (fork->total_size != cpu_to_be64(inode->i_size)) {
+               set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags);
+               inode->i_sb->s_dirt = 1;
        }
-       return ret;
+       hfsplus_inode_write_fork(inode, fork);
+       if (tree)
+               hfs_btree_write(tree);
+       return 0;
+}
+
+static int hfsplus_write_inode(struct inode *inode,
+               struct writeback_control *wbc)
+{
+       dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
+
+       hfsplus_ext_write_extent(inode);
+
+       if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
+           inode->i_ino == HFSPLUS_ROOT_CNID)
+               return hfsplus_cat_write_inode(inode);
+       else
+               return hfsplus_system_write_inode(inode);
 }
 
 static void hfsplus_evict_inode(struct inode *inode)
@@ -151,51 +148,53 @@ static void hfsplus_evict_inode(struct inode *inode)
        truncate_inode_pages(&inode->i_data, 0);
        end_writeback(inode);
        if (HFSPLUS_IS_RSRC(inode)) {
-               HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
-               iput(HFSPLUS_I(inode).rsrc_inode);
+               HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
+               iput(HFSPLUS_I(inode)->rsrc_inode);
        }
 }
 
 int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
-       struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       struct hfsplus_vh *vhdr = sbi->s_vhdr;
 
        dprint(DBG_SUPER, "hfsplus_write_super\n");
 
-       lock_super(sb);
+       mutex_lock(&sbi->vh_mutex);
+       mutex_lock(&sbi->alloc_mutex);
        sb->s_dirt = 0;
 
-       vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks);
-       vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc);
-       vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid);
-       vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count);
-       vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count);
+       vhdr->free_blocks = cpu_to_be32(sbi->free_blocks);
+       vhdr->next_cnid = cpu_to_be32(sbi->next_cnid);
+       vhdr->folder_count = cpu_to_be32(sbi->folder_count);
+       vhdr->file_count = cpu_to_be32(sbi->file_count);
 
-       mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-       if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) {
-               if (HFSPLUS_SB(sb).sect_count) {
+       mark_buffer_dirty(sbi->s_vhbh);
+       if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) {
+               if (sbi->sect_count) {
                        struct buffer_head *bh;
                        u32 block, offset;
 
-                       block = HFSPLUS_SB(sb).blockoffset;
-                       block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
-                       offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
-                       printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
-                               HFSPLUS_SB(sb).sect_count, block, offset);
+                       block = sbi->blockoffset;
+                       block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9);
+                       offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1);
+                       printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n",
+                                         sbi->blockoffset, sbi->sect_count,
+                                         block, offset);
                        bh = sb_bread(sb, block);
                        if (bh) {
                                vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
                                if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) {
-                                       memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr));
+                                       memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr));
                                        mark_buffer_dirty(bh);
                                        brelse(bh);
                                } else
                                        printk(KERN_WARNING "hfs: backup not found!\n");
                        }
                }
-               HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
        }
-       unlock_super(sb);
+       mutex_unlock(&sbi->alloc_mutex);
+       mutex_unlock(&sbi->vh_mutex);
        return 0;
 }
 
@@ -209,48 +208,48 @@ static void hfsplus_write_super(struct super_block *sb)
 
 static void hfsplus_put_super(struct super_block *sb)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+
        dprint(DBG_SUPER, "hfsplus_put_super\n");
+
        if (!sb->s_fs_info)
                return;
 
-       lock_kernel();
-
        if (sb->s_dirt)
                hfsplus_write_super(sb);
-       if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
-               struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+       if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
+               struct hfsplus_vh *vhdr = sbi->s_vhdr;
 
                vhdr->modify_date = hfsp_now2mt();
                vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
                vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
-               mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-               sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
+               mark_buffer_dirty(sbi->s_vhbh);
+               sync_dirty_buffer(sbi->s_vhbh);
        }
 
-       hfs_btree_close(HFSPLUS_SB(sb).cat_tree);
-       hfs_btree_close(HFSPLUS_SB(sb).ext_tree);
-       iput(HFSPLUS_SB(sb).alloc_file);
-       iput(HFSPLUS_SB(sb).hidden_dir);
-       brelse(HFSPLUS_SB(sb).s_vhbh);
-       unload_nls(HFSPLUS_SB(sb).nls);
+       hfs_btree_close(sbi->cat_tree);
+       hfs_btree_close(sbi->ext_tree);
+       iput(sbi->alloc_file);
+       iput(sbi->hidden_dir);
+       brelse(sbi->s_vhbh);
+       unload_nls(sbi->nls);
        kfree(sb->s_fs_info);
        sb->s_fs_info = NULL;
-
-       unlock_kernel();
 }
 
 static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
        buf->f_type = HFSPLUS_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
-       buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
-       buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift;
+       buf->f_blocks = sbi->total_blocks << sbi->fs_shift;
+       buf->f_bfree = sbi->free_blocks << sbi->fs_shift;
        buf->f_bavail = buf->f_bfree;
        buf->f_files = 0xFFFFFFFF;
-       buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid;
+       buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid;
        buf->f_fsid.val[0] = (u32)id;
        buf->f_fsid.val[1] = (u32)(id >> 32);
        buf->f_namelen = HFSPLUS_MAX_STRLEN;
@@ -263,11 +262,11 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
        if (!(*flags & MS_RDONLY)) {
-               struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+               struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr;
                struct hfsplus_sb_info sbi;
 
                memset(&sbi, 0, sizeof(struct hfsplus_sb_info));
-               sbi.nls = HFSPLUS_SB(sb).nls;
+               sbi.nls = HFSPLUS_SB(sb)->nls;
                if (!hfsplus_parse_options(data, &sbi))
                        return -EINVAL;
 
@@ -276,7 +275,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
                               "running fsck.hfsplus is recommended.  leaving read-only.\n");
                        sb->s_flags |= MS_RDONLY;
                        *flags |= MS_RDONLY;
-               } else if (sbi.flags & HFSPLUS_SB_FORCE) {
+               } else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) {
                        /* nothing */
                } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
                        printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
@@ -320,7 +319,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
 
        sb->s_fs_info = sbi;
-       INIT_HLIST_HEAD(&sbi->rsrc_inodes);
+       mutex_init(&sbi->alloc_mutex);
+       mutex_init(&sbi->vh_mutex);
        hfsplus_fill_defaults(sbi);
        if (!hfsplus_parse_options(data, sbi)) {
                printk(KERN_ERR "hfs: unable to parse mount options\n");
@@ -344,7 +344,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                err = -EINVAL;
                goto cleanup;
        }
-       vhdr = HFSPLUS_SB(sb).s_vhdr;
+       vhdr = sbi->s_vhdr;
 
        /* Copy parts of the volume header into the superblock */
        sb->s_magic = HFSPLUS_VOLHEAD_SIG;
@@ -353,18 +353,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                printk(KERN_ERR "hfs: wrong filesystem version\n");
                goto cleanup;
        }
-       HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
-       HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks);
-       HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc);
-       HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid);
-       HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count);
-       HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count);
-       HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-       if (!HFSPLUS_SB(sb).data_clump_blocks)
-               HFSPLUS_SB(sb).data_clump_blocks = 1;
-       HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-       if (!HFSPLUS_SB(sb).rsrc_clump_blocks)
-               HFSPLUS_SB(sb).rsrc_clump_blocks = 1;
+       sbi->total_blocks = be32_to_cpu(vhdr->total_blocks);
+       sbi->free_blocks = be32_to_cpu(vhdr->free_blocks);
+       sbi->next_cnid = be32_to_cpu(vhdr->next_cnid);
+       sbi->file_count = be32_to_cpu(vhdr->file_count);
+       sbi->folder_count = be32_to_cpu(vhdr->folder_count);
+       sbi->data_clump_blocks =
+               be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift;
+       if (!sbi->data_clump_blocks)
+               sbi->data_clump_blocks = 1;
+       sbi->rsrc_clump_blocks =
+               be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift;
+       if (!sbi->rsrc_clump_blocks)
+               sbi->rsrc_clump_blocks = 1;
 
        /* Set up operations so we can load metadata */
        sb->s_op = &hfsplus_sops;
@@ -374,7 +375,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
                       "running fsck.hfsplus is recommended.  mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
-       } else if (sbi->flags & HFSPLUS_SB_FORCE) {
+       } else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) {
                /* nothing */
        } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
                printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
@@ -384,16 +385,15 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                       "use the force option at your own risk, mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
        }
-       sbi->flags &= ~HFSPLUS_SB_FORCE;
 
        /* Load metadata objects (B*Trees) */
-       HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
-       if (!HFSPLUS_SB(sb).ext_tree) {
+       sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
+       if (!sbi->ext_tree) {
                printk(KERN_ERR "hfs: failed to load extents file\n");
                goto cleanup;
        }
-       HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
-       if (!HFSPLUS_SB(sb).cat_tree) {
+       sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
+       if (!sbi->cat_tree) {
                printk(KERN_ERR "hfs: failed to load catalog file\n");
                goto cleanup;
        }
@@ -404,7 +404,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                err = PTR_ERR(inode);
                goto cleanup;
        }
-       HFSPLUS_SB(sb).alloc_file = inode;
+       sbi->alloc_file = inode;
 
        /* Load the root directory */
        root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID);
@@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 
        str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
        str.name = HFSP_HIDDENDIR_NAME;
-       hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+       hfs_find_init(sbi->cat_tree, &fd);
        hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
        if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
                hfs_find_exit(&fd);
@@ -434,7 +434,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                        err = PTR_ERR(inode);
                        goto cleanup;
                }
-               HFSPLUS_SB(sb).hidden_dir = inode;
+               sbi->hidden_dir = inode;
        } else
                hfs_find_exit(&fd);
 
@@ -449,15 +449,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        be32_add_cpu(&vhdr->write_count, 1);
        vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
        vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
-       mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-       sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
+       mark_buffer_dirty(sbi->s_vhbh);
+       sync_dirty_buffer(sbi->s_vhbh);
 
-       if (!HFSPLUS_SB(sb).hidden_dir) {
+       if (!sbi->hidden_dir) {
                printk(KERN_DEBUG "hfs: create hidden dir...\n");
-               HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
-               hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
-                                  &str, HFSPLUS_SB(sb).hidden_dir);
-               mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir);
+
+               mutex_lock(&sbi->vh_mutex);
+               sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
+               hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode,
+                                  &str, sbi->hidden_dir);
+               mutex_unlock(&sbi->vh_mutex);
+
+               mark_inode_dirty(sbi->hidden_dir);
        }
 out:
        unload_nls(sbi->nls);
@@ -486,7 +490,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb)
 
 static void hfsplus_destroy_inode(struct inode *inode)
 {
-       kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode));
+       kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode));
 }
 
 #define HFSPLUS_INODE_SIZE     sizeof(struct hfsplus_inode_info)
index 628ccf6fa402500aa15d7d53969b0f62b6ea5188..b66d67de882c3d098d661f54cbc2b19983bab32b 100644 (file)
@@ -121,7 +121,7 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
 int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p)
 {
        const hfsplus_unichr *ip;
-       struct nls_table *nls = HFSPLUS_SB(sb).nls;
+       struct nls_table *nls = HFSPLUS_SB(sb)->nls;
        u8 *op;
        u16 cc, c0, c1;
        u16 *ce1, *ce2;
@@ -132,7 +132,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, c
        ustrlen = be16_to_cpu(ustr->length);
        len = *len_p;
        ce1 = NULL;
-       compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+       compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
 
        while (ustrlen > 0) {
                c0 = be16_to_cpu(*ip++);
@@ -246,7 +246,7 @@ out:
 static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
                              wchar_t *uc)
 {
-       int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+       int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc);
        if (size <= 0) {
                *uc = '?';
                size = 1;
@@ -293,7 +293,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
        u16 *dstr, outlen = 0;
        wchar_t c;
 
-       decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+       decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
        while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
                size = asc2unichar(sb, astr, len, &c);
 
@@ -330,8 +330,8 @@ int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
        wchar_t c;
        u16 c2;
 
-       casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
-       decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+       casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
+       decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
        hash = init_name_hash();
        astr = str->name;
        len = str->len;
@@ -373,8 +373,8 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *
        u16 c1, c2;
        wchar_t c;
 
-       casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
-       decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+       casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
+       decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
        astr1 = s1->name;
        len1 = s1->len;
        astr2 = s2->name;
index bed78ac8f6d1f5e530a93c0afac22e1cfdf2178a..8972c20b3216941a88eb3deffa591d89ea3c114a 100644 (file)
@@ -65,8 +65,8 @@ static int hfsplus_get_last_session(struct super_block *sb,
        *start = 0;
        *size = sb->s_bdev->bd_inode->i_size >> 9;
 
-       if (HFSPLUS_SB(sb).session >= 0) {
-               te.cdte_track = HFSPLUS_SB(sb).session;
+       if (HFSPLUS_SB(sb)->session >= 0) {
+               te.cdte_track = HFSPLUS_SB(sb)->session;
                te.cdte_format = CDROM_LBA;
                res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te);
                if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
@@ -87,6 +87,7 @@ static int hfsplus_get_last_session(struct super_block *sb,
 /* Takes in super block, returns true if good data read */
 int hfsplus_read_wrapper(struct super_block *sb)
 {
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct buffer_head *bh;
        struct hfsplus_vh *vhdr;
        struct hfsplus_wd wd;
@@ -122,7 +123,7 @@ int hfsplus_read_wrapper(struct super_block *sb)
                if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
                        break;
                if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
-                       HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
+                       set_bit(HFSPLUS_SB_HFSX, &sbi->flags);
                        break;
                }
                brelse(bh);
@@ -143,11 +144,11 @@ int hfsplus_read_wrapper(struct super_block *sb)
        if (blocksize < HFSPLUS_SECTOR_SIZE ||
            ((blocksize - 1) & blocksize))
                return -EINVAL;
-       HFSPLUS_SB(sb).alloc_blksz = blocksize;
-       HFSPLUS_SB(sb).alloc_blksz_shift = 0;
+       sbi->alloc_blksz = blocksize;
+       sbi->alloc_blksz_shift = 0;
        while ((blocksize >>= 1) != 0)
-               HFSPLUS_SB(sb).alloc_blksz_shift++;
-       blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE);
+               sbi->alloc_blksz_shift++;
+       blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE);
 
        /* align block size to block offset */
        while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1))
@@ -158,23 +159,26 @@ int hfsplus_read_wrapper(struct super_block *sb)
                return -EINVAL;
        }
 
-       HFSPLUS_SB(sb).blockoffset = part_start >>
-                       (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
-       HFSPLUS_SB(sb).sect_count = part_size;
-       HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift -
-                       sb->s_blocksize_bits;
+       sbi->blockoffset =
+               part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
+       sbi->sect_count = part_size;
+       sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
 
        bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
        if (!bh)
                return -EIO;
 
        /* should still be the same... */
-       if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
-                               cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
-                               cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
-               goto error;
-       HFSPLUS_SB(sb).s_vhbh = bh;
-       HFSPLUS_SB(sb).s_vhdr = vhdr;
+       if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+               if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
+                       goto error;
+       } else {
+               if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
+                       goto error;
+       }
+
+       sbi->s_vhbh = bh;
+       sbi->s_vhdr = vhdr;
 
        return 0;
  error:
index 56bd15c5bf6cffee6cdd2e36c379eeb42c22d604..63b6f56323187256685dbaf669398fd186b4ef4b 100644 (file)
@@ -1,6 +1,7 @@
 config HPFS_FS
        tristate "OS/2 HPFS file system support"
        depends on BLOCK
+       depends on BKL # nontrivial to fix
        help
          OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
          is the file system used for organizing files on OS/2 hard disk
index 2607010be2fe5019b9700926d57c0f272be79f17..c969a1aa163a7cd3fb0b48094edf1ac90f63816c 100644 (file)
@@ -477,11 +477,15 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        int o;
 
+       lock_kernel();
+
        save_mount_options(s, options);
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-       if (!sbi)
+       if (!sbi) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        s->s_fs_info = sbi;
 
        sbi->sb_bmp_dir = NULL;
@@ -666,6 +670,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
                        root->i_blocks = 5;
                hpfs_brelse4(&qbh);
        }
+       unlock_kernel();
        return 0;
 
 bail4: brelse(bh2);
@@ -677,6 +682,7 @@ bail0:
        kfree(sbi->sb_cp_table);
        s->s_fs_info = NULL;
        kfree(sbi);
+       unlock_kernel();
        return -EINVAL;
 }
 
index 7b027720d8209b1c041de80e01e4be5aa7cd0ec2..4e2a45ea6140ddde677446d52f022eadbe020395 100644 (file)
@@ -598,6 +598,7 @@ static const struct file_operations hppfs_dir_fops = {
        .readdir        = hppfs_readdir,
        .open           = hppfs_dir_open,
        .fsync          = hppfs_fsync,
+       .llseek         = default_llseek,
 };
 
 static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
index 6e5bd42f38604dd1573992bb16aad0076a03be03..113eba3d3c386e139453abedb72f1da8dc844097 100644 (file)
@@ -674,6 +674,7 @@ const struct file_operations hugetlbfs_file_operations = {
        .mmap                   = hugetlbfs_file_mmap,
        .fsync                  = noop_fsync,
        .get_unmapped_area      = hugetlb_get_unmapped_area,
+       .llseek         = default_llseek,
 };
 
 static const struct inode_operations hugetlbfs_dir_inode_operations = {
index e0aca9a0ac68b9f5a75764a570df2c3d0bd81a72..0542b6eedf8060b64103cb86abb9643df499a2cf 100644 (file)
@@ -10,7 +10,6 @@
  *
  *  isofs directory handling functions
  */
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -255,18 +254,19 @@ static int isofs_readdir(struct file *filp,
        char *tmpname;
        struct iso_directory_record *tmpde;
        struct inode *inode = filp->f_path.dentry->d_inode;
+       struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 
        tmpname = (char *)__get_free_page(GFP_KERNEL);
        if (tmpname == NULL)
                return -ENOMEM;
 
-       lock_kernel();
+       mutex_lock(&sbi->s_mutex);
        tmpde = (struct iso_directory_record *) (tmpname+1024);
 
        result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
 
        free_page((unsigned long) tmpname);
-       unlock_kernel();
+       mutex_unlock(&sbi->s_mutex);
        return result;
 }
 
index 5a44811b5027ab73958ec6d87757a44dee5ff911..09ff41a752a092431068b991b9e323bbe5276fbd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/nls.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
 #include <linux/statfs.h>
 #include <linux/cdrom.h>
 #include <linux/parser.h>
@@ -44,11 +43,7 @@ static void isofs_put_super(struct super_block *sb)
        struct isofs_sb_info *sbi = ISOFS_SB(sb);
 
 #ifdef CONFIG_JOLIET
-       lock_kernel();
-
        unload_nls(sbi->s_nls_iocharset);
-
-       unlock_kernel();
 #endif
 
        kfree(sbi);
@@ -823,6 +818,7 @@ root_found:
        sbi->s_utf8 = opt.utf8;
        sbi->s_nocompress = opt.nocompress;
        sbi->s_overriderockperm = opt.overriderockperm;
+       mutex_init(&sbi->s_mutex);
        /*
         * It would be incredibly stupid to allow people to mark every file
         * on the disk as suid, so we merely allow them to set the default
@@ -977,8 +973,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
        int section, rv, error;
        struct iso_inode_info *ei = ISOFS_I(inode);
 
-       lock_kernel();
-
        error = -EIO;
        rv = 0;
        if (iblock < 0 || iblock != iblock_s) {
@@ -1054,7 +1048,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
 
        error = 0;
 abort:
-       unlock_kernel();
        return rv != 0 ? rv : error;
 }
 
index 7d33de84f52adec9b647bfc23f883f811f939ca9..2882dc089f87ce60c92e534d5cc6219030e4103f 100644 (file)
@@ -55,6 +55,7 @@ struct isofs_sb_info {
        gid_t s_gid;
        uid_t s_uid;
        struct nls_table *s_nls_iocharset; /* Native language support table */
+       struct mutex s_mutex; /* replaces BKL, please remove if possible */
 };
 
 #define ISOFS_INVALID_MODE ((mode_t) -1)
index ab438beb867cca718bcedf66e0355f09168b8669..0d23abfd428017697c6932d9d5c2f2b003ae43ef 100644 (file)
@@ -6,7 +6,6 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -168,6 +167,7 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
        int found;
        unsigned long uninitialized_var(block);
        unsigned long uninitialized_var(offset);
+       struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
        struct inode *inode;
        struct page *page;
 
@@ -177,7 +177,7 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
        if (!page)
                return ERR_PTR(-ENOMEM);
 
-       lock_kernel();
+       mutex_lock(&sbi->s_mutex);
        found = isofs_find_entry(dir, dentry,
                                &block, &offset,
                                page_address(page),
@@ -188,10 +188,10 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
        if (found) {
                inode = isofs_iget(dir->i_sb, block, offset);
                if (IS_ERR(inode)) {
-                       unlock_kernel();
+                       mutex_unlock(&sbi->s_mutex);
                        return ERR_CAST(inode);
                }
        }
-       unlock_kernel();
+       mutex_unlock(&sbi->s_mutex);
        return d_splice_alias(inode, dentry);
 }
index 96a685c550fde27420a1e8d2e697ef5c4bc72705..f9cd04db6eab9509958a375a65f3b4d8eb0d6d90 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "isofs.h"
 #include "rock.h"
@@ -661,6 +660,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
        struct iso_inode_info *ei = ISOFS_I(inode);
+       struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
        char *link = kmap(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        struct buffer_head *bh;
@@ -673,12 +673,12 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
        struct rock_state rs;
        int ret;
 
-       if (!ISOFS_SB(inode->i_sb)->s_rock)
+       if (!sbi->s_rock)
                goto error;
 
        init_rock_state(&rs, inode);
        block = ei->i_iget5_block;
-       lock_kernel();
+       mutex_lock(&sbi->s_mutex);
        bh = sb_bread(inode->i_sb, block);
        if (!bh)
                goto out_noread;
@@ -748,7 +748,7 @@ repeat:
                goto fail;
        brelse(bh);
        *rpnt = '\0';
-       unlock_kernel();
+       mutex_unlock(&sbi->s_mutex);
        SetPageUptodate(page);
        kunmap(page);
        unlock_page(page);
@@ -765,7 +765,7 @@ out_bad_span:
        printk("symlink spans iso9660 blocks\n");
 fail:
        brelse(bh);
-       unlock_kernel();
+       mutex_unlock(&sbi->s_mutex);
 error:
        SetPageError(page);
        kunmap(page);
index 0e8014ea6b94ad8985f1b0b842f2cea550578e67..262419f83d800bfb6e4bbfb0ca93e3af2c3f64be 100644 (file)
@@ -1371,6 +1371,10 @@ int jbd2_journal_check_used_features (journal_t *journal, unsigned long compat,
 
        if (!compat && !ro && !incompat)
                return 1;
+       /* Load journal superblock if it is not loaded yet. */
+       if (journal->j_format_version == 0 &&
+           journal_get_superblock(journal) != 0)
+               return 0;
        if (journal->j_format_version == 1)
                return 0;
 
index 6b2964a19850936dce9648c28669c40f4a1928c8..d9beb06e6fcaf55c7fdc2f46367ce2f280bff859 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 static int jffs2_flash_setup(struct jffs2_sb_info *c);
@@ -391,7 +390,6 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
           This also catches the case where it was stopped and this
           is just a remount to restart it.
           Flush the writebuffer, if neccecary, else we loose it */
-       lock_kernel();
        if (!(sb->s_flags & MS_RDONLY)) {
                jffs2_stop_garbage_collect_thread(c);
                mutex_lock(&c->alloc_sem);
@@ -403,8 +401,6 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
                jffs2_start_garbage_collect_thread(c);
 
        *flags |= MS_NOATIME;
-
-       unlock_kernel();
        return 0;
 }
 
index 662bba099501277caff6bd0b0c54abe1aaddf8cf..d1ae5dfc22b97cd04c29fa9c901ac88ba31f0670 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
@@ -146,6 +145,7 @@ static const struct super_operations jffs2_super_operations =
 static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct jffs2_sb_info *c;
+       int ret;
 
        D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
                  " New superblock for device %d (\"%s\")\n",
@@ -175,7 +175,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
        sb->s_flags |= MS_POSIXACL;
 #endif
-       return jffs2_do_fill_super(sb, data, silent);
+       ret = jffs2_do_fill_super(sb, data, silent);
+       return ret;
 }
 
 static int jffs2_get_sb(struct file_system_type *fs_type,
@@ -192,8 +193,6 @@ static void jffs2_put_super (struct super_block *sb)
 
        D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
 
-       lock_kernel();
-
        if (sb->s_dirt)
                jffs2_write_super(sb);
 
@@ -215,8 +214,6 @@ static void jffs2_put_super (struct super_block *sb)
        if (c->mtd->sync)
                c->mtd->sync(c->mtd);
 
-       unlock_kernel();
-
        D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
 }
 
index ec8c3e4baca3f78d666c33982d7040afcf73628b..68eee2bf629ee4ba6d5d6ad326012aca03d09c4f 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -176,8 +175,6 @@ static void jfs_put_super(struct super_block *sb)
 
        dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
-       lock_kernel();
-
        rc = jfs_umount(sb);
        if (rc)
                jfs_err("jfs_umount failed with return code %d", rc);
@@ -188,8 +185,6 @@ static void jfs_put_super(struct super_block *sb)
        iput(sbi->direct_inode);
 
        kfree(sbi);
-
-       unlock_kernel();
 }
 
 enum {
@@ -369,19 +364,16 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
        if (!parse_options(data, sb, &newLVSize, &flag)) {
                return -EINVAL;
        }
-       lock_kernel();
+
        if (newLVSize) {
                if (sb->s_flags & MS_RDONLY) {
                        printk(KERN_ERR
                  "JFS: resize requires volume to be mounted read-write\n");
-                       unlock_kernel();
                        return -EROFS;
                }
                rc = jfs_extendfs(sb, newLVSize, 0);
-               if (rc) {
-                       unlock_kernel();
+               if (rc)
                        return rc;
-               }
        }
 
        if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
@@ -397,36 +389,30 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
                /* mark the fs r/w for quota activity */
                sb->s_flags &= ~MS_RDONLY;
 
-               unlock_kernel();
                dquot_resume(sb, -1);
                return ret;
        }
        if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) {
                rc = dquot_suspend(sb, -1);
                if (rc < 0) {
-                       unlock_kernel();
                        return rc;
                }
                rc = jfs_umount_rw(sb);
                JFS_SBI(sb)->flag = flag;
-               unlock_kernel();
                return rc;
        }
        if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
                if (!(sb->s_flags & MS_RDONLY)) {
                        rc = jfs_umount_rw(sb);
-                       if (rc) {
-                               unlock_kernel();
+                       if (rc)
                                return rc;
-                       }
+
                        JFS_SBI(sb)->flag = flag;
                        ret = jfs_mount_rw(sb, 1);
-                       unlock_kernel();
                        return ret;
                }
        JFS_SBI(sb)->flag = flag;
 
-       unlock_kernel();
        return 0;
 }
 
@@ -446,6 +432,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
        sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
+
        sb->s_fs_info = sbi;
        sbi->sb = sb;
        sbi->uid = sbi->gid = sbi->umask = -1;
index 0a9da95317f76a6ffdebb9120a3e71dc0ff4cf72..62baa0387d6e03869e726b89ffaddccce4fc090c 100644 (file)
@@ -913,6 +913,35 @@ int generic_file_fsync(struct file *file, int datasync)
 }
 EXPORT_SYMBOL(generic_file_fsync);
 
+/**
+ * generic_check_addressable - Check addressability of file system
+ * @blocksize_bits:    log of file system block size
+ * @num_blocks:                number of blocks in file system
+ *
+ * Determine whether a file system with @num_blocks blocks (and a
+ * block size of 2**@blocksize_bits) is addressable by the sector_t
+ * and page cache of the system.  Return 0 if so and -EFBIG otherwise.
+ */
+int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
+{
+       u64 last_fs_block = num_blocks - 1;
+       u64 last_fs_page =
+               last_fs_block >> (PAGE_CACHE_SHIFT - blocksize_bits);
+
+       if (unlikely(num_blocks == 0))
+               return 0;
+
+       if ((blocksize_bits < 9) || (blocksize_bits > PAGE_CACHE_SHIFT))
+               return -EINVAL;
+
+       if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
+           (last_fs_page > (pgoff_t)(~0ULL))) {
+               return -EFBIG;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(generic_check_addressable);
+
 /*
  * No-op implementation of ->fsync for in-memory filesystems.
  */
index ab24d49fc04844e93bbedb1cd7c61083cb74e2b8..8b2b6ad56a090b0bd1cb58ef839fd9ecedf536cf 100644 (file)
@@ -143,6 +143,22 @@ int lease_break_time = 45;
 static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
+/*
+ * Protects the two list heads above, plus the inode->i_flock list
+ * FIXME: should use a spinlock, once lockd and ceph are ready.
+ */
+void lock_flocks(void)
+{
+       lock_kernel();
+}
+EXPORT_SYMBOL_GPL(lock_flocks);
+
+void unlock_flocks(void)
+{
+       unlock_kernel();
+}
+EXPORT_SYMBOL_GPL(unlock_flocks);
+
 static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
@@ -511,9 +527,9 @@ static void __locks_delete_block(struct file_lock *waiter)
  */
 static void locks_delete_block(struct file_lock *waiter)
 {
-       lock_kernel();
+       lock_flocks();
        __locks_delete_block(waiter);
-       unlock_kernel();
+       unlock_flocks();
 }
 
 /* Insert waiter into blocker's block list.
@@ -644,7 +660,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
 {
        struct file_lock *cfl;
 
-       lock_kernel();
+       lock_flocks();
        for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
                if (!IS_POSIX(cfl))
                        continue;
@@ -657,7 +673,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
                        fl->fl_pid = pid_vnr(cfl->fl_nspid);
        } else
                fl->fl_type = F_UNLCK;
-       unlock_kernel();
+       unlock_flocks();
        return;
 }
 EXPORT_SYMBOL(posix_test_lock);
@@ -730,18 +746,16 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
        int error = 0;
        int found = 0;
 
-       lock_kernel();
-       if (request->fl_flags & FL_ACCESS)
-               goto find_conflict;
-
-       if (request->fl_type != F_UNLCK) {
-               error = -ENOMEM;
+       if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
                new_fl = locks_alloc_lock();
-               if (new_fl == NULL)
-                       goto out;
-               error = 0;
+               if (!new_fl)
+                       return -ENOMEM;
        }
 
+       lock_flocks();
+       if (request->fl_flags & FL_ACCESS)
+               goto find_conflict;
+
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
@@ -767,8 +781,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
         * If a higher-priority process was blocked on the old file lock,
         * give it the opportunity to lock the file.
         */
-       if (found)
+       if (found) {
+               unlock_flocks();
                cond_resched();
+               lock_flocks();
+       }
 
 find_conflict:
        for_each_lock(inode, before) {
@@ -794,7 +811,7 @@ find_conflict:
        error = 0;
 
 out:
-       unlock_kernel();
+       unlock_flocks();
        if (new_fl)
                locks_free_lock(new_fl);
        return error;
@@ -823,7 +840,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                new_fl2 = locks_alloc_lock();
        }
 
-       lock_kernel();
+       lock_flocks();
        if (request->fl_type != F_UNLCK) {
                for_each_lock(inode, before) {
                        fl = *before;
@@ -991,7 +1008,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                locks_wake_up_blocks(left);
        }
  out:
-       unlock_kernel();
+       unlock_flocks();
        /*
         * Free any unused locks.
         */
@@ -1066,14 +1083,14 @@ int locks_mandatory_locked(struct inode *inode)
        /*
         * Search the lock list for this inode for any POSIX locks.
         */
-       lock_kernel();
+       lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (!IS_POSIX(fl))
                        continue;
                if (fl->fl_owner != owner)
                        break;
        }
-       unlock_kernel();
+       unlock_flocks();
        return fl ? -EAGAIN : 0;
 }
 
@@ -1186,7 +1203,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
 
        new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
 
-       lock_kernel();
+       lock_flocks();
 
        time_out_leases(inode);
 
@@ -1247,8 +1264,10 @@ restart:
                        break_time++;
        }
        locks_insert_block(flock, new_fl);
+       unlock_flocks();
        error = wait_event_interruptible_timeout(new_fl->fl_wait,
                                                !new_fl->fl_next, break_time);
+       lock_flocks();
        __locks_delete_block(new_fl);
        if (error >= 0) {
                if (error == 0)
@@ -1263,7 +1282,7 @@ restart:
        }
 
 out:
-       unlock_kernel();
+       unlock_flocks();
        if (!IS_ERR(new_fl))
                locks_free_lock(new_fl);
        return error;
@@ -1319,7 +1338,7 @@ int fcntl_getlease(struct file *filp)
        struct file_lock *fl;
        int type = F_UNLCK;
 
-       lock_kernel();
+       lock_flocks();
        time_out_leases(filp->f_path.dentry->d_inode);
        for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
                        fl = fl->fl_next) {
@@ -1328,7 +1347,7 @@ int fcntl_getlease(struct file *filp)
                        break;
                }
        }
-       unlock_kernel();
+       unlock_flocks();
        return type;
 }
 
@@ -1341,7 +1360,7 @@ int fcntl_getlease(struct file *filp)
  *     The (input) flp->fl_lmops->fl_break function is required
  *     by break_lease().
  *
- *     Called with kernel lock held.
+ *     Called with file_lock_lock held.
  */
 int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 {
@@ -1436,7 +1455,15 @@ out:
 }
 EXPORT_SYMBOL(generic_setlease);
 
- /**
+static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
+{
+       if (filp->f_op && filp->f_op->setlease)
+               return filp->f_op->setlease(filp, arg, lease);
+       else
+               return generic_setlease(filp, arg, lease);
+}
+
+/**
  *     vfs_setlease        -       sets a lease on an open file
  *     @filp: file pointer
  *     @arg: type of lease to obtain
@@ -1467,12 +1494,9 @@ int vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
 {
        int error;
 
-       lock_kernel();
-       if (filp->f_op && filp->f_op->setlease)
-               error = filp->f_op->setlease(filp, arg, lease);
-       else
-               error = generic_setlease(filp, arg, lease);
-       unlock_kernel();
+       lock_flocks();
+       error = __vfs_setlease(filp, arg, lease);
+       unlock_flocks();
 
        return error;
 }
@@ -1499,9 +1523,9 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
        if (error)
                return error;
 
-       lock_kernel();
+       lock_flocks();
 
-       error = vfs_setlease(filp, arg, &flp);
+       error = __vfs_setlease(filp, arg, &flp);
        if (error || arg == F_UNLCK)
                goto out_unlock;
 
@@ -1516,7 +1540,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
 
        error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
 out_unlock:
-       unlock_kernel();
+       unlock_flocks();
        return error;
 }
 
@@ -2020,7 +2044,7 @@ void locks_remove_flock(struct file *filp)
                        fl.fl_ops->fl_release_private(&fl);
        }
 
-       lock_kernel();
+       lock_flocks();
        before = &inode->i_flock;
 
        while ((fl = *before) != NULL) {
@@ -2038,7 +2062,7 @@ void locks_remove_flock(struct file *filp)
                }
                before = &fl->fl_next;
        }
-       unlock_kernel();
+       unlock_flocks();
 }
 
 /**
@@ -2053,12 +2077,12 @@ posix_unblock_lock(struct file *filp, struct file_lock *waiter)
 {
        int status = 0;
 
-       lock_kernel();
+       lock_flocks();
        if (waiter->fl_next)
                __locks_delete_block(waiter);
        else
                status = -ENOENT;
-       unlock_kernel();
+       unlock_flocks();
        return status;
 }
 
@@ -2172,7 +2196,7 @@ static int locks_show(struct seq_file *f, void *v)
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
-       lock_kernel();
+       lock_flocks();
        f->private = (void *)1;
        return seq_list_start(&file_lock_list, *pos);
 }
@@ -2184,7 +2208,7 @@ static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
 
 static void locks_stop(struct seq_file *f, void *v)
 {
-       unlock_kernel();
+       unlock_flocks();
 }
 
 static const struct seq_operations locks_seq_operations = {
@@ -2231,7 +2255,7 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len)
 {
        struct file_lock *fl;
        int result = 1;
-       lock_kernel();
+       lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (IS_POSIX(fl)) {
                        if (fl->fl_type == F_RDLCK)
@@ -2248,7 +2272,7 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len)
                result = 0;
                break;
        }
-       unlock_kernel();
+       unlock_flocks();
        return result;
 }
 
@@ -2271,7 +2295,7 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len)
 {
        struct file_lock *fl;
        int result = 1;
-       lock_kernel();
+       lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (IS_POSIX(fl)) {
                        if ((fl->fl_end < start) || (fl->fl_start > (start + len)))
@@ -2286,7 +2310,7 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len)
                result = 0;
                break;
        }
-       unlock_kernel();
+       unlock_flocks();
        return result;
 }
 
index 9777eb5b552248410bd3331f97fb89e853149866..1eb4e89e045b082d9f02d6d005edd3f61e5c48c8 100644 (file)
@@ -827,4 +827,5 @@ const struct file_operations logfs_dir_fops = {
        .unlocked_ioctl = logfs_ioctl,
        .readdir        = logfs_readdir,
        .read           = generic_read_dir,
+       .llseek         = default_llseek,
 };
index e20ee85955d1c77c3a410da2c82893cd38acce8e..f3f3578393a417085812ba1ad7e0b7c1e4e5c981 100644 (file)
@@ -115,7 +115,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
 
        inode_inc_link_count(dir);
 
-       inode = minix_new_inode(dir, mode, &err);
+       inode = minix_new_inode(dir, S_IFDIR | mode, &err);
        if (!inode)
                goto out_dir;
 
index de402eb6eafbad3df3957ca7b74ee92256c1e8c4..7ca5182c0bedd547e21531e777175d2058ea2982 100644 (file)
@@ -1483,6 +1483,23 @@ out_unlock:
        return err;
 }
 
+/*
+ * Sanity check the flags to change_mnt_propagation.
+ */
+
+static int flags_to_propagation_type(int flags)
+{
+       int type = flags & ~MS_REC;
+
+       /* Fail if any non-propagation flags are set */
+       if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+               return 0;
+       /* Only one propagation flag should be set */
+       if (!is_power_of_2(type))
+               return 0;
+       return type;
+}
+
 /*
  * recursively change the type of the mountpoint.
  */
@@ -1490,7 +1507,7 @@ static int do_change_type(struct path *path, int flag)
 {
        struct vfsmount *m, *mnt = path->mnt;
        int recurse = flag & MS_REC;
-       int type = flag & ~MS_REC;
+       int type;
        int err = 0;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -1499,6 +1516,10 @@ static int do_change_type(struct path *path, int flag)
        if (path->dentry != path->mnt->mnt_root)
                return -EINVAL;
 
+       type = flags_to_propagation_type(flag);
+       if (!type)
+               return -EINVAL;
+
        down_write(&namespace_sem);
        if (type == MS_SHARED) {
                err = invent_group_ids(mnt, recurse);
@@ -1723,9 +1744,7 @@ static int do_new_mount(struct path *path, char *type, int flags,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       lock_kernel();
        mnt = do_kern_mount(type, flags, name, data);
-       unlock_kernel();
        if (IS_ERR(mnt))
                return PTR_ERR(mnt);
 
index 9578cbe0cd589ad00ce590d60172c2433d16688e..aac8832e919e9a56cb95af787af658fb03d8d0d1 100644 (file)
@@ -95,6 +95,34 @@ const struct dentry_operations ncp_root_dentry_operations =
 };
 
 
+#define ncp_namespace(i)       (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
+
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
+{
+#ifdef CONFIG_NCPFS_SMALLDOS
+       int ns = ncp_namespace(i);
+
+       if ((ns == NW_NS_DOS)
+#ifdef CONFIG_NCPFS_OS2_NS
+               || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+#endif /* CONFIG_NCPFS_OS2_NS */
+          )
+               return 0;
+#endif /* CONFIG_NCPFS_SMALLDOS */
+       return 1;
+}
+
+#define ncp_preserve_case(i)   (ncp_namespace(i) != NW_NS_DOS)
+
+static inline int ncp_case_sensitive(struct dentry *dentry)
+{
+#ifdef CONFIG_NCPFS_NFS_NS
+       return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
+#else
+       return 0;
+#endif /* CONFIG_NCPFS_NFS_NS */
+}
+
 /*
  * Note: leave the hash unchanged if the directory
  * is case-sensitive.
@@ -102,13 +130,12 @@ const struct dentry_operations ncp_root_dentry_operations =
 static int 
 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
 {
-       struct nls_table *t;
-       unsigned long hash;
-       int i;
-
-       t = NCP_IO_TABLE(dentry);
+       if (!ncp_case_sensitive(dentry)) {
+               struct nls_table *t;
+               unsigned long hash;
+               int i;
 
-       if (!ncp_case_sensitive(dentry->d_inode)) {
+               t = NCP_IO_TABLE(dentry);
                hash = init_name_hash();
                for (i=0; i<this->len ; i++)
                        hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -124,7 +151,7 @@ ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
        if (a->len != b->len)
                return 1;
 
-       if (ncp_case_sensitive(dentry->d_inode))
+       if (ncp_case_sensitive(dentry))
                return strncmp(a->name, b->name, a->len);
 
        return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
@@ -266,7 +293,7 @@ leave_me:;
 
 
 static int
-__ncp_lookup_validate(struct dentry *dentry)
+ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
 {
        struct ncp_server *server;
        struct dentry *parent;
@@ -283,9 +310,6 @@ __ncp_lookup_validate(struct dentry *dentry)
 
        server = NCP_SERVER(dir);
 
-       if (!ncp_conn_valid(server))
-               goto finished;
-
        /*
         * Inspired by smbfs:
         * The default validation is based on dentry age:
@@ -304,8 +328,11 @@ __ncp_lookup_validate(struct dentry *dentry)
        if (ncp_is_server_root(dir)) {
                res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
                                 dentry->d_name.len, 1);
-               if (!res)
+               if (!res) {
                        res = ncp_lookup_volume(server, __name, &(finfo.i));
+                       if (!res)
+                               ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+               }
        } else {
                res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
                                 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -320,13 +347,17 @@ __ncp_lookup_validate(struct dentry *dentry)
         * what we remember, it's not valid any more.
         */
        if (!res) {
-               if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
+               struct inode *inode = dentry->d_inode;
+
+               mutex_lock(&inode->i_mutex);
+               if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
                        ncp_new_dentry(dentry);
                        val=1;
                } else
                        DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
 
-               ncp_update_inode2(dentry->d_inode, &finfo);
+               ncp_update_inode2(inode, &finfo);
+               mutex_unlock(&inode->i_mutex);
        }
 
 finished:
@@ -335,16 +366,6 @@ finished:
        return val;
 }
 
-static int
-ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
-{
-       int res;
-       lock_kernel();
-       res = __ncp_lookup_validate(dentry);
-       unlock_kernel();
-       return res;
-}
-
 static struct dentry *
 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 {
@@ -411,8 +432,6 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
        int result, mtime_valid = 0;
        time_t mtime = 0;
 
-       lock_kernel();
-
        ctl.page  = NULL;
        ctl.cache = NULL;
 
@@ -421,6 +440,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
                (int) filp->f_pos);
 
        result = -EIO;
+       /* Do not generate '.' and '..' when server is dead. */
        if (!ncp_conn_valid(server))
                goto out;
 
@@ -532,6 +552,12 @@ read_really:
        ctl.head.end = ctl.fpos - 1;
        ctl.head.eof = ctl.valid;
 finished:
+       if (ctl.page) {
+               kunmap(ctl.page);
+               SetPageUptodate(ctl.page);
+               unlock_page(ctl.page);
+               page_cache_release(ctl.page);
+       }
        if (page) {
                cache->head = ctl.head;
                kunmap(page);
@@ -539,23 +565,17 @@ finished:
                unlock_page(page);
                page_cache_release(page);
        }
-       if (ctl.page) {
-               kunmap(ctl.page);
-               SetPageUptodate(ctl.page);
-               unlock_page(ctl.page);
-               page_cache_release(ctl.page);
-       }
 out:
-       unlock_kernel();
        return result;
 }
 
 static int
 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-               struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
+               struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
+               int inval_childs)
 {
        struct dentry *newdent, *dentry = filp->f_path.dentry;
-       struct inode *newino, *inode = dentry->d_inode;
+       struct inode *dir = dentry->d_inode;
        struct ncp_cache_control ctl = *ctrl;
        struct qstr qname;
        int valid = 0;
@@ -564,9 +584,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        __u8 __name[NCP_MAXPATHLEN + 1];
 
        qname.len = sizeof(__name);
-       if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
+       if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
                        entry->i.entryName, entry->i.nameLen,
-                       !ncp_preserve_entry_case(inode, entry->i.NSCreator)))
+                       !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
                return 1; /* I'm not sure */
 
        qname.name = __name;
@@ -584,22 +604,64 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
                        goto end_advance;
        } else {
                hashed = 1;
-               memcpy((char *) newdent->d_name.name, qname.name,
-                                                       newdent->d_name.len);
+
+               /* If case sensitivity changed for this volume, all entries below this one
+                  should be thrown away.  This entry itself is not affected, as its case
+                  sensitivity is controlled by its own parent. */
+               if (inval_childs)
+                       shrink_dcache_parent(newdent);
+
+               /*
+                * It is not as dangerous as it looks.  NetWare's OS2 namespace is
+                * case preserving yet case insensitive.  So we update dentry's name
+                * as received from server.  We found dentry via d_lookup with our
+                * hash, so we know that hash does not change, and so replacing name
+                * should be reasonably safe.
+                */
+               if (qname.len == newdent->d_name.len &&
+                   memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
+                       struct inode *inode = newdent->d_inode;
+
+                       /*
+                        * Inside ncpfs all uses of d_name are either for debugging,
+                        * or on functions which acquire inode mutex (mknod, creat,
+                        * lookup).  So grab i_mutex here, to be sure.  d_path
+                        * uses dcache_lock when generating path, so we should too.
+                        * And finally d_compare is protected by dentry's d_lock, so
+                        * here we go.
+                        */
+                       if (inode)
+                               mutex_lock(&inode->i_mutex);
+                       spin_lock(&dcache_lock);
+                       spin_lock(&newdent->d_lock);
+                       memcpy((char *) newdent->d_name.name, qname.name,
+                                                               newdent->d_name.len);
+                       spin_unlock(&newdent->d_lock);
+                       spin_unlock(&dcache_lock);
+                       if (inode)
+                               mutex_unlock(&inode->i_mutex);
+               }
        }
 
        if (!newdent->d_inode) {
+               struct inode *inode;
+
                entry->opened = 0;
-               entry->ino = iunique(inode->i_sb, 2);
-               newino = ncp_iget(inode->i_sb, entry);
-               if (newino) {
+               entry->ino = iunique(dir->i_sb, 2);
+               inode = ncp_iget(dir->i_sb, entry);
+               if (inode) {
                        newdent->d_op = &ncp_dentry_operations;
-                       d_instantiate(newdent, newino);
+                       d_instantiate(newdent, inode);
                        if (!hashed)
                                d_rehash(newdent);
                }
-       } else
-               ncp_update_inode2(newdent->d_inode, entry);
+       } else {
+               struct inode *inode = newdent->d_inode;
+
+               mutex_lock(&inode->i_mutex);
+               ncp_update_inode2(inode, entry);
+               mutex_unlock(&inode->i_mutex);
+       }
 
        if (newdent->d_inode) {
                ino = newdent->d_inode->i_ino;
@@ -617,7 +679,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
                ctl.cache = NULL;
                ctl.idx  -= NCP_DIRCACHE_SIZE;
                ctl.ofs  += 1;
-               ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
+               ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
                if (ctl.page)
                        ctl.cache = kmap(ctl.page);
        }
@@ -633,7 +695,7 @@ end_advance:
                if (!ino)
                        ino = find_inode_number(dentry, &qname);
                if (!ino)
-                       ino = iunique(inode->i_sb, 2);
+                       ino = iunique(dir->i_sb, 2);
                ctl.filled = filldir(dirent, qname.name, qname.len,
                                     filp->f_pos, ino, DT_UNKNOWN);
                if (!ctl.filled)
@@ -660,6 +722,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
                        (unsigned long) filp->f_pos);
 
        for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
+               int inval_dentry;
 
                if (ncp_get_volume_info_with_number(server, i, &info) != 0)
                        return;
@@ -675,8 +738,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
                                info.volume_name);
                        continue;
                }
+               inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
                entry.volume = entry.i.volNumber;
-               if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+               if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
                        return;
        }
 }
@@ -739,7 +803,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
                        rpl += onerpl;
                        rpls -= onerpl;
                        entry.volume = entry.i.volNumber;
-                       if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+                       if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
                                break;
                }
        } while (more);
@@ -775,17 +839,19 @@ int ncp_conn_logged_in(struct super_block *sb)
                if (dent) {
                        struct inode* ino = dent->d_inode;
                        if (ino) {
+                               ncp_update_known_namespace(server, volNumber, NULL);
                                NCP_FINFO(ino)->volNumber = volNumber;
                                NCP_FINFO(ino)->dirEntNum = dirEntNum;
                                NCP_FINFO(ino)->DosDirNum = DosDirNum;
+                               result = 0;
                        } else {
                                DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
                        }
                } else {
                        DPRINTK("ncpfs: sb->s_root == NULL!\n");
                }
-       }
-       result = 0;
+       } else
+               result = 0;
 
 out:
        return result;
@@ -799,7 +865,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc
        int error, res, len;
        __u8 __name[NCP_MAXPATHLEN + 1];
 
-       lock_kernel();
        error = -EIO;
        if (!ncp_conn_valid(server))
                goto finished;
@@ -813,6 +878,8 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc
                                 dentry->d_name.len, 1);
                if (!res)
                        res = ncp_lookup_volume(server, __name, &(finfo.i));
+                       if (!res)
+                               ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
        } else {
                res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
                                 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -846,7 +913,6 @@ add_entry:
 
 finished:
        PPRINTK("ncp_lookup: result=%d\n", error);
-       unlock_kernel();
        return ERR_PTR(error);
 }
 
@@ -887,11 +953,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
        PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
                dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 
-       error = -EIO;
-       lock_kernel();
-       if (!ncp_conn_valid(server))
-               goto out;
-
        ncp_age_dentry(server, dentry);
        len = sizeof(__name);
        error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -917,6 +978,8 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
                if (result) {
                        if (result == 0x87)
                                error = -ENAMETOOLONG;
+                       else if (result < 0)
+                               error = result;
                        DPRINTK("ncp_create: %s/%s failed\n",
                                dentry->d_parent->d_name.name, dentry->d_name.name);
                        goto out;
@@ -935,7 +998,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
 
        error = ncp_instantiate(dir, dentry, &finfo);
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -955,11 +1017,6 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        DPRINTK("ncp_mkdir: making %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       error = -EIO;
-       lock_kernel();
-       if (!ncp_conn_valid(server))
-               goto out;
-
        ncp_age_dentry(server, dentry);
        len = sizeof(__name);
        error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -967,12 +1024,11 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (error)
                goto out;
 
-       error = -EACCES;
-       if (ncp_open_create_file_or_subdir(server, dir, __name,
+       error = ncp_open_create_file_or_subdir(server, dir, __name,
                                           OC_MODE_CREATE, aDIR,
                                           cpu_to_le16(0xffff),
-                                          &finfo) == 0)
-       {
+                                          &finfo);
+       if (error == 0) {
                if (ncp_is_nfs_extras(server, finfo.volume)) {
                        mode |= S_IFDIR;
                        finfo.i.nfs.mode = mode;
@@ -983,9 +1039,10 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                                goto out;
                }
                error = ncp_instantiate(dir, dentry, &finfo);
+       } else if (error > 0) {
+               error = -EACCES;
        }
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -998,11 +1055,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
        DPRINTK("ncp_rmdir: removing %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       error = -EIO;
-       lock_kernel();
-       if (!ncp_conn_valid(server))
-               goto out;
-
        error = -EBUSY;
        if (!d_unhashed(dentry))
                goto out;
@@ -1036,11 +1088,10 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
                        error = -ENOENT;
                        break;
                default:
-                       error = -EACCES;
+                       error = result < 0 ? result : -EACCES;
                        break;
                }
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -1050,15 +1101,10 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
        struct ncp_server *server;
        int error;
 
-       lock_kernel();
        server = NCP_SERVER(dir);
        DPRINTK("ncp_unlink: unlinking %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
        
-       error = -EIO;
-       if (!ncp_conn_valid(server))
-               goto out;
-
        /*
         * Check whether to close the file ...
         */
@@ -1097,12 +1143,9 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
                        error = -ENOENT;
                        break;
                default:
-                       error = -EACCES;
+                       error = error < 0 ? error : -EACCES;
                        break;
        }
-               
-out:
-       unlock_kernel();
        return error;
 }
 
@@ -1118,11 +1161,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
                old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
-       error = -EIO;
-       lock_kernel();
-       if (!ncp_conn_valid(server))
-               goto out;
-
        ncp_age_dentry(server, old_dentry);
        ncp_age_dentry(server, new_dentry);
 
@@ -1161,11 +1199,10 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
                        error = -ENOENT;
                        break;
                default:
-                       error = -EACCES;
+                       error = error < 0 ? error : -EACCES;
                        break;
        }
 out:
-       unlock_kernel();
        return error;
 }
 
index 3639cc5cbdae58d8961308c77caf70f2535db579..6c754f70c5296be3fbe5c323bbb985d7ee326512 100644 (file)
@@ -113,9 +113,6 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        DPRINTK("ncp_file_read: enter %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       if (!ncp_conn_valid(NCP_SERVER(inode)))
-               return -EIO;
-
        pos = *ppos;
 
        if ((ssize_t) count < 0) {
@@ -192,13 +189,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 
        DPRINTK("ncp_file_write: enter %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
-       if (!ncp_conn_valid(NCP_SERVER(inode)))
-               return -EIO;
        if ((ssize_t) count < 0)
                return -EINVAL;
        pos = *ppos;
        if (file->f_flags & O_APPEND) {
-               pos = inode->i_size;
+               pos = i_size_read(inode);
        }
 
        if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
@@ -264,8 +259,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 
        *ppos = pos;
 
-       if (pos > inode->i_size) {
-               inode->i_size = pos;
+       if (pos > i_size_read(inode)) {
+               mutex_lock(&inode->i_mutex);
+               if (pos > i_size_read(inode))
+                       i_size_write(inode, pos);
+               mutex_unlock(&inode->i_mutex);
        }
        DPRINTK("ncp_file_write: exit %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -281,18 +279,9 @@ static int ncp_release(struct inode *inode, struct file *file) {
        return 0;
 }
 
-static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin)
-{
-       loff_t ret;
-       lock_kernel();
-       ret = generic_file_llseek_unlocked(file, offset, origin);
-       unlock_kernel();
-       return ret;
-}
-
 const struct file_operations ncp_file_operations =
 {
-       .llseek         = ncp_remote_llseek,
+       .llseek         = generic_file_llseek,
        .read           = ncp_file_read,
        .write          = ncp_file_write,
        .unlocked_ioctl = ncp_ioctl,
index b4de38cf49f5f3a802a112cbd99226e12d49cf38..985fabb26aca44edcacc889af0a8d2c5c47e8f04 100644 (file)
@@ -139,7 +139,7 @@ static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
                inode->i_mode = nwi->nfs.mode;
        }
 
-       inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
+       inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
        inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
        inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
@@ -158,18 +158,21 @@ static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
                inode->i_mode = server->m.dir_mode;
                /* for directories dataStreamSize seems to be some
                   Object ID ??? */
-               inode->i_size = NCP_BLOCK_SIZE;
+               i_size_write(inode, NCP_BLOCK_SIZE);
        } else {
+               u32 size;
+
                inode->i_mode = server->m.file_mode;
-               inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+               size = le32_to_cpu(nwi->dataStreamSize);
+               i_size_write(inode, size);
 #ifdef CONFIG_NCPFS_EXTRAS
                if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
                 && (nwi->attributes & aSHARED)) {
                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
                                case aHIDDEN:
                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-                                               if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-                                                && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+                                               if (/* (size >= NCP_MIN_SYMLINK_SIZE)
+                                                && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
                                                        NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
                                                        break;
@@ -208,7 +211,7 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
 }
 
 /*
- * Fill in the inode based on the ncp_entry_info structure.
+ * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
  */
 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 {
@@ -254,6 +257,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
        if (inode) {
                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 
+               inode->i_mapping->backing_dev_info = sb->s_bdi;
                inode->i_ino = info->ino;
                ncp_set_attr(inode, info);
                if (S_ISREG(inode->i_mode)) {
@@ -299,10 +303,12 @@ ncp_evict_inode(struct inode *inode)
 
 static void ncp_stop_tasks(struct ncp_server *server) {
        struct sock* sk = server->ncp_sock->sk;
-               
+
+       lock_sock(sk);
        sk->sk_error_report = server->error_report;
        sk->sk_data_ready   = server->data_ready;
        sk->sk_write_space  = server->write_space;
+       release_sock(sk);
        del_timer_sync(&server->timeout_tm);
        flush_scheduled_work();
 }
@@ -565,10 +571,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 /*     server->conn_status = 0;        */
 /*     server->root_dentry = NULL;     */
 /*     server->root_setuped = 0;       */
+       mutex_init(&server->root_setup_lock);
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 /*     server->sign_wanted = 0;        */
 /*     server->sign_active = 0;        */
 #endif
+       init_rwsem(&server->auth_rwsem);
        server->auth.auth_type = NCP_AUTH_NONE;
 /*     server->auth.object_name_len = 0;       */
 /*     server->auth.object_name = NULL;        */
@@ -593,16 +601,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server->nls_io = load_nls_default();
 #endif /* CONFIG_NCPFS_NLS */
 
-       server->dentry_ttl = 0; /* no caching */
+       atomic_set(&server->dentry_ttl, 0);     /* no caching */
 
        INIT_LIST_HEAD(&server->tx.requests);
        mutex_init(&server->rcv.creq_mutex);
        server->tx.creq         = NULL;
        server->rcv.creq        = NULL;
-       server->data_ready      = sock->sk->sk_data_ready;
-       server->write_space     = sock->sk->sk_write_space;
-       server->error_report    = sock->sk->sk_error_report;
-       sock->sk->sk_user_data  = server;
 
        init_timer(&server->timeout_tm);
 #undef NCP_PACKET_SIZE
@@ -619,6 +623,11 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        if (server->rxbuf == NULL)
                goto out_txbuf;
 
+       lock_sock(sock->sk);
+       server->data_ready      = sock->sk->sk_data_ready;
+       server->write_space     = sock->sk->sk_write_space;
+       server->error_report    = sock->sk->sk_error_report;
+       sock->sk->sk_user_data  = server;
        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
        sock->sk->sk_error_report = ncp_tcp_error_report;
        if (sock->type == SOCK_STREAM) {
@@ -634,6 +643,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                server->timeout_tm.data = (unsigned long)server;
                server->timeout_tm.function = ncpdgram_timeout_call;
        }
+       release_sock(sock->sk);
 
        ncp_lock_server(server);
        error = ncp_connect(server);
@@ -658,8 +668,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                goto out_disconnect;
                        }
                }
+               ncp_lock_server(server);
                if (options & 2)
                        server->sign_wanted = 1;
+               ncp_unlock_server(server);
        }
        else 
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
@@ -720,6 +732,9 @@ out_nls:
        unload_nls(server->nls_io);
        unload_nls(server->nls_vol);
 #endif
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
 out_fput2:
        if (server->info_filp)
                fput(server->info_filp);
@@ -743,8 +758,6 @@ static void ncp_put_super(struct super_block *sb)
 {
        struct ncp_server *server = NCP_SBP(sb);
 
-       lock_kernel();
-
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
@@ -756,6 +769,9 @@ static void ncp_put_super(struct super_block *sb)
        unload_nls(server->nls_vol);
        unload_nls(server->nls_io);
 #endif /* CONFIG_NCPFS_NLS */
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
 
        if (server->info_filp)
                fput(server->info_filp);
@@ -771,8 +787,6 @@ static void ncp_put_super(struct super_block *sb)
        vfree(server->packet);
        sb->s_fs_info = NULL;
        kfree(server);
-
-       unlock_kernel();
 }
 
 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -851,10 +865,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 
        result = -EIO;
 
-       lock_kernel();  
-
        server = NCP_SERVER(inode);
-       if ((!server) || !ncp_conn_valid(server))
+       if (!server)    /* How this could happen? */
                goto out;
 
        /* ageing the dentry to force validation */
@@ -981,8 +993,6 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
                                      inode, info_mask, &info);
                if (result != 0) {
-                       result = -EACCES;
-
                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
                                /* NetWare seems not to allow this. I
                                   do not know why. So, just tell the
@@ -1005,7 +1015,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
        mark_inode_dirty(inode);
 
 out:
-       unlock_kernel();
+       if (result > 0)
+               result = -EACCES;
        return result;
 }
 
index 84a8cfc4e38ec533ecaf7b7ad2812fc306a18c3a..c2a1f9a155c3a6e8f82800334337b1b1b0aaa65a 100644 (file)
 #define NCP_PACKET_SIZE_INTERNAL 65536
 
 static int
-ncp_get_fs_info(struct ncp_server * server, struct file *file,
+ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
                struct ncp_fs_info __user *arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
        struct ncp_fs_info info;
 
-       if (file_permission(file, MAY_WRITE) != 0
-           && current_uid() != server->m.mounted_uid)
-               return -EACCES;
-
        if (copy_from_user(&info, arg, sizeof(info)))
                return -EFAULT;
 
@@ -65,16 +60,11 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,
 }
 
 static int
-ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
                   struct ncp_fs_info_v2 __user * arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
        struct ncp_fs_info_v2 info2;
 
-       if (file_permission(file, MAY_WRITE) != 0
-           && current_uid() != server->m.mounted_uid)
-               return -EACCES;
-
        if (copy_from_user(&info2, arg, sizeof(info2)))
                return -EFAULT;
 
@@ -136,16 +126,11 @@ struct compat_ncp_privatedata_ioctl
 #define NCP_IOC_SETPRIVATEDATA_32      _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
 
 static int
-ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
                   struct compat_ncp_fs_info_v2 __user * arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
        struct compat_ncp_fs_info_v2 info2;
 
-       if (file_permission(file, MAY_WRITE) != 0
-           && current_uid() != server->m.mounted_uid)
-               return -EACCES;
-
        if (copy_from_user(&info2, arg, sizeof(info2)))
                return -EFAULT;
 
@@ -182,11 +167,8 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
        struct nls_table *iocharset;
        struct nls_table *oldset_io;
        struct nls_table *oldset_cp;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EACCES;
-       if (server->root_setuped)
-               return -EBUSY;
+       int utf8;
+       int err;
 
        if (copy_from_user(&user, arg, sizeof(user)))
                return -EFAULT;
@@ -206,28 +188,40 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
        user.iocharset[NCP_IOCSNAME_LEN] = 0;
        if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
                iocharset = load_nls_default();
-               NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+               utf8 = 0;
        } else if (!strcmp(user.iocharset, "utf8")) {
                iocharset = load_nls_default();
-               NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+               utf8 = 1;
        } else {
                iocharset = load_nls(user.iocharset);
                if (!iocharset) {
                        unload_nls(codepage);
                        return -EBADRQC;
                }
-               NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+               utf8 = 0;
        }
 
-       oldset_cp = server->nls_vol;
-       server->nls_vol = codepage;
-       oldset_io = server->nls_io;
-       server->nls_io = iocharset;
-
+       mutex_lock(&server->root_setup_lock);
+       if (server->root_setuped) {
+               oldset_cp = codepage;
+               oldset_io = iocharset;
+               err = -EBUSY;
+       } else {
+               if (utf8)
+                       NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+               else
+                       NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+               oldset_cp = server->nls_vol;
+               server->nls_vol = codepage;
+               oldset_io = server->nls_io;
+               server->nls_io = iocharset;
+               err = 0;
+       }
+       mutex_unlock(&server->root_setup_lock);
        unload_nls(oldset_cp);
        unload_nls(oldset_io);
 
-       return 0;
+       return err;
 }
 
 static int
@@ -237,6 +231,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
        int len;
 
        memset(&user, 0, sizeof(user));
+       mutex_lock(&server->root_setup_lock);
        if (server->nls_vol && server->nls_vol->charset) {
                len = strlen(server->nls_vol->charset);
                if (len > NCP_IOCSNAME_LEN)
@@ -254,6 +249,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
                strncpy(user.iocharset, server->nls_io->charset, len);
                user.iocharset[len] = 0;
        }
+       mutex_unlock(&server->root_setup_lock);
 
        if (copy_to_user(arg, &user, sizeof(user)))
                return -EFAULT;
@@ -261,25 +257,19 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
 }
 #endif /* CONFIG_NCPFS_NLS */
 
-static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
        struct ncp_server *server = NCP_SERVER(inode);
        int result;
        struct ncp_ioctl_request request;
        char* bouncebuffer;
        void __user *argp = (void __user *)arg;
-       uid_t uid = current_uid();
 
        switch (cmd) {
 #ifdef CONFIG_COMPAT
        case NCP_IOC_NCPREQUEST_32:
 #endif
        case NCP_IOC_NCPREQUEST:
-               if (file_permission(filp, MAY_WRITE) != 0
-                   && uid != server->m.mounted_uid)
-                       return -EACCES;
-
 #ifdef CONFIG_COMPAT
                if (cmd == NCP_IOC_NCPREQUEST_32) {
                        struct compat_ncp_ioctl_request request32;
@@ -314,7 +304,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                server->current_size = request.size;
                memcpy(server->packet, bouncebuffer, request.size);
 
-               result = ncp_request2(server, request.function, 
+               result = ncp_request2(server, request.function,
                        bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
                if (result < 0)
                        result = -EIO;
@@ -331,69 +321,69 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
        case NCP_IOC_CONN_LOGGED_IN:
 
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EACCES;
                if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
                        return -EINVAL;
+               mutex_lock(&server->root_setup_lock);
                if (server->root_setuped)
-                       return -EBUSY;
-               server->root_setuped = 1;
-               return ncp_conn_logged_in(inode->i_sb);
+                       result = -EBUSY;
+               else {
+                       result = ncp_conn_logged_in(inode->i_sb);
+                       if (result == 0)
+                               server->root_setuped = 1;
+               }
+               mutex_unlock(&server->root_setup_lock);
+               return result;
 
        case NCP_IOC_GET_FS_INFO:
-               return ncp_get_fs_info(server, filp, argp);
+               return ncp_get_fs_info(server, inode, argp);
 
        case NCP_IOC_GET_FS_INFO_V2:
-               return ncp_get_fs_info_v2(server, filp, argp);
+               return ncp_get_fs_info_v2(server, inode, argp);
 
 #ifdef CONFIG_COMPAT
        case NCP_IOC_GET_FS_INFO_V2_32:
-               return ncp_get_compat_fs_info_v2(server, filp, argp);
+               return ncp_get_compat_fs_info_v2(server, inode, argp);
 #endif
        /* we have too many combinations of CONFIG_COMPAT,
         * CONFIG_64BIT and CONFIG_UID16, so just handle
         * any of the possible ioctls */
        case NCP_IOC_GETMOUNTUID16:
-       case NCP_IOC_GETMOUNTUID32:
-       case NCP_IOC_GETMOUNTUID64:
-               if (file_permission(filp, MAY_READ) != 0
-                       && uid != server->m.mounted_uid)
-                       return -EACCES;
-
-               if (cmd == NCP_IOC_GETMOUNTUID16) {
+               {
                        u16 uid;
+
                        SET_UID(uid, server->m.mounted_uid);
                        if (put_user(uid, (u16 __user *)argp))
                                return -EFAULT;
-               } else if (cmd == NCP_IOC_GETMOUNTUID32) {
-                       if (put_user(server->m.mounted_uid,
-                                               (u32 __user *)argp))
-                               return -EFAULT;
-               } else {
-                       if (put_user(server->m.mounted_uid,
-                                               (u64 __user *)argp))
-                               return -EFAULT;
+                       return 0;
                }
+       case NCP_IOC_GETMOUNTUID32:
+               if (put_user(server->m.mounted_uid,
+                            (u32 __user *)argp))
+                       return -EFAULT;
+               return 0;
+       case NCP_IOC_GETMOUNTUID64:
+               if (put_user(server->m.mounted_uid,
+                            (u64 __user *)argp))
+                       return -EFAULT;
                return 0;
 
        case NCP_IOC_GETROOT:
                {
                        struct ncp_setroot_ioctl sr;
 
-                       if (file_permission(filp, MAY_READ) != 0
-                           && uid != server->m.mounted_uid)
-                               return -EACCES;
-
+                       result = -EACCES;
+                       mutex_lock(&server->root_setup_lock);
                        if (server->m.mounted_vol[0]) {
                                struct dentry* dentry = inode->i_sb->s_root;
 
                                if (dentry) {
                                        struct inode* s_inode = dentry->d_inode;
-                               
+
                                        if (s_inode) {
                                                sr.volNumber = NCP_FINFO(s_inode)->volNumber;
                                                sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
                                                sr.namespace = server->name_space[sr.volNumber];
+                                               result = 0;
                                        } else
                                                DPRINTK("ncpfs: s_root->d_inode==NULL\n");
                                } else
@@ -402,10 +392,12 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                sr.volNumber = -1;
                                sr.namespace = 0;
                                sr.dirEntNum = 0;
+                               result = 0;
                        }
-                       if (copy_to_user(argp, &sr, sizeof(sr)))
-                               return -EFAULT;
-                       return 0;
+                       mutex_unlock(&server->root_setup_lock);
+                       if (!result && copy_to_user(argp, &sr, sizeof(sr)))
+                               result = -EFAULT;
+                       return result;
                }
 
        case NCP_IOC_SETROOT:
@@ -416,103 +408,114 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        __le32 dosde;
                        struct dentry* dentry;
 
-                       if (!capable(CAP_SYS_ADMIN))
-                       {
-                               return -EACCES;
-                       }
-                       if (server->root_setuped) return -EBUSY;
                        if (copy_from_user(&sr, argp, sizeof(sr)))
                                return -EFAULT;
-                       if (sr.volNumber < 0) {
-                               server->m.mounted_vol[0] = 0;
-                               vnum = NCP_NUMBER_OF_VOLUMES;
-                               de = 0;
-                               dosde = 0;
-                       } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
-                               return -EINVAL;
-                       } else if (ncp_mount_subdir(server, sr.volNumber,
-                                               sr.namespace, sr.dirEntNum,
-                                               &vnum, &de, &dosde)) {
-                               return -ENOENT;
-                       }
-                       
-                       dentry = inode->i_sb->s_root;
-                       server->root_setuped = 1;
-                       if (dentry) {
-                               struct inode* s_inode = dentry->d_inode;
-                               
-                               if (s_inode) {
-                                       NCP_FINFO(s_inode)->volNumber = vnum;
-                                       NCP_FINFO(s_inode)->dirEntNum = de;
-                                       NCP_FINFO(s_inode)->DosDirNum = dosde;
+                       mutex_lock(&server->root_setup_lock);
+                       if (server->root_setuped)
+                               result = -EBUSY;
+                       else {
+                               if (sr.volNumber < 0) {
+                                       server->m.mounted_vol[0] = 0;
+                                       vnum = NCP_NUMBER_OF_VOLUMES;
+                                       de = 0;
+                                       dosde = 0;
+                                       result = 0;
+                               } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
+                                       result = -EINVAL;
+                               } else if (ncp_mount_subdir(server, sr.volNumber,
+                                                       sr.namespace, sr.dirEntNum,
+                                                       &vnum, &de, &dosde)) {
+                                       result = -ENOENT;
                                } else
-                                       DPRINTK("ncpfs: s_root->d_inode==NULL\n");
-                       } else
-                               DPRINTK("ncpfs: s_root==NULL\n");
+                                       result = 0;
+
+                               if (result == 0) {
+                                       dentry = inode->i_sb->s_root;
+                                       if (dentry) {
+                                               struct inode* s_inode = dentry->d_inode;
+
+                                               if (s_inode) {
+                                                       NCP_FINFO(s_inode)->volNumber = vnum;
+                                                       NCP_FINFO(s_inode)->dirEntNum = de;
+                                                       NCP_FINFO(s_inode)->DosDirNum = dosde;
+                                                       server->root_setuped = 1;
+                                               } else {
+                                                       DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+                                                       result = -EIO;
+                                               }
+                                       } else {
+                                               DPRINTK("ncpfs: s_root==NULL\n");
+                                               result = -EIO;
+                                       }
+                               }
+                               result = 0;
+                       }
+                       mutex_unlock(&server->root_setup_lock);
 
-                       return 0;
+                       return result;
                }
 
-#ifdef CONFIG_NCPFS_PACKET_SIGNING     
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
        case NCP_IOC_SIGN_INIT:
-               if (file_permission(filp, MAY_WRITE) != 0
-                   && uid != server->m.mounted_uid)
-                       return -EACCES;
-
-               if (argp) {
-                       if (server->sign_wanted)
-                       {
-                               struct ncp_sign_init sign;
+               {
+                       struct ncp_sign_init sign;
 
+                       if (argp)
                                if (copy_from_user(&sign, argp, sizeof(sign)))
                                        return -EFAULT;
-                               memcpy(server->sign_root,sign.sign_root,8);
-                               memcpy(server->sign_last,sign.sign_last,16);
-                               server->sign_active = 1;
+                       ncp_lock_server(server);
+                       mutex_lock(&server->rcv.creq_mutex);
+                       if (argp) {
+                               if (server->sign_wanted) {
+                                       memcpy(server->sign_root,sign.sign_root,8);
+                                       memcpy(server->sign_last,sign.sign_last,16);
+                                       server->sign_active = 1;
+                               }
+                               /* ignore when signatures not wanted */
+                       } else {
+                               server->sign_active = 0;
                        }
-                       /* ignore when signatures not wanted */
-               } else {
-                       server->sign_active = 0;
+                       mutex_unlock(&server->rcv.creq_mutex);
+                       ncp_unlock_server(server);
+                       return 0;
                }
-               return 0;               
-               
+
         case NCP_IOC_SIGN_WANTED:
-               if (file_permission(filp, MAY_READ) != 0
-                   && uid != server->m.mounted_uid)
-                       return -EACCES;
-               
-                if (put_user(server->sign_wanted, (int __user *)argp))
-                       return -EFAULT;
-                return 0;
+               {
+                       int state;
+
+                       ncp_lock_server(server);
+                       state = server->sign_wanted;
+                       ncp_unlock_server(server);
+                       if (put_user(state, (int __user *)argp))
+                               return -EFAULT;
+                       return 0;
+               }
 
        case NCP_IOC_SET_SIGN_WANTED:
                {
                        int newstate;
 
-                       if (file_permission(filp, MAY_WRITE) != 0
-                           && uid != server->m.mounted_uid)
-                               return -EACCES;
-
                        /* get only low 8 bits... */
                        if (get_user(newstate, (unsigned char __user *)argp))
                                return -EFAULT;
+                       result = 0;
+                       ncp_lock_server(server);
                        if (server->sign_active) {
                                /* cannot turn signatures OFF when active */
-                               if (!newstate) return -EINVAL;
+                               if (!newstate)
+                                       result = -EINVAL;
                        } else {
                                server->sign_wanted = newstate != 0;
                        }
-                       return 0;
+                       ncp_unlock_server(server);
+                       return result;
                }
 
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
        case NCP_IOC_LOCKUNLOCK:
-               if (file_permission(filp, MAY_WRITE) != 0
-                   && uid != server->m.mounted_uid)
-                       return -EACCES;
-
                {
                        struct ncp_lock_ioctl    rqdata;
 
@@ -541,16 +544,13 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        {
                                return result;
                        }
-                       result = -EIO;
-                       if (!ncp_conn_valid(server))
-                               goto outrel;
                        result = -EISDIR;
                        if (!S_ISREG(inode->i_mode))
                                goto outrel;
                        if (rqdata.cmd == NCP_LOCK_CLEAR)
                        {
                                result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
-                                                       NCP_FINFO(inode)->file_handle, 
+                                                       NCP_FINFO(inode)->file_handle,
                                                        rqdata.offset,
                                                        rqdata.length);
                                if (result > 0) result = 0;     /* no such lock */
@@ -573,7 +573,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                                        rqdata.timeout);
                                if (result > 0) result = -EAGAIN;
                        }
-outrel:                        
+outrel:
                        ncp_inode_close(inode);
                        return result;
                }
@@ -581,60 +581,62 @@ outrel:
 
 #ifdef CONFIG_COMPAT
        case NCP_IOC_GETOBJECTNAME_32:
-               if (uid != server->m.mounted_uid)
-                       return -EACCES;
                {
                        struct compat_ncp_objectname_ioctl user;
                        size_t outl;
 
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
+                       down_read(&server->auth_rwsem);
                        user.auth_type = server->auth.auth_type;
                        outl = user.object_name_len;
                        user.object_name_len = server->auth.object_name_len;
                        if (outl > user.object_name_len)
                                outl = user.object_name_len;
+                       result = 0;
                        if (outl) {
                                if (copy_to_user(compat_ptr(user.object_name),
                                                 server->auth.object_name,
-                                                outl)) return -EFAULT;
+                                                outl))
+                                       result = -EFAULT;
                        }
-                       if (copy_to_user(argp, &user, sizeof(user)))
-                               return -EFAULT;
-                       return 0;
+                       up_read(&server->auth_rwsem);
+                       if (!result && copy_to_user(argp, &user, sizeof(user)))
+                               result = -EFAULT;
+                       return result;
                }
 #endif
 
        case NCP_IOC_GETOBJECTNAME:
-               if (uid != server->m.mounted_uid)
-                       return -EACCES;
                {
                        struct ncp_objectname_ioctl user;
                        size_t outl;
 
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
+                       down_read(&server->auth_rwsem);
                        user.auth_type = server->auth.auth_type;
                        outl = user.object_name_len;
                        user.object_name_len = server->auth.object_name_len;
                        if (outl > user.object_name_len)
                                outl = user.object_name_len;
+                       result = 0;
                        if (outl) {
                                if (copy_to_user(user.object_name,
                                                 server->auth.object_name,
-                                                outl)) return -EFAULT;
+                                                outl))
+                                       result = -EFAULT;
                        }
-                       if (copy_to_user(argp, &user, sizeof(user)))
-                               return -EFAULT;
-                       return 0;
+                       up_read(&server->auth_rwsem);
+                       if (!result && copy_to_user(argp, &user, sizeof(user)))
+                               result = -EFAULT;
+                       return result;
                }
 
 #ifdef CONFIG_COMPAT
        case NCP_IOC_SETOBJECTNAME_32:
 #endif
        case NCP_IOC_SETOBJECTNAME:
-               if (uid != server->m.mounted_uid)
-                       return -EACCES;
                {
                        struct ncp_objectname_ioctl user;
                        void* newname;
@@ -666,9 +668,7 @@ outrel:
                        } else {
                                newname = NULL;
                        }
-                       /* enter critical section */
-                       /* maybe that kfree can sleep so do that this way */
-                       /* it is at least more SMP friendly (in future...) */
+                       down_write(&server->auth_rwsem);
                        oldname = server->auth.object_name;
                        oldnamelen = server->auth.object_name_len;
                        oldprivate = server->priv.data;
@@ -678,7 +678,7 @@ outrel:
                        server->auth.object_name = newname;
                        server->priv.len = 0;
                        server->priv.data = NULL;
-                       /* leave critical section */
+                       up_write(&server->auth_rwsem);
                        kfree(oldprivate);
                        kfree(oldname);
                        return 0;
@@ -688,8 +688,6 @@ outrel:
        case NCP_IOC_GETPRIVATEDATA_32:
 #endif
        case NCP_IOC_GETPRIVATEDATA:
-               if (uid != server->m.mounted_uid)
-                       return -EACCES;
                {
                        struct ncp_privatedata_ioctl user;
                        size_t outl;
@@ -706,14 +704,20 @@ outrel:
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
 
+                       down_read(&server->auth_rwsem);
                        outl = user.len;
                        user.len = server->priv.len;
                        if (outl > user.len) outl = user.len;
+                       result = 0;
                        if (outl) {
                                if (copy_to_user(user.data,
                                                 server->priv.data,
-                                                outl)) return -EFAULT;
+                                                outl))
+                                       result = -EFAULT;
                        }
+                       up_read(&server->auth_rwsem);
+                       if (result)
+                               return result;
 #ifdef CONFIG_COMPAT
                        if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
                                struct compat_ncp_privatedata_ioctl user32;
@@ -733,8 +737,6 @@ outrel:
        case NCP_IOC_SETPRIVATEDATA_32:
 #endif
        case NCP_IOC_SETPRIVATEDATA:
-               if (uid != server->m.mounted_uid)
-                       return -EACCES;
                {
                        struct ncp_privatedata_ioctl user;
                        void* new;
@@ -762,12 +764,12 @@ outrel:
                        } else {
                                new = NULL;
                        }
-                       /* enter critical section */
+                       down_write(&server->auth_rwsem);
                        old = server->priv.data;
                        oldlen = server->priv.len;
                        server->priv.len = user.len;
                        server->priv.data = new;
-                       /* leave critical section */
+                       up_write(&server->auth_rwsem);
                        kfree(old);
                        return 0;
                }
@@ -775,17 +777,13 @@ outrel:
 #ifdef CONFIG_NCPFS_NLS
        case NCP_IOC_SETCHARSETS:
                return ncp_set_charsets(server, argp);
-               
+
        case NCP_IOC_GETCHARSETS:
                return ncp_get_charsets(server, argp);
 
 #endif /* CONFIG_NCPFS_NLS */
 
        case NCP_IOC_SETDENTRYTTL:
-               if (file_permission(filp, MAY_WRITE) != 0 &&
-                   uid != server->m.mounted_uid)
-                       return -EACCES;
-
                {
                        u_int32_t user;
 
@@ -795,13 +793,13 @@ outrel:
                        if (user > 20000)
                                return -EINVAL;
                        user = (user * HZ) / 1000;
-                       server->dentry_ttl = user;
+                       atomic_set(&server->dentry_ttl, user);
                        return 0;
                }
-               
+
        case NCP_IOC_GETDENTRYTTL:
                {
-                       u_int32_t user = (server->dentry_ttl * 1000) / HZ;
+                       u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
                        if (copy_to_user(argp, &user, sizeof(user)))
                                return -EFAULT;
                        return 0;
@@ -811,59 +809,103 @@ outrel:
        return -EINVAL;
 }
 
-static int ncp_ioctl_need_write(unsigned int cmd)
+long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct ncp_server *server = NCP_SERVER(inode);
+       uid_t uid = current_uid();
+       int need_drop_write = 0;
+       long ret;
+
        switch (cmd) {
-       case NCP_IOC_GET_FS_INFO:
-       case NCP_IOC_GET_FS_INFO_V2:
-       case NCP_IOC_NCPREQUEST:
-       case NCP_IOC_SETDENTRYTTL:
-       case NCP_IOC_SIGN_INIT:
-       case NCP_IOC_LOCKUNLOCK:
-       case NCP_IOC_SET_SIGN_WANTED:
-               return 1;
-       case NCP_IOC_GETOBJECTNAME:
-       case NCP_IOC_SETOBJECTNAME:
-       case NCP_IOC_GETPRIVATEDATA:
-       case NCP_IOC_SETPRIVATEDATA:
        case NCP_IOC_SETCHARSETS:
-       case NCP_IOC_GETCHARSETS:
        case NCP_IOC_CONN_LOGGED_IN:
-       case NCP_IOC_GETDENTRYTTL:
-       case NCP_IOC_GETMOUNTUID2:
-       case NCP_IOC_SIGN_WANTED:
-       case NCP_IOC_GETROOT:
        case NCP_IOC_SETROOT:
-               return 0;
-       default:
-               /* unknown IOCTL command, assume write */
-               return 1;
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EACCES;
+                       goto out;
+               }
+               break;
        }
-}
-
-long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       long ret;
-
-       lock_kernel();
-       if (ncp_ioctl_need_write(cmd)) {
+       if (server->m.mounted_uid != uid) {
+               switch (cmd) {
                /*
-                * inside the ioctl(), any failures which
-                * are because of file_permission() are
-                * -EACCESS, so it seems consistent to keep
-                *  that here.
+                * Only mount owner can issue these ioctls.  Information
+                * necessary to authenticate to other NDS servers are
+                * stored here.
                 */
-               if (mnt_want_write(filp->f_path.mnt)) {
+               case NCP_IOC_GETOBJECTNAME:
+               case NCP_IOC_SETOBJECTNAME:
+               case NCP_IOC_GETPRIVATEDATA:
+               case NCP_IOC_SETPRIVATEDATA:
+#ifdef CONFIG_COMPAT
+               case NCP_IOC_GETOBJECTNAME_32:
+               case NCP_IOC_SETOBJECTNAME_32:
+               case NCP_IOC_GETPRIVATEDATA_32:
+               case NCP_IOC_SETPRIVATEDATA_32:
+#endif
                        ret = -EACCES;
                        goto out;
+               /*
+                * These require write access on the inode if user id
+                * does not match.  Note that they do not write to the
+                * file...  But old code did mnt_want_write, so I keep
+                * it as is.  Of course not for mountpoint owner, as
+                * that breaks read-only mounts altogether as ncpmount
+                * needs working NCP_IOC_NCPREQUEST and
+                * NCP_IOC_GET_FS_INFO.  Some of these codes (setdentryttl,
+                * signinit, setsignwanted) should be probably restricted
+                * to owner only, or even more to CAP_SYS_ADMIN).
+                */
+               case NCP_IOC_GET_FS_INFO:
+               case NCP_IOC_GET_FS_INFO_V2:
+               case NCP_IOC_NCPREQUEST:
+               case NCP_IOC_SETDENTRYTTL:
+               case NCP_IOC_SIGN_INIT:
+               case NCP_IOC_LOCKUNLOCK:
+               case NCP_IOC_SET_SIGN_WANTED:
+#ifdef CONFIG_COMPAT
+               case NCP_IOC_GET_FS_INFO_V2_32:
+               case NCP_IOC_NCPREQUEST_32:
+#endif
+                       ret = mnt_want_write_file(filp);
+                       if (ret)
+                               goto out;
+                       need_drop_write = 1;
+                       ret = inode_permission(inode, MAY_WRITE);
+                       if (ret)
+                               goto outDropWrite;
+                       break;
+               /*
+                * Read access required.
+                */
+               case NCP_IOC_GETMOUNTUID16:
+               case NCP_IOC_GETMOUNTUID32:
+               case NCP_IOC_GETMOUNTUID64:
+               case NCP_IOC_GETROOT:
+               case NCP_IOC_SIGN_WANTED:
+                       ret = inode_permission(inode, MAY_READ);
+                       if (ret)
+                               goto out;
+                       break;
+               /*
+                * Anybody can read these.
+                */
+               case NCP_IOC_GETCHARSETS:
+               case NCP_IOC_GETDENTRYTTL:
+               default:
+               /* Three codes below are protected by CAP_SYS_ADMIN above. */
+               case NCP_IOC_SETCHARSETS:
+               case NCP_IOC_CONN_LOGGED_IN:
+               case NCP_IOC_SETROOT:
+                       break;
                }
        }
-       ret = __ncp_ioctl(filp, cmd, arg);
-       if (ncp_ioctl_need_write(cmd))
+       ret = __ncp_ioctl(inode, cmd, arg);
+outDropWrite:
+       if (need_drop_write)
                mnt_drop_write(filp->f_path.mnt);
-
 out:
-       unlock_kernel();
        return ret;
 }
 
@@ -872,10 +914,8 @@ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       lock_kernel();
        arg = (unsigned long) compat_ptr(arg);
        ret = ncp_ioctl(file, cmd, arg);
-       unlock_kernel();
        return ret;
 }
 #endif
index 0ec6237a5970f162e0ed0d72b33fa9f1e15a7b86..a95615a0b6ac420fcfedbc8e6460173ddb3b3f97 100644 (file)
@@ -107,17 +107,17 @@ ncp_reply_data(struct ncp_server *server, int offset)
        return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
 }
 
-static inline u8 BVAL(void *data)
+static inline u8 BVAL(const void *data)
 {
-       return *(u8 *)data;
+       return *(const u8 *)data;
 }
 
 static u8 ncp_reply_byte(struct ncp_server *server, int offset)
 {
-       return *(u8 *)ncp_reply_data(server, offset);
+       return *(const u8 *)ncp_reply_data(server, offset);
 }
 
-static inline u16 WVAL_LH(void *data)
+static inline u16 WVAL_LH(const void *data)
 {
        return get_unaligned_le16(data);
 }
@@ -134,7 +134,7 @@ ncp_reply_be16(struct ncp_server *server, int offset)
        return get_unaligned_be16(ncp_reply_data(server, offset));
 }
 
-static inline u32 DVAL_LH(void *data)
+static inline u32 DVAL_LH(const void *data)
 {
        return get_unaligned_le32(data);
 }
@@ -349,9 +349,9 @@ int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
        return result;
 }
 
-void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
+void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
 {
-       __u8 *name_len;
+       const __u8 *name_len;
        const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
 
        memcpy(target, structure, info_struct_size);
@@ -364,7 +364,7 @@ void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
 }
 
 #ifdef CONFIG_NCPFS_NFS_NS
-static inline void ncp_extract_nfs_info(unsigned char *structure,
+static inline void ncp_extract_nfs_info(const unsigned char *structure,
                                 struct nw_nfs_info *target)
 {
        target->mode = DVAL_LH(structure);
@@ -417,7 +417,7 @@ int ncp_obtain_nfs_info(struct ncp_server *server,
  * Returns information for a (one-component) name relative to
  * the specified directory.
  */
-int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
+int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
                        struct nw_info_struct *target)
 {
        __u8  volnum = NCP_FINFO(dir)->volNumber;
@@ -452,16 +452,16 @@ out:
 #ifdef CONFIG_NCPFS_NFS_NS
 static int
 ncp_obtain_DOS_dir_base(struct ncp_server *server,
-               __u8 volnum, __le32 dirent,
-               char *path, /* At most 1 component */
+               __u8 ns, __u8 volnum, __le32 dirent,
+               const char *path, /* At most 1 component */
                __le32 *DOS_dir_base)
 {
        int result;
 
        ncp_init_request(server);
        ncp_add_byte(server, 6); /* subfunction */
-       ncp_add_byte(server, server->name_space[volnum]);
-       ncp_add_byte(server, server->name_space[volnum]);
+       ncp_add_byte(server, ns);
+       ncp_add_byte(server, ns);
        ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
        ncp_add_dword(server, RIM_DIRECTORY);
        ncp_add_handle_path(server, volnum, dirent, 1, path);
@@ -523,10 +523,27 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
 #endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
 }
 
+int
+ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
+{
+       int ns = ncp_get_known_namespace(server, volume);
+
+       if (ret_ns)
+               *ret_ns = ns;
+
+       DPRINTK("lookup_vol: namespace[%d] = %d\n",
+               volume, server->name_space[volume]);
+
+       if (server->name_space[volume] == ns)
+               return 0;
+       server->name_space[volume] = ns;
+       return 1;
+}
+
 static int
 ncp_ObtainSpecificDirBase(struct ncp_server *server,
                __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
-               char *path, /* At most 1 component */
+               const char *path, /* At most 1 component */
                __le32 *dirEntNum, __le32 *DosDirNum)
 {
        int result;
@@ -560,14 +577,13 @@ ncp_mount_subdir(struct ncp_server *server,
 {
        int dstNS;
        int result;
-       
-       dstNS = ncp_get_known_namespace(server, volNumber);
+
+       ncp_update_known_namespace(server, volNumber, &dstNS);
        if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
                                      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
        {
                return result;
        }
-       server->name_space[volNumber] = dstNS;
        *volume = volNumber;
        server->m.mounted_vol[1] = 0;
        server->m.mounted_vol[0] = 'X';
@@ -575,11 +591,10 @@ ncp_mount_subdir(struct ncp_server *server,
 }
 
 int 
-ncp_get_volume_root(struct ncp_server *server, const char *volname,
-                   __u32* volume, __le32* dirent, __le32* dosdirent)
+ncp_get_volume_root(struct ncp_server *server,
+                   const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
 {
        int result;
-       __u8 volnum;
 
        DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
 
@@ -601,21 +616,14 @@ ncp_get_volume_root(struct ncp_server *server, const char *volname,
                return result;
        }
        *dirent = *dosdirent = ncp_reply_dword(server, 4);
-       volnum = ncp_reply_byte(server, 8);
+       *volume = ncp_reply_byte(server, 8);
        ncp_unlock_server(server);
-       *volume = volnum;
-
-       server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
-
-       DPRINTK("lookup_vol: namespace[%d] = %d\n",
-               volnum, server->name_space[volnum]);
-
        return 0;
 }
 
 int
-ncp_lookup_volume(struct ncp_server *server, const char *volname,
-                 struct nw_info_struct *target)
+ncp_lookup_volume(struct ncp_server *server,
+                 const char *volname, struct nw_info_struct *target)
 {
        int result;
 
@@ -625,6 +633,7 @@ ncp_lookup_volume(struct ncp_server *server, const char *volname,
        if (result) {
                return result;
        }
+       ncp_update_known_namespace(server, target->volNumber, NULL);
        target->nameLen = strlen(volname);
        memcpy(target->entryName, volname, target->nameLen+1);
        target->attributes = aDIR;
@@ -676,8 +685,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
 {
        int result = 0;
 
+       ncp_init_request(server);
        if (server->name_space[volnum] == NW_NS_NFS) {
-               ncp_init_request(server);
                ncp_add_byte(server, 25);       /* subfunction */
                ncp_add_byte(server, server->name_space[volnum]);
                ncp_add_byte(server, NW_NS_NFS);
@@ -690,8 +699,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
                ncp_add_dword_lh(server, 1);    /* nlinks */
                ncp_add_dword_lh(server, rdev);
                result = ncp_request(server, 87);
-               ncp_unlock_server(server);
        }
+       ncp_unlock_server(server);
        return result;
 }
 #endif
@@ -700,7 +709,7 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
                  __u8 have_dir_base, __u8 volnum, __le32 dirent,
-                 char* name, __u8 ns, __le16 attr)
+                 const char* name, __u8 ns, __le16 attr)
 {
        int result;
 
@@ -734,23 +743,25 @@ ncp_del_file_or_subdir2(struct ncp_server *server,
 
 int
 ncp_del_file_or_subdir(struct ncp_server *server,
-                      struct inode *dir, char *name)
+                      struct inode *dir, const char *name)
 {
        __u8  volnum = NCP_FINFO(dir)->volNumber;
        __le32 dirent = NCP_FINFO(dir)->dirEntNum;
+       int name_space;
 
+       name_space = server->name_space[volnum];
 #ifdef CONFIG_NCPFS_NFS_NS
-       if (server->name_space[volnum]==NW_NS_NFS)
+       if (name_space == NW_NS_NFS)
        {
                int result;
  
-               result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent);
+               result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
                if (result) return result;
-               return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
+               name = NULL;
+               name_space = NW_NS_DOS;
        }
-       else
 #endif /* CONFIG_NCPFS_NFS_NS */
-               return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006));
+       return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
 }
 
 static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
@@ -765,7 +776,7 @@ static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
 /* If both dir and name are NULL, then in target there's already a
    looked-up entry that wants to be opened. */
 int ncp_open_create_file_or_subdir(struct ncp_server *server,
-                                  struct inode *dir, char *name,
+                                  struct inode *dir, const char *name,
                                   int open_create_mode,
                                   __le32 create_attributes,
                                   __le16 desired_acc_rights,
@@ -890,8 +901,8 @@ int ncp_search_for_fileset(struct ncp_server *server,
 
 static int
 ncp_RenameNSEntry(struct ncp_server *server,
-                 struct inode *old_dir, char *old_name, __le16 old_type,
-                 struct inode *new_dir, char *new_name)
+                 struct inode *old_dir, const char *old_name, __le16 old_type,
+                 struct inode *new_dir, const char *new_name)
 {
        int result = -EINVAL;
 
@@ -929,8 +940,8 @@ out:
 }
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-                               struct inode *old_dir, char *old_name,
-                               struct inode *new_dir, char *new_name)
+                               struct inode *old_dir, const char *old_name,
+                               struct inode *new_dir, const char *new_name)
 {
         int result;
         __le16 old_type = cpu_to_le16(0x06);
@@ -958,7 +969,7 @@ int
 ncp_read_kernel(struct ncp_server *server, const char *file_id,
             __u32 offset, __u16 to_read, char *target, int *bytes_read)
 {
-       char *source;
+       const char *source;
        int result;
 
        ncp_init_request(server);
index 2441d1ab57dc57abe66ba24126b3b9221b1692bc..3c57eca634ce12f5d76b77959a3422677c9c3c53 100644 (file)
@@ -65,10 +65,11 @@ static inline void ncp_inode_close(struct inode *inode) {
        atomic_dec(&NCP_FINFO(inode)->opened);
 }
 
-void ncp_extract_file_info(void* src, struct nw_info_struct* target);
-int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
+void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
+int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
                struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
+int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
 int ncp_get_volume_root(struct ncp_server *server, const char *volname,
                        __u32 *volume, __le32 *dirent, __le32 *dosdirent);
 int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
@@ -80,8 +81,8 @@ int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
                        __u32 mode, __u32 rdev);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
-int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
-int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
+int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
+int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
                                int, __le32, __le16, struct ncp_entry_info *);
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
@@ -93,7 +94,7 @@ int ncp_search_for_fileset(struct ncp_server *server,
                           char** rbuf, size_t* rsize);
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-                             struct inode *, char *, struct inode *, char *);
+                             struct inode *, const char *, struct inode *, const char *);
 
 
 int
@@ -170,13 +171,13 @@ static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
 #endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)    (jiffies - (dentry)->d_time)
-#define NCP_MAX_AGE(server)    ((server)->dentry_ttl)
+#define NCP_MAX_AGE(server)    atomic_read(&(server)->dentry_ttl)
 #define NCP_TEST_AGE(server,dentry)    (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
 
 static inline void
 ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
 {
-       dentry->d_time = jiffies - server->dentry_ttl;
+       dentry->d_time = jiffies - NCP_MAX_AGE(server);
 }
 
 static inline void
index 7c0b5c21e6cf668dc791212327ebe46b8a3007bf..d8b2d7e6910b1a843a425b7a84164b2b061e99b6 100644 (file)
 
 /* i386: 32-bit, little endian, handles mis-alignment */
 #ifdef __i386__
-#define GET_LE32(p) (*(int *)(p))
+#define GET_LE32(p) (*(const int *)(p))
 #define PUT_LE32(p,v) { *(int *)(p)=v; }
 #else
 /* from include/ncplib.h */
-#define BVAL(buf,pos) (((__u8 *)(buf))[pos])
+#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
-#define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
+#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
 
 static inline __u16
-WVAL_LH(__u8 * buf, int pos)
+WVAL_LH(const __u8 * buf, int pos)
 {
        return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
 }
 static inline __u32
-DVAL_LH(__u8 * buf, int pos)
+DVAL_LH(const __u8 * buf, int pos)
 {
        return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
 }
index c7ff6c700a6efdca195b43a18414e221ecafc824..668bd267346e57ed80700e4b8af541ad9dd5f476 100644 (file)
@@ -746,7 +746,6 @@ static int ncp_do_request(struct ncp_server *server, int size,
                return -EIO;
        }
        if (!ncp_conn_valid(server)) {
-               printk(KERN_ERR "ncpfs: Connection invalid!\n");
                return -EIO;
        }
        {
index 6c2aad49d7318054b57c22b58c6b4eaa0be50178..b950415d7c4340b0bb30da28cbb6e96c1a011826 100644 (file)
@@ -1,6 +1,7 @@
 config NFS_FS
        tristate "NFS client support"
        depends on INET && FILE_LOCKING
+       depends on BKL # fix as soon as lockd is done
        select LOCKD
        select SUNRPC
        select NFS_ACL_SUPPORT if NFS_V3_ACL
@@ -63,6 +64,7 @@ config NFS_V3_ACL
 config NFS_V4
        bool "NFS client support for NFS version 4"
        depends on NFS_FS
+       select SUNRPC_GSS
        help
          This option enables support for version 4 of the NFS protocol
          (RFC 3530) in the kernel's NFS client.
index 4e7df2adb2125724a4ea9ade0fc767606d54c4b3..e7340729af896e2bce1097fe4f8521618680173e 100644 (file)
@@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
            sin1->sin6_scope_id != sin2->sin6_scope_id)
                return 0;
 
-       return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr);
+       return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
 }
 #else  /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
 static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
index b9c3c43cea1def16da3d9df934fd846dd478488f..232a7eead33a488c4a5d67bc83e3a1971d9665df 100644 (file)
@@ -71,20 +71,20 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
        if (inode->i_flock == NULL)
                goto out;
 
-       /* Protect inode->i_flock using the BKL */
-       lock_kernel();
+       /* Protect inode->i_flock using the file locks lock */
+       lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
                        continue;
                if (nfs_file_open_context(fl->fl_file) != ctx)
                        continue;
-               unlock_kernel();
+               unlock_flocks();
                status = nfs4_lock_delegation_recall(state, fl);
                if (status < 0)
                        goto out;
-               lock_kernel();
+               lock_flocks();
        }
-       unlock_kernel();
+       unlock_flocks();
 out:
        return status;
 }
index eb51bd6201da0cd361d8265b4c6b0e3edee50ec9..05bf3c0dc751d5d489b1c7be2cf594005caf1695 100644 (file)
@@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
                default:
                        BUG();
        }
-       if (res < 0)
-               dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager"
-                       " - error %d!\n",
-                               __func__, res);
        return res;
 }
 
index 3e2f19b04c06b4b3fb0f01cb409a544054940222..96524c5dca6b8bd45fc0c845546e783d318d7e4f 100644 (file)
@@ -40,7 +40,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
@@ -970,13 +970,13 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
        /* Guard against delegation returns and new lock/unlock calls */
        down_write(&nfsi->rwsem);
        /* Protect inode->i_flock using the BKL */
-       lock_kernel();
+       lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
                        continue;
                if (nfs_file_open_context(fl->fl_file)->state != state)
                        continue;
-               unlock_kernel();
+               unlock_flocks();
                status = ops->recover_lock(state, fl);
                switch (status) {
                        case 0:
@@ -1003,9 +1003,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
                                /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                                status = 0;
                }
-               lock_kernel();
+               lock_flocks();
        }
-       unlock_kernel();
+       unlock_flocks();
 out:
        up_write(&nfsi->rwsem);
        return status;
index ec3966e4706b2f70d8709199f86456392a6e6584..f4cbf0c306c64d6583cbfffaa14cfbc7a467dfaa 100644 (file)
@@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
                goto out_err;
 
        error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
+       if (unlikely(error == -ESTALE)) {
+               struct dentry *pd_dentry;
 
+               pd_dentry = dget_parent(dentry);
+               if (pd_dentry != NULL) {
+                       nfs_zap_caches(pd_dentry->d_inode);
+                       dput(pd_dentry);
+               }
+       }
        nfs_free_fattr(res.fattr);
        if (error < 0)
                goto out_err;
index 95932f523aef2b2b7ef4686b8bb4a18383b4a395..7cf4ddafb4abc3b0ae4f511bb0d264eab0f563d4 100644 (file)
@@ -2,6 +2,7 @@ config NFSD
        tristate "NFS server support"
        depends on INET
        depends on FILE_LOCKING
+       depends on BKL # fix as soon as lockd is done
        select LOCKD
        select SUNRPC
        select EXPORTFS
@@ -69,6 +70,7 @@ config NFSD_V4
        depends on NFSD && PROC_FS && EXPERIMENTAL
        select NFSD_V3
        select FS_POSIX_ACL
+       select SUNRPC_GSS
        help
          This option enables support in your system's NFS server for
          version 4 of the NFS protocol (RFC 3530).
index 2e7357104cfdf3208a6abe357c91e92536d8e815..a7292fcf7718e0d1471ddcfd2dab4e3957f17e18 100644 (file)
@@ -33,7 +33,7 @@
 */
 
 #include <linux/file.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/swap.h>
@@ -440,7 +440,7 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
 
 static int nfs4_access_to_omode(u32 access)
 {
-       switch (access) {
+       switch (access & NFS4_SHARE_ACCESS_BOTH) {
        case NFS4_SHARE_ACCESS_READ:
                return O_RDONLY;
        case NFS4_SHARE_ACCESS_WRITE:
@@ -2450,14 +2450,13 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
 static __be32
 nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
 {
-       u32 op_share_access, new_access;
+       u32 op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
+       bool new_access;
        __be32 status;
 
-       set_access(&new_access, stp->st_access_bmap);
-       new_access = (~new_access) & open->op_share_access & ~NFS4_SHARE_WANT_MASK;
-
+       new_access = !test_bit(op_share_access, &stp->st_access_bmap);
        if (new_access) {
-               status = nfs4_get_vfs_file(rqstp, fp, cur_fh, new_access);
+               status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access);
                if (status)
                        return status;
        }
@@ -2470,7 +2469,6 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
                return status;
        }
        /* remember the open */
-       op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
        __set_bit(op_share_access, &stp->st_access_bmap);
        __set_bit(open->op_share_deny, &stp->st_deny_bmap);
 
@@ -2983,7 +2981,6 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                                *filpp = find_readable_file(stp->st_file);
                        else
                                *filpp = find_writeable_file(stp->st_file);
-                       BUG_ON(!*filpp); /* assured by check_openmode */
                }
        }
        status = nfs_ok;
@@ -3561,7 +3558,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct nfs4_stateowner *open_sop = NULL;
        struct nfs4_stateowner *lock_sop = NULL;
        struct nfs4_stateid *lock_stp;
-       struct file *filp;
+       struct nfs4_file *fp;
+       struct file *filp = NULL;
        struct file_lock file_lock;
        struct file_lock conflock;
        __be32 status = 0;
@@ -3591,7 +3589,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                 * lock stateid.
                 */
                struct nfs4_stateid *open_stp = NULL;
-               struct nfs4_file *fp;
                
                status = nfserr_stale_clientid;
                if (!nfsd4_has_session(cstate) &&
@@ -3634,6 +3631,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                if (status)
                        goto out;
                lock_sop = lock->lk_replay_owner;
+               fp = lock_stp->st_file;
        }
        /* lock->lk_replay_owner and lock_stp have been created or found */
 
@@ -3648,13 +3646,19 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        switch (lock->lk_type) {
                case NFS4_READ_LT:
                case NFS4_READW_LT:
-                       filp = find_readable_file(lock_stp->st_file);
+                       if (find_readable_file(lock_stp->st_file)) {
+                               nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ);
+                               filp = find_readable_file(lock_stp->st_file);
+                       }
                        file_lock.fl_type = F_RDLCK;
                        cmd = F_SETLK;
                break;
                case NFS4_WRITE_LT:
                case NFS4_WRITEW_LT:
-                       filp = find_writeable_file(lock_stp->st_file);
+                       if (find_writeable_file(lock_stp->st_file)) {
+                               nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE);
+                               filp = find_writeable_file(lock_stp->st_file);
+                       }
                        file_lock.fl_type = F_WRLCK;
                        cmd = F_SETLK;
                break;
@@ -3891,7 +3895,7 @@ check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
        struct inode *inode = filp->fi_inode;
        int status = 0;
 
-       lock_kernel();
+       lock_flocks();
        for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
                if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
                        status = 1;
@@ -3899,7 +3903,7 @@ check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
                }
        }
 out:
-       unlock_kernel();
+       unlock_flocks();
        return status;
 }
 
index b53b1d042f1ff3190b6696876da88cf355277b5a..06fa87e52e8243cc46a41d5f861aa91388581d7b 100644 (file)
@@ -137,6 +137,7 @@ static const struct file_operations transaction_ops = {
        .write          = nfsctl_transaction_write,
        .read           = nfsctl_transaction_read,
        .release        = simple_transaction_release,
+       .llseek         = default_llseek,
 };
 
 static int exports_open(struct inode *inode, struct file *file)
index cdfb8c6a420674cbde75467a09d6a158977a4b61..c16f8d8331b5afcd80baec98cbdbc4594c66142d 100644 (file)
@@ -196,8 +196,6 @@ fh_lock(struct svc_fh *fhp)
 static inline void
 fh_unlock(struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_dentry);
-
        if (fhp->fh_locked) {
                fill_post_wcc(fhp);
                mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
index 7731a75971ddf88347b7ed634604e72fcc0b027c..322518c88e4b09eee40473ed8efaece99e02410b 100644 (file)
@@ -363,23 +363,23 @@ struct nfs4_file {
  * at all? */
 static inline struct file *find_writeable_file(struct nfs4_file *f)
 {
-       if (f->fi_fds[O_RDWR])
-               return f->fi_fds[O_RDWR];
-       return f->fi_fds[O_WRONLY];
+       if (f->fi_fds[O_WRONLY])
+               return f->fi_fds[O_WRONLY];
+       return f->fi_fds[O_RDWR];
 }
 
 static inline struct file *find_readable_file(struct nfs4_file *f)
 {
-       if (f->fi_fds[O_RDWR])
-               return f->fi_fds[O_RDWR];
-       return f->fi_fds[O_RDONLY];
+       if (f->fi_fds[O_RDONLY])
+               return f->fi_fds[O_RDONLY];
+       return f->fi_fds[O_RDWR];
 }
 
 static inline struct file *find_any_file(struct nfs4_file *f)
 {
        if (f->fi_fds[O_RDWR])
                return f->fi_fds[O_RDWR];
-       else if (f->fi_fds[O_RDWR])
+       else if (f->fi_fds[O_WRONLY])
                return f->fi_fds[O_WRONLY];
        else
                return f->fi_fds[O_RDONLY];
index 96360a83cb91f670d7a0d5df012ebf75324f4d7e..661a6cf8e8265eaeca988e2aabc0ba1ede767717 100644 (file)
@@ -2033,15 +2033,17 @@ out:
 __be32
 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
 {
-       struct path path = {
-               .mnt    = fhp->fh_export->ex_path.mnt,
-               .dentry = fhp->fh_dentry,
-       };
        __be32 err;
 
        err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
-       if (!err && vfs_statfs(&path, stat))
-               err = nfserr_io;
+       if (!err) {
+               struct path path = {
+                       .mnt    = fhp->fh_export->ex_path.mnt,
+                       .dentry = fhp->fh_dentry,
+               };
+               if (vfs_statfs(&path, stat))
+                       err = nfserr_io;
+       }
        return err;
 }
 
index f90a33d9a5b097c06038f614cbbcecb1abfab191..0442ee3b394fd7f65315482078cc4bc463f300eb 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <linux/fs.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>    /* lock_kernel(), unlock_kernel() */
 #include <linux/slab.h>
 #include <linux/capability.h>  /* capable() */
 #include <linux/uaccess.h>     /* copy_from_user(), copy_to_user() */
index 922263393c765664f6b5598f4c144093ec9e582c..9f4913f78408a80e5c9b1253c19ac092adecb2b2 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
 #include <linux/kobject.h>
@@ -342,8 +341,6 @@ static void nilfs_put_super(struct super_block *sb)
        struct nilfs_sb_info *sbi = NILFS_SB(sb);
        struct the_nilfs *nilfs = sbi->s_nilfs;
 
-       lock_kernel();
-
        nilfs_detach_segment_constructor(sbi);
 
        if (!(sb->s_flags & MS_RDONLY)) {
@@ -361,8 +358,6 @@ static void nilfs_put_super(struct super_block *sb)
        sbi->s_super = NULL;
        sb->s_fs_info = NULL;
        nilfs_put_sbinfo(sbi);
-
-       unlock_kernel();
 }
 
 static int nilfs_sync_fs(struct super_block *sb, int wait)
@@ -949,8 +944,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
        struct nilfs_mount_options old_opts;
        int was_snapshot, err;
 
-       lock_kernel();
-
        down_write(&nilfs->ns_super_sem);
        old_sb_flags = sb->s_flags;
        old_opts.mount_opt = sbi->s_mount_opt;
@@ -1024,7 +1017,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
        }
  out:
        up_write(&nilfs->ns_super_sem);
-       unlock_kernel();
        return 0;
 
  restore_opts:
@@ -1032,7 +1024,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
        sbi->s_mount_opt = old_opts.mount_opt;
        sbi->s_snapshot_cno = old_opts.snapshot_cno;
        up_write(&nilfs->ns_super_sem);
-       unlock_kernel();
        return err;
 }
 
@@ -1205,7 +1196,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
        put_nilfs(nilfs);
  failed:
        close_bdev_exclusive(sd.bdev, mode);
-
        return err;
 
  cancel_new:
index 4317f177ea7cb27c46cb315f5055205f3a0addc7..ba7c10c917fcd1545a668c53f6abb2819b04f3bc 100644 (file)
@@ -446,6 +446,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
        nilfs_mdt_destroy(nilfs->ns_cpfile);
        nilfs_mdt_destroy(nilfs->ns_sufile);
        nilfs_mdt_destroy(nilfs->ns_dat);
+       nilfs_mdt_destroy(nilfs->ns_gc_dat);
 
  failed:
        nilfs_clear_recovery_info(&ri);
index d269a93d3467a03235585d55ac34bc5786277e93..6e40e42a43de57b1586413b90fc897cf3d457617 100644 (file)
@@ -19,4 +19,5 @@ static int no_blkdev_open(struct inode * inode, struct file * filp)
 
 const struct file_operations def_blk_fops = {
        .open           = no_blkdev_open,
+       .llseek         = noop_llseek,
 };
index 22c629eedd82d70425704ee86b4ddf816b7bd174..b388443c3a09b01574b78befaabbf7fe03f9eeb4 100644 (file)
@@ -3,4 +3,4 @@ config FSNOTIFY
 
 source "fs/notify/dnotify/Kconfig"
 source "fs/notify/inotify/Kconfig"
-source "fs/notify/fanotify/Kconfig"
+#source "fs/notify/fanotify/Kconfig"
index 756566fe844909c2499f3e5a53903fd2f62f2419..85366c78cc3759b1a0027e1a3d5d0598e2f2fdec 100644 (file)
@@ -165,9 +165,6 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
                 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
                 inode_mark, vfsmnt_mark, event_mask, data, data_type);
 
-       pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n",
-                __func__, group, vfsmnt_mark, inode_mark, event_mask);
-
        /* sorry, fanotify only gives a damn about files and dirs */
        if (!S_ISREG(to_tell->i_mode) &&
            !S_ISDIR(to_tell->i_mode))
index 032b837fcd11912e54a01920ddf40b9506f1c8f9..bbcb98e7fcc611d692e9d85c4c74dd742d417507 100644 (file)
@@ -195,6 +195,14 @@ static int prepare_for_access_response(struct fsnotify_group *group,
        re->fd = fd;
 
        mutex_lock(&group->fanotify_data.access_mutex);
+
+       if (group->fanotify_data.bypass_perm) {
+               mutex_unlock(&group->fanotify_data.access_mutex);
+               kmem_cache_free(fanotify_response_event_cache, re);
+               event->response = FAN_ALLOW;
+               return 0;
+       }
+               
        list_add_tail(&re->list, &group->fanotify_data.access_list);
        mutex_unlock(&group->fanotify_data.access_mutex);
 
@@ -364,9 +372,28 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t
 static int fanotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
+       struct fanotify_response_event *re, *lre;
 
        pr_debug("%s: file=%p group=%p\n", __func__, file, group);
 
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       mutex_lock(&group->fanotify_data.access_mutex);
+
+       group->fanotify_data.bypass_perm = true;
+
+       list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
+               pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
+                        re, re->event);
+
+               list_del_init(&re->list);
+               re->event->response = FAN_ALLOW;
+
+               kmem_cache_free(fanotify_response_event_cache, re);
+       }
+       mutex_unlock(&group->fanotify_data.access_mutex);
+
+       wake_up(&group->fanotify_data.access_waitq);
+#endif
        /* matches the fanotify_init->fsnotify_alloc_group */
        fsnotify_put_group(group);
 
@@ -406,6 +433,7 @@ static const struct file_operations fanotify_fops = {
        .release        = fanotify_release,
        .unlocked_ioctl = fanotify_ioctl,
        .compat_ioctl   = fanotify_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
@@ -614,7 +642,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
                __func__, flags, event_f_flags);
 
        if (!capable(CAP_SYS_ADMIN))
-               return -EACCES;
+               return -EPERM;
 
        if (flags & ~FAN_ALL_INIT_FLAGS)
                return -EINVAL;
index 3970392b272264810574ca6536eed74bd3fc013d..36802420d69a94024eefde05f1eab9f6a9932241 100644 (file)
@@ -148,13 +148,14 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
                         const unsigned char *file_name,
                         struct fsnotify_event **event)
 {
-       struct fsnotify_group *group = inode_mark->group;
-       __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
-       __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
+       struct fsnotify_group *group = NULL;
+       __u32 inode_test_mask = 0;
+       __u32 vfsmount_test_mask = 0;
 
-       pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p"
-                " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell,
-                mnt, inode_mark, mask, data, data_is, cookie, *event);
+       if (unlikely(!inode_mark && !vfsmount_mark)) {
+               BUG();
+               return 0;
+       }
 
        /* clear ignored on inode modification */
        if (mask & FS_MODIFY) {
@@ -168,18 +169,29 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
 
        /* does the inode mark tell us to do something? */
        if (inode_mark) {
+               group = inode_mark->group;
+               inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
                inode_test_mask &= inode_mark->mask;
                inode_test_mask &= ~inode_mark->ignored_mask;
        }
 
        /* does the vfsmount_mark tell us to do something? */
        if (vfsmount_mark) {
+               vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
+               group = vfsmount_mark->group;
                vfsmount_test_mask &= vfsmount_mark->mask;
                vfsmount_test_mask &= ~vfsmount_mark->ignored_mask;
                if (inode_mark)
                        vfsmount_test_mask &= ~inode_mark->ignored_mask;
        }
 
+       pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p"
+                " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
+                " data=%p data_is=%d cookie=%d event=%p\n",
+                __func__, group, to_tell, mnt, mask, inode_mark,
+                inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
+                data_is, cookie, *event);
+
        if (!inode_test_mask && !vfsmount_test_mask)
                return 0;
 
@@ -207,13 +219,12 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
 int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
             const unsigned char *file_name, u32 cookie)
 {
-       struct hlist_node *inode_node, *vfsmount_node;
+       struct hlist_node *inode_node = NULL, *vfsmount_node = NULL;
        struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
        struct fsnotify_group *inode_group, *vfsmount_group;
        struct fsnotify_event *event = NULL;
        struct vfsmount *mnt;
        int idx, ret = 0;
-       bool used_inode = false, used_vfsmount = false;
        /* global tests shouldn't care about events on child only the specific event */
        __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 
@@ -238,57 +249,50 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
            (test_mask & to_tell->i_fsnotify_mask))
                inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first,
                                              &fsnotify_mark_srcu);
-       else
-               inode_node = NULL;
 
-       if (mnt) {
-               if ((mask & FS_MODIFY) ||
-                   (test_mask & mnt->mnt_fsnotify_mask))
-                       vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first,
-                                                        &fsnotify_mark_srcu);
-               else
-                       vfsmount_node = NULL;
-       } else {
-               mnt = NULL;
-               vfsmount_node = NULL;
+       if (mnt && ((mask & FS_MODIFY) ||
+                   (test_mask & mnt->mnt_fsnotify_mask))) {
+               vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first,
+                                                &fsnotify_mark_srcu);
+               inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first,
+                                             &fsnotify_mark_srcu);
        }
 
        while (inode_node || vfsmount_node) {
+               inode_group = vfsmount_group = NULL;
+
                if (inode_node) {
                        inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
                                                 struct fsnotify_mark, i.i_list);
                        inode_group = inode_mark->group;
-               } else
-                       inode_group = (void *)-1;
+               }
 
                if (vfsmount_node) {
                        vfsmount_mark = hlist_entry(srcu_dereference(vfsmount_node, &fsnotify_mark_srcu),
                                                        struct fsnotify_mark, m.m_list);
                        vfsmount_group = vfsmount_mark->group;
-               } else
-                       vfsmount_group = (void *)-1;
+               }
 
-               if (inode_group < vfsmount_group) {
+               if (inode_group > vfsmount_group) {
                        /* handle inode */
                        send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
                                      data_is, cookie, file_name, &event);
-                       used_inode = true;
-               } else if (vfsmount_group < inode_group) {
+                       /* we didn't use the vfsmount_mark */
+                       vfsmount_group = NULL;
+               } else if (vfsmount_group > inode_group) {
                        send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
                                      data_is, cookie, file_name, &event);
-                       used_vfsmount = true;
+                       inode_group = NULL;
                } else {
                        send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
                                      mask, data, data_is, cookie, file_name,
                                      &event);
-                       used_vfsmount = true;
-                       used_inode = true;
                }
 
-               if (used_inode)
+               if (inode_group)
                        inode_node = srcu_dereference(inode_node->next,
                                                      &fsnotify_mark_srcu);
-               if (used_vfsmount)
+               if (vfsmount_group)
                        vfsmount_node = srcu_dereference(vfsmount_node->next,
                                                         &fsnotify_mark_srcu);
        }
index bf7f6d776c31a22e71573ef86e00516c195e95e6..24edc1185d53fd1b2a0d61e646d02f4bd7fc0afb 100644 (file)
@@ -344,6 +344,7 @@ static const struct file_operations inotify_fops = {
        .release        = inotify_release,
        .unlocked_ioctl = inotify_ioctl,
        .compat_ioctl   = inotify_ioctl,
+       .llseek         = noop_llseek,
 };
 
 
index 512806171bfa2e2dfb73975feb60ea9560a654a7..19c5180f8a28c063b9a8cf5fefc58a6c61512455 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/moduleparam.h>
-#include <linux/smp_lock.h>
 #include <linux/bitmap.h>
 
 #include "sysctl.h"
@@ -445,7 +444,6 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
 
        ntfs_debug("Entering with remount options string: %s", opt);
 
-       lock_kernel();
 #ifndef NTFS_RW
        /* For read-only compiled driver, enforce read-only flag. */
        *flags |= MS_RDONLY;
@@ -469,18 +467,15 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
                if (NVolErrors(vol)) {
                        ntfs_error(sb, "Volume has errors and is read-only%s",
                                        es);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (vol->vol_flags & VOLUME_IS_DIRTY) {
                        ntfs_error(sb, "Volume is dirty and read-only%s", es);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) {
                        ntfs_error(sb, "Volume has been modified by chkdsk "
                                        "and is read-only%s", es);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {
@@ -488,13 +483,11 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
                                        "(0x%x) and is read-only%s",
                                        (unsigned)le16_to_cpu(vol->vol_flags),
                                        es);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {
                        ntfs_error(sb, "Failed to set dirty bit in volume "
                                        "information flags%s", es);
-                       unlock_kernel();
                        return -EROFS;
                }
 #if 0
@@ -514,21 +507,18 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
                        ntfs_error(sb, "Failed to empty journal $LogFile%s",
                                        es);
                        NVolSetErrors(vol);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (!ntfs_mark_quotas_out_of_date(vol)) {
                        ntfs_error(sb, "Failed to mark quotas out of date%s",
                                        es);
                        NVolSetErrors(vol);
-                       unlock_kernel();
                        return -EROFS;
                }
                if (!ntfs_stamp_usnjrnl(vol)) {
                        ntfs_error(sb, "Failed to stamp transation log "
                                        "($UsnJrnl)%s", es);
                        NVolSetErrors(vol);
-                       unlock_kernel();
                        return -EROFS;
                }
        } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
@@ -544,11 +534,9 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
 
        // TODO: Deal with *flags.
 
-       if (!parse_options(vol, opt)) {
-               unlock_kernel();
+       if (!parse_options(vol, opt))
                return -EINVAL;
-       }
-       unlock_kernel();
+
        ntfs_debug("Done.");
        return 0;
 }
@@ -2261,8 +2249,6 @@ static void ntfs_put_super(struct super_block *sb)
 
        ntfs_debug("Entering.");
 
-       lock_kernel();
-
 #ifdef NTFS_RW
        /*
         * Commit all inodes while they are still open in case some of them
@@ -2433,8 +2419,6 @@ static void ntfs_put_super(struct super_block *sb)
 
        sb->s_fs_info = NULL;
        kfree(vol);
-
-       unlock_kernel();
 }
 
 /**
@@ -2772,8 +2756,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
        init_rwsem(&vol->mftbmp_lock);
        init_rwsem(&vol->lcnbmp_lock);
 
-       unlock_kernel();
-
        /* By default, enable sparse support. */
        NVolSetSparseEnabled(vol);
 
@@ -2940,7 +2922,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
                }
                mutex_unlock(&ntfs_lock);
                sb->s_export_op = &ntfs_export_ops;
-               lock_kernel();
                lockdep_on();
                return 0;
        }
@@ -3057,7 +3038,6 @@ iput_tmp_ino_err_out_now:
        }
        /* Errors at this stage are irrelevant. */
 err_out_now:
-       lock_kernel();
        sb->s_fs_info = NULL;
        kfree(vol);
        ntfs_debug("Failed, returning -EINVAL.");
index a76e0aa5cd3fc5188a392639618858a7e7e34092..391915093fe1c494a58ec8feae54cd576fd2464a 100644 (file)
@@ -209,7 +209,10 @@ static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
        }
 
        inode->i_mode = new_mode;
+       inode->i_ctime = CURRENT_TIME;
        di->i_mode = cpu_to_le16(inode->i_mode);
+       di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+       di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
 
        ocfs2_journal_dirty(handle, di_bh);
 
index 215e12ce1d85e2079359838cf287f1c3c670ff31..592fae5007d1245baade87453ce731121aa6efe5 100644 (file)
@@ -6672,7 +6672,7 @@ int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
        last_page_bytes = PAGE_ALIGN(end);
        index = start >> PAGE_CACHE_SHIFT;
        do {
-               pages[numpages] = grab_cache_page(mapping, index);
+               pages[numpages] = find_or_create_page(mapping, index, GFP_NOFS);
                if (!pages[numpages]) {
                        ret = -ENOMEM;
                        mlog_errno(ret);
index 0de69c9a08be0e4732925f9cd049fc927b6bb851..5cfeee11815881b04a3250d42a72838e40289200 100644 (file)
@@ -883,8 +883,8 @@ struct ocfs2_write_ctxt {
         * out in so that future reads from that region will get
         * zero's.
         */
-       struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
        unsigned int                    w_num_pages;
+       struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
        struct page                     *w_target_page;
 
        /*
@@ -1642,7 +1642,8 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh,
        return ret;
 }
 
-int ocfs2_write_begin_nolock(struct address_space *mapping,
+int ocfs2_write_begin_nolock(struct file *filp,
+                            struct address_space *mapping,
                             loff_t pos, unsigned len, unsigned flags,
                             struct page **pagep, void **fsdata,
                             struct buffer_head *di_bh, struct page *mmap_page)
@@ -1692,7 +1693,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                mlog_errno(ret);
                goto out;
        } else if (ret == 1) {
-               ret = ocfs2_refcount_cow(inode, di_bh,
+               ret = ocfs2_refcount_cow(inode, filp, di_bh,
                                         wc->w_cpos, wc->w_clen, UINT_MAX);
                if (ret) {
                        mlog_errno(ret);
@@ -1854,7 +1855,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
         */
        down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-       ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+       ret = ocfs2_write_begin_nolock(file, mapping, pos, len, flags, pagep,
                                       fsdata, di_bh, NULL);
        if (ret) {
                mlog_errno(ret);
index c48e93ffc513025b737ea38d59b63a886c0b0b88..7606f663da6d1e1181dac172736ed9dfbbb3fd84 100644 (file)
@@ -48,7 +48,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
                           loff_t pos, unsigned len, unsigned copied,
                           struct page *page, void *fsdata);
 
-int ocfs2_write_begin_nolock(struct address_space *mapping,
+int ocfs2_write_begin_nolock(struct file *filp,
+                            struct address_space *mapping,
                             loff_t pos, unsigned len, unsigned flags,
                             struct page **pagep, void **fsdata,
                             struct buffer_head *di_bh, struct page *mmap_page);
index ec6d123395932b69b6a67ba0b5256be02b811c6f..c7ee03c22226253d970cce94beb11f6353b3e1d0 100644 (file)
@@ -439,7 +439,7 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
 
        ocfs2_blockcheck_inc_failure(stats);
        mlog(ML_ERROR,
-            "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
+            "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
             (unsigned int)check.bc_crc32e, (unsigned int)crc);
 
        /* Ok, try ECC fixups */
@@ -453,7 +453,7 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
                goto out;
        }
 
-       mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
+       mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
             (unsigned int)check.bc_crc32e, (unsigned int)crc);
 
        rc = -EIO;
index 41d5f1f92d56f60a45f6066d875598bda7caddf2..52c7557f3e25ad4cce288883ed070eb48f970a4e 100644 (file)
@@ -62,10 +62,51 @@ static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
 static LIST_HEAD(o2hb_node_events);
 static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue);
 
+/*
+ * In global heartbeat, we maintain a series of region bitmaps.
+ *     - o2hb_region_bitmap allows us to limit the region number to max region.
+ *     - o2hb_live_region_bitmap tracks live regions (seen steady iterations).
+ *     - o2hb_quorum_region_bitmap tracks live regions that have seen all nodes
+ *             heartbeat on it.
+ *     - o2hb_failed_region_bitmap tracks the regions that have seen io timeouts.
+ */
+static unsigned long o2hb_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_live_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_quorum_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_failed_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+
+#define O2HB_DB_TYPE_LIVENODES         0
+#define O2HB_DB_TYPE_LIVEREGIONS       1
+#define O2HB_DB_TYPE_QUORUMREGIONS     2
+#define O2HB_DB_TYPE_FAILEDREGIONS     3
+#define O2HB_DB_TYPE_REGION_LIVENODES  4
+#define O2HB_DB_TYPE_REGION_NUMBER     5
+#define O2HB_DB_TYPE_REGION_ELAPSED_TIME       6
+struct o2hb_debug_buf {
+       int db_type;
+       int db_size;
+       int db_len;
+       void *db_data;
+};
+
+static struct o2hb_debug_buf *o2hb_db_livenodes;
+static struct o2hb_debug_buf *o2hb_db_liveregions;
+static struct o2hb_debug_buf *o2hb_db_quorumregions;
+static struct o2hb_debug_buf *o2hb_db_failedregions;
+
 #define O2HB_DEBUG_DIR                 "o2hb"
 #define O2HB_DEBUG_LIVENODES           "livenodes"
+#define O2HB_DEBUG_LIVEREGIONS         "live_regions"
+#define O2HB_DEBUG_QUORUMREGIONS       "quorum_regions"
+#define O2HB_DEBUG_FAILEDREGIONS       "failed_regions"
+#define O2HB_DEBUG_REGION_NUMBER       "num"
+#define O2HB_DEBUG_REGION_ELAPSED_TIME "elapsed_time_in_ms"
+
 static struct dentry *o2hb_debug_dir;
 static struct dentry *o2hb_debug_livenodes;
+static struct dentry *o2hb_debug_liveregions;
+static struct dentry *o2hb_debug_quorumregions;
+static struct dentry *o2hb_debug_failedregions;
 
 static LIST_HEAD(o2hb_all_regions);
 
@@ -77,7 +118,19 @@ static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type);
 
 #define O2HB_DEFAULT_BLOCK_BITS       9
 
+enum o2hb_heartbeat_modes {
+       O2HB_HEARTBEAT_LOCAL            = 0,
+       O2HB_HEARTBEAT_GLOBAL,
+       O2HB_HEARTBEAT_NUM_MODES,
+};
+
+char *o2hb_heartbeat_mode_desc[O2HB_HEARTBEAT_NUM_MODES] = {
+               "local",        /* O2HB_HEARTBEAT_LOCAL */
+               "global",       /* O2HB_HEARTBEAT_GLOBAL */
+};
+
 unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD;
+unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL;
 
 /* Only sets a new threshold if there are no active regions.
  *
@@ -94,6 +147,22 @@ static void o2hb_dead_threshold_set(unsigned int threshold)
        }
 }
 
+static int o2hb_global_hearbeat_mode_set(unsigned int hb_mode)
+{
+       int ret = -1;
+
+       if (hb_mode < O2HB_HEARTBEAT_NUM_MODES) {
+               spin_lock(&o2hb_live_lock);
+               if (list_empty(&o2hb_all_regions)) {
+                       o2hb_heartbeat_mode = hb_mode;
+                       ret = 0;
+               }
+               spin_unlock(&o2hb_live_lock);
+       }
+
+       return ret;
+}
+
 struct o2hb_node_event {
        struct list_head        hn_item;
        enum o2hb_callback_type hn_event_type;
@@ -135,6 +204,18 @@ struct o2hb_region {
        struct block_device     *hr_bdev;
        struct o2hb_disk_slot   *hr_slots;
 
+       /* live node map of this region */
+       unsigned long           hr_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned int            hr_region_num;
+
+       struct dentry           *hr_debug_dir;
+       struct dentry           *hr_debug_livenodes;
+       struct dentry           *hr_debug_regnum;
+       struct dentry           *hr_debug_elapsed_time;
+       struct o2hb_debug_buf   *hr_db_livenodes;
+       struct o2hb_debug_buf   *hr_db_regnum;
+       struct o2hb_debug_buf   *hr_db_elapsed_time;
+
        /* let the person setting up hb wait for it to return until it
         * has reached a 'steady' state.  This will be fixed when we have
         * a more complete api that doesn't lead to this sort of fragility. */
@@ -163,8 +244,19 @@ struct o2hb_bio_wait_ctxt {
        int               wc_error;
 };
 
+static int o2hb_pop_count(void *map, int count)
+{
+       int i = -1, pop = 0;
+
+       while ((i = find_next_bit(map, count, i + 1)) < count)
+               pop++;
+       return pop;
+}
+
 static void o2hb_write_timeout(struct work_struct *work)
 {
+       int failed, quorum;
+       unsigned long flags;
        struct o2hb_region *reg =
                container_of(work, struct o2hb_region,
                             hr_write_timeout_work.work);
@@ -172,6 +264,28 @@ static void o2hb_write_timeout(struct work_struct *work)
        mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u "
             "milliseconds\n", reg->hr_dev_name,
             jiffies_to_msecs(jiffies - reg->hr_last_timeout_start));
+
+       if (o2hb_global_heartbeat_active()) {
+               spin_lock_irqsave(&o2hb_live_lock, flags);
+               if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+                       set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
+               failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+                                       O2NM_MAX_REGIONS);
+               quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+                                       O2NM_MAX_REGIONS);
+               spin_unlock_irqrestore(&o2hb_live_lock, flags);
+
+               mlog(ML_HEARTBEAT, "Number of regions %d, failed regions %d\n",
+                    quorum, failed);
+
+               /*
+                * Fence if the number of failed regions >= half the number
+                * of  quorum regions
+                */
+               if ((failed << 1) < quorum)
+                       return;
+       }
+
        o2quo_disk_timeout();
 }
 
@@ -180,6 +294,11 @@ static void o2hb_arm_write_timeout(struct o2hb_region *reg)
        mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n",
             O2HB_MAX_WRITE_TIMEOUT_MS);
 
+       if (o2hb_global_heartbeat_active()) {
+               spin_lock(&o2hb_live_lock);
+               clear_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
+               spin_unlock(&o2hb_live_lock);
+       }
        cancel_delayed_work(&reg->hr_write_timeout_work);
        reg->hr_last_timeout_start = jiffies;
        schedule_delayed_work(&reg->hr_write_timeout_work,
@@ -513,6 +632,8 @@ static void o2hb_queue_node_event(struct o2hb_node_event *event,
 {
        assert_spin_locked(&o2hb_live_lock);
 
+       BUG_ON((!node) && (type != O2HB_NODE_DOWN_CB));
+
        event->hn_event_type = type;
        event->hn_node = node;
        event->hn_node_num = node_num;
@@ -554,6 +675,35 @@ static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot)
        o2nm_node_put(node);
 }
 
+static void o2hb_set_quorum_device(struct o2hb_region *reg,
+                                  struct o2hb_disk_slot *slot)
+{
+       assert_spin_locked(&o2hb_live_lock);
+
+       if (!o2hb_global_heartbeat_active())
+               return;
+
+       if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+               return;
+
+       /*
+        * A region can be added to the quorum only when it sees all
+        * live nodes heartbeat on it. In other words, the region has been
+        * added to all nodes.
+        */
+       if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap,
+                  sizeof(o2hb_live_node_bitmap)))
+               return;
+
+       if (slot->ds_changed_samples < O2HB_LIVE_THRESHOLD)
+               return;
+
+       printk(KERN_NOTICE "o2hb: Region %s is now a quorum device\n",
+              config_item_name(&reg->hr_item));
+
+       set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
+}
+
 static int o2hb_check_slot(struct o2hb_region *reg,
                           struct o2hb_disk_slot *slot)
 {
@@ -565,14 +715,22 @@ static int o2hb_check_slot(struct o2hb_region *reg,
        u64 cputime;
        unsigned int dead_ms = o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS;
        unsigned int slot_dead_ms;
+       int tmp;
 
        memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes);
 
-       /* Is this correct? Do we assume that the node doesn't exist
-        * if we're not configured for him? */
+       /*
+        * If a node is no longer configured but is still in the livemap, we
+        * may need to clear that bit from the livemap.
+        */
        node = o2nm_get_node_by_num(slot->ds_node_num);
-       if (!node)
-               return 0;
+       if (!node) {
+               spin_lock(&o2hb_live_lock);
+               tmp = test_bit(slot->ds_node_num, o2hb_live_node_bitmap);
+               spin_unlock(&o2hb_live_lock);
+               if (!tmp)
+                       return 0;
+       }
 
        if (!o2hb_verify_crc(reg, hb_block)) {
                /* all paths from here will drop o2hb_live_lock for
@@ -639,8 +797,12 @@ fire_callbacks:
                mlog(ML_HEARTBEAT, "Node %d (id 0x%llx) joined my region\n",
                     slot->ds_node_num, (long long)slot->ds_last_generation);
 
+               set_bit(slot->ds_node_num, reg->hr_live_node_bitmap);
+
                /* first on the list generates a callback */
                if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+                       mlog(ML_HEARTBEAT, "o2hb: Add node %d to live nodes "
+                            "bitmap\n", slot->ds_node_num);
                        set_bit(slot->ds_node_num, o2hb_live_node_bitmap);
 
                        o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node,
@@ -684,13 +846,18 @@ fire_callbacks:
                mlog(ML_HEARTBEAT, "Node %d left my region\n",
                     slot->ds_node_num);
 
+               clear_bit(slot->ds_node_num, reg->hr_live_node_bitmap);
+
                /* last off the live_slot generates a callback */
                list_del_init(&slot->ds_live_item);
                if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+                       mlog(ML_HEARTBEAT, "o2hb: Remove node %d from live "
+                            "nodes bitmap\n", slot->ds_node_num);
                        clear_bit(slot->ds_node_num, o2hb_live_node_bitmap);
 
-                       o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node,
-                                             slot->ds_node_num);
+                       /* node can be null */
+                       o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB,
+                                             node, slot->ds_node_num);
 
                        changed = 1;
                }
@@ -706,11 +873,14 @@ fire_callbacks:
                slot->ds_equal_samples = 0;
        }
 out:
+       o2hb_set_quorum_device(reg, slot);
+
        spin_unlock(&o2hb_live_lock);
 
        o2hb_run_event_list(&event);
 
-       o2nm_node_put(node);
+       if (node)
+               o2nm_node_put(node);
        return changed;
 }
 
@@ -737,6 +907,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 {
        int i, ret, highest_node, change = 0;
        unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
        struct o2hb_bio_wait_ctxt write_wc;
 
        ret = o2nm_configured_node_map(configured_nodes,
@@ -746,6 +917,17 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
                return ret;
        }
 
+       /*
+        * If a node is not configured but is in the livemap, we still need
+        * to read the slot so as to be able to remove it from the livemap.
+        */
+       o2hb_fill_node_map(live_node_bitmap, sizeof(live_node_bitmap));
+       i = -1;
+       while ((i = find_next_bit(live_node_bitmap,
+                                 O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
+               set_bit(i, configured_nodes);
+       }
+
        highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
        if (highest_node >= O2NM_MAX_NODES) {
                mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
@@ -917,21 +1099,59 @@ static int o2hb_thread(void *data)
 #ifdef CONFIG_DEBUG_FS
 static int o2hb_debug_open(struct inode *inode, struct file *file)
 {
+       struct o2hb_debug_buf *db = inode->i_private;
+       struct o2hb_region *reg;
        unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
        char *buf = NULL;
        int i = -1;
        int out = 0;
 
+       /* max_nodes should be the largest bitmap we pass here */
+       BUG_ON(sizeof(map) < db->db_size);
+
        buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
        if (!buf)
                goto bail;
 
-       o2hb_fill_node_map(map, sizeof(map));
+       switch (db->db_type) {
+       case O2HB_DB_TYPE_LIVENODES:
+       case O2HB_DB_TYPE_LIVEREGIONS:
+       case O2HB_DB_TYPE_QUORUMREGIONS:
+       case O2HB_DB_TYPE_FAILEDREGIONS:
+               spin_lock(&o2hb_live_lock);
+               memcpy(map, db->db_data, db->db_size);
+               spin_unlock(&o2hb_live_lock);
+               break;
+
+       case O2HB_DB_TYPE_REGION_LIVENODES:
+               spin_lock(&o2hb_live_lock);
+               reg = (struct o2hb_region *)db->db_data;
+               memcpy(map, reg->hr_live_node_bitmap, db->db_size);
+               spin_unlock(&o2hb_live_lock);
+               break;
+
+       case O2HB_DB_TYPE_REGION_NUMBER:
+               reg = (struct o2hb_region *)db->db_data;
+               out += snprintf(buf + out, PAGE_SIZE - out, "%d\n",
+                               reg->hr_region_num);
+               goto done;
+
+       case O2HB_DB_TYPE_REGION_ELAPSED_TIME:
+               reg = (struct o2hb_region *)db->db_data;
+               out += snprintf(buf + out, PAGE_SIZE - out, "%u\n",
+                               jiffies_to_msecs(jiffies -
+                                                reg->hr_last_timeout_start));
+               goto done;
+
+       default:
+               goto done;
+       }
 
-       while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
+       while ((i = find_next_bit(map, db->db_len, i + 1)) < db->db_len)
                out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i);
        out += snprintf(buf + out, PAGE_SIZE - out, "\n");
 
+done:
        i_size_write(inode, out);
 
        file->private_data = buf;
@@ -978,10 +1198,104 @@ static const struct file_operations o2hb_debug_fops = {
 
 void o2hb_exit(void)
 {
-       if (o2hb_debug_livenodes)
-               debugfs_remove(o2hb_debug_livenodes);
-       if (o2hb_debug_dir)
-               debugfs_remove(o2hb_debug_dir);
+       kfree(o2hb_db_livenodes);
+       kfree(o2hb_db_liveregions);
+       kfree(o2hb_db_quorumregions);
+       kfree(o2hb_db_failedregions);
+       debugfs_remove(o2hb_debug_failedregions);
+       debugfs_remove(o2hb_debug_quorumregions);
+       debugfs_remove(o2hb_debug_liveregions);
+       debugfs_remove(o2hb_debug_livenodes);
+       debugfs_remove(o2hb_debug_dir);
+}
+
+static struct dentry *o2hb_debug_create(const char *name, struct dentry *dir,
+                                       struct o2hb_debug_buf **db, int db_len,
+                                       int type, int size, int len, void *data)
+{
+       *db = kmalloc(db_len, GFP_KERNEL);
+       if (!*db)
+               return NULL;
+
+       (*db)->db_type = type;
+       (*db)->db_size = size;
+       (*db)->db_len = len;
+       (*db)->db_data = data;
+
+       return debugfs_create_file(name, S_IFREG|S_IRUSR, dir, *db,
+                                  &o2hb_debug_fops);
+}
+
+static int o2hb_debug_init(void)
+{
+       int ret = -ENOMEM;
+
+       o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
+       if (!o2hb_debug_dir) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       o2hb_debug_livenodes = o2hb_debug_create(O2HB_DEBUG_LIVENODES,
+                                                o2hb_debug_dir,
+                                                &o2hb_db_livenodes,
+                                                sizeof(*o2hb_db_livenodes),
+                                                O2HB_DB_TYPE_LIVENODES,
+                                                sizeof(o2hb_live_node_bitmap),
+                                                O2NM_MAX_NODES,
+                                                o2hb_live_node_bitmap);
+       if (!o2hb_debug_livenodes) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       o2hb_debug_liveregions = o2hb_debug_create(O2HB_DEBUG_LIVEREGIONS,
+                                                  o2hb_debug_dir,
+                                                  &o2hb_db_liveregions,
+                                                  sizeof(*o2hb_db_liveregions),
+                                                  O2HB_DB_TYPE_LIVEREGIONS,
+                                                  sizeof(o2hb_live_region_bitmap),
+                                                  O2NM_MAX_REGIONS,
+                                                  o2hb_live_region_bitmap);
+       if (!o2hb_debug_liveregions) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       o2hb_debug_quorumregions =
+                       o2hb_debug_create(O2HB_DEBUG_QUORUMREGIONS,
+                                         o2hb_debug_dir,
+                                         &o2hb_db_quorumregions,
+                                         sizeof(*o2hb_db_quorumregions),
+                                         O2HB_DB_TYPE_QUORUMREGIONS,
+                                         sizeof(o2hb_quorum_region_bitmap),
+                                         O2NM_MAX_REGIONS,
+                                         o2hb_quorum_region_bitmap);
+       if (!o2hb_debug_quorumregions) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       o2hb_debug_failedregions =
+                       o2hb_debug_create(O2HB_DEBUG_FAILEDREGIONS,
+                                         o2hb_debug_dir,
+                                         &o2hb_db_failedregions,
+                                         sizeof(*o2hb_db_failedregions),
+                                         O2HB_DB_TYPE_FAILEDREGIONS,
+                                         sizeof(o2hb_failed_region_bitmap),
+                                         O2NM_MAX_REGIONS,
+                                         o2hb_failed_region_bitmap);
+       if (!o2hb_debug_failedregions) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       ret = 0;
+bail:
+       if (ret)
+               o2hb_exit();
+
+       return ret;
 }
 
 int o2hb_init(void)
@@ -997,24 +1311,12 @@ int o2hb_init(void)
        INIT_LIST_HEAD(&o2hb_node_events);
 
        memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap));
+       memset(o2hb_region_bitmap, 0, sizeof(o2hb_region_bitmap));
+       memset(o2hb_live_region_bitmap, 0, sizeof(o2hb_live_region_bitmap));
+       memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap));
+       memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap));
 
-       o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
-       if (!o2hb_debug_dir) {
-               mlog_errno(-ENOMEM);
-               return -ENOMEM;
-       }
-
-       o2hb_debug_livenodes = debugfs_create_file(O2HB_DEBUG_LIVENODES,
-                                                  S_IFREG|S_IRUSR,
-                                                  o2hb_debug_dir, NULL,
-                                                  &o2hb_debug_fops);
-       if (!o2hb_debug_livenodes) {
-               mlog_errno(-ENOMEM);
-               debugfs_remove(o2hb_debug_dir);
-               return -ENOMEM;
-       }
-
-       return 0;
+       return o2hb_debug_init();
 }
 
 /* if we're already in a callback then we're already serialized by the sem */
@@ -1078,6 +1380,13 @@ static void o2hb_region_release(struct config_item *item)
        if (reg->hr_slots)
                kfree(reg->hr_slots);
 
+       kfree(reg->hr_db_regnum);
+       kfree(reg->hr_db_livenodes);
+       debugfs_remove(reg->hr_debug_livenodes);
+       debugfs_remove(reg->hr_debug_regnum);
+       debugfs_remove(reg->hr_debug_elapsed_time);
+       debugfs_remove(reg->hr_debug_dir);
+
        spin_lock(&o2hb_live_lock);
        list_del(&reg->hr_all_item);
        spin_unlock(&o2hb_live_lock);
@@ -1441,6 +1750,8 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        /* Ok, we were woken.  Make sure it wasn't by drop_item() */
        spin_lock(&o2hb_live_lock);
        hb_task = reg->hr_task;
+       if (o2hb_global_heartbeat_active())
+               set_bit(reg->hr_region_num, o2hb_live_region_bitmap);
        spin_unlock(&o2hb_live_lock);
 
        if (hb_task)
@@ -1448,6 +1759,10 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        else
                ret = -EIO;
 
+       if (hb_task && o2hb_global_heartbeat_active())
+               printk(KERN_NOTICE "o2hb: Heartbeat started on region %s\n",
+                      config_item_name(&reg->hr_item));
+
 out:
        if (filp)
                fput(filp);
@@ -1586,21 +1901,94 @@ static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group
                : NULL;
 }
 
+static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+{
+       int ret = -ENOMEM;
+
+       reg->hr_debug_dir =
+               debugfs_create_dir(config_item_name(&reg->hr_item), dir);
+       if (!reg->hr_debug_dir) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       reg->hr_debug_livenodes =
+                       o2hb_debug_create(O2HB_DEBUG_LIVENODES,
+                                         reg->hr_debug_dir,
+                                         &(reg->hr_db_livenodes),
+                                         sizeof(*(reg->hr_db_livenodes)),
+                                         O2HB_DB_TYPE_REGION_LIVENODES,
+                                         sizeof(reg->hr_live_node_bitmap),
+                                         O2NM_MAX_NODES, reg);
+       if (!reg->hr_debug_livenodes) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       reg->hr_debug_regnum =
+                       o2hb_debug_create(O2HB_DEBUG_REGION_NUMBER,
+                                         reg->hr_debug_dir,
+                                         &(reg->hr_db_regnum),
+                                         sizeof(*(reg->hr_db_regnum)),
+                                         O2HB_DB_TYPE_REGION_NUMBER,
+                                         0, O2NM_MAX_NODES, reg);
+       if (!reg->hr_debug_regnum) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       reg->hr_debug_elapsed_time =
+                       o2hb_debug_create(O2HB_DEBUG_REGION_ELAPSED_TIME,
+                                         reg->hr_debug_dir,
+                                         &(reg->hr_db_elapsed_time),
+                                         sizeof(*(reg->hr_db_elapsed_time)),
+                                         O2HB_DB_TYPE_REGION_ELAPSED_TIME,
+                                         0, 0, reg);
+       if (!reg->hr_debug_elapsed_time) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       ret = 0;
+bail:
+       return ret;
+}
+
 static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group,
                                                          const char *name)
 {
        struct o2hb_region *reg = NULL;
+       int ret;
 
        reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
        if (reg == NULL)
                return ERR_PTR(-ENOMEM);
 
-       config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
+       if (strlen(name) > O2HB_MAX_REGION_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
 
        spin_lock(&o2hb_live_lock);
+       reg->hr_region_num = 0;
+       if (o2hb_global_heartbeat_active()) {
+               reg->hr_region_num = find_first_zero_bit(o2hb_region_bitmap,
+                                                        O2NM_MAX_REGIONS);
+               if (reg->hr_region_num >= O2NM_MAX_REGIONS) {
+                       spin_unlock(&o2hb_live_lock);
+                       return ERR_PTR(-EFBIG);
+               }
+               set_bit(reg->hr_region_num, o2hb_region_bitmap);
+       }
        list_add_tail(&reg->hr_all_item, &o2hb_all_regions);
        spin_unlock(&o2hb_live_lock);
 
+       config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
+
+       ret = o2hb_debug_region_init(reg, o2hb_debug_dir);
+       if (ret) {
+               config_item_put(&reg->hr_item);
+               return ERR_PTR(ret);
+       }
+
        return &reg->hr_item;
 }
 
@@ -1612,6 +2000,10 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 
        /* stop the thread when the user removes the region dir */
        spin_lock(&o2hb_live_lock);
+       if (o2hb_global_heartbeat_active()) {
+               clear_bit(reg->hr_region_num, o2hb_region_bitmap);
+               clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
+       }
        hb_task = reg->hr_task;
        reg->hr_task = NULL;
        spin_unlock(&o2hb_live_lock);
@@ -1628,6 +2020,9 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
                wake_up(&o2hb_steady_queue);
        }
 
+       if (o2hb_global_heartbeat_active())
+               printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n",
+                      config_item_name(&reg->hr_item));
        config_item_put(item);
 }
 
@@ -1688,6 +2083,41 @@ static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group
        return count;
 }
 
+static
+ssize_t o2hb_heartbeat_group_mode_show(struct o2hb_heartbeat_group *group,
+                                      char *page)
+{
+       return sprintf(page, "%s\n",
+                      o2hb_heartbeat_mode_desc[o2hb_heartbeat_mode]);
+}
+
+static
+ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
+                                       const char *page, size_t count)
+{
+       unsigned int i;
+       int ret;
+       size_t len;
+
+       len = (page[count - 1] == '\n') ? count - 1 : count;
+       if (!len)
+               return -EINVAL;
+
+       for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) {
+               if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len))
+                       continue;
+
+               ret = o2hb_global_hearbeat_mode_set(i);
+               if (!ret)
+                       printk(KERN_NOTICE "o2hb: Heartbeat mode set to %s\n",
+                              o2hb_heartbeat_mode_desc[i]);
+               return count;
+       }
+
+       return -EINVAL;
+
+}
+
 static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = {
        .attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "dead_threshold",
@@ -1696,8 +2126,17 @@ static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold
        .store  = o2hb_heartbeat_group_threshold_store,
 };
 
+static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_mode = {
+       .attr   = { .ca_owner = THIS_MODULE,
+               .ca_name = "mode",
+               .ca_mode = S_IRUGO | S_IWUSR },
+       .show   = o2hb_heartbeat_group_mode_show,
+       .store  = o2hb_heartbeat_group_mode_store,
+};
+
 static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
        &o2hb_heartbeat_group_attr_threshold.attr,
+       &o2hb_heartbeat_group_attr_mode.attr,
        NULL,
 };
 
@@ -1963,3 +2402,34 @@ void o2hb_stop_all_regions(void)
        spin_unlock(&o2hb_live_lock);
 }
 EXPORT_SYMBOL_GPL(o2hb_stop_all_regions);
+
+int o2hb_get_all_regions(char *region_uuids, u8 max_regions)
+{
+       struct o2hb_region *reg;
+       int numregs = 0;
+       char *p;
+
+       spin_lock(&o2hb_live_lock);
+
+       p = region_uuids;
+       list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) {
+               mlog(0, "Region: %s\n", config_item_name(&reg->hr_item));
+               if (numregs < max_regions) {
+                       memcpy(p, config_item_name(&reg->hr_item),
+                              O2HB_MAX_REGION_NAME_LEN);
+                       p += O2HB_MAX_REGION_NAME_LEN;
+               }
+               numregs++;
+       }
+
+       spin_unlock(&o2hb_live_lock);
+
+       return numregs;
+}
+EXPORT_SYMBOL_GPL(o2hb_get_all_regions);
+
+int o2hb_global_heartbeat_active(void)
+{
+       return (o2hb_heartbeat_mode == O2HB_HEARTBEAT_GLOBAL);
+}
+EXPORT_SYMBOL(o2hb_global_heartbeat_active);
index 2f1649253b497bed42fc14ef87685e59377dc2be..00ad8e8fea510ede2cf33d48eecf9178d65a9605 100644 (file)
@@ -31,6 +31,8 @@
 
 #define O2HB_REGION_TIMEOUT_MS         2000
 
+#define O2HB_MAX_REGION_NAME_LEN       32
+
 /* number of changes to be seen as live */
 #define O2HB_LIVE_THRESHOLD       2
 /* number of equal samples to be seen as dead */
@@ -81,5 +83,7 @@ int o2hb_check_node_heartbeating(u8 node_num);
 int o2hb_check_node_heartbeating_from_callback(u8 node_num);
 int o2hb_check_local_node_heartbeating(void);
 void o2hb_stop_all_regions(void);
+int o2hb_get_all_regions(char *region_uuids, u8 numregions);
+int o2hb_global_heartbeat_active(void);
 
 #endif /* O2CLUSTER_HEARTBEAT_H */
index fd96e2a2fa56556018d5ebc56ba0bc1a610f7e1e..ea2ed9f56c94ad0654a5f79259e50a1f046bed97 100644 (file)
 #define ML_ERROR       0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE      0x0000000200000000ULL /* setn to KERN_NOTICE */
 #define ML_KTHREAD     0x0000000400000000ULL /* kernel thread activity */
-#define        ML_RESERVATIONS 0x0000000800000000ULL /* ocfs2 alloc reservations */
+#define ML_RESERVATIONS        0x0000000800000000ULL /* ocfs2 alloc reservations */
+#define ML_CLUSTER     0x0000001000000000ULL /* cluster stack */
 
 #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
 #define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
index ed0c9f367fed03fe0114b6956b6bb4a34ade5b77..bb240647ca5f5e0f47f52c43860ae7d1c3be435a 100644 (file)
@@ -711,6 +711,8 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group,
        config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
        spin_lock_init(&node->nd_lock);
 
+       mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name);
+
        return &node->nd_item;
 }
 
@@ -744,6 +746,9 @@ static void o2nm_node_group_drop_item(struct config_group *group,
        }
        write_unlock(&cluster->cl_nodes_lock);
 
+       mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n",
+            config_item_name(&node->nd_item));
+
        config_item_put(item);
 }
 
index 5b9854bad571c26d561ea2969d69f7693f759c5a..49b594325bec50c958d9f82a93d3deae3448fb01 100644 (file)
 /* host name, group name, cluster name all 64 bytes */
 #define O2NM_MAX_NAME_LEN        64    // __NEW_UTS_LEN
 
+/*
+ * Maximum number of global heartbeat regions allowed.
+ * **CAUTION**  Changing this number will break dlm compatibility.
+ */
+#define O2NM_MAX_REGIONS       32
+
 #endif /* _OCFS2_NODEMANAGER_H */
index 1361997cf205d132a04ddeb87760aa233c3e707d..9aa426e4212330994255aaa25c85a9f60ec3874b 100644 (file)
@@ -977,7 +977,7 @@ static int o2net_tx_can_proceed(struct o2net_node *nn,
 int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
                           size_t caller_veclen, u8 target_node, int *status)
 {
-       int ret;
+       int ret = 0;
        struct o2net_msg *msg = NULL;
        size_t veclen, caller_bytes = 0;
        struct kvec *vec = NULL;
@@ -1696,6 +1696,9 @@ static void o2net_hb_node_down_cb(struct o2nm_node *node, int node_num,
 {
        o2quo_hb_down(node_num);
 
+       if (!node)
+               return;
+
        if (node_num != o2nm_this_node())
                o2net_disconnect_node(node);
 
@@ -1709,6 +1712,8 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
 
        o2quo_hb_up(node_num);
 
+       BUG_ON(!node);
+
        /* ensure an immediate connect attempt */
        nn->nn_last_connect_attempt = jiffies -
                (msecs_to_jiffies(o2net_reconnect_delay()) + 1);
index b4957c7d9fe2262a203a3efb3573eda9ed3d2638..edaded48e7e9f083ac7c67e72a9f031123f7844a 100644 (file)
 #include "inode.h"
 #include "super.h"
 
+void ocfs2_dentry_attach_gen(struct dentry *dentry)
+{
+       unsigned long gen =
+               OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+       BUG_ON(dentry->d_inode);
+       dentry->d_fsdata = (void *)gen;
+}
+
 
 static int ocfs2_dentry_revalidate(struct dentry *dentry,
                                   struct nameidata *nd)
@@ -51,11 +59,20 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
        mlog_entry("(0x%p, '%.*s')\n", dentry,
                   dentry->d_name.len, dentry->d_name.name);
 
-       /* Never trust a negative dentry - force a new lookup. */
+       /* For a negative dentry -
+        * check the generation number of the parent and compare with the
+        * one stored in the inode.
+        */
        if (inode == NULL) {
-               mlog(0, "negative dentry: %.*s\n", dentry->d_name.len,
-                    dentry->d_name.name);
-               goto bail;
+               unsigned long gen = (unsigned long) dentry->d_fsdata;
+               unsigned long pgen =
+                       OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+               mlog(0, "negative dentry: %.*s parent gen: %lu "
+                       "dentry gen: %lu\n",
+                       dentry->d_name.len, dentry->d_name.name, pgen, gen);
+               if (gen != pgen)
+                       goto bail;
+               goto valid;
        }
 
        BUG_ON(!osb);
@@ -96,6 +113,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
                goto bail;
        }
 
+valid:
        ret = 1;
 
 bail:
@@ -227,6 +245,12 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
        if (!inode)
                return 0;
 
+       if (!dentry->d_inode && dentry->d_fsdata) {
+               /* Converting a negative dentry to positive
+                  Clear dentry->d_fsdata */
+               dentry->d_fsdata = dl = NULL;
+       }
+
        if (dl) {
                mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
                                " \"%.*s\": old parent: %llu, new: %llu\n",
@@ -452,6 +476,7 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode)
 
 out:
        iput(inode);
+       ocfs2_dentry_attach_gen(dentry);
 }
 
 /*
index f5dd1789acf1b4527373217ce7c6b0374695eb17..b79eff709958f806ce92f937cbfd7730e4d36a29 100644 (file)
@@ -64,5 +64,6 @@ void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target,
                       struct inode *old_dir, struct inode *new_dir);
 
 extern spinlock_t dentry_attach_lock;
+void ocfs2_dentry_attach_gen(struct dentry *dentry);
 
 #endif /* OCFS2_DCACHE_H */
index f04ebcfffc4a5e1516c2a7307ffa8032db8e19d7..c49f6de0e7abb6e096ddc56e795957e0194bb8dd 100644 (file)
@@ -3931,6 +3931,15 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
                goto out_commit;
        }
 
+       cpos = split_hash;
+       ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
+                                      data_ac, meta_ac, new_dx_leaves,
+                                      num_dx_leaves);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
        for (i = 0; i < num_dx_leaves; i++) {
                ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
                                              orig_dx_leaves[i],
@@ -3939,15 +3948,14 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
                        mlog_errno(ret);
                        goto out_commit;
                }
-       }
 
-       cpos = split_hash;
-       ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
-                                      data_ac, meta_ac, new_dx_leaves,
-                                      num_dx_leaves);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
+               ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
+                                             new_dx_leaves[i],
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
        }
 
        ocfs2_dx_dir_transfer_leaf(dir, split_hash, handle, tmp_dx_leaf,
index 4b6ae2c13b47a85c6a31f6f7d2a1072099354935..b36d0bf77a5a4ca5fa1de836dca82037d4f0c491 100644 (file)
@@ -445,7 +445,9 @@ enum {
        DLM_LOCK_REQUEST_MSG,    /* 515 */
        DLM_RECO_DATA_DONE_MSG,  /* 516 */
        DLM_BEGIN_RECO_MSG,      /* 517 */
-       DLM_FINALIZE_RECO_MSG    /* 518 */
+       DLM_FINALIZE_RECO_MSG,   /* 518 */
+       DLM_QUERY_REGION,        /* 519 */
+       DLM_QUERY_NODEINFO,      /* 520 */
 };
 
 struct dlm_reco_node_data
@@ -727,6 +729,31 @@ struct dlm_cancel_join
        u8 domain[O2NM_MAX_NAME_LEN];
 };
 
+struct dlm_query_region {
+       u8 qr_node;
+       u8 qr_numregions;
+       u8 qr_namelen;
+       u8 pad1;
+       u8 qr_domain[O2NM_MAX_NAME_LEN];
+       u8 qr_regions[O2HB_MAX_REGION_NAME_LEN * O2NM_MAX_REGIONS];
+};
+
+struct dlm_node_info {
+       u8 ni_nodenum;
+       u8 pad1;
+       u16 ni_ipv4_port;
+       u32 ni_ipv4_address;
+};
+
+struct dlm_query_nodeinfo {
+       u8 qn_nodenum;
+       u8 qn_numnodes;
+       u8 qn_namelen;
+       u8 pad1;
+       u8 qn_domain[O2NM_MAX_NAME_LEN];
+       struct dlm_node_info qn_nodes[O2NM_MAX_NODES];
+};
+
 struct dlm_exit_domain
 {
        u8 node_idx;
@@ -1030,6 +1057,7 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm,
                         struct dlm_lock_resource *res);
 void dlm_clean_master_list(struct dlm_ctxt *dlm,
                           u8 dead_node);
+void dlm_force_free_mles(struct dlm_ctxt *dlm);
 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock);
 int __dlm_lockres_has_locks(struct dlm_lock_resource *res);
 int __dlm_lockres_unused(struct dlm_lock_resource *res);
index 5efdd37dfe484f2f6207ac2c7c6927fda0cc1ea0..272ec8631a514fdb9ae45d5ef07390e18da07ac4 100644 (file)
@@ -493,7 +493,7 @@ static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
        struct hlist_head *bucket;
        struct hlist_node *list;
        int i, out = 0;
-       unsigned long total = 0, longest = 0, bktcnt;
+       unsigned long total = 0, longest = 0, bucket_count = 0;
 
        out += snprintf(db->buf + out, db->len - out,
                        "Dumping MLEs for Domain: %s\n", dlm->name);
@@ -505,13 +505,13 @@ static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
                        mle = hlist_entry(list, struct dlm_master_list_entry,
                                          master_hash_node);
                        ++total;
-                       ++bktcnt;
+                       ++bucket_count;
                        if (db->len - out < 200)
                                continue;
                        out += dump_mle(mle, db->buf + out, db->len - out);
                }
-               longest = max(longest, bktcnt);
-               bktcnt = 0;
+               longest = max(longest, bucket_count);
+               bucket_count = 0;
        }
        spin_unlock(&dlm->master_lock);
 
@@ -636,8 +636,14 @@ static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
        spin_lock(&dlm->track_lock);
        if (oldres)
                track_list = &oldres->tracking;
-       else
+       else {
                track_list = &dlm->tracking_list;
+               if (list_empty(track_list)) {
+                       dl = NULL;
+                       spin_unlock(&dlm->track_lock);
+                       goto bail;
+               }
+       }
 
        list_for_each_entry(res, track_list, tracking) {
                if (&res->tracking == &dlm->tracking_list)
@@ -660,6 +666,7 @@ static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
        } else
                dl = NULL;
 
+bail:
        /* passed to seq_show */
        return dl;
 }
@@ -775,7 +782,9 @@ static int debug_state_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
 
        /* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
        out += snprintf(db->buf + out, db->len - out,
-                       "Domain: %s  Key: 0x%08x\n", dlm->name, dlm->key);
+                       "Domain: %s  Key: 0x%08x  Protocol: %d.%d\n",
+                       dlm->name, dlm->key, dlm->dlm_locking_proto.pv_major,
+                       dlm->dlm_locking_proto.pv_minor);
 
        /* Thread Pid: xxx  Node: xxx  State: xxxxx */
        out += snprintf(db->buf + out, db->len - out,
index 153abb5abef024d2ca63f6d4a23ee1c126b89f13..58a93b953735ebcaeda134794195449da4e98a53 100644 (file)
@@ -128,10 +128,14 @@ static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
  * will have a negotiated version with the same major number and a minor
  * number equal or smaller.  The dlm_ctxt->dlm_locking_proto field should
  * be used to determine what a running domain is actually using.
+ *
+ * New in version 1.1:
+ *     - Message DLM_QUERY_REGION added to support global heartbeat
+ *     - Message DLM_QUERY_NODEINFO added to allow online node removes
  */
 static const struct dlm_protocol_version dlm_protocol = {
        .pv_major = 1,
-       .pv_minor = 0,
+       .pv_minor = 1,
 };
 
 #define DLM_DOMAIN_BACKOFF_MS 200
@@ -142,6 +146,8 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
                                     void **ret_data);
 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
                                   void **ret_data);
+static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
+                                   void *data, void **ret_data);
 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
                                   void **ret_data);
 static int dlm_protocol_compare(struct dlm_protocol_version *existing,
@@ -693,6 +699,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
 
                dlm_mark_domain_leaving(dlm);
                dlm_leave_domain(dlm);
+               dlm_force_free_mles(dlm);
                dlm_complete_dlm_shutdown(dlm);
        }
        dlm_put(dlm);
@@ -920,6 +927,370 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
        return 0;
 }
 
+static int dlm_match_regions(struct dlm_ctxt *dlm,
+                            struct dlm_query_region *qr)
+{
+       char *local = NULL, *remote = qr->qr_regions;
+       char *l, *r;
+       int localnr, i, j, foundit;
+       int status = 0;
+
+       if (!o2hb_global_heartbeat_active()) {
+               if (qr->qr_numregions) {
+                       mlog(ML_ERROR, "Domain %s: Joining node %d has global "
+                            "heartbeat enabled but local node %d does not\n",
+                            qr->qr_domain, qr->qr_node, dlm->node_num);
+                       status = -EINVAL;
+               }
+               goto bail;
+       }
+
+       if (o2hb_global_heartbeat_active() && !qr->qr_numregions) {
+               mlog(ML_ERROR, "Domain %s: Local node %d has global "
+                    "heartbeat enabled but joining node %d does not\n",
+                    qr->qr_domain, dlm->node_num, qr->qr_node);
+               status = -EINVAL;
+               goto bail;
+       }
+
+       r = remote;
+       for (i = 0; i < qr->qr_numregions; ++i) {
+               mlog(0, "Region %.*s\n", O2HB_MAX_REGION_NAME_LEN, r);
+               r += O2HB_MAX_REGION_NAME_LEN;
+       }
+
+       local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL);
+       if (!local) {
+               status = -ENOMEM;
+               goto bail;
+       }
+
+       localnr = o2hb_get_all_regions(local, O2NM_MAX_REGIONS);
+
+       /* compare local regions with remote */
+       l = local;
+       for (i = 0; i < localnr; ++i) {
+               foundit = 0;
+               r = remote;
+               for (j = 0; j <= qr->qr_numregions; ++j) {
+                       if (!memcmp(l, r, O2HB_MAX_REGION_NAME_LEN)) {
+                               foundit = 1;
+                               break;
+                       }
+                       r += O2HB_MAX_REGION_NAME_LEN;
+               }
+               if (!foundit) {
+                       status = -EINVAL;
+                       mlog(ML_ERROR, "Domain %s: Region '%.*s' registered "
+                            "in local node %d but not in joining node %d\n",
+                            qr->qr_domain, O2HB_MAX_REGION_NAME_LEN, l,
+                            dlm->node_num, qr->qr_node);
+                       goto bail;
+               }
+               l += O2HB_MAX_REGION_NAME_LEN;
+       }
+
+       /* compare remote with local regions */
+       r = remote;
+       for (i = 0; i < qr->qr_numregions; ++i) {
+               foundit = 0;
+               l = local;
+               for (j = 0; j < localnr; ++j) {
+                       if (!memcmp(r, l, O2HB_MAX_REGION_NAME_LEN)) {
+                               foundit = 1;
+                               break;
+                       }
+                       l += O2HB_MAX_REGION_NAME_LEN;
+               }
+               if (!foundit) {
+                       status = -EINVAL;
+                       mlog(ML_ERROR, "Domain %s: Region '%.*s' registered "
+                            "in joining node %d but not in local node %d\n",
+                            qr->qr_domain, O2HB_MAX_REGION_NAME_LEN, r,
+                            qr->qr_node, dlm->node_num);
+                       goto bail;
+               }
+               r += O2HB_MAX_REGION_NAME_LEN;
+       }
+
+bail:
+       kfree(local);
+
+       return status;
+}
+
+static int dlm_send_regions(struct dlm_ctxt *dlm, unsigned long *node_map)
+{
+       struct dlm_query_region *qr = NULL;
+       int status, ret = 0, i;
+       char *p;
+
+       if (find_next_bit(node_map, O2NM_MAX_NODES, 0) >= O2NM_MAX_NODES)
+               goto bail;
+
+       qr = kzalloc(sizeof(struct dlm_query_region), GFP_KERNEL);
+       if (!qr) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       qr->qr_node = dlm->node_num;
+       qr->qr_namelen = strlen(dlm->name);
+       memcpy(qr->qr_domain, dlm->name, qr->qr_namelen);
+       /* if local hb, the numregions will be zero */
+       if (o2hb_global_heartbeat_active())
+               qr->qr_numregions = o2hb_get_all_regions(qr->qr_regions,
+                                                        O2NM_MAX_REGIONS);
+
+       p = qr->qr_regions;
+       for (i = 0; i < qr->qr_numregions; ++i, p += O2HB_MAX_REGION_NAME_LEN)
+               mlog(0, "Region %.*s\n", O2HB_MAX_REGION_NAME_LEN, p);
+
+       i = -1;
+       while ((i = find_next_bit(node_map, O2NM_MAX_NODES,
+                                 i + 1)) < O2NM_MAX_NODES) {
+               if (i == dlm->node_num)
+                       continue;
+
+               mlog(0, "Sending regions to node %d\n", i);
+
+               ret = o2net_send_message(DLM_QUERY_REGION, DLM_MOD_KEY, qr,
+                                        sizeof(struct dlm_query_region),
+                                        i, &status);
+               if (ret >= 0)
+                       ret = status;
+               if (ret) {
+                       mlog(ML_ERROR, "Region mismatch %d, node %d\n",
+                            ret, i);
+                       break;
+               }
+       }
+
+bail:
+       kfree(qr);
+       return ret;
+}
+
+static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
+                                   void *data, void **ret_data)
+{
+       struct dlm_query_region *qr;
+       struct dlm_ctxt *dlm = NULL;
+       int status = 0;
+       int locked = 0;
+
+       qr = (struct dlm_query_region *) msg->buf;
+
+       mlog(0, "Node %u queries hb regions on domain %s\n", qr->qr_node,
+            qr->qr_domain);
+
+       status = -EINVAL;
+
+       spin_lock(&dlm_domain_lock);
+       dlm = __dlm_lookup_domain_full(qr->qr_domain, qr->qr_namelen);
+       if (!dlm) {
+               mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+                    "before join domain\n", qr->qr_node, qr->qr_domain);
+               goto bail;
+       }
+
+       spin_lock(&dlm->spinlock);
+       locked = 1;
+       if (dlm->joining_node != qr->qr_node) {
+               mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+                    "but joining node is %d\n", qr->qr_node, qr->qr_domain,
+                    dlm->joining_node);
+               goto bail;
+       }
+
+       /* Support for global heartbeat was added in 1.1 */
+       if (dlm->dlm_locking_proto.pv_major == 1 &&
+           dlm->dlm_locking_proto.pv_minor == 0) {
+               mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+                    "but active dlm protocol is %d.%d\n", qr->qr_node,
+                    qr->qr_domain, dlm->dlm_locking_proto.pv_major,
+                    dlm->dlm_locking_proto.pv_minor);
+               goto bail;
+       }
+
+       status = dlm_match_regions(dlm, qr);
+
+bail:
+       if (locked)
+               spin_unlock(&dlm->spinlock);
+       spin_unlock(&dlm_domain_lock);
+
+       return status;
+}
+
+static int dlm_match_nodes(struct dlm_ctxt *dlm, struct dlm_query_nodeinfo *qn)
+{
+       struct o2nm_node *local;
+       struct dlm_node_info *remote;
+       int i, j;
+       int status = 0;
+
+       for (j = 0; j < qn->qn_numnodes; ++j)
+               mlog(0, "Node %3d, %pI4:%u\n", qn->qn_nodes[j].ni_nodenum,
+                    &(qn->qn_nodes[j].ni_ipv4_address),
+                    ntohs(qn->qn_nodes[j].ni_ipv4_port));
+
+       for (i = 0; i < O2NM_MAX_NODES && !status; ++i) {
+               local = o2nm_get_node_by_num(i);
+               remote = NULL;
+               for (j = 0; j < qn->qn_numnodes; ++j) {
+                       if (qn->qn_nodes[j].ni_nodenum == i) {
+                               remote = &(qn->qn_nodes[j]);
+                               break;
+                       }
+               }
+
+               if (!local && !remote)
+                       continue;
+
+               if ((local && !remote) || (!local && remote))
+                       status = -EINVAL;
+
+               if (!status &&
+                   ((remote->ni_nodenum != local->nd_num) ||
+                    (remote->ni_ipv4_port != local->nd_ipv4_port) ||
+                    (remote->ni_ipv4_address != local->nd_ipv4_address)))
+                       status = -EINVAL;
+
+               if (status) {
+                       if (remote && !local)
+                               mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) "
+                                    "registered in joining node %d but not in "
+                                    "local node %d\n", qn->qn_domain,
+                                    remote->ni_nodenum,
+                                    &(remote->ni_ipv4_address),
+                                    ntohs(remote->ni_ipv4_port),
+                                    qn->qn_nodenum, dlm->node_num);
+                       if (local && !remote)
+                               mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) "
+                                    "registered in local node %d but not in "
+                                    "joining node %d\n", qn->qn_domain,
+                                    local->nd_num, &(local->nd_ipv4_address),
+                                    ntohs(local->nd_ipv4_port),
+                                    dlm->node_num, qn->qn_nodenum);
+                       BUG_ON((!local && !remote));
+               }
+
+               if (local)
+                       o2nm_node_put(local);
+       }
+
+       return status;
+}
+
+static int dlm_send_nodeinfo(struct dlm_ctxt *dlm, unsigned long *node_map)
+{
+       struct dlm_query_nodeinfo *qn = NULL;
+       struct o2nm_node *node;
+       int ret = 0, status, count, i;
+
+       if (find_next_bit(node_map, O2NM_MAX_NODES, 0) >= O2NM_MAX_NODES)
+               goto bail;
+
+       qn = kzalloc(sizeof(struct dlm_query_nodeinfo), GFP_KERNEL);
+       if (!qn) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto bail;
+       }
+
+       for (i = 0, count = 0; i < O2NM_MAX_NODES; ++i) {
+               node = o2nm_get_node_by_num(i);
+               if (!node)
+                       continue;
+               qn->qn_nodes[count].ni_nodenum = node->nd_num;
+               qn->qn_nodes[count].ni_ipv4_port = node->nd_ipv4_port;
+               qn->qn_nodes[count].ni_ipv4_address = node->nd_ipv4_address;
+               mlog(0, "Node %3d, %pI4:%u\n", node->nd_num,
+                    &(node->nd_ipv4_address), ntohs(node->nd_ipv4_port));
+               ++count;
+               o2nm_node_put(node);
+       }
+
+       qn->qn_nodenum = dlm->node_num;
+       qn->qn_numnodes = count;
+       qn->qn_namelen = strlen(dlm->name);
+       memcpy(qn->qn_domain, dlm->name, qn->qn_namelen);
+
+       i = -1;
+       while ((i = find_next_bit(node_map, O2NM_MAX_NODES,
+                                 i + 1)) < O2NM_MAX_NODES) {
+               if (i == dlm->node_num)
+                       continue;
+
+               mlog(0, "Sending nodeinfo to node %d\n", i);
+
+               ret = o2net_send_message(DLM_QUERY_NODEINFO, DLM_MOD_KEY,
+                                        qn, sizeof(struct dlm_query_nodeinfo),
+                                        i, &status);
+               if (ret >= 0)
+                       ret = status;
+               if (ret) {
+                       mlog(ML_ERROR, "node mismatch %d, node %d\n", ret, i);
+                       break;
+               }
+       }
+
+bail:
+       kfree(qn);
+       return ret;
+}
+
+static int dlm_query_nodeinfo_handler(struct o2net_msg *msg, u32 len,
+                                     void *data, void **ret_data)
+{
+       struct dlm_query_nodeinfo *qn;
+       struct dlm_ctxt *dlm = NULL;
+       int locked = 0, status = -EINVAL;
+
+       qn = (struct dlm_query_nodeinfo *) msg->buf;
+
+       mlog(0, "Node %u queries nodes on domain %s\n", qn->qn_nodenum,
+            qn->qn_domain);
+
+       spin_lock(&dlm_domain_lock);
+       dlm = __dlm_lookup_domain_full(qn->qn_domain, qn->qn_namelen);
+       if (!dlm) {
+               mlog(ML_ERROR, "Node %d queried nodes on domain %s before "
+                    "join domain\n", qn->qn_nodenum, qn->qn_domain);
+               goto bail;
+       }
+
+       spin_lock(&dlm->spinlock);
+       locked = 1;
+       if (dlm->joining_node != qn->qn_nodenum) {
+               mlog(ML_ERROR, "Node %d queried nodes on domain %s but "
+                    "joining node is %d\n", qn->qn_nodenum, qn->qn_domain,
+                    dlm->joining_node);
+               goto bail;
+       }
+
+       /* Support for node query was added in 1.1 */
+       if (dlm->dlm_locking_proto.pv_major == 1 &&
+           dlm->dlm_locking_proto.pv_minor == 0) {
+               mlog(ML_ERROR, "Node %d queried nodes on domain %s "
+                    "but active dlm protocol is %d.%d\n", qn->qn_nodenum,
+                    qn->qn_domain, dlm->dlm_locking_proto.pv_major,
+                    dlm->dlm_locking_proto.pv_minor);
+               goto bail;
+       }
+
+       status = dlm_match_nodes(dlm, qn);
+
+bail:
+       if (locked)
+               spin_unlock(&dlm->spinlock);
+       spin_unlock(&dlm_domain_lock);
+
+       return status;
+}
+
 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
                                   void **ret_data)
 {
@@ -1240,6 +1611,20 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
        set_bit(dlm->node_num, dlm->domain_map);
        spin_unlock(&dlm->spinlock);
 
+       /* Support for global heartbeat and node info was added in 1.1 */
+       if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) {
+               status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map);
+               if (status) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+               status = dlm_send_regions(dlm, ctxt->yes_resp_map);
+               if (status) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        dlm_send_join_asserts(dlm, ctxt->yes_resp_map);
 
        /* Joined state *must* be set before the joining node
@@ -1806,7 +2191,21 @@ static int dlm_register_net_handlers(void)
                                        sizeof(struct dlm_cancel_join),
                                        dlm_cancel_join_handler,
                                        NULL, NULL, &dlm_join_handlers);
+       if (status)
+               goto bail;
+
+       status = o2net_register_handler(DLM_QUERY_REGION, DLM_MOD_KEY,
+                                       sizeof(struct dlm_query_region),
+                                       dlm_query_region_handler,
+                                       NULL, NULL, &dlm_join_handlers);
 
+       if (status)
+               goto bail;
+
+       status = o2net_register_handler(DLM_QUERY_NODEINFO, DLM_MOD_KEY,
+                                       sizeof(struct dlm_query_nodeinfo),
+                                       dlm_query_nodeinfo_handler,
+                                       NULL, NULL, &dlm_join_handlers);
 bail:
        if (status < 0)
                dlm_unregister_net_handlers();
index ffb4c68dafa495bc739165eb30f718f1eb0865ec..f564b0e5f80d8c89e08eeba4a5e133b24cb67373 100644 (file)
@@ -3433,3 +3433,43 @@ void dlm_lockres_release_ast(struct dlm_ctxt *dlm,
        wake_up(&res->wq);
        wake_up(&dlm->migration_wq);
 }
+
+void dlm_force_free_mles(struct dlm_ctxt *dlm)
+{
+       int i;
+       struct hlist_head *bucket;
+       struct dlm_master_list_entry *mle;
+       struct hlist_node *tmp, *list;
+
+       /*
+        * We notified all other nodes that we are exiting the domain and
+        * marked the dlm state to DLM_CTXT_LEAVING. If any mles are still
+        * around we force free them and wake any processes that are waiting
+        * on the mles
+        */
+       spin_lock(&dlm->spinlock);
+       spin_lock(&dlm->master_lock);
+
+       BUG_ON(dlm->dlm_state != DLM_CTXT_LEAVING);
+       BUG_ON((find_next_bit(dlm->domain_map, O2NM_MAX_NODES, 0) < O2NM_MAX_NODES));
+
+       for (i = 0; i < DLM_HASH_BUCKETS; i++) {
+               bucket = dlm_master_hash(dlm, i);
+               hlist_for_each_safe(list, tmp, bucket) {
+                       mle = hlist_entry(list, struct dlm_master_list_entry,
+                                         master_hash_node);
+                       if (mle->type != DLM_MLE_BLOCK) {
+                               mlog(ML_ERROR, "bad mle: %p\n", mle);
+                               dlm_print_one_mle(mle);
+                       }
+                       atomic_set(&mle->woken, 1);
+                       wake_up(&mle->wq);
+
+                       __dlm_unlink_mle(dlm, mle);
+                       __dlm_mle_detach_hb_events(dlm, mle);
+                       __dlm_put_mle(mle);
+               }
+       }
+       spin_unlock(&dlm->master_lock);
+       spin_unlock(&dlm->spinlock);
+}
index c2903b84bb7a8ccbc0ea099e4a8585559d3fcf67..a7ebd9d42dc8853e89dd381af65afeab3e5df8fe 100644 (file)
@@ -612,6 +612,7 @@ static const struct file_operations dlmfs_file_operations = {
        .poll           = dlmfs_file_poll,
        .read           = dlmfs_file_read,
        .write          = dlmfs_file_write,
+       .llseek         = default_llseek,
 };
 
 static const struct inode_operations dlmfs_dir_inode_operations = {
index 5e02a893f46ea5e1e4fa5a5c0313b5d7356e1526..e8d94d722ecb8b6dc7aad1ceaa749c99d51cf8a6 100644 (file)
@@ -3635,10 +3635,18 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
 {
        struct inode *inode;
        struct address_space *mapping;
+       struct ocfs2_inode_info *oi;
 
                inode = ocfs2_lock_res_inode(lockres);
        mapping = inode->i_mapping;
 
+       if (S_ISDIR(inode->i_mode)) {
+               oi = OCFS2_I(inode);
+               oi->ip_dir_lock_gen++;
+               mlog(0, "generation: %u\n", oi->ip_dir_lock_gen);
+               goto out;
+       }
+
        if (!S_ISREG(inode->i_mode))
                goto out;
 
index d1ce48e1b3d6029e5861cf2863cbb0a544511b40..1d596d8c4a4a55dfd185ecaff4d7d9900bf10b24 100644 (file)
@@ -84,6 +84,7 @@ enum {
        OI_LS_PARENT,
        OI_LS_RENAME1,
        OI_LS_RENAME2,
+       OI_LS_REFLINK_TARGET,
 };
 
 int ocfs2_dlm_init(struct ocfs2_super *osb);
index 81296b4e364632dd5936f59d8adeab9832f2d2fd..9e8cc4346b761e6246494416787b5b78c193f01e 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/writeback.h>
 #include <linux/falloc.h>
 #include <linux/quotaops.h>
+#include <linux/blkdev.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
 
 #include "buffer_head_io.h"
 
-static int ocfs2_sync_inode(struct inode *inode)
-{
-       filemap_fdatawrite(inode->i_mapping);
-       return sync_mapping_buffers(inode->i_mapping);
-}
-
 static int ocfs2_init_file_private(struct inode *inode, struct file *file)
 {
        struct ocfs2_file_private *fp;
@@ -179,19 +174,23 @@ static int ocfs2_sync_file(struct file *file, int datasync)
 {
        int err = 0;
        journal_t *journal;
-       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = file->f_mapping->host;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-       mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", file, dentry, datasync,
-                  dentry->d_name.len, dentry->d_name.name);
-
-       err = ocfs2_sync_inode(dentry->d_inode);
-       if (err)
-               goto bail;
+       mlog_entry("(0x%p, %d, 0x%p, '%.*s')\n", file, datasync,
+                  file->f_path.dentry, file->f_path.dentry->d_name.len,
+                  file->f_path.dentry->d_name.name);
 
-       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
+               /*
+                * We still have to flush drive's caches to get data to the
+                * platter
+                */
+               if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
+                       blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
+                                          NULL, BLKDEV_IFL_WAIT);
                goto bail;
+       }
 
        journal = osb->journal->j_journal;
        err = jbd2_journal_force_commit(journal);
@@ -361,7 +360,7 @@ static int ocfs2_cow_file_pos(struct inode *inode,
        if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
                goto out;
 
-       return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1);
+       return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1);
 
 out:
        return status;
@@ -774,7 +773,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
        BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT));
        BUG_ON(abs_from & (inode->i_blkbits - 1));
 
-       page = grab_cache_page(mapping, index);
+       page = find_or_create_page(mapping, index, GFP_NOFS);
        if (!page) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -904,8 +903,8 @@ static int ocfs2_zero_extend_get_range(struct inode *inode,
                zero_clusters = last_cpos - zero_cpos;
 
        if (needs_cow) {
-               rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, zero_clusters,
-                                       UINT_MAX);
+               rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos,
+                                       zero_clusters, UINT_MAX);
                if (rc) {
                        mlog_errno(rc);
                        goto out;
@@ -2053,6 +2052,7 @@ out:
 }
 
 static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
+                                           struct file *file,
                                            loff_t pos, size_t count,
                                            int *meta_level)
 {
@@ -2070,7 +2070,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
 
        *meta_level = 1;
 
-       ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
+       ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX);
        if (ret)
                mlog_errno(ret);
 out:
@@ -2078,7 +2078,7 @@ out:
        return ret;
 }
 
-static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
+static int ocfs2_prepare_inode_for_write(struct file *file,
                                         loff_t *ppos,
                                         size_t count,
                                         int appending,
@@ -2086,6 +2086,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                                         int *has_refcount)
 {
        int ret = 0, meta_level = 0;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        loff_t saved_pos, end;
 
@@ -2141,6 +2142,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                        meta_level = -1;
 
                        ret = ocfs2_prepare_inode_for_refcount(inode,
+                                                              file,
                                                               saved_pos,
                                                               count,
                                                               &meta_level);
@@ -2223,6 +2225,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       int full_coherency = !(osb->s_mount_opt &
+                              OCFS2_MOUNT_COHERENCY_BUFFERED);
 
        mlog_entry("(0x%p, %u, '%.*s')\n", file,
                   (unsigned int)nr_segs,
@@ -2246,16 +2250,39 @@ relock:
                have_alloc_sem = 1;
        }
 
-       /* concurrent O_DIRECT writes are allowed */
-       rw_level = !direct_io;
+       /*
+        * Concurrent O_DIRECT writes are allowed with
+        * mount_option "coherency=buffered".
+        */
+       rw_level = (!direct_io || full_coherency);
+
        ret = ocfs2_rw_lock(inode, rw_level);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_sems;
        }
 
+       /*
+        * O_DIRECT writes with "coherency=full" need to take EX cluster
+        * inode_lock to guarantee coherency.
+        */
+       if (direct_io && full_coherency) {
+               /*
+                * We need to take and drop the inode lock to force
+                * other nodes to drop their caches.  Buffered I/O
+                * already does this in write_begin().
+                */
+               ret = ocfs2_inode_lock(inode, NULL, 1);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_sems;
+               }
+
+               ocfs2_inode_unlock(inode, 1);
+       }
+
        can_do_direct = direct_io;
-       ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos,
+       ret = ocfs2_prepare_inode_for_write(file, ppos,
                                            iocb->ki_left, appending,
                                            &can_do_direct, &has_refcount);
        if (ret < 0) {
@@ -2303,17 +2330,6 @@ relock:
                written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
                                                    ppos, count, ocount);
                if (written < 0) {
-                       /*
-                        * direct write may have instantiated a few
-                        * blocks outside i_size. Trim these off again.
-                        * Don't need i_size_read because we hold i_mutex.
-                        *
-                        * XXX(truncate): this looks buggy because ocfs2 did not
-                        * actually implement ->truncate.  Take a look at
-                        * the new truncate sequence and update this accordingly
-                        */
-                       if (*ppos + count > inode->i_size)
-                               truncate_setsize(inode, inode->i_size);
                        ret = written;
                        goto out_dio;
                }
@@ -2329,7 +2345,7 @@ out_dio:
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
        if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
-           ((file->f_flags & O_DIRECT) && has_refcount)) {
+           ((file->f_flags & O_DIRECT) && !direct_io)) {
                ret = filemap_fdatawrite_range(file->f_mapping, pos,
                                               pos + count - 1);
                if (ret < 0)
@@ -2385,7 +2401,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
 {
        int ret;
 
-       ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
+       ret = ocfs2_prepare_inode_for_write(out, &sd->pos,
                                            sd->total_len, 0, NULL, NULL);
        if (ret < 0) {
                mlog_errno(ret);
index 0492464916b19324e73425e29c473956b0b4bd33..f935fd6600dd1e07e7625161671758795ce477b0 100644 (file)
@@ -335,6 +335,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                    else
                            inode->i_fop = &ocfs2_dops_no_plocks;
                    i_size_write(inode, le64_to_cpu(fe->i_size));
+                   OCFS2_I(inode)->ip_dir_lock_gen = 1;
                    break;
            case S_IFLNK:
                    if (ocfs2_inode_is_fast_symlink(inode))
@@ -488,7 +489,11 @@ static int ocfs2_read_locked_inode(struct inode *inode,
                                                     OCFS2_BH_IGNORE_CACHE);
        } else {
                status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
-               if (!status)
+               /*
+                * If buffer is in jbd, then its checksum may not have been
+                * computed as yet.
+                */
+               if (!status && !buffer_jbd(bh))
                        status = ocfs2_validate_inode_block(osb->sb, bh);
        }
        if (status < 0) {
index 6de5a869db300061e23e3e924a0517460f660e3d..1c508b149b3ac1bd4325fd33a9aae6bdb70e024a 100644 (file)
@@ -46,30 +46,28 @@ struct ocfs2_inode_info
        /* These fields are protected by ip_lock */
        spinlock_t                      ip_lock;
        u32                             ip_open_count;
-       u32                             ip_clusters;
        struct list_head                ip_io_markers;
+       u32                             ip_clusters;
 
+       u16                             ip_dyn_features;
        struct mutex                    ip_io_mutex;
-
        u32                             ip_flags; /* see below */
        u32                             ip_attr; /* inode attributes */
-       u16                             ip_dyn_features;
 
        /* protected by recovery_lock. */
        struct inode                    *ip_next_orphan;
 
-       u32                             ip_dir_start_lookup;
-
        struct ocfs2_caching_info       ip_metadata_cache;
-
        struct ocfs2_extent_map         ip_extent_map;
-
        struct inode                    vfs_inode;
        struct jbd2_inode               ip_jinode;
 
+       u32                             ip_dir_start_lookup;
+
        /* Only valid if the inode is the dir. */
        u32                             ip_last_used_slot;
        u64                             ip_last_used_group;
+       u32                             ip_dir_lock_gen;
 
        struct ocfs2_alloc_reservation  ip_la_data_resv;
 };
index 7d9d9c132cef3a5d59a412aa4d0d3c26c10a5fb0..7a48681961521a957e1947ba9abdbb8d290f9cde 100644 (file)
 
 #include <linux/ext2_fs.h>
 
+#define o2info_from_user(a, b) \
+               copy_from_user(&(a), (b), sizeof(a))
+#define o2info_to_user(a, b)   \
+               copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
+
+/*
+ * This call is void because we are already reporting an error that may
+ * be -EFAULT.  The error will be returned from the ioctl(2) call.  It's
+ * just a best-effort to tell userspace that this request caused the error.
+ */
+static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq,
+                                       struct ocfs2_info_request __user *req)
+{
+       kreq->ir_flags |= OCFS2_INFO_FL_ERROR;
+       (void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags));
+}
+
+#define o2info_set_request_error(a, b) \
+               __o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
+
 static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
 {
        int status;
@@ -109,6 +129,328 @@ bail:
        return status;
 }
 
+int ocfs2_info_handle_blocksize(struct inode *inode,
+                               struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_blocksize oib;
+
+       if (o2info_from_user(oib, req))
+               goto bail;
+
+       oib.ib_blocksize = inode->i_sb->s_blocksize;
+       oib.ib_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oib, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oib, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_clustersize(struct inode *inode,
+                                 struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_clustersize oic;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oic, req))
+               goto bail;
+
+       oic.ic_clustersize = osb->s_clustersize;
+       oic.ic_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oic, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oic, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_maxslots(struct inode *inode,
+                              struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_maxslots oim;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oim, req))
+               goto bail;
+
+       oim.im_max_slots = osb->max_slots;
+       oim.im_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oim, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oim, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_label(struct inode *inode,
+                           struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_label oil;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oil, req))
+               goto bail;
+
+       memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
+       oil.il_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oil, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oil, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_uuid(struct inode *inode,
+                          struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_uuid oiu;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oiu, req))
+               goto bail;
+
+       memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
+       oiu.iu_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oiu, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oiu, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_fs_features(struct inode *inode,
+                                 struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_fs_features oif;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oif, req))
+               goto bail;
+
+       oif.if_compat_features = osb->s_feature_compat;
+       oif.if_incompat_features = osb->s_feature_incompat;
+       oif.if_ro_compat_features = osb->s_feature_ro_compat;
+       oif.if_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oif, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oif, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_journal_size(struct inode *inode,
+                                  struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_journal_size oij;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (o2info_from_user(oij, req))
+               goto bail;
+
+       oij.ij_journal_size = osb->journal->j_inode->i_size;
+
+       oij.ij_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oij, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oij, req);
+
+       return status;
+}
+
+int ocfs2_info_handle_unknown(struct inode *inode,
+                             struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_request oir;
+
+       if (o2info_from_user(oir, req))
+               goto bail;
+
+       oir.ir_flags &= ~OCFS2_INFO_FL_FILLED;
+
+       if (o2info_to_user(oir, req))
+               goto bail;
+
+       status = 0;
+bail:
+       if (status)
+               o2info_set_request_error(oir, req);
+
+       return status;
+}
+
+/*
+ * Validate and distinguish OCFS2_IOC_INFO requests.
+ *
+ * - validate the magic number.
+ * - distinguish different requests.
+ * - validate size of different requests.
+ */
+int ocfs2_info_handle_request(struct inode *inode,
+                             struct ocfs2_info_request __user *req)
+{
+       int status = -EFAULT;
+       struct ocfs2_info_request oir;
+
+       if (o2info_from_user(oir, req))
+               goto bail;
+
+       status = -EINVAL;
+       if (oir.ir_magic != OCFS2_INFO_MAGIC)
+               goto bail;
+
+       switch (oir.ir_code) {
+       case OCFS2_INFO_BLOCKSIZE:
+               if (oir.ir_size == sizeof(struct ocfs2_info_blocksize))
+                       status = ocfs2_info_handle_blocksize(inode, req);
+               break;
+       case OCFS2_INFO_CLUSTERSIZE:
+               if (oir.ir_size == sizeof(struct ocfs2_info_clustersize))
+                       status = ocfs2_info_handle_clustersize(inode, req);
+               break;
+       case OCFS2_INFO_MAXSLOTS:
+               if (oir.ir_size == sizeof(struct ocfs2_info_maxslots))
+                       status = ocfs2_info_handle_maxslots(inode, req);
+               break;
+       case OCFS2_INFO_LABEL:
+               if (oir.ir_size == sizeof(struct ocfs2_info_label))
+                       status = ocfs2_info_handle_label(inode, req);
+               break;
+       case OCFS2_INFO_UUID:
+               if (oir.ir_size == sizeof(struct ocfs2_info_uuid))
+                       status = ocfs2_info_handle_uuid(inode, req);
+               break;
+       case OCFS2_INFO_FS_FEATURES:
+               if (oir.ir_size == sizeof(struct ocfs2_info_fs_features))
+                       status = ocfs2_info_handle_fs_features(inode, req);
+               break;
+       case OCFS2_INFO_JOURNAL_SIZE:
+               if (oir.ir_size == sizeof(struct ocfs2_info_journal_size))
+                       status = ocfs2_info_handle_journal_size(inode, req);
+               break;
+       default:
+               status = ocfs2_info_handle_unknown(inode, req);
+               break;
+       }
+
+bail:
+       return status;
+}
+
+int ocfs2_get_request_ptr(struct ocfs2_info *info, int idx,
+                         u64 *req_addr, int compat_flag)
+{
+       int status = -EFAULT;
+       u64 __user *bp = NULL;
+
+       if (compat_flag) {
+#ifdef CONFIG_COMPAT
+               /*
+                * pointer bp stores the base address of a pointers array,
+                * which collects all addresses of separate request.
+                */
+               bp = (u64 __user *)(unsigned long)compat_ptr(info->oi_requests);
+#else
+               BUG();
+#endif
+       } else
+               bp = (u64 __user *)(unsigned long)(info->oi_requests);
+
+       if (o2info_from_user(*req_addr, bp + idx))
+               goto bail;
+
+       status = 0;
+bail:
+       return status;
+}
+
+/*
+ * OCFS2_IOC_INFO handles an array of requests passed from userspace.
+ *
+ * ocfs2_info_handle() recevies a large info aggregation, grab and
+ * validate the request count from header, then break it into small
+ * pieces, later specific handlers can handle them one by one.
+ *
+ * Idea here is to make each separate request small enough to ensure
+ * a better backward&forward compatibility, since a small piece of
+ * request will be less likely to be broken if disk layout get changed.
+ */
+int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
+                     int compat_flag)
+{
+       int i, status = 0;
+       u64 req_addr;
+       struct ocfs2_info_request __user *reqp;
+
+       if ((info->oi_count > OCFS2_INFO_MAX_REQUEST) ||
+           (!info->oi_requests)) {
+               status = -EINVAL;
+               goto bail;
+       }
+
+       for (i = 0; i < info->oi_count; i++) {
+
+               status = ocfs2_get_request_ptr(info, i, &req_addr, compat_flag);
+               if (status)
+                       break;
+
+               reqp = (struct ocfs2_info_request *)(unsigned long)req_addr;
+               if (!reqp) {
+                       status = -EINVAL;
+                       goto bail;
+               }
+
+               status = ocfs2_info_handle_request(inode, reqp);
+               if (status)
+                       break;
+       }
+
+bail:
+       return status;
+}
+
 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = filp->f_path.dentry->d_inode;
@@ -120,6 +462,7 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        struct reflink_arguments args;
        const char *old_path, *new_path;
        bool preserve;
+       struct ocfs2_info info;
 
        switch (cmd) {
        case OCFS2_IOC_GETFLAGS:
@@ -174,6 +517,12 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                preserve = (args.preserve != 0);
 
                return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
+       case OCFS2_IOC_INFO:
+               if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
+                                  sizeof(struct ocfs2_info)))
+                       return -EFAULT;
+
+               return ocfs2_info_handle(inode, &info, 0);
        default:
                return -ENOTTY;
        }
@@ -185,6 +534,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        bool preserve;
        struct reflink_arguments args;
        struct inode *inode = file->f_path.dentry->d_inode;
+       struct ocfs2_info info;
 
        switch (cmd) {
        case OCFS2_IOC32_GETFLAGS:
@@ -209,6 +559,12 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 
                return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
                                           compat_ptr(args.new_path), preserve);
+       case OCFS2_IOC_INFO:
+               if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
+                                  sizeof(struct ocfs2_info)))
+                       return -EFAULT;
+
+               return ocfs2_info_handle(inode, &info, 1);
        default:
                return -ENOIOCTLCMD;
        }
index 9b57c0350ff9337b20a9c96869e209c925246c4f..faa2303dbf0a4b5bd0b21a013abee4af82dda47f 100644 (file)
@@ -301,7 +301,6 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
 {
        int status = 0;
        unsigned int flushed;
-       unsigned long old_id;
        struct ocfs2_journal *journal = NULL;
 
        mlog_entry_void();
@@ -326,7 +325,7 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
                goto finally;
        }
 
-       old_id = ocfs2_inc_trans_id(journal);
+       ocfs2_inc_trans_id(journal);
 
        flushed = atomic_read(&journal->j_num_trans);
        atomic_set(&journal->j_num_trans, 0);
@@ -342,9 +341,6 @@ finally:
        return status;
 }
 
-/* pass it NULL and it will allocate a new handle object for you.  If
- * you pass it a handle however, it may still return error, in which
- * case it has free'd the passed handle for you. */
 handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
 {
        journal_t *journal = osb->journal->j_journal;
@@ -1888,6 +1884,8 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb)
 
        os = &osb->osb_orphan_scan;
 
+       mlog(0, "Begin orphan scan\n");
+
        if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE)
                goto out;
 
@@ -1920,6 +1918,7 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb)
 unlock:
        ocfs2_orphan_scan_unlock(osb, seqno);
 out:
+       mlog(0, "Orphan scan completed\n");
        return;
 }
 
index b5baaa8e710f234b08878c111d84ffe55f52df7d..43e56b97f9c016c923614f887bcce3e9ba58da04 100644 (file)
@@ -67,11 +67,12 @@ struct ocfs2_journal {
        struct buffer_head        *j_bh;      /* Journal disk inode block */
        atomic_t                  j_num_trans; /* Number of transactions
                                                * currently in the system. */
+       spinlock_t                j_lock;
        unsigned long             j_trans_id;
        struct rw_semaphore       j_trans_barrier;
        wait_queue_head_t         j_checkpointed;
 
-       spinlock_t                j_lock;
+       /* both fields protected by j_lock*/
        struct list_head          j_la_cleanups;
        struct work_struct        j_recovery_work;
 };
index af2b8fe1f13999e26f6e2543a047847bcf517c4e..7e32db9c2c993b38e67f5d1282525f0a089b54b0 100644 (file)
@@ -59,10 +59,11 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
        return ret;
 }
 
-static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
                                struct page *page)
 {
        int ret;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
        loff_t pos = page_offset(page);
        unsigned int len = PAGE_CACHE_SIZE;
@@ -74,9 +75,11 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
        /*
         * Another node might have truncated while we were waiting on
         * cluster locks.
+        * We don't check size == 0 before the shift. This is borrowed
+        * from do_generic_file_read.
         */
-       last_index = size >> PAGE_CACHE_SHIFT;
-       if (page->index > last_index) {
+       last_index = (size - 1) >> PAGE_CACHE_SHIFT;
+       if (unlikely(!size || page->index > last_index)) {
                ret = -EINVAL;
                goto out;
        }
@@ -107,9 +110,9 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
         * because the "write" would invalidate their data.
         */
        if (page->index == last_index)
-               len = size & ~PAGE_CACHE_MASK;
+               len = ((size - 1) & ~PAGE_CACHE_MASK) + 1;
 
-       ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+       ret = ocfs2_write_begin_nolock(file, mapping, pos, len, 0, &locked_page,
                                       &fsdata, di_bh, page);
        if (ret) {
                if (ret != -ENOSPC)
@@ -157,7 +160,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
         */
        down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-       ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+       ret = __ocfs2_page_mkwrite(vma->vm_file, di_bh, page);
 
        up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
index f171b51a74f78d6e268b5d743a24df4e702f9643..e7bde21149aee4f4e1dfed501069358927a064d7 100644 (file)
@@ -171,7 +171,8 @@ bail_add:
                        ret = ERR_PTR(status);
                        goto bail_unlock;
                }
-       }
+       } else
+               ocfs2_dentry_attach_gen(dentry);
 
 bail_unlock:
        /* Don't drop the cluster lock until *after* the d_add --
@@ -472,32 +473,23 @@ leave:
        return status;
 }
 
-static int ocfs2_mknod_locked(struct ocfs2_super *osb,
-                             struct inode *dir,
-                             struct inode *inode,
-                             dev_t dev,
-                             struct buffer_head **new_fe_bh,
-                             struct buffer_head *parent_fe_bh,
-                             handle_t *handle,
-                             struct ocfs2_alloc_context *inode_ac)
+static int __ocfs2_mknod_locked(struct inode *dir,
+                               struct inode *inode,
+                               dev_t dev,
+                               struct buffer_head **new_fe_bh,
+                               struct buffer_head *parent_fe_bh,
+                               handle_t *handle,
+                               struct ocfs2_alloc_context *inode_ac,
+                               u64 fe_blkno, u64 suballoc_loc, u16 suballoc_bit)
 {
        int status = 0;
+       struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_extent_list *fel;
-       u64 suballoc_loc, fe_blkno = 0;
-       u16 suballoc_bit;
        u16 feat;
 
        *new_fe_bh = NULL;
 
-       status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh,
-                                      inode_ac, &suballoc_loc,
-                                      &suballoc_bit, &fe_blkno);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-       }
-
        /* populate as many fields early on as possible - many of
         * these are used by the support functions here and in
         * callers. */
@@ -591,6 +583,34 @@ leave:
        return status;
 }
 
+static int ocfs2_mknod_locked(struct ocfs2_super *osb,
+                             struct inode *dir,
+                             struct inode *inode,
+                             dev_t dev,
+                             struct buffer_head **new_fe_bh,
+                             struct buffer_head *parent_fe_bh,
+                             handle_t *handle,
+                             struct ocfs2_alloc_context *inode_ac)
+{
+       int status = 0;
+       u64 suballoc_loc, fe_blkno = 0;
+       u16 suballoc_bit;
+
+       *new_fe_bh = NULL;
+
+       status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh,
+                                      inode_ac, &suballoc_loc,
+                                      &suballoc_bit, &fe_blkno);
+       if (status < 0) {
+               mlog_errno(status);
+               return status;
+       }
+
+       return __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh,
+                                   parent_fe_bh, handle, inode_ac,
+                                   fe_blkno, suballoc_loc, suballoc_bit);
+}
+
 static int ocfs2_mkdir(struct inode *dir,
                       struct dentry *dentry,
                       int mode)
@@ -1852,61 +1872,117 @@ bail:
        return status;
 }
 
-static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
-                                   struct inode **ret_orphan_dir,
-                                   u64 blkno,
-                                   char *name,
-                                   struct ocfs2_dir_lookup_result *lookup)
+static int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb,
+                                       struct inode **ret_orphan_dir,
+                                       struct buffer_head **ret_orphan_dir_bh)
 {
        struct inode *orphan_dir_inode;
        struct buffer_head *orphan_dir_bh = NULL;
-       int status = 0;
-
-       status = ocfs2_blkno_stringify(blkno, name);
-       if (status < 0) {
-               mlog_errno(status);
-               return status;
-       }
+       int ret = 0;
 
        orphan_dir_inode = ocfs2_get_system_file_inode(osb,
                                                       ORPHAN_DIR_SYSTEM_INODE,
                                                       osb->slot_num);
        if (!orphan_dir_inode) {
-               status = -ENOENT;
-               mlog_errno(status);
-               return status;
+               ret = -ENOENT;
+               mlog_errno(ret);
+               return ret;
        }
 
        mutex_lock(&orphan_dir_inode->i_mutex);
 
-       status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
+       ret = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
+       if (ret < 0) {
+               mutex_unlock(&orphan_dir_inode->i_mutex);
+               iput(orphan_dir_inode);
+
+               mlog_errno(ret);
+               return ret;
        }
 
-       status = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
-                                             orphan_dir_bh, name,
-                                             OCFS2_ORPHAN_NAMELEN, lookup);
-       if (status < 0) {
-               ocfs2_inode_unlock(orphan_dir_inode, 1);
+       *ret_orphan_dir = orphan_dir_inode;
+       *ret_orphan_dir_bh = orphan_dir_bh;
 
-               mlog_errno(status);
-               goto leave;
+       return 0;
+}
+
+static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode,
+                                     struct buffer_head *orphan_dir_bh,
+                                     u64 blkno,
+                                     char *name,
+                                     struct ocfs2_dir_lookup_result *lookup)
+{
+       int ret;
+       struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb);
+
+       ret = ocfs2_blkno_stringify(blkno, name);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
+                                          orphan_dir_bh, name,
+                                          OCFS2_ORPHAN_NAMELEN, lookup);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for
+ * insertion of an orphan.
+ * @osb: ocfs2 file system
+ * @ret_orphan_dir: Orphan dir inode - returned locked!
+ * @blkno: Actual block number of the inode to be inserted into orphan dir.
+ * @lookup: dir lookup result, to be passed back into functions like
+ *          ocfs2_orphan_add
+ *
+ * Returns zero on success and the ret_orphan_dir, name and lookup
+ * fields will be populated.
+ *
+ * Returns non-zero on failure. 
+ */
+static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
+                                   struct inode **ret_orphan_dir,
+                                   u64 blkno,
+                                   char *name,
+                                   struct ocfs2_dir_lookup_result *lookup)
+{
+       struct inode *orphan_dir_inode = NULL;
+       struct buffer_head *orphan_dir_bh = NULL;
+       int ret = 0;
+
+       ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode,
+                                          &orphan_dir_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh,
+                                        blkno, name, lookup);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
        }
 
        *ret_orphan_dir = orphan_dir_inode;
 
-leave:
-       if (status) {
+out:
+       brelse(orphan_dir_bh);
+
+       if (ret) {
+               ocfs2_inode_unlock(orphan_dir_inode, 1);
                mutex_unlock(&orphan_dir_inode->i_mutex);
                iput(orphan_dir_inode);
        }
 
-       brelse(orphan_dir_bh);
-
-       mlog_exit(status);
-       return status;
+       mlog_exit(ret);
+       return ret;
 }
 
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
@@ -2053,6 +2129,99 @@ leave:
        return status;
 }
 
+/**
+ * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to recieve a newly
+ * allocated file. This is different from the typical 'add to orphan dir'
+ * operation in that the inode does not yet exist. This is a problem because
+ * the orphan dir stringifies the inode block number to come up with it's
+ * dirent. Obviously if the inode does not yet exist we have a chicken and egg
+ * problem. This function works around it by calling deeper into the orphan
+ * and suballoc code than other callers. Use this only by necessity.
+ * @dir: The directory which this inode will ultimately wind up under - not the
+ * orphan dir!
+ * @dir_bh: buffer_head the @dir inode block
+ * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled
+ * with the string to be used for orphan dirent. Pass back to the orphan dir
+ * code.
+ * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan
+ * dir code.
+ * @ret_di_blkno: block number where the new inode will be allocated.
+ * @orphan_insert: Dir insert context to be passed back into orphan dir code.
+ * @ret_inode_ac: Inode alloc context to be passed back to the allocator.
+ *
+ * Returns zero on success and the ret_orphan_dir, name and lookup
+ * fields will be populated.
+ *
+ * Returns non-zero on failure. 
+ */
+static int ocfs2_prep_new_orphaned_file(struct inode *dir,
+                                       struct buffer_head *dir_bh,
+                                       char *orphan_name,
+                                       struct inode **ret_orphan_dir,
+                                       u64 *ret_di_blkno,
+                                       struct ocfs2_dir_lookup_result *orphan_insert,
+                                       struct ocfs2_alloc_context **ret_inode_ac)
+{
+       int ret;
+       u64 di_blkno;
+       struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+       struct inode *orphan_dir = NULL;
+       struct buffer_head *orphan_dir_bh = NULL;
+       struct ocfs2_alloc_context *inode_ac = NULL;
+
+       ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir, &orphan_dir_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       /* reserve an inode spot */
+       ret = ocfs2_reserve_new_inode(osb, &inode_ac);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac,
+                                      &di_blkno);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh,
+                                        di_blkno, orphan_name, orphan_insert);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+out:
+       if (ret == 0) {
+               *ret_orphan_dir = orphan_dir;
+               *ret_di_blkno = di_blkno;
+               *ret_inode_ac = inode_ac;
+               /*
+                * orphan_name and orphan_insert are already up to
+                * date via prepare_orphan_dir
+                */
+       } else {
+               /* Unroll reserve_new_inode* */
+               if (inode_ac)
+                       ocfs2_free_alloc_context(inode_ac);
+
+               /* Unroll orphan dir locking */
+               mutex_unlock(&orphan_dir->i_mutex);
+               ocfs2_inode_unlock(orphan_dir, 1);
+               iput(orphan_dir);
+       }
+
+       brelse(orphan_dir_bh);
+
+       return 0;
+}
+
 int ocfs2_create_inode_in_orphan(struct inode *dir,
                                 int mode,
                                 struct inode **new_inode)
@@ -2068,6 +2237,8 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        struct buffer_head *new_di_bh = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
+       u64 uninitialized_var(di_blkno), suballoc_loc;
+       u16 suballoc_bit;
 
        status = ocfs2_inode_lock(dir, &parent_di_bh, 1);
        if (status < 0) {
@@ -2076,20 +2247,9 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
                return status;
        }
 
-       /*
-        * We give the orphan dir the root blkno to fake an orphan name,
-        * and allocate enough space for our insertion.
-        */
-       status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
-                                         osb->root_blkno,
-                                         orphan_name, &orphan_insert);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-       }
-
-       /* reserve an inode spot */
-       status = ocfs2_reserve_new_inode(osb, &inode_ac);
+       status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh,
+                                             orphan_name, &orphan_dir,
+                                             &di_blkno, &orphan_insert, &inode_ac);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -2116,17 +2276,20 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
                goto leave;
        did_quota_inode = 1;
 
-       inode->i_nlink = 0;
-       /* do the real work now. */
-       status = ocfs2_mknod_locked(osb, dir, inode,
-                                   0, &new_di_bh, parent_di_bh, handle,
-                                   inode_ac);
+       status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac,
+                                             &suballoc_loc,
+                                             &suballoc_bit, di_blkno);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, orphan_name);
+       inode->i_nlink = 0;
+       /* do the real work now. */
+       status = __ocfs2_mknod_locked(dir, inode,
+                                     0, &new_di_bh, parent_di_bh, handle,
+                                     inode_ac, di_blkno, suballoc_loc,
+                                     suballoc_bit);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
index c67003b6b5a257d9e914ff1088d132425d8a2cba..d8408217e3bd0657a3446f77a56833a20f03ad52 100644 (file)
@@ -150,26 +150,33 @@ typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
 struct ocfs2_lock_res {
        void                    *l_priv;
        struct ocfs2_lock_res_ops *l_ops;
-       spinlock_t               l_lock;
+
 
        struct list_head         l_blocked_list;
        struct list_head         l_mask_waiters;
 
-       enum ocfs2_lock_type     l_type;
        unsigned long            l_flags;
        char                     l_name[OCFS2_LOCK_ID_MAX_LEN];
-       int                      l_level;
        unsigned int             l_ro_holders;
        unsigned int             l_ex_holders;
-       struct ocfs2_dlm_lksb    l_lksb;
+       unsigned char            l_level;
+
+       /* Data packed - type enum ocfs2_lock_type */
+       unsigned char            l_type;
 
        /* used from AST/BAST funcs. */
-       enum ocfs2_ast_action    l_action;
-       enum ocfs2_unlock_action l_unlock_action;
-       int                      l_requested;
-       int                      l_blocking;
+       /* Data packed - enum type ocfs2_ast_action */
+       unsigned char            l_action;
+       /* Data packed - enum type ocfs2_unlock_action */
+       unsigned char            l_unlock_action;
+       unsigned char            l_requested;
+       unsigned char            l_blocking;
        unsigned int             l_pending_gen;
 
+       spinlock_t               l_lock;
+
+       struct ocfs2_dlm_lksb    l_lksb;
+
        wait_queue_head_t        l_event;
 
        struct list_head         l_debug_list;
@@ -243,7 +250,7 @@ enum ocfs2_local_alloc_state
 
 enum ocfs2_mount_options
 {
-       OCFS2_MOUNT_HB_LOCAL   = 1 << 0, /* Heartbeat started in local mode */
+       OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Local heartbeat */
        OCFS2_MOUNT_BARRIER = 1 << 1,   /* Use block barriers */
        OCFS2_MOUNT_NOINTR  = 1 << 2,   /* Don't catch signals */
        OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */
@@ -256,6 +263,10 @@ enum ocfs2_mount_options
                                                   control lists */
        OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */
        OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */
+       OCFS2_MOUNT_COHERENCY_BUFFERED = 1 << 12, /* Allow concurrent O_DIRECT
+                                                    writes */
+       OCFS2_MOUNT_HB_NONE = 1 << 13, /* No heartbeat */
+       OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */
 };
 
 #define OCFS2_OSB_SOFT_RO                      0x0001
@@ -277,7 +288,8 @@ struct ocfs2_super
        struct super_block *sb;
        struct inode *root_inode;
        struct inode *sys_root_inode;
-       struct inode *system_inodes[NUM_SYSTEM_INODES];
+       struct inode *global_system_inodes[NUM_GLOBAL_SYSTEM_INODES];
+       struct inode **local_system_inodes;
 
        struct ocfs2_slot_info *slot_info;
 
@@ -368,6 +380,8 @@ struct ocfs2_super
        struct ocfs2_alloc_stats alloc_stats;
        char dev_str[20];               /* "major,minor" of the device */
 
+       u8 osb_stackflags;
+
        char osb_cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
        struct ocfs2_cluster_connection *cconn;
        struct ocfs2_lock_res osb_super_lockres;
@@ -601,10 +615,35 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
        return ret;
 }
 
-static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
+static inline int ocfs2_clusterinfo_valid(struct ocfs2_super *osb)
 {
        return (osb->s_feature_incompat &
-               OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK);
+               (OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK |
+                OCFS2_FEATURE_INCOMPAT_CLUSTERINFO));
+}
+
+static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
+{
+       if (ocfs2_clusterinfo_valid(osb) &&
+           memcmp(osb->osb_cluster_stack, OCFS2_CLASSIC_CLUSTER_STACK,
+                  OCFS2_STACK_LABEL_LEN))
+               return 1;
+       return 0;
+}
+
+static inline int ocfs2_o2cb_stack(struct ocfs2_super *osb)
+{
+       if (ocfs2_clusterinfo_valid(osb) &&
+           !memcmp(osb->osb_cluster_stack, OCFS2_CLASSIC_CLUSTER_STACK,
+                  OCFS2_STACK_LABEL_LEN))
+               return 1;
+       return 0;
+}
+
+static inline int ocfs2_cluster_o2cb_global_heartbeat(struct ocfs2_super *osb)
+{
+       return ocfs2_o2cb_stack(osb) &&
+               (osb->osb_stackflags & OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT);
 }
 
 static inline int ocfs2_mount_local(struct ocfs2_super *osb)
index 33f1c9a8258d1d4de5a17fe1ebf1d0d39c4098c3..c2e4f8222e2f0ac707de217555bee7edd51f76d6 100644 (file)
                                         | OCFS2_FEATURE_INCOMPAT_META_ECC \
                                         | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
                                         | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
-                                        | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
+                                        | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG  \
+                                        | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP   (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
                                         | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
                                         | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
 /* Discontigous block groups */
 #define OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG    0x2000
 
+/*
+ * Incompat bit to indicate useable clusterinfo with stackflags for all
+ * cluster stacks (userspace adnd o2cb). If this bit is set,
+ * INCOMPAT_USERSPACE_STACK becomes superfluous and thus should not be set.
+ */
+#define OCFS2_FEATURE_INCOMPAT_CLUSTERINFO     0x4000
+
 /*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
 #define OCFS2_HAS_REFCOUNT_FL   (0x0010)
 
 /* Inode attributes, keep in sync with EXT2 */
-#define OCFS2_SECRM_FL         (0x00000001)    /* Secure deletion */
-#define OCFS2_UNRM_FL          (0x00000002)    /* Undelete */
-#define OCFS2_COMPR_FL         (0x00000004)    /* Compress file */
-#define OCFS2_SYNC_FL          (0x00000008)    /* Synchronous updates */
-#define OCFS2_IMMUTABLE_FL     (0x00000010)    /* Immutable file */
-#define OCFS2_APPEND_FL                (0x00000020)    /* writes to file may only append */
-#define OCFS2_NODUMP_FL                (0x00000040)    /* do not dump file */
-#define OCFS2_NOATIME_FL       (0x00000080)    /* do not update atime */
-#define OCFS2_DIRSYNC_FL       (0x00010000)    /* dirsync behaviour (directories only) */
-
-#define OCFS2_FL_VISIBLE       (0x000100FF)    /* User visible flags */
-#define OCFS2_FL_MODIFIABLE    (0x000100FF)    /* User modifiable flags */
+#define OCFS2_SECRM_FL                 FS_SECRM_FL     /* Secure deletion */
+#define OCFS2_UNRM_FL                  FS_UNRM_FL      /* Undelete */
+#define OCFS2_COMPR_FL                 FS_COMPR_FL     /* Compress file */
+#define OCFS2_SYNC_FL                  FS_SYNC_FL      /* Synchronous updates */
+#define OCFS2_IMMUTABLE_FL             FS_IMMUTABLE_FL /* Immutable file */
+#define OCFS2_APPEND_FL                        FS_APPEND_FL    /* writes to file may only append */
+#define OCFS2_NODUMP_FL                        FS_NODUMP_FL    /* do not dump file */
+#define OCFS2_NOATIME_FL               FS_NOATIME_FL   /* do not update atime */
+/* Reserved for compression usage... */
+#define OCFS2_DIRTY_FL                 FS_DIRTY_FL
+#define OCFS2_COMPRBLK_FL              FS_COMPRBLK_FL  /* One or more compressed clusters */
+#define OCFS2_NOCOMP_FL                        FS_NOCOMP_FL    /* Don't compress */
+#define OCFS2_ECOMPR_FL                        FS_ECOMPR_FL    /* Compression error */
+/* End compression flags --- maybe not all used */
+#define OCFS2_BTREE_FL                 FS_BTREE_FL     /* btree format dir */
+#define OCFS2_INDEX_FL                 FS_INDEX_FL     /* hash-indexed directory */
+#define OCFS2_IMAGIC_FL                        FS_IMAGIC_FL    /* AFS directory */
+#define OCFS2_JOURNAL_DATA_FL          FS_JOURNAL_DATA_FL /* Reserved for ext3 */
+#define OCFS2_NOTAIL_FL                        FS_NOTAIL_FL    /* file tail should not be merged */
+#define OCFS2_DIRSYNC_FL               FS_DIRSYNC_FL   /* dirsync behaviour (directories only) */
+#define OCFS2_TOPDIR_FL                        FS_TOPDIR_FL    /* Top of directory hierarchies*/
+#define OCFS2_RESERVED_FL              FS_RESERVED_FL  /* reserved for ext2 lib */
+
+#define OCFS2_FL_VISIBLE               FS_FL_USER_VISIBLE      /* User visible flags */
+#define OCFS2_FL_MODIFIABLE            FS_FL_USER_MODIFIABLE   /* User modifiable flags */
 
 /*
  * Extent record flags (e_node.leaf.flags)
 #define OCFS2_VOL_UUID_LEN             16
 #define OCFS2_MAX_VOL_LABEL_LEN                64
 
-/* The alternate, userspace stack fields */
+/* The cluster stack fields */
 #define OCFS2_STACK_LABEL_LEN          4
 #define OCFS2_CLUSTER_NAME_LEN         16
 
+/* Classic (historically speaking) cluster stack */
+#define OCFS2_CLASSIC_CLUSTER_STACK    "o2cb"
+
 /* Journal limits (in bytes) */
 #define OCFS2_MIN_JOURNAL_SIZE         (4 * 1024 * 1024)
 
  */
 #define OCFS2_MIN_XATTR_INLINE_SIZE     256
 
+/*
+ * Cluster info flags (ocfs2_cluster_info.ci_stackflags)
+ */
+#define OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT    (0x01)
+
 struct ocfs2_system_inode_info {
        char    *si_name;
        int     si_iflags;
@@ -309,6 +338,7 @@ enum {
        USER_QUOTA_SYSTEM_INODE,
        GROUP_QUOTA_SYSTEM_INODE,
 #define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE
+#define OCFS2_FIRST_LOCAL_SYSTEM_INODE ORPHAN_DIR_SYSTEM_INODE
        ORPHAN_DIR_SYSTEM_INODE,
        EXTENT_ALLOC_SYSTEM_INODE,
        INODE_ALLOC_SYSTEM_INODE,
@@ -317,8 +347,12 @@ enum {
        TRUNCATE_LOG_SYSTEM_INODE,
        LOCAL_USER_QUOTA_SYSTEM_INODE,
        LOCAL_GROUP_QUOTA_SYSTEM_INODE,
+#define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE
        NUM_SYSTEM_INODES
 };
+#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE
+#define NUM_LOCAL_SYSTEM_INODES        \
+               (NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE)
 
 static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
        /* Global system inodes (single copy) */
@@ -347,6 +381,7 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
 /* Parameter passed from mount.ocfs2 to module */
 #define OCFS2_HB_NONE                  "heartbeat=none"
 #define OCFS2_HB_LOCAL                 "heartbeat=local"
+#define OCFS2_HB_GLOBAL                        "heartbeat=global"
 
 /*
  * OCFS2 directory file types.  Only the low 3 bits are used.  The
@@ -553,9 +588,21 @@ struct ocfs2_slot_map_extended {
  */
 };
 
+/*
+ * ci_stackflags is only valid if the incompat bit
+ * OCFS2_FEATURE_INCOMPAT_CLUSTERINFO is set.
+ */
 struct ocfs2_cluster_info {
 /*00*/ __u8   ci_stack[OCFS2_STACK_LABEL_LEN];
-       __le32 ci_reserved;
+       union {
+               __le32 ci_reserved;
+               struct {
+                       __u8 ci_stackflags;
+                       __u8 ci_reserved1;
+                       __u8 ci_reserved2;
+                       __u8 ci_reserved3;
+               };
+       };
 /*08*/ __u8   ci_cluster[OCFS2_CLUSTER_NAME_LEN];
 /*18*/
 };
@@ -592,9 +639,9 @@ struct ocfs2_super_block {
                                         * group header */
 /*50*/ __u8  s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
 /*90*/ __u8  s_uuid[OCFS2_VOL_UUID_LEN];       /* 128-bit uuid */
-/*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Selected userspace
-                                                    stack.  Only valid
-                                                    with INCOMPAT flag. */
+/*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Only valid if either
+                                                    userspace or clusterinfo
+                                                    INCOMPAT flag set. */
 /*B8*/ __le16 s_xattr_inline_size;     /* extended attribute inline size
                                           for this fs*/
        __le16 s_reserved0;
index 2d3420af1a839e0e13626a34c289cd2227bf095a..b46f39bf7438d5048dd5637d5762b4d6c44990e4 100644 (file)
 /*
  * ioctl commands
  */
-#define OCFS2_IOC_GETFLAGS     _IOR('f', 1, long)
-#define OCFS2_IOC_SETFLAGS     _IOW('f', 2, long)
-#define OCFS2_IOC32_GETFLAGS   _IOR('f', 1, int)
-#define OCFS2_IOC32_SETFLAGS   _IOW('f', 2, int)
+#define OCFS2_IOC_GETFLAGS     FS_IOC_GETFLAGS
+#define OCFS2_IOC_SETFLAGS     FS_IOC_SETFLAGS
+#define OCFS2_IOC32_GETFLAGS   FS_IOC32_GETFLAGS
+#define OCFS2_IOC32_SETFLAGS   FS_IOC32_SETFLAGS
 
 /*
  * Space reservation / allocation / free ioctls and argument structure
@@ -76,4 +76,99 @@ struct reflink_arguments {
 };
 #define OCFS2_IOC_REFLINK      _IOW('o', 4, struct reflink_arguments)
 
+/* Following definitions dedicated for ocfs2_info_request ioctls. */
+#define OCFS2_INFO_MAX_REQUEST         (50)
+#define OCFS2_TEXT_UUID_LEN            (OCFS2_VOL_UUID_LEN * 2)
+
+/* Magic number of all requests */
+#define OCFS2_INFO_MAGIC               (0x4F32494E)
+
+/*
+ * Always try to separate info request into small pieces to
+ * guarantee the backward&forward compatibility.
+ */
+struct ocfs2_info {
+       __u64 oi_requests;      /* Array of __u64 pointers to requests */
+       __u32 oi_count;         /* Number of requests in info_requests */
+       __u32 oi_pad;
+};
+
+struct ocfs2_info_request {
+/*00*/ __u32 ir_magic; /* Magic number */
+       __u32 ir_code;  /* Info request code */
+       __u32 ir_size;  /* Size of request */
+       __u32 ir_flags; /* Request flags */
+/*10*/                 /* Request specific fields */
+};
+
+struct ocfs2_info_clustersize {
+       struct ocfs2_info_request ic_req;
+       __u32 ic_clustersize;
+       __u32 ic_pad;
+};
+
+struct ocfs2_info_blocksize {
+       struct ocfs2_info_request ib_req;
+       __u32 ib_blocksize;
+       __u32 ib_pad;
+};
+
+struct ocfs2_info_maxslots {
+       struct ocfs2_info_request im_req;
+       __u32 im_max_slots;
+       __u32 im_pad;
+};
+
+struct ocfs2_info_label {
+       struct ocfs2_info_request il_req;
+       __u8    il_label[OCFS2_MAX_VOL_LABEL_LEN];
+} __attribute__ ((packed));
+
+struct ocfs2_info_uuid {
+       struct ocfs2_info_request iu_req;
+       __u8    iu_uuid_str[OCFS2_TEXT_UUID_LEN + 1];
+} __attribute__ ((packed));
+
+struct ocfs2_info_fs_features {
+       struct ocfs2_info_request if_req;
+       __u32 if_compat_features;
+       __u32 if_incompat_features;
+       __u32 if_ro_compat_features;
+       __u32 if_pad;
+};
+
+struct ocfs2_info_journal_size {
+       struct ocfs2_info_request ij_req;
+       __u64 ij_journal_size;
+};
+
+/* Codes for ocfs2_info_request */
+enum ocfs2_info_type {
+       OCFS2_INFO_CLUSTERSIZE = 1,
+       OCFS2_INFO_BLOCKSIZE,
+       OCFS2_INFO_MAXSLOTS,
+       OCFS2_INFO_LABEL,
+       OCFS2_INFO_UUID,
+       OCFS2_INFO_FS_FEATURES,
+       OCFS2_INFO_JOURNAL_SIZE,
+       OCFS2_INFO_NUM_TYPES
+};
+
+/* Flags for struct ocfs2_info_request */
+/* Filled by the caller */
+#define OCFS2_INFO_FL_NON_COHERENT     (0x00000001)    /* Cluster coherency not
+                                                          required. This is a hint.
+                                                          It is up to ocfs2 whether
+                                                          the request can be fulfilled
+                                                          without locking. */
+/* Filled by ocfs2 */
+#define OCFS2_INFO_FL_FILLED           (0x40000000)    /* Filesystem understood
+                                                          this request and
+                                                          filled in the answer */
+
+#define OCFS2_INFO_FL_ERROR            (0x80000000)    /* Error happened during
+                                                          request handling. */
+
+#define OCFS2_IOC_INFO         _IOR('o', 5, struct ocfs2_info)
+
 #endif /* OCFS2_IOCTL_H */
index 73a11ccfd4c280681abe672c5e9cd81e3b229a93..b5f9160e93e9119b949451bb3e5db66b3c1df62c 100644 (file)
@@ -49,6 +49,7 @@
 
 struct ocfs2_cow_context {
        struct inode *inode;
+       struct file *file;
        u32 cow_start;
        u32 cow_len;
        struct ocfs2_extent_tree data_et;
@@ -2932,13 +2933,16 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
        u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster);
        struct page *page;
        pgoff_t page_index;
-       unsigned int from, to;
+       unsigned int from, to, readahead_pages;
        loff_t offset, end, map_end;
        struct address_space *mapping = context->inode->i_mapping;
 
        mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster,
             new_cluster, new_len, cpos);
 
+       readahead_pages =
+               (ocfs2_cow_contig_clusters(sb) <<
+                OCFS2_SB(sb)->s_clustersize_bits) >> PAGE_CACHE_SHIFT;
        offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits;
        end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits);
        /*
@@ -2960,7 +2964,7 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
                if (map_end & (PAGE_CACHE_SIZE - 1))
                        to = map_end & (PAGE_CACHE_SIZE - 1);
 
-               page = grab_cache_page(mapping, page_index);
+               page = find_or_create_page(mapping, page_index, GFP_NOFS);
 
                /*
                 * In case PAGE_CACHE_SIZE <= CLUSTER_SIZE, This page
@@ -2969,6 +2973,14 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
                if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize)
                        BUG_ON(PageDirty(page));
 
+               if (PageReadahead(page) && context->file) {
+                       page_cache_async_readahead(mapping,
+                                                  &context->file->f_ra,
+                                                  context->file,
+                                                  page, page_index,
+                                                  readahead_pages);
+               }
+
                if (!PageUptodate(page)) {
                        ret = block_read_full_page(page, ocfs2_get_block);
                        if (ret) {
@@ -3179,7 +3191,8 @@ static int ocfs2_cow_sync_writeback(struct super_block *sb,
                if (map_end > end)
                        map_end = end;
 
-               page = grab_cache_page(context->inode->i_mapping, page_index);
+               page = find_or_create_page(context->inode->i_mapping,
+                                          page_index, GFP_NOFS);
                BUG_ON(!page);
 
                wait_on_page_writeback(page);
@@ -3408,12 +3421,35 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context)
        return ret;
 }
 
+static void ocfs2_readahead_for_cow(struct inode *inode,
+                                   struct file *file,
+                                   u32 start, u32 len)
+{
+       struct address_space *mapping;
+       pgoff_t index;
+       unsigned long num_pages;
+       int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+
+       if (!file)
+               return;
+
+       mapping = file->f_mapping;
+       num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT;
+       if (!num_pages)
+               num_pages = 1;
+
+       index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT;
+       page_cache_sync_readahead(mapping, &file->f_ra, file,
+                                 index, num_pages);
+}
+
 /*
  * Starting at cpos, try to CoW write_len clusters.  Don't CoW
  * past max_cpos.  This will stop when it runs into a hole or an
  * unrefcounted extent.
  */
 static int ocfs2_refcount_cow_hunk(struct inode *inode,
+                                  struct file *file,
                                   struct buffer_head *di_bh,
                                   u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3442,6 +3478,8 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
 
        BUG_ON(cow_len == 0);
 
+       ocfs2_readahead_for_cow(inode, file, cow_start, cow_len);
+
        context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS);
        if (!context) {
                ret = -ENOMEM;
@@ -3463,6 +3501,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
        context->ref_root_bh = ref_root_bh;
        context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page;
        context->get_clusters = ocfs2_di_get_clusters;
+       context->file = file;
 
        ocfs2_init_dinode_extent_tree(&context->data_et,
                                      INODE_CACHE(inode), di_bh);
@@ -3491,6 +3530,7 @@ out:
  * clusters between cpos and cpos+write_len are safe to modify.
  */
 int ocfs2_refcount_cow(struct inode *inode,
+                      struct file *file,
                       struct buffer_head *di_bh,
                       u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3510,7 +3550,7 @@ int ocfs2_refcount_cow(struct inode *inode,
                        num_clusters = write_len;
 
                if (ext_flags & OCFS2_EXT_REFCOUNTED) {
-                       ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos,
+                       ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos,
                                                      num_clusters, max_cpos);
                        if (ret) {
                                mlog_errno(ret);
@@ -4200,8 +4240,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry,
                goto out;
        }
 
-       mutex_lock(&new_inode->i_mutex);
-       ret = ocfs2_inode_lock(new_inode, &new_bh, 1);
+       mutex_lock_nested(&new_inode->i_mutex, I_MUTEX_CHILD);
+       ret = ocfs2_inode_lock_nested(new_inode, &new_bh, 1,
+                                     OI_LS_REFLINK_TARGET);
        if (ret) {
                mlog_errno(ret);
                goto out_unlock;
index 9983ba1570e20073bb45e3d8e47f78e320afe1a5..c8ce46f7d8e30ee842cc8966a8c034aefae3b98b 100644 (file)
@@ -21,14 +21,14 @@ struct ocfs2_refcount_tree {
        struct rb_node rf_node;
        u64 rf_blkno;
        u32 rf_generation;
+       struct kref rf_getcnt;
        struct rw_semaphore rf_sem;
        struct ocfs2_lock_res rf_lockres;
-       struct kref rf_getcnt;
        int rf_removed;
 
        /* the following 4 fields are used by caching_info. */
-       struct ocfs2_caching_info rf_ci;
        spinlock_t rf_lock;
+       struct ocfs2_caching_info rf_ci;
        struct mutex rf_io_mutex;
        struct super_block *rf_sb;
 };
@@ -52,7 +52,8 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
                                          u32 clusters,
                                          int *credits,
                                          int *ref_blocks);
-int ocfs2_refcount_cow(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_refcount_cow(struct inode *inode,
+                      struct file *filep, struct buffer_head *di_bh,
                       u32 cpos, u32 write_len, u32 max_cpos);
 
 typedef int (ocfs2_post_refcount_func)(struct inode *inode,
index d8b6e4259b80022cb824326f4ce2c665089b5818..3e78db361bc70b3ffc327a6f21b6d4580305d0eb 100644 (file)
@@ -732,25 +732,23 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap,
                           struct ocfs2_alloc_reservation *resv,
                           int *cstart, int *clen)
 {
-       unsigned int wanted = *clen;
-
        if (resv == NULL || ocfs2_resmap_disabled(resmap))
                return -ENOSPC;
 
        spin_lock(&resv_lock);
 
-       /*
-        * We don't want to over-allocate for temporary
-        * windows. Otherwise, we run the risk of fragmenting the
-        * allocation space.
-        */
-       wanted = ocfs2_resv_window_bits(resmap, resv);
-       if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen)
-               wanted = *clen;
-
        if (ocfs2_resv_empty(resv)) {
-               mlog(0, "empty reservation, find new window\n");
+               /*
+                * We don't want to over-allocate for temporary
+                * windows. Otherwise, we run the risk of fragmenting the
+                * allocation space.
+                */
+               unsigned int wanted = ocfs2_resv_window_bits(resmap, resv);
 
+               if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen)
+                       wanted = *clen;
+
+               mlog(0, "empty reservation, find new window\n");
                /*
                 * Try to get a window here. If it works, we must fall
                 * through and test the bitmap . This avoids some
index bfbd7e9e949f0a26bbf0afecba362a449c6e45cf..ab4e0172cc1d11abc3c5d70c62a9298d652fb096 100644 (file)
@@ -357,7 +357,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
 {
        int status = 0;
        u64 blkno;
-       unsigned long long blocks, bytes;
+       unsigned long long blocks, bytes = 0;
        unsigned int i;
        struct buffer_head *bh;
 
index 0d3049f696c5418448173ed3538020bd5d51b9d0..19965b00c43caee7df4e09428775a55150ba9f8c 100644 (file)
@@ -283,6 +283,8 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
        /* for now we only have one cluster/node, make sure we see it
         * in the heartbeat universe */
        if (!o2hb_check_local_node_heartbeating()) {
+               if (o2hb_global_heartbeat_active())
+                       mlog(ML_ERROR, "Global heartbeat not started\n");
                rc = -EINVAL;
                goto out;
        }
index 2dc57bca0688165366364d88448d1e884ef6dd9f..252e7c82f929c203aca6a294d24b49dd17612cee 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/reboot.h>
 #include <asm/uaccess.h>
 
@@ -612,12 +611,10 @@ static int ocfs2_control_open(struct inode *inode, struct file *file)
                return -ENOMEM;
        p->op_this_node = -1;
 
-       lock_kernel();
        mutex_lock(&ocfs2_control_lock);
        file->private_data = p;
        list_add(&p->op_list, &ocfs2_control_private_list);
        mutex_unlock(&ocfs2_control_lock);
-       unlock_kernel();
 
        return 0;
 }
@@ -628,6 +625,7 @@ static const struct file_operations ocfs2_control_fops = {
        .read    = ocfs2_control_read,
        .write   = ocfs2_control_write,
        .owner   = THIS_MODULE,
+       .llseek  = default_llseek,
 };
 
 static struct miscdevice ocfs2_control_device = {
index a8e6a95a353f03dcb8a34cf928ded84ff7e6d127..5fed60de7630f4ed94c4ab429eb8f7187f679468 100644 (file)
@@ -57,11 +57,28 @@ struct ocfs2_suballoc_result {
        u64             sr_bg_blkno;    /* The bg we allocated from.  Set
                                           to 0 when a block group is
                                           contiguous. */
+       u64             sr_bg_stable_blkno; /*
+                                            * Doesn't change, always
+                                            * set to target block
+                                            * group descriptor
+                                            * block.
+                                            */
        u64             sr_blkno;       /* The first allocated block */
        unsigned int    sr_bit_offset;  /* The bit in the bg */
        unsigned int    sr_bits;        /* How many bits we claimed */
 };
 
+static u64 ocfs2_group_from_res(struct ocfs2_suballoc_result *res)
+{
+       if (res->sr_blkno == 0)
+               return 0;
+
+       if (res->sr_bg_blkno)
+               return res->sr_bg_blkno;
+
+       return ocfs2_which_suballoc_group(res->sr_blkno, res->sr_bit_offset);
+}
+
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
 static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
 static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
@@ -138,6 +155,10 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
        brelse(ac->ac_bh);
        ac->ac_bh = NULL;
        ac->ac_resv = NULL;
+       if (ac->ac_find_loc_priv) {
+               kfree(ac->ac_find_loc_priv);
+               ac->ac_find_loc_priv = NULL;
+       }
 }
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
@@ -336,7 +357,7 @@ out:
 static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb,
                                          struct ocfs2_group_desc *bg,
                                          struct ocfs2_chain_list *cl,
-                                         u64 p_blkno, u32 clusters)
+                                         u64 p_blkno, unsigned int clusters)
 {
        struct ocfs2_extent_list *el = &bg->bg_list;
        struct ocfs2_extent_rec *rec;
@@ -348,7 +369,7 @@ static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb,
        rec->e_blkno = cpu_to_le64(p_blkno);
        rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) /
                                  le16_to_cpu(cl->cl_bpc));
-       rec->e_leaf_clusters = cpu_to_le32(clusters);
+       rec->e_leaf_clusters = cpu_to_le16(clusters);
        le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc));
        le16_add_cpu(&bg->bg_free_bits_count,
                     clusters * le16_to_cpu(cl->cl_bpc));
@@ -1359,6 +1380,14 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        }
 
        le16_add_cpu(&bg->bg_free_bits_count, -num_bits);
+       if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
+               ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
+                           " count %u but claims %u are freed. num_bits %d",
+                           (unsigned long long)le64_to_cpu(bg->bg_blkno),
+                           le16_to_cpu(bg->bg_bits),
+                           le16_to_cpu(bg->bg_free_bits_count), num_bits);
+               return -EROFS;
+       }
        while(num_bits--)
                ocfs2_set_bit(bit_off++, bitmap);
 
@@ -1678,6 +1707,15 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
        if (!ret)
                ocfs2_bg_discontig_fix_result(ac, gd, res);
 
+       /*
+        * sr_bg_blkno might have been changed by
+        * ocfs2_bg_discontig_fix_result
+        */
+       res->sr_bg_stable_blkno = group_bh->b_blocknr;
+
+       if (ac->ac_find_loc_only)
+               goto out_loc_only;
+
        ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
                                               res->sr_bits,
                                               le16_to_cpu(gd->bg_chain));
@@ -1691,6 +1729,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
        if (ret < 0)
                mlog_errno(ret);
 
+out_loc_only:
        *bits_left = le16_to_cpu(gd->bg_free_bits_count);
 
 out:
@@ -1708,7 +1747,6 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 {
        int status;
        u16 chain;
-       u32 tmp_used;
        u64 next_group;
        struct inode *alloc_inode = ac->ac_inode;
        struct buffer_head *group_bh = NULL;
@@ -1770,6 +1808,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        if (!status)
                ocfs2_bg_discontig_fix_result(ac, bg, res);
 
+       /*
+        * sr_bg_blkno might have been changed by
+        * ocfs2_bg_discontig_fix_result
+        */
+       res->sr_bg_stable_blkno = group_bh->b_blocknr;
 
        /*
         * Keep track of previous block descriptor read. When
@@ -1796,22 +1839,17 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                }
        }
 
-       /* Ok, claim our bits now: set the info on dinode, chainlist
-        * and then the group */
-       status = ocfs2_journal_access_di(handle,
-                                        INODE_CACHE(alloc_inode),
-                                        ac->ac_bh,
-                                        OCFS2_JOURNAL_ACCESS_WRITE);
-       if (status < 0) {
+       if (ac->ac_find_loc_only)
+               goto out_loc_only;
+
+       status = ocfs2_alloc_dinode_update_counts(alloc_inode, handle,
+                                                 ac->ac_bh, res->sr_bits,
+                                                 chain);
+       if (status) {
                mlog_errno(status);
                goto bail;
        }
 
-       tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
-       fe->id1.bitmap1.i_used = cpu_to_le32(res->sr_bits + tmp_used);
-       le32_add_cpu(&cl->cl_recs[chain].c_free, -res->sr_bits);
-       ocfs2_journal_dirty(handle, ac->ac_bh);
-
        status = ocfs2_block_group_set_bits(handle,
                                            alloc_inode,
                                            bg,
@@ -1826,6 +1864,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
             (unsigned long long)le64_to_cpu(fe->i_blkno));
 
+out_loc_only:
        *bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
        brelse(group_bh);
@@ -1845,6 +1884,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
        int status;
        u16 victim, i;
        u16 bits_left = 0;
+       u64 hint = ac->ac_last_group;
        struct ocfs2_chain_list *cl;
        struct ocfs2_dinode *fe;
 
@@ -1872,7 +1912,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
                goto bail;
        }
 
-       res->sr_bg_blkno = ac->ac_last_group;
+       res->sr_bg_blkno = hint;
        if (res->sr_bg_blkno) {
                /* Attempt to short-circuit the usual search mechanism
                 * by jumping straight to the most recently used
@@ -1896,8 +1936,10 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
 
        status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
                                    res, &bits_left);
-       if (!status)
+       if (!status) {
+               hint = ocfs2_group_from_res(res);
                goto set_hint;
+       }
        if (status < 0 && status != -ENOSPC) {
                mlog_errno(status);
                goto bail;
@@ -1920,8 +1962,10 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
                ac->ac_chain = i;
                status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
                                            res, &bits_left);
-               if (!status)
+               if (!status) {
+                       hint = ocfs2_group_from_res(res);
                        break;
+               }
                if (status < 0 && status != -ENOSPC) {
                        mlog_errno(status);
                        goto bail;
@@ -1936,7 +1980,7 @@ set_hint:
                if (bits_left < min_bits)
                        ac->ac_last_group = 0;
                else
-                       ac->ac_last_group = res->sr_bg_blkno;
+                       ac->ac_last_group = hint;
        }
 
 bail:
@@ -2016,6 +2060,136 @@ static inline void ocfs2_save_inode_ac_group(struct inode *dir,
        OCFS2_I(dir)->ip_last_used_slot = ac->ac_alloc_slot;
 }
 
+int ocfs2_find_new_inode_loc(struct inode *dir,
+                            struct buffer_head *parent_fe_bh,
+                            struct ocfs2_alloc_context *ac,
+                            u64 *fe_blkno)
+{
+       int ret;
+       handle_t *handle = NULL;
+       struct ocfs2_suballoc_result *res;
+
+       BUG_ON(!ac);
+       BUG_ON(ac->ac_bits_given != 0);
+       BUG_ON(ac->ac_bits_wanted != 1);
+       BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE);
+
+       res = kzalloc(sizeof(*res), GFP_NOFS);
+       if (res == NULL) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ocfs2_init_inode_ac_group(dir, parent_fe_bh, ac);
+
+       /*
+        * The handle started here is for chain relink. Alternatively,
+        * we could just disable relink for these calls.
+        */
+       handle = ocfs2_start_trans(OCFS2_SB(dir->i_sb), OCFS2_SUBALLOC_ALLOC);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       /*
+        * This will instruct ocfs2_claim_suballoc_bits and
+        * ocfs2_search_one_group to search but save actual allocation
+        * for later.
+        */
+       ac->ac_find_loc_only = 1;
+
+       ret = ocfs2_claim_suballoc_bits(ac, handle, 1, 1, res);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ac->ac_find_loc_priv = res;
+       *fe_blkno = res->sr_blkno;
+
+out:
+       if (handle)
+               ocfs2_commit_trans(OCFS2_SB(dir->i_sb), handle);
+
+       if (ret)
+               kfree(res);
+
+       return ret;
+}
+
+int ocfs2_claim_new_inode_at_loc(handle_t *handle,
+                                struct inode *dir,
+                                struct ocfs2_alloc_context *ac,
+                                u64 *suballoc_loc,
+                                u16 *suballoc_bit,
+                                u64 di_blkno)
+{
+       int ret;
+       u16 chain;
+       struct ocfs2_suballoc_result *res = ac->ac_find_loc_priv;
+       struct buffer_head *bg_bh = NULL;
+       struct ocfs2_group_desc *bg;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *) ac->ac_bh->b_data;
+
+       /*
+        * Since di_blkno is being passed back in, we check for any
+        * inconsistencies which may have happened between
+        * calls. These are code bugs as di_blkno is not expected to
+        * change once returned from ocfs2_find_new_inode_loc()
+        */
+       BUG_ON(res->sr_blkno != di_blkno);
+
+       ret = ocfs2_read_group_descriptor(ac->ac_inode, di,
+                                         res->sr_bg_stable_blkno, &bg_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+       chain = le16_to_cpu(bg->bg_chain);
+
+       ret = ocfs2_alloc_dinode_update_counts(ac->ac_inode, handle,
+                                              ac->ac_bh, res->sr_bits,
+                                              chain);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_block_group_set_bits(handle,
+                                        ac->ac_inode,
+                                        bg,
+                                        bg_bh,
+                                        res->sr_bit_offset,
+                                        res->sr_bits);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
+            (unsigned long long)di_blkno);
+
+       atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
+
+       BUG_ON(res->sr_bits != 1);
+
+       *suballoc_loc = res->sr_bg_blkno;
+       *suballoc_bit = res->sr_bit_offset;
+       ac->ac_bits_given++;
+       ocfs2_save_inode_ac_group(dir, ac);
+
+out:
+       brelse(bg_bh);
+
+       return ret;
+}
+
 int ocfs2_claim_new_inode(handle_t *handle,
                          struct inode *dir,
                          struct buffer_head *parent_fe_bh,
@@ -2253,6 +2427,14 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
                                (unsigned long *) undo_bg->bg_bitmap);
        }
        le16_add_cpu(&bg->bg_free_bits_count, num_bits);
+       if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
+               ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
+                           " count %u but claims %u are freed. num_bits %d",
+                           (unsigned long long)le64_to_cpu(bg->bg_blkno),
+                           le16_to_cpu(bg->bg_bits),
+                           le16_to_cpu(bg->bg_free_bits_count), num_bits);
+               return -EROFS;
+       }
 
        if (undo_fn)
                jbd_unlock_bh_state(group_bh);
@@ -2567,7 +2749,8 @@ out:
  * suballoc_bit.
  */
 static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno,
-                                      u16 *suballoc_slot, u16 *suballoc_bit)
+                                      u16 *suballoc_slot, u64 *group_blkno,
+                                      u16 *suballoc_bit)
 {
        int status;
        struct buffer_head *inode_bh = NULL;
@@ -2604,6 +2787,8 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno,
                *suballoc_slot = le16_to_cpu(inode_fe->i_suballoc_slot);
        if (suballoc_bit)
                *suballoc_bit = le16_to_cpu(inode_fe->i_suballoc_bit);
+       if (group_blkno)
+               *group_blkno = le64_to_cpu(inode_fe->i_suballoc_loc);
 
 bail:
        brelse(inode_bh);
@@ -2621,7 +2806,8 @@ bail:
  */
 static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
                                   struct inode *suballoc,
-                                  struct buffer_head *alloc_bh, u64 blkno,
+                                  struct buffer_head *alloc_bh,
+                                  u64 group_blkno, u64 blkno,
                                   u16 bit, int *res)
 {
        struct ocfs2_dinode *alloc_di;
@@ -2642,10 +2828,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
                goto bail;
        }
 
-       if (alloc_di->i_suballoc_loc)
-               bg_blkno = le64_to_cpu(alloc_di->i_suballoc_loc);
-       else
-               bg_blkno = ocfs2_which_suballoc_group(blkno, bit);
+       bg_blkno = group_blkno ? group_blkno :
+                  ocfs2_which_suballoc_group(blkno, bit);
        status = ocfs2_read_group_descriptor(suballoc, alloc_di, bg_blkno,
                                             &group_bh);
        if (status < 0) {
@@ -2680,6 +2864,7 @@ bail:
 int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
 {
        int status;
+       u64 group_blkno = 0;
        u16 suballoc_bit = 0, suballoc_slot = 0;
        struct inode *inode_alloc_inode;
        struct buffer_head *alloc_bh = NULL;
@@ -2687,7 +2872,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
        mlog_entry("blkno: %llu", (unsigned long long)blkno);
 
        status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot,
-                                            &suballoc_bit);
+                                            &group_blkno, &suballoc_bit);
        if (status < 0) {
                mlog(ML_ERROR, "get alloc slot and bit failed %d\n", status);
                goto bail;
@@ -2715,7 +2900,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
        }
 
        status = ocfs2_test_suballoc_bit(osb, inode_alloc_inode, alloc_bh,
-                                        blkno, suballoc_bit, res);
+                                        group_blkno, blkno, suballoc_bit, res);
        if (status < 0)
                mlog(ML_ERROR, "test suballoc bit failed %d\n", status);
 
index a017dd3ee7d9ce2d6c0429d090b57ac077ed585a..b8afabfeede4c43694bdb8bf0a9664b0befd24a6 100644 (file)
@@ -56,6 +56,9 @@ struct ocfs2_alloc_context {
        u64    ac_max_block;  /* Highest block number to allocate. 0 is
                                 is the same as ~0 - unlimited */
 
+       int    ac_find_loc_only;  /* hack for reflink operation ordering */
+       struct ocfs2_suballoc_result *ac_find_loc_priv; /* */
+
        struct ocfs2_alloc_reservation  *ac_resv;
 };
 
@@ -197,4 +200,22 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_extent_tree *et,
                          struct ocfs2_alloc_context **meta_ac);
 
 int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res);
+
+
+
+/*
+ * The following two interfaces are for ocfs2_create_inode_in_orphan().
+ */
+int ocfs2_find_new_inode_loc(struct inode *dir,
+                            struct buffer_head *parent_fe_bh,
+                            struct ocfs2_alloc_context *ac,
+                            u64 *fe_blkno);
+
+int ocfs2_claim_new_inode_at_loc(handle_t *handle,
+                                struct inode *dir,
+                                struct ocfs2_alloc_context *ac,
+                                u64 *suballoc_loc,
+                                u16 *suballoc_bit,
+                                u64 di_blkno);
+
 #endif /* _CHAINALLOC_H_ */
index fa1be1b304d10b7bf30c4ecb2c7a3fd9b3ecd8ca..56f0cb3958209b944ecb07a3a8262efc3b9aa75d 100644 (file)
@@ -162,6 +162,7 @@ enum {
        Opt_nointr,
        Opt_hb_none,
        Opt_hb_local,
+       Opt_hb_global,
        Opt_data_ordered,
        Opt_data_writeback,
        Opt_atime_quantum,
@@ -177,6 +178,8 @@ enum {
        Opt_noacl,
        Opt_usrquota,
        Opt_grpquota,
+       Opt_coherency_buffered,
+       Opt_coherency_full,
        Opt_resv_level,
        Opt_dir_resv_level,
        Opt_err,
@@ -190,6 +193,7 @@ static const match_table_t tokens = {
        {Opt_nointr, "nointr"},
        {Opt_hb_none, OCFS2_HB_NONE},
        {Opt_hb_local, OCFS2_HB_LOCAL},
+       {Opt_hb_global, OCFS2_HB_GLOBAL},
        {Opt_data_ordered, "data=ordered"},
        {Opt_data_writeback, "data=writeback"},
        {Opt_atime_quantum, "atime_quantum=%u"},
@@ -205,6 +209,8 @@ static const match_table_t tokens = {
        {Opt_noacl, "noacl"},
        {Opt_usrquota, "usrquota"},
        {Opt_grpquota, "grpquota"},
+       {Opt_coherency_buffered, "coherency=buffered"},
+       {Opt_coherency_full, "coherency=full"},
        {Opt_resv_level, "resv_level=%u"},
        {Opt_dir_resv_level, "dir_resv_level=%u"},
        {Opt_err, NULL}
@@ -514,11 +520,11 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
 
        mlog_entry_void();
 
-       for (i = 0; i < NUM_SYSTEM_INODES; i++) {
-               inode = osb->system_inodes[i];
+       for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) {
+               inode = osb->global_system_inodes[i];
                if (inode) {
                        iput(inode);
-                       osb->system_inodes[i] = NULL;
+                       osb->global_system_inodes[i] = NULL;
                }
        }
 
@@ -534,6 +540,20 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
                osb->root_inode = NULL;
        }
 
+       if (!osb->local_system_inodes)
+               goto out;
+
+       for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) {
+               if (osb->local_system_inodes[i]) {
+                       iput(osb->local_system_inodes[i]);
+                       osb->local_system_inodes[i] = NULL;
+               }
+       }
+
+       kfree(osb->local_system_inodes);
+       osb->local_system_inodes = NULL;
+
+out:
        mlog_exit(0);
 }
 
@@ -608,8 +628,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
        int ret = 0;
        struct mount_options parsed_options;
        struct ocfs2_super *osb = OCFS2_SB(sb);
-
-       lock_kernel();
+       u32 tmp;
 
        if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
            !ocfs2_check_set_options(sb, &parsed_options)) {
@@ -617,8 +636,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                goto out;
        }
 
-       if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) !=
-           (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+       tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
+               OCFS2_MOUNT_HB_NONE;
+       if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) {
                ret = -EINVAL;
                mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n");
                goto out;
@@ -717,7 +737,6 @@ unlock_osb:
                                                        MS_POSIXACL : 0);
        }
 out:
-       unlock_kernel();
        return ret;
 }
 
@@ -809,23 +828,29 @@ bail:
 
 static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
 {
-       if (ocfs2_mount_local(osb)) {
-               if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+       u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL;
+
+       if (osb->s_mount_opt & hb_enabled) {
+               if (ocfs2_mount_local(osb)) {
                        mlog(ML_ERROR, "Cannot heartbeat on a locally "
                             "mounted device.\n");
                        return -EINVAL;
                }
-       }
-
-       if (ocfs2_userspace_stack(osb)) {
-               if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+               if (ocfs2_userspace_stack(osb)) {
                        mlog(ML_ERROR, "Userspace stack expected, but "
                             "o2cb heartbeat arguments passed to mount\n");
                        return -EINVAL;
                }
+               if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) &&
+                    !ocfs2_cluster_o2cb_global_heartbeat(osb)) ||
+                   ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) &&
+                    ocfs2_cluster_o2cb_global_heartbeat(osb))) {
+                       mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n");
+                       return -EINVAL;
+               }
        }
 
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+       if (!(osb->s_mount_opt & hb_enabled)) {
                if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) &&
                    !ocfs2_userspace_stack(osb)) {
                        mlog(ML_ERROR, "Heartbeat has to be started to mount "
@@ -1291,6 +1316,7 @@ static int ocfs2_parse_options(struct super_block *sb,
 {
        int status;
        char *p;
+       u32 tmp;
 
        mlog_entry("remount: %d, options: \"%s\"\n", is_remount,
                   options ? options : "(none)");
@@ -1322,7 +1348,10 @@ static int ocfs2_parse_options(struct super_block *sb,
                        mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL;
                        break;
                case Opt_hb_none:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL;
+                       mopt->mount_opt |= OCFS2_MOUNT_HB_NONE;
+                       break;
+               case Opt_hb_global:
+                       mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL;
                        break;
                case Opt_barrier:
                        if (match_int(&args[0], &option)) {
@@ -1438,6 +1467,12 @@ static int ocfs2_parse_options(struct super_block *sb,
                case Opt_grpquota:
                        mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
                        break;
+               case Opt_coherency_buffered:
+                       mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED;
+                       break;
+               case Opt_coherency_full:
+                       mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED;
+                       break;
                case Opt_acl:
                        mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
                        mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL;
@@ -1477,6 +1512,15 @@ static int ocfs2_parse_options(struct super_block *sb,
                }
        }
 
+       /* Ensure only one heartbeat mode */
+       tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
+                                OCFS2_MOUNT_HB_NONE);
+       if (hweight32(tmp) != 1) {
+               mlog(ML_ERROR, "Invalid heartbeat mount options\n");
+               status = 0;
+               goto bail;
+       }
+
        status = 1;
 
 bail:
@@ -1490,10 +1534,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        unsigned long opts = osb->s_mount_opt;
        unsigned int local_alloc_megs;
 
-       if (opts & OCFS2_MOUNT_HB_LOCAL)
-               seq_printf(s, ",_netdev,heartbeat=local");
-       else
-               seq_printf(s, ",heartbeat=none");
+       if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) {
+               seq_printf(s, ",_netdev");
+               if (opts & OCFS2_MOUNT_HB_LOCAL)
+                       seq_printf(s, ",%s", OCFS2_HB_LOCAL);
+               else
+                       seq_printf(s, ",%s", OCFS2_HB_GLOBAL);
+       } else
+               seq_printf(s, ",%s", OCFS2_HB_NONE);
 
        if (opts & OCFS2_MOUNT_NOINTR)
                seq_printf(s, ",nointr");
@@ -1536,6 +1584,11 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (opts & OCFS2_MOUNT_GRPQUOTA)
                seq_printf(s, ",grpquota");
 
+       if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED)
+               seq_printf(s, ",coherency=buffered");
+       else
+               seq_printf(s, ",coherency=full");
+
        if (opts & OCFS2_MOUNT_NOUSERXATTR)
                seq_printf(s, ",nouser_xattr");
        else
@@ -1640,13 +1693,9 @@ static void ocfs2_put_super(struct super_block *sb)
 {
        mlog_entry("(0x%p)\n", sb);
 
-       lock_kernel();
-
        ocfs2_sync_blockdev(sb);
        ocfs2_dismount_volume(sb, 0);
 
-       unlock_kernel();
-
        mlog_exit_void();
 }
 
@@ -1990,6 +2039,36 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu
        return 0;
 }
 
+/* Make sure entire volume is addressable by our journal.  Requires
+   osb_clusters_at_boot to be valid and for the journal to have been
+   initialized by ocfs2_journal_init(). */
+static int ocfs2_journal_addressable(struct ocfs2_super *osb)
+{
+       int status = 0;
+       u64 max_block =
+               ocfs2_clusters_to_blocks(osb->sb,
+                                        osb->osb_clusters_at_boot) - 1;
+
+       /* 32-bit block number is always OK. */
+       if (max_block <= (u32)~0ULL)
+               goto out;
+
+       /* Volume is "huge", so see if our journal is new enough to
+          support it. */
+       if (!(OCFS2_HAS_COMPAT_FEATURE(osb->sb,
+                                      OCFS2_FEATURE_COMPAT_JBD2_SB) &&
+             jbd2_journal_check_used_features(osb->journal->j_journal, 0, 0,
+                                              JBD2_FEATURE_INCOMPAT_64BIT))) {
+               mlog(ML_ERROR, "The journal cannot address the entire volume. "
+                    "Enable the 'block64' journal option with tunefs.ocfs2");
+               status = -EFBIG;
+               goto out;
+       }
+
+ out:
+       return status;
+}
+
 static int ocfs2_initialize_super(struct super_block *sb,
                                  struct buffer_head *bh,
                                  int sector_size,
@@ -2002,6 +2081,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
        struct ocfs2_journal *journal;
        __le32 uuid_net_key;
        struct ocfs2_super *osb;
+       u64 total_blocks;
 
        mlog_entry_void();
 
@@ -2060,6 +2140,15 @@ static int ocfs2_initialize_super(struct super_block *sb,
        snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
                 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
 
+       osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);
+       if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {
+               mlog(ML_ERROR, "Invalid number of node slots (%u)\n",
+                    osb->max_slots);
+               status = -EINVAL;
+               goto bail;
+       }
+       mlog(0, "max_slots for this device: %u\n", osb->max_slots);
+
        ocfs2_orphan_scan_init(osb);
 
        status = ocfs2_recovery_init(osb);
@@ -2098,15 +2187,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
                goto bail;
        }
 
-       osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);
-       if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {
-               mlog(ML_ERROR, "Invalid number of node slots (%u)\n",
-                    osb->max_slots);
-               status = -EINVAL;
-               goto bail;
-       }
-       mlog(0, "max_slots for this device: %u\n", osb->max_slots);
-
        osb->slot_recovery_generations =
                kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations),
                        GFP_KERNEL);
@@ -2149,7 +2229,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
                goto bail;
        }
 
-       if (ocfs2_userspace_stack(osb)) {
+       if (ocfs2_clusterinfo_valid(osb)) {
+               osb->osb_stackflags =
+                       OCFS2_RAW_SB(di)->s_cluster_info.ci_stackflags;
                memcpy(osb->osb_cluster_stack,
                       OCFS2_RAW_SB(di)->s_cluster_info.ci_stack,
                       OCFS2_STACK_LABEL_LEN);
@@ -2214,11 +2296,15 @@ static int ocfs2_initialize_super(struct super_block *sb,
                goto bail;
        }
 
-       if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1)
-           > (u32)~0UL) {
-               mlog(ML_ERROR, "Volume might try to write to blocks beyond "
-                    "what jbd can address in 32 bits.\n");
-               status = -EINVAL;
+       total_blocks = ocfs2_clusters_to_blocks(osb->sb,
+                                               le32_to_cpu(di->i_clusters));
+
+       status = generic_check_addressable(osb->sb->s_blocksize_bits,
+                                          total_blocks);
+       if (status) {
+               mlog(ML_ERROR, "Volume too large "
+                    "to mount safely on this system");
+               status = -EFBIG;
                goto bail;
        }
 
@@ -2380,6 +2466,12 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                goto finally;
        }
 
+       /* Now that journal has been initialized, check to make sure
+          entire volume is addressable. */
+       status = ocfs2_journal_addressable(osb);
+       if (status)
+               goto finally;
+
        /* If the journal was unmounted cleanly then we don't want to
         * recover anything. Otherwise, journal_load will do that
         * dirty work for us :) */
index 32499d213fc4f80f37efde6f71196283236896bf..9975457c981f904ca18a512dd7bcbe0f092ac664 100644 (file)
@@ -128,7 +128,7 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry,
        }
 
        /* Fast symlinks can't be large */
-       len = strlen(target);
+       len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb));
        link = kzalloc(len + 1, GFP_NOFS);
        if (!link) {
                status = -ENOMEM;
index bfe7190cdbf1b0969cc5e2ade3096a9cea16e9ad..902efb23b6a66cbe086e3d6f0b95fb883d6f95b2 100644 (file)
@@ -44,11 +44,6 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
                                                   int type,
                                                   u32 slot);
 
-static inline int is_global_system_inode(int type);
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
-                                          int type,
-                                          u32 slot);
-
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
 #endif
@@ -59,11 +54,52 @@ static inline int is_global_system_inode(int type)
                type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
 }
 
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
-                                          int type,
-                                          u32 slot)
+static struct inode **get_local_system_inode(struct ocfs2_super *osb,
+                                            int type,
+                                            u32 slot)
 {
-       return slot == osb->slot_num || is_global_system_inode(type);
+       int index;
+       struct inode **local_system_inodes, **free = NULL;
+
+       BUG_ON(slot == OCFS2_INVALID_SLOT);
+       BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE ||
+              type > OCFS2_LAST_LOCAL_SYSTEM_INODE);
+
+       spin_lock(&osb->osb_lock);
+       local_system_inodes = osb->local_system_inodes;
+       spin_unlock(&osb->osb_lock);
+
+       if (unlikely(!local_system_inodes)) {
+               local_system_inodes = kzalloc(sizeof(struct inode *) *
+                                             NUM_LOCAL_SYSTEM_INODES *
+                                             osb->max_slots,
+                                             GFP_NOFS);
+               if (!local_system_inodes) {
+                       mlog_errno(-ENOMEM);
+                       /*
+                        * return NULL here so that ocfs2_get_sytem_file_inodes
+                        * will try to create an inode and use it. We will try
+                        * to initialize local_system_inodes next time.
+                        */
+                       return NULL;
+               }
+
+               spin_lock(&osb->osb_lock);
+               if (osb->local_system_inodes) {
+                       /* Someone has initialized it for us. */
+                       free = local_system_inodes;
+                       local_system_inodes = osb->local_system_inodes;
+               } else
+                       osb->local_system_inodes = local_system_inodes;
+               spin_unlock(&osb->osb_lock);
+               if (unlikely(free))
+                       kfree(free);
+       }
+
+       index = (slot * NUM_LOCAL_SYSTEM_INODES) +
+               (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
+
+       return &local_system_inodes[index];
 }
 
 struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
@@ -74,8 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
        struct inode **arr = NULL;
 
        /* avoid the lookup if cached in local system file array */
-       if (is_in_system_inode_array(osb, type, slot))
-               arr = &(osb->system_inodes[type]);
+       if (is_global_system_inode(type)) {
+               arr = &(osb->global_system_inodes[type]);
+       } else
+               arr = get_local_system_inode(osb, type, slot);
 
        if (arr && ((inode = *arr) != NULL)) {
                /* get a ref in addition to the array ref */
index d03469f618012ea4aff64b62f1f77e3e8b8ec47d..67cd43914641f5d3d522c098763437e21b7c7f46 100644 (file)
@@ -1286,13 +1286,11 @@ int ocfs2_xattr_get_nolock(struct inode *inode,
        xis.inode_bh = xbs.inode_bh = di_bh;
        di = (struct ocfs2_dinode *)di_bh->b_data;
 
-       down_read(&oi->ip_xattr_sem);
        ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer,
                                    buffer_size, &xis);
        if (ret == -ENODATA && di->i_xattr_loc)
                ret = ocfs2_xattr_block_get(inode, name_index, name, buffer,
                                            buffer_size, &xbs);
-       up_read(&oi->ip_xattr_sem);
 
        return ret;
 }
@@ -1316,8 +1314,10 @@ static int ocfs2_xattr_get(struct inode *inode,
                mlog_errno(ret);
                return ret;
        }
+       down_read(&OCFS2_I(inode)->ip_xattr_sem);
        ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
                                     name, buffer, buffer_size);
+       up_read(&OCFS2_I(inode)->ip_xattr_sem);
 
        ocfs2_inode_unlock(inode, 0);
 
@@ -7081,7 +7081,7 @@ static int ocfs2_reflink_xattr_in_block(struct ocfs2_xattr_reflink *args,
                goto out;
        }
 
-       if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED))
+       if (!indexed)
                ret = ocfs2_reflink_xattr_block(args, blk_bh, new_blk_bh);
        else
                ret = ocfs2_reflink_xattr_tree(args, blk_bh, new_blk_bh);
index a1c43e7c8a7be4ce70c729f3338eae09097f4025..dc5d5f51f3fe4dc564a19e06cb330d09abc9b6a4 100644 (file)
@@ -1151,6 +1151,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
 static const struct file_operations proc_oom_score_adj_operations = {
        .read           = oom_score_adj_read,
        .write          = oom_score_adj_write,
+       .llseek         = default_llseek,
 };
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -2039,11 +2040,13 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
 static const struct file_operations proc_fdinfo_file_operations = {
        .open           = nonseekable_open,
        .read           = proc_fdinfo_read,
+       .llseek         = no_llseek,
 };
 
 static const struct file_operations proc_fd_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_readfd,
+       .llseek         = default_llseek,
 };
 
 /*
@@ -2112,6 +2115,7 @@ static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
 static const struct file_operations proc_fdinfo_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_readfdinfo,
+       .llseek         = default_llseek,
 };
 
 /*
@@ -2343,6 +2347,7 @@ static int proc_attr_dir_readdir(struct file * filp,
 static const struct file_operations proc_attr_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_attr_dir_readdir,
+       .llseek         = default_llseek,
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
@@ -2675,7 +2680,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        INF("auxv",       S_IRUSR, proc_pid_auxv),
        ONE("status",     S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
-       INF("limits",     S_IRUSR, proc_pid_limits),
+       INF("limits",     S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
@@ -2751,6 +2756,7 @@ static int proc_tgid_base_readdir(struct file * filp,
 static const struct file_operations proc_tgid_base_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_tgid_base_readdir,
+       .llseek         = default_llseek,
 };
 
 static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
@@ -3011,7 +3017,7 @@ static const struct pid_entry tid_base_stuff[] = {
        INF("auxv",      S_IRUSR, proc_pid_auxv),
        ONE("status",    S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
-       INF("limits",    S_IRUSR, proc_pid_limits),
+       INF("limits",    S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
@@ -3088,6 +3094,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den
 static const struct file_operations proc_tid_base_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_tid_base_readdir,
+       .llseek         = default_llseek,
 };
 
 static const struct inode_operations proc_tid_base_inode_operations = {
@@ -3324,4 +3331,5 @@ static const struct inode_operations proc_task_inode_operations = {
 static const struct file_operations proc_task_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_task_readdir,
+       .llseek         = default_llseek,
 };
index 180cf5a0bd67119218c170b265cf944c103b889b..3b8b456603318f1ff017056cdeda40129d559ab4 100644 (file)
@@ -146,7 +146,7 @@ u64 stable_page_flags(struct page *page)
        u |= kpf_copy_bit(k, KPF_HWPOISON,      PG_hwpoison);
 #endif
 
-#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
        u |= kpf_copy_bit(k, KPF_UNCACHED,      PG_uncached);
 #endif
 
index 5be436ea088eeea37ab8a440e64a32f0b879fb7c..2fc52552271d91cf904213ee98576e20237ec1da 100644 (file)
@@ -364,6 +364,7 @@ static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
 static const struct file_operations proc_sys_file_operations = {
        .read           = proc_sys_read,
        .write          = proc_sys_write,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_sys_dir_file_operations = {
index 4258384ed22d9afa22fe579dd7c4242039e8ab8e..93d99b316325164758ed1d48a740f65ef9a59e9b 100644 (file)
@@ -179,6 +179,7 @@ static int proc_root_readdir(struct file * filp,
 static const struct file_operations proc_root_operations = {
        .read            = generic_read_dir,
        .readdir         = proc_root_readdir,
+       .llseek         = default_llseek,
 };
 
 /*
index 439fc1f1c1c41487ad76d23523d995a9f416b926..871e25ed006970667229eea95c56342836c53525 100644 (file)
@@ -224,7 +224,8 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
        /* We don't show the stack guard page in /proc/maps */
        start = vma->vm_start;
        if (vma->vm_flags & VM_GROWSDOWN)
-               start += PAGE_SIZE;
+               if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
+                       start += PAGE_SIZE;
 
        seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
                        start,
@@ -362,13 +363,13 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                        mss->referenced += PAGE_SIZE;
                mapcount = page_mapcount(page);
                if (mapcount >= 2) {
-                       if (pte_dirty(ptent))
+                       if (pte_dirty(ptent) || PageDirty(page))
                                mss->shared_dirty += PAGE_SIZE;
                        else
                                mss->shared_clean += PAGE_SIZE;
                        mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
                } else {
-                       if (pte_dirty(ptent))
+                       if (pte_dirty(ptent) || PageDirty(page))
                                mss->private_dirty += PAGE_SIZE;
                        else
                                mss->private_clean += PAGE_SIZE;
@@ -538,6 +539,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 
 const struct file_operations proc_clear_refs_operations = {
        .write          = clear_refs_write,
+       .llseek         = noop_llseek,
 };
 
 struct pagemapread {
index 91c817ff02c3847a874e1e99f7638b1148869a77..2367fb3f70bc6ba468ab0ccb628b5b88fabac955 100644 (file)
@@ -163,7 +163,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
 
 static const struct file_operations proc_vmcore_operations = {
        .read           = read_vmcore,
-       .llseek         = generic_file_llseek,
+       .llseek         = default_llseek,
 };
 
 static struct vmcore* __init get_new_element(void)
index 6e8fc62b40a8c4142351ebc5c23a958c9d9b412e..7b0329468a5d9629196527039fa31771554a0494 100644 (file)
@@ -11,7 +11,6 @@
  * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -29,8 +28,6 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
        QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
        QNX4DEBUG((KERN_INFO "filp->f_pos         = %ld\n", (long) filp->f_pos));
 
-       lock_kernel();
-
        while (filp->f_pos < inode->i_size) {
                blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS );
                bh = sb_bread(inode->i_sb, blknum);
@@ -71,7 +68,6 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
                brelse(bh);
        }
 out:
-       unlock_kernel();
        return 0;
 }
 
index 16829722be93658abb8a153bff2422396c02e8b0..01bad30026fc7ea1026da00bba7bd3f507e1d468 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/highuid.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
@@ -157,8 +156,6 @@ static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct super_block *sb = dentry->d_sb;
        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
-       lock_kernel();
-
        buf->f_type    = sb->s_magic;
        buf->f_bsize   = sb->s_blocksize;
        buf->f_blocks  = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;
@@ -168,8 +165,6 @@ static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_fsid.val[0] = (u32)id;
        buf->f_fsid.val[1] = (u32)(id >> 32);
 
-       unlock_kernel();
-
        return 0;
 }
 
@@ -283,7 +278,6 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
                goto outi;
 
        brelse(bh);
-
        return 0;
 
       outi:
index 58703ebba879e36c35824bc61bbf8669efb7ad32..275327b5615ea0c2fc8485eb7511dce6ec43c643 100644 (file)
@@ -12,7 +12,6 @@
  * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -109,7 +108,6 @@ struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nam
        int len = dentry->d_name.len;
        struct inode *foundinode = NULL;
 
-       lock_kernel();
        if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
                goto out;
        /* The entry is linked, let's get the real info */
@@ -123,13 +121,11 @@ struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nam
 
        foundinode = qnx4_iget(dir->i_sb, ino);
        if (IS_ERR(foundinode)) {
-               unlock_kernel();
                QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
                           PTR_ERR(foundinode)));
                return ERR_CAST(foundinode);
        }
 out:
-       unlock_kernel();
        d_add(dentry, foundinode);
 
        return NULL;
index 74e36586e4d3076db68cae1579d0c3b50c78a3b2..e757ef26e4cecb6d47fd628b32f204e90c4b8497 100644 (file)
@@ -124,7 +124,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
 {
        loff_t retval;
 
-       lock_kernel();
+       mutex_lock(&file->f_dentry->d_inode->i_mutex);
        switch (origin) {
                case SEEK_END:
                        offset += i_size_read(file->f_path.dentry->d_inode);
@@ -145,7 +145,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
                retval = offset;
        }
 out:
-       unlock_kernel();
+       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
        return retval;
 }
 EXPORT_SYMBOL(default_llseek);
@@ -156,7 +156,6 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
 
        fn = no_llseek;
        if (file->f_mode & FMODE_LSEEK) {
-               fn = default_llseek;
                if (file->f_op && file->f_op->llseek)
                        fn = file->f_op->llseek;
        }
index f53505de071217399e39bf2013304ba46bd0c7f5..5cbb81e134aca031b21e3c88661400ff1c1b174f 100644 (file)
@@ -170,6 +170,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
 int reiserfs_unpack(struct inode *inode, struct file *filp)
 {
        int retval = 0;
+       int depth;
        int index;
        struct page *page;
        struct address_space *mapping;
@@ -188,8 +189,8 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
        /* we need to make sure nobody is changing the file size beneath
         ** us
         */
-       mutex_lock(&inode->i_mutex);
-       reiserfs_write_lock(inode->i_sb);
+       reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
 
        write_from = inode->i_size & (blocksize - 1);
        /* if we are on a block boundary, we are already unpacked.  */
@@ -224,6 +225,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
 
       out:
        mutex_unlock(&inode->i_mutex);
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
        return retval;
 }
index 42d213546894a3b412bea8634f7c9535f25cdb19..268580535c92ba462a1af5983618ab0d11a321a7 100644 (file)
@@ -282,6 +282,7 @@ error:
 static const struct file_operations romfs_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = romfs_readdir,
+       .llseek         = default_llseek,
 };
 
 static const struct inode_operations romfs_dir_inode_operations = {
index 1c5a6add779d07c1da65aa644d2300ef89dfe7d8..74047304b01a4300bf7f781ad4d2838dc3bc316b 100644 (file)
@@ -206,6 +206,7 @@ static const struct file_operations signalfd_fops = {
        .release        = signalfd_release,
        .poll           = signalfd_poll,
        .read           = signalfd_read,
+       .llseek         = noop_llseek,
 };
 
 SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
index e668127c8b2e7bcd5fdab9aaab08ffc10ce6e163..2bc24a8c40390417d2537cd8518dc58ecd9eda2d 100644 (file)
@@ -1,5 +1,6 @@
 config SMB_FS
        tristate "SMB file system support (OBSOLETE, please use CIFS)"
+       depends on BKL # probably unfixable
        depends on INET
        select NLS
        help
index 450c9194198861483daa183fb6582e1c9790eadb..8fc5e50e142fad71ad05aa38f726ae0d6d4ca566 100644 (file)
@@ -501,6 +501,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
        void *mem;
        static int warn_count;
 
+       lock_kernel();
+
        if (warn_count < 5) {
                warn_count++;
                printk(KERN_EMERG "smbfs is deprecated and will be removed"
@@ -621,6 +623,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
 
        smb_new_dentry(sb->s_root);
 
+       unlock_kernel();
        return 0;
 
 out_no_root:
@@ -643,9 +646,11 @@ out_wrong_data:
 out_no_data:
        printk(KERN_ERR "smb_fill_super: missing data argument\n");
 out_fail:
+       unlock_kernel();
        return -EINVAL;
 out_no_server:
        printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n");
+       unlock_kernel();
        return -ENOMEM;
 }
 
index 12b933ac6585d7d0291608cf3253754223a07fd4..0dc340aa2be97d5373e719f74c84d866e00ef465 100644 (file)
@@ -230,5 +230,6 @@ failed_read:
 
 const struct file_operations squashfs_dir_ops = {
        .read = generic_read_dir,
-       .readdir = squashfs_readdir
+       .readdir = squashfs_readdir,
+       .llseek = default_llseek,
 };
index 88b4f8606652b8e675621a2f545aff357ea176ae..07a4f115604850d77191baed3a7fd96c7d161661 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -354,8 +353,6 @@ static int squashfs_remount(struct super_block *sb, int *flags, char *data)
 
 static void squashfs_put_super(struct super_block *sb)
 {
-       lock_kernel();
-
        if (sb->s_fs_info) {
                struct squashfs_sb_info *sbi = sb->s_fs_info;
                squashfs_cache_delete(sbi->block_cache);
@@ -370,8 +367,6 @@ static void squashfs_put_super(struct super_block *sb)
                kfree(sb->s_fs_info);
                sb->s_fs_info = NULL;
        }
-
-       unlock_kernel();
 }
 
 
index 1b27b5688f62fdfd8abd40386c6e1ece7aa1bf49..da3fefe91a8f855f59e62c84f0ef70a2a9bd0524 100644 (file)
@@ -340,7 +340,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        char *p;
 
        p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
-       if (p)
+       if (!IS_ERR(p))
                memmove(last_sysfs_file, p, strlen(p) + 1);
 
        /* need attr_sd for attr and ops, its parent for kobj */
index 23c1e598792a088cfdd757030f9d733251943fb7..442f34ff1af80178ee63e9a7d8ae2abe3df6154e 100644 (file)
@@ -148,6 +148,65 @@ void sysfs_remove_group(struct kobject * kobj,
        sysfs_put(sd);
 }
 
+/**
+ * sysfs_merge_group - merge files into a pre-existing attribute group.
+ * @kobj:      The kobject containing the group.
+ * @grp:       The files to create and the attribute group they belong to.
+ *
+ * This function returns an error if the group doesn't exist or any of the
+ * files already exist in that group, in which case none of the new files
+ * are created.
+ */
+int sysfs_merge_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+       struct sysfs_dirent *dir_sd;
+       int error = 0;
+       struct attribute *const *attr;
+       int i;
+
+       if (grp)
+               dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+       else
+               dir_sd = sysfs_get(kobj->sd);
+       if (!dir_sd)
+               return -ENOENT;
+
+       for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
+               error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
+       if (error) {
+               while (--i >= 0)
+                       sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
+       }
+       sysfs_put(dir_sd);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_merge_group);
+
+/**
+ * sysfs_unmerge_group - remove files from a pre-existing attribute group.
+ * @kobj:      The kobject containing the group.
+ * @grp:       The files to remove and the attribute group they belong to.
+ */
+void sysfs_unmerge_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+       struct sysfs_dirent *dir_sd;
+       struct attribute *const *attr;
+
+       if (grp)
+               dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+       else
+               dir_sd = sysfs_get(kobj->sd);
+       if (dir_sd) {
+               for (attr = grp->attrs; *attr; ++attr)
+                       sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+               sysfs_put(dir_sd);
+       }
+}
+EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
+
 
 EXPORT_SYMBOL_GPL(sysfs_create_group);
 EXPORT_SYMBOL_GPL(sysfs_update_group);
index b86ab8eff79ac8f36ace73c604e554cb4efa8820..8c4fc1425b3eff171bd37b9e1bed290b93473e11 100644 (file)
@@ -144,6 +144,7 @@ static const struct file_operations timerfd_fops = {
        .release        = timerfd_release,
        .poll           = timerfd_poll,
        .read           = timerfd_read,
+       .llseek         = noop_llseek,
 };
 
 static struct file *timerfd_fget(int fd)
index 37fa7ed062d8624fdfe6810aaacda6a6503bcd6a..02429d81ca3374fef11d9646391d3ee7f1878139 100644 (file)
@@ -63,7 +63,9 @@ static int do_commit(struct ubifs_info *c)
        struct ubifs_lp_stats lst;
 
        dbg_cmt("start");
-       if (c->ro_media) {
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+
+       if (c->ro_error) {
                err = -EROFS;
                goto out_up;
        }
index c2a68baa782f8d4b4331f689c594a2db640e6d0f..0bee4dbffc31fc7c0412f863cb630f070c274f09 100644 (file)
@@ -2239,6 +2239,162 @@ out_free:
        return err;
 }
 
+/**
+ * dbg_check_data_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+       struct list_head *cur;
+       struct ubifs_scan_node *sa, *sb;
+
+       if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+               return 0;
+
+       for (cur = head->next; cur->next != head; cur = cur->next) {
+               ino_t inuma, inumb;
+               uint32_t blka, blkb;
+
+               cond_resched();
+               sa = container_of(cur, struct ubifs_scan_node, list);
+               sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+               if (sa->type != UBIFS_DATA_NODE) {
+                       ubifs_err("bad node type %d", sa->type);
+                       dbg_dump_node(c, sa->node);
+                       return -EINVAL;
+               }
+               if (sb->type != UBIFS_DATA_NODE) {
+                       ubifs_err("bad node type %d", sb->type);
+                       dbg_dump_node(c, sb->node);
+                       return -EINVAL;
+               }
+
+               inuma = key_inum(c, &sa->key);
+               inumb = key_inum(c, &sb->key);
+
+               if (inuma < inumb)
+                       continue;
+               if (inuma > inumb) {
+                       ubifs_err("larger inum %lu goes before inum %lu",
+                                 (unsigned long)inuma, (unsigned long)inumb);
+                       goto error_dump;
+               }
+
+               blka = key_block(c, &sa->key);
+               blkb = key_block(c, &sb->key);
+
+               if (blka > blkb) {
+                       ubifs_err("larger block %u goes before %u", blka, blkb);
+                       goto error_dump;
+               }
+               if (blka == blkb) {
+                       ubifs_err("two data nodes for the same block");
+                       goto error_dump;
+               }
+       }
+
+       return 0;
+
+error_dump:
+       dbg_dump_node(c, sa->node);
+       dbg_dump_node(c, sb->node);
+       return -EINVAL;
+}
+
+/**
+ * dbg_check_nondata_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of non-data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+       struct list_head *cur;
+       struct ubifs_scan_node *sa, *sb;
+
+       if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+               return 0;
+
+       for (cur = head->next; cur->next != head; cur = cur->next) {
+               ino_t inuma, inumb;
+               uint32_t hasha, hashb;
+
+               cond_resched();
+               sa = container_of(cur, struct ubifs_scan_node, list);
+               sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+               if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+                   sa->type != UBIFS_XENT_NODE) {
+                       ubifs_err("bad node type %d", sa->type);
+                       dbg_dump_node(c, sa->node);
+                       return -EINVAL;
+               }
+               if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+                   sa->type != UBIFS_XENT_NODE) {
+                       ubifs_err("bad node type %d", sb->type);
+                       dbg_dump_node(c, sb->node);
+                       return -EINVAL;
+               }
+
+               if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+                       ubifs_err("non-inode node goes before inode node");
+                       goto error_dump;
+               }
+
+               if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE)
+                       continue;
+
+               if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+                       /* Inode nodes are sorted in descending size order */
+                       if (sa->len < sb->len) {
+                               ubifs_err("smaller inode node goes first");
+                               goto error_dump;
+                       }
+                       continue;
+               }
+
+               /*
+                * This is either a dentry or xentry, which should be sorted in
+                * ascending (parent ino, hash) order.
+                */
+               inuma = key_inum(c, &sa->key);
+               inumb = key_inum(c, &sb->key);
+
+               if (inuma < inumb)
+                       continue;
+               if (inuma > inumb) {
+                       ubifs_err("larger inum %lu goes before inum %lu",
+                                 (unsigned long)inuma, (unsigned long)inumb);
+                       goto error_dump;
+               }
+
+               hasha = key_block(c, &sa->key);
+               hashb = key_block(c, &sb->key);
+
+               if (hasha > hashb) {
+                       ubifs_err("larger hash %u goes before %u", hasha, hashb);
+                       goto error_dump;
+               }
+       }
+
+       return 0;
+
+error_dump:
+       ubifs_msg("dumping first node");
+       dbg_dump_node(c, sa->node);
+       ubifs_msg("dumping second node");
+       dbg_dump_node(c, sb->node);
+       return -EINVAL;
+       return 0;
+}
+
 static int invocation_cnt;
 
 int dbg_force_in_the_gaps(void)
@@ -2625,6 +2781,7 @@ static const struct file_operations dfs_fops = {
        .open = open_debugfs_file,
        .write = write_debugfs_file,
        .owner = THIS_MODULE,
+       .llseek = default_llseek,
 };
 
 /**
index 29d960101ea668723f9ca7049f05f80defd7bada..69ebe4729151e04bc8caaa2fea0728531b34e3e7 100644 (file)
@@ -324,6 +324,8 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
                        int row, int col);
 int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
                         loff_t size);
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
 /* Force the use of in-the-gaps method for testing */
 
@@ -465,6 +467,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 #define dbg_check_lprops(c)                        0
 #define dbg_check_lpt_nodes(c, cnode, row, col)    0
 #define dbg_check_inode_size(c, inode, size)       0
+#define dbg_check_data_nodes_order(c, head)        0
+#define dbg_check_nondata_nodes_order(c, head)     0
 #define dbg_force_in_the_gaps_enabled              0
 #define dbg_force_in_the_gaps()                    0
 #define dbg_failure_mode                           0
index 03ae894c45dea3a04181a20cb3c5b123bac083ce..d77db7e36484e3f79bece27ee4a11f3a6b80df6f 100644 (file)
@@ -433,8 +433,9 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
        struct page *page;
 
        ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
-       if (unlikely(c->ro_media))
+       if (unlikely(c->ro_error))
                return -EROFS;
 
        /* Try out the fast-path part first */
@@ -1439,9 +1440,9 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vm
 
        dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
                i_size_read(inode));
-       ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
-       if (unlikely(c->ro_media))
+       if (unlikely(c->ro_error))
                return VM_FAULT_SIGBUS; /* -EROFS */
 
        /*
index 918d1582ca05ce4a43f884b75fbf5e2522156275..151f108828204dc4d88c9d890fbcce051b2d8912 100644 (file)
@@ -125,10 +125,16 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
        struct ubifs_scan_node *sa, *sb;
 
        cond_resched();
+       if (a == b)
+               return 0;
+
        sa = list_entry(a, struct ubifs_scan_node, list);
        sb = list_entry(b, struct ubifs_scan_node, list);
+
        ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY);
        ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY);
+       ubifs_assert(sa->type == UBIFS_DATA_NODE);
+       ubifs_assert(sb->type == UBIFS_DATA_NODE);
 
        inuma = key_inum(c, &sa->key);
        inumb = key_inum(c, &sb->key);
@@ -157,28 +163,40 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
  */
 int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
 {
-       int typea, typeb;
        ino_t inuma, inumb;
        struct ubifs_info *c = priv;
        struct ubifs_scan_node *sa, *sb;
 
        cond_resched();
+       if (a == b)
+               return 0;
+
        sa = list_entry(a, struct ubifs_scan_node, list);
        sb = list_entry(b, struct ubifs_scan_node, list);
-       typea = key_type(c, &sa->key);
-       typeb = key_type(c, &sb->key);
-       ubifs_assert(typea != UBIFS_DATA_KEY && typeb != UBIFS_DATA_KEY);
+
+       ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY &&
+                    key_type(c, &sb->key) != UBIFS_DATA_KEY);
+       ubifs_assert(sa->type != UBIFS_DATA_NODE &&
+                    sb->type != UBIFS_DATA_NODE);
 
        /* Inodes go before directory entries */
-       if (typea == UBIFS_INO_KEY) {
-               if (typeb == UBIFS_INO_KEY)
+       if (sa->type == UBIFS_INO_NODE) {
+               if (sb->type == UBIFS_INO_NODE)
                        return sb->len - sa->len;
                return -1;
        }
-       if (typeb == UBIFS_INO_KEY)
+       if (sb->type == UBIFS_INO_NODE)
                return 1;
 
-       ubifs_assert(typea == UBIFS_DENT_KEY && typeb == UBIFS_DENT_KEY);
+       ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY ||
+                    key_type(c, &sa->key) == UBIFS_XENT_KEY);
+       ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY ||
+                    key_type(c, &sb->key) == UBIFS_XENT_KEY);
+       ubifs_assert(sa->type == UBIFS_DENT_NODE ||
+                    sa->type == UBIFS_XENT_NODE);
+       ubifs_assert(sb->type == UBIFS_DENT_NODE ||
+                    sb->type == UBIFS_XENT_NODE);
+
        inuma = key_inum(c, &sa->key);
        inumb = key_inum(c, &sb->key);
 
@@ -224,17 +242,33 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
 static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                      struct list_head *nondata, int *min)
 {
+       int err;
        struct ubifs_scan_node *snod, *tmp;
 
        *min = INT_MAX;
 
        /* Separate data nodes and non-data nodes */
        list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-               int err;
+               ubifs_assert(snod->type == UBIFS_INO_NODE  ||
+                            snod->type == UBIFS_DATA_NODE ||
+                            snod->type == UBIFS_DENT_NODE ||
+                            snod->type == UBIFS_XENT_NODE ||
+                            snod->type == UBIFS_TRUN_NODE);
+
+               if (snod->type != UBIFS_INO_NODE  &&
+                   snod->type != UBIFS_DATA_NODE &&
+                   snod->type != UBIFS_DENT_NODE &&
+                   snod->type != UBIFS_XENT_NODE) {
+                       /* Probably truncation node, zap it */
+                       list_del(&snod->list);
+                       kfree(snod);
+                       continue;
+               }
 
-               ubifs_assert(snod->type != UBIFS_IDX_NODE);
-               ubifs_assert(snod->type != UBIFS_REF_NODE);
-               ubifs_assert(snod->type != UBIFS_CS_NODE);
+               ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY ||
+                            key_type(c, &snod->key) == UBIFS_INO_KEY  ||
+                            key_type(c, &snod->key) == UBIFS_DENT_KEY ||
+                            key_type(c, &snod->key) == UBIFS_XENT_KEY);
 
                err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
                                         snod->offs, 0);
@@ -258,6 +292,13 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        /* Sort data and non-data nodes */
        list_sort(c, &sleb->nodes, &data_nodes_cmp);
        list_sort(c, nondata, &nondata_nodes_cmp);
+
+       err = dbg_check_data_nodes_order(c, &sleb->nodes);
+       if (err)
+               return err;
+       err = dbg_check_nondata_nodes_order(c, nondata);
+       if (err)
+               return err;
        return 0;
 }
 
@@ -575,13 +616,14 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
        struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
 
        ubifs_assert_cmt_locked(c);
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
        if (ubifs_gc_should_commit(c))
                return -EAGAIN;
 
        mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-       if (c->ro_media) {
+       if (c->ro_error) {
                ret = -EROFS;
                goto out_unlock;
        }
@@ -677,14 +719,12 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 
                ret = ubifs_garbage_collect_leb(c, &lp);
                if (ret < 0) {
-                       if (ret == -EAGAIN || ret == -ENOSPC) {
+                       if (ret == -EAGAIN) {
                                /*
-                                * These codes are not errors, so we have to
-                                * return the LEB to lprops. But if the
-                                * 'ubifs_return_leb()' function fails, its
-                                * failure code is propagated to the caller
-                                * instead of the original '-EAGAIN' or
-                                * '-ENOSPC'.
+                                * This is not error, so we have to return the
+                                * LEB to lprops. But if 'ubifs_return_leb()'
+                                * fails, its failure code is propagated to the
+                                * caller instead of the original '-EAGAIN'.
                                 */
                                err = ubifs_return_leb(c, lp.lnum);
                                if (err)
@@ -774,8 +814,8 @@ out_unlock:
 out:
        ubifs_assert(ret < 0);
        ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
-       ubifs_ro_mode(c, ret);
        ubifs_wbuf_sync_nolock(wbuf);
+       ubifs_ro_mode(c, ret);
        mutex_unlock(&wbuf->io_mutex);
        ubifs_return_leb(c, lp.lnum);
        return ret;
index bcf5a16f30bb26f865e49f27124dd0856a2f85d2..d82173182eeb6fca5269f8e757b520916a6babd0 100644 (file)
@@ -61,8 +61,8 @@
  */
 void ubifs_ro_mode(struct ubifs_info *c, int err)
 {
-       if (!c->ro_media) {
-               c->ro_media = 1;
+       if (!c->ro_error) {
+               c->ro_error = 1;
                c->no_chk_data_crc = 0;
                c->vfs_sb->s_flags |= MS_RDONLY;
                ubifs_warn("switched to read-only mode, error %d", err);
@@ -356,11 +356,11 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 
        dbg_io("LEB %d:%d, %d bytes, jhead %s",
               wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
-       ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
        ubifs_assert(!(wbuf->avail & 7));
        ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
-       if (c->ro_media)
+       if (c->ro_error)
                return -EROFS;
 
        ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
@@ -440,11 +440,12 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
 {
        int err, i;
 
+       ubifs_assert(!c->ro_media && !c->ro_mount);
        if (!c->need_wbuf_sync)
                return 0;
        c->need_wbuf_sync = 0;
 
-       if (c->ro_media) {
+       if (c->ro_error) {
                err = -EROFS;
                goto out_timers;
        }
@@ -519,6 +520,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
        ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
        ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
        ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
        if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
                err = -ENOSPC;
@@ -527,7 +529,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 
        cancel_wbuf_timer_nolock(wbuf);
 
-       if (c->ro_media)
+       if (c->ro_error)
                return -EROFS;
 
        if (aligned_len <= wbuf->avail) {
@@ -663,8 +665,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
               buf_len);
        ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
        ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
+       ubifs_assert(!c->ro_media && !c->ro_mount);
 
-       if (c->ro_media)
+       if (c->ro_error)
                return -EROFS;
 
        ubifs_prepare_node(c, buf, len, 1);
@@ -815,7 +818,8 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
        return 0;
 
 out:
-       ubifs_err("bad node at LEB %d:%d", lnum, offs);
+       ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
+                 ubi_is_mapped(c->ubi, lnum));
        dbg_dump_node(c, buf);
        dbg_dump_stack();
        return -EINVAL;
index d321baeca68db65cb0bcce2fcd38ead5ee4e2e65..914f1bd89e571f2df8ce99d053f718ad3cc29dbd 100644 (file)
@@ -122,11 +122,12 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len)
         * better to try to allocate space at the ends of eraseblocks. This is
         * what the squeeze parameter does.
         */
+       ubifs_assert(!c->ro_media && !c->ro_mount);
        squeeze = (jhead == BASEHD);
 again:
        mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-       if (c->ro_media) {
+       if (c->ro_error) {
                err = -EROFS;
                goto out_unlock;
        }
index 0f530c684f0ba13c99c1424c6614d54f0f3ae23b..92a8491a8f8c2da7fa61b9e870cc7a75d1ea8263 100644 (file)
@@ -305,6 +305,20 @@ static inline void trun_key_init(const struct ubifs_info *c,
        key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS;
 }
 
+/**
+ * invalid_key_init - initialize invalid node key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ *
+ * This is a helper function which marks a @key object as invalid.
+ */
+static inline void invalid_key_init(const struct ubifs_info *c,
+                                   union ubifs_key *key)
+{
+       key->u32[0] = 0xDEADBEAF;
+       key->u32[1] = UBIFS_INVALID_KEY;
+}
+
 /**
  * key_type - get key type.
  * @c: UBIFS file-system description object
index c345e125f42c5cd765229166848f97bec300d90d..4d0cb1241460fbc2eacd709188293d5782b1dd3b 100644 (file)
@@ -159,7 +159,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
                jhead = &c->jheads[bud->jhead];
                list_add_tail(&bud->list, &jhead->buds_list);
        } else
-               ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
+               ubifs_assert(c->replaying && c->ro_mount);
 
        /*
         * Note, although this is a new bud, we anyway account this space now,
@@ -223,8 +223,8 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
        }
 
        mutex_lock(&c->log_mutex);
-
-       if (c->ro_media) {
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error) {
                err = -EROFS;
                goto out_unlock;
        }
index 0084a33c4c69bba01e8a264bf7a6576ddede3744..72775d35b99e55308b1ad963cc9c13487b5412fc 100644 (file)
@@ -1363,6 +1363,7 @@ static int read_lsave(struct ubifs_info *c)
                goto out;
        for (i = 0; i < c->lsave_cnt; i++) {
                int lnum = c->lsave[i];
+               struct ubifs_lprops *lprops;
 
                /*
                 * Due to automatic resizing, the values in the lsave table
@@ -1370,7 +1371,11 @@ static int read_lsave(struct ubifs_info *c)
                 */
                if (lnum >= c->leb_cnt)
                        continue;
-               ubifs_lpt_lookup(c, lnum);
+               lprops = ubifs_lpt_lookup(c, lnum);
+               if (IS_ERR(lprops)) {
+                       err = PTR_ERR(lprops);
+                       goto out;
+               }
        }
 out:
        vfree(buf);
index d12535b7fc789dda7c473593aacfc6816afc90be..5c90dec5db0b17bd79c1c1c8bd024c400b5c0514 100644 (file)
@@ -705,6 +705,9 @@ static int make_tree_dirty(struct ubifs_info *c)
        struct ubifs_pnode *pnode;
 
        pnode = pnode_lookup(c, 0);
+       if (IS_ERR(pnode))
+               return PTR_ERR(pnode);
+
        while (pnode) {
                do_make_pnode_dirty(c, pnode);
                pnode = next_pnode_to_dirty(c, pnode);
index 28beaeedadc07d5ad7c3c312d27e30d7be01ee64..21f47afdacff170b5241d69e00edbb6fb3e0ae4b 100644 (file)
@@ -361,7 +361,8 @@ int ubifs_write_master(struct ubifs_info *c)
 {
        int err, lnum, offs, len;
 
-       if (c->ro_media)
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
                return -EROFS;
 
        lnum = UBIFS_MST_LNUM;
index 4fa81d867e4107cc726074a78762abb5f681ca63..c3de04dc952a5c735428f73ad53c3ad40cf3dc4e 100644 (file)
@@ -132,7 +132,8 @@ static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
 {
        int err;
 
-       if (c->ro_media)
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
                return -EROFS;
        err = ubi_leb_unmap(c->ubi, lnum);
        if (err) {
@@ -159,7 +160,8 @@ static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
 {
        int err;
 
-       if (c->ro_media)
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
                return -EROFS;
        err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
        if (err) {
@@ -186,7 +188,8 @@ static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
 {
        int err;
 
-       if (c->ro_media)
+       ubifs_assert(!c->ro_media && !c->ro_mount);
+       if (c->ro_error)
                return -EROFS;
        err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
        if (err) {
index daae9e1f5382142482490798b0c0ba1aed581221..77e9b874b6c22d4105186116c5092bcbbb7f5de0 100644 (file)
@@ -292,7 +292,7 @@ int ubifs_recover_master_node(struct ubifs_info *c)
 
        memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
 
-       if ((c->vfs_sb->s_flags & MS_RDONLY)) {
+       if (c->ro_mount) {
                /* Read-only mode. Keep a copy for switching to rw mode */
                c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
                if (!c->rcvrd_mst_node) {
@@ -469,7 +469,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                endpt = snod->offs + snod->len;
        }
 
-       if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
+       if (c->ro_mount && !c->remounting_rw) {
                /* Add to recovery list */
                struct ubifs_unclean_leb *ucleb;
 
@@ -772,7 +772,8 @@ out_free:
  * @sbuf: LEB-sized buffer to use
  *
  * This function does a scan of a LEB, but caters for errors that might have
- * been caused by the unclean unmount from which we are attempting to recover.
+ * been caused by unclean reboots from which we are attempting to recover
+ * (assume that only the last log LEB can be corrupted by an unclean reboot).
  *
  * This function returns %0 on success and a negative error code on failure.
  */
@@ -883,7 +884,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
 {
        int err;
 
-       ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
+       ubifs_assert(!c->ro_mount || c->remounting_rw);
 
        dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
        err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
@@ -1461,7 +1462,7 @@ int ubifs_recover_size(struct ubifs_info *c)
                        }
                }
                if (e->exists && e->i_size < e->d_size) {
-                       if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
+                       if (!e->inode && c->ro_mount) {
                                /* Fix the inode size and pin it in memory */
                                struct inode *inode;
 
index 5c2d6d759a3e76fa87bfc9bd29e10bd10eff0c6d..eed0fcff8d731710dc7723d25b1adb10ecbe6805 100644 (file)
@@ -627,8 +627,7 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
        ubifs_assert(sleb->endpt - offs >= used);
        ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-       if (sleb->endpt + c->min_io_size <= c->leb_size &&
-           !(c->vfs_sb->s_flags & MS_RDONLY))
+       if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
                err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
                                             sleb->endpt, UBI_SHORTTERM);
 
@@ -840,6 +839,11 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
        if (IS_ERR(sleb)) {
                if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
                        return PTR_ERR(sleb);
+               /*
+                * Note, the below function will recover this log LEB only if
+                * it is the last, because unclean reboots can possibly corrupt
+                * only the tail of the log.
+                */
                sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
                if (IS_ERR(sleb))
                        return PTR_ERR(sleb);
@@ -851,7 +855,6 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
        }
 
        node = sleb->buf;
-
        snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
        if (c->cs_sqnum == 0) {
                /*
@@ -898,7 +901,6 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
        }
 
        list_for_each_entry(snod, &sleb->nodes, list) {
-
                cond_resched();
 
                if (snod->sqnum >= SQNUM_WATERMARK) {
@@ -1011,7 +1013,6 @@ out:
 int ubifs_replay_journal(struct ubifs_info *c)
 {
        int err, i, lnum, offs, free;
-       void *sbuf = NULL;
 
        BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1026,14 +1027,8 @@ int ubifs_replay_journal(struct ubifs_info *c)
                return -EINVAL;
        }
 
-       sbuf = vmalloc(c->leb_size);
-       if (!sbuf)
-               return -ENOMEM;
-
        dbg_mnt("start replaying the journal");
-
        c->replaying = 1;
-
        lnum = c->ltail_lnum = c->lhead_lnum;
        offs = c->lhead_offs;
 
@@ -1046,7 +1041,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
                        lnum = UBIFS_LOG_LNUM;
                        offs = 0;
                }
-               err = replay_log_leb(c, lnum, offs, sbuf);
+               err = replay_log_leb(c, lnum, offs, c->sbuf);
                if (err == 1)
                        /* We hit the end of the log */
                        break;
@@ -1079,7 +1074,6 @@ int ubifs_replay_journal(struct ubifs_info *c)
 out:
        destroy_replay_tree(c);
        destroy_bud_list(c);
-       vfree(sbuf);
        c->replaying = 0;
        return err;
 }
index 96cb62c8a9ddaa7cbcd432dc15442830632d3995..bf31b4729e51ce466560777a1e24bad90356311b 100644 (file)
@@ -542,11 +542,8 @@ int ubifs_read_superblock(struct ubifs_info *c)
         * due to the unavailability of time-travelling equipment.
         */
        if (c->fmt_version > UBIFS_FORMAT_VERSION) {
-               struct super_block *sb = c->vfs_sb;
-               int mounting_ro = sb->s_flags & MS_RDONLY;
-
-               ubifs_assert(!c->ro_media || mounting_ro);
-               if (!mounting_ro ||
+               ubifs_assert(!c->ro_media || c->ro_mount);
+               if (!c->ro_mount ||
                    c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
                        ubifs_err("on-flash format version is w%d/r%d, but "
                                  "software only supports up to version "
@@ -624,7 +621,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
        c->old_leb_cnt = c->leb_cnt;
        if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
                c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
-               if (c->vfs_sb->s_flags & MS_RDONLY)
+               if (c->ro_mount)
                        dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
                                c->old_leb_cnt, c->leb_cnt);
                else {
index 96c525384191d91af6ce99c700295dc78cb744cf..3e1ee57dbeaa5f88f2898ae8562a03577f13d098 100644 (file)
@@ -197,7 +197,7 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        struct ubifs_ino_node *ino = buf;
        struct ubifs_scan_node *snod;
 
-       snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
+       snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
        if (!snod)
                return -ENOMEM;
 
@@ -212,13 +212,15 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        case UBIFS_DENT_NODE:
        case UBIFS_XENT_NODE:
        case UBIFS_DATA_NODE:
-       case UBIFS_TRUN_NODE:
                /*
                 * The key is in the same place in all keyed
                 * nodes.
                 */
                key_read(c, &ino->key, &snod->key);
                break;
+       default:
+               invalid_key_init(c, &snod->key);
+               break;
        }
        list_add_tail(&snod->list, &sleb->nodes);
        sleb->nodes_cnt += 1;
index 0b201114a5adf9cfc9c04b6730442748c079fa9d..46961c00323627f3ee2a77d4633b7bcd44a839b8 100644 (file)
@@ -250,7 +250,7 @@ static int kick_a_thread(void)
                        dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
 
                        if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
-                           c->ro_media) {
+                           c->ro_mount || c->ro_error) {
                                mutex_unlock(&c->umount_mutex);
                                continue;
                        }
index cd5900b85d38373cc4998a562152fcbe334f541f..9a47c9f0ad07e69fddc57f5debc488982aab9429 100644 (file)
@@ -1137,11 +1137,11 @@ static int check_free_space(struct ubifs_info *c)
  */
 static int mount_ubifs(struct ubifs_info *c)
 {
-       struct super_block *sb = c->vfs_sb;
-       int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
+       int err;
        long long x;
        size_t sz;
 
+       c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
        err = init_constants_early(c);
        if (err)
                return err;
@@ -1154,7 +1154,7 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_free;
 
-       if (c->empty && (mounted_read_only || c->ro_media)) {
+       if (c->empty && (c->ro_mount || c->ro_media)) {
                /*
                 * This UBI volume is empty, and read-only, or the file system
                 * is mounted read-only - we cannot format it.
@@ -1165,7 +1165,7 @@ static int mount_ubifs(struct ubifs_info *c)
                goto out_free;
        }
 
-       if (c->ro_media && !mounted_read_only) {
+       if (c->ro_media && !c->ro_mount) {
                ubifs_err("cannot mount read-write - read-only media");
                err = -EROFS;
                goto out_free;
@@ -1185,7 +1185,7 @@ static int mount_ubifs(struct ubifs_info *c)
        if (!c->sbuf)
                goto out_free;
 
-       if (!mounted_read_only) {
+       if (!c->ro_mount) {
                c->ileb_buf = vmalloc(c->leb_size);
                if (!c->ileb_buf)
                        goto out_free;
@@ -1228,7 +1228,7 @@ static int mount_ubifs(struct ubifs_info *c)
        }
 
        sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
-       if (!mounted_read_only) {
+       if (!c->ro_mount) {
                err = alloc_wbufs(c);
                if (err)
                        goto out_cbuf;
@@ -1254,12 +1254,12 @@ static int mount_ubifs(struct ubifs_info *c)
        if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
                ubifs_msg("recovery needed");
                c->need_recovery = 1;
-               if (!mounted_read_only) {
+               if (!c->ro_mount) {
                        err = ubifs_recover_inl_heads(c, c->sbuf);
                        if (err)
                                goto out_master;
                }
-       } else if (!mounted_read_only) {
+       } else if (!c->ro_mount) {
                /*
                 * Set the "dirty" flag so that if we reboot uncleanly we
                 * will notice this immediately on the next mount.
@@ -1270,7 +1270,7 @@ static int mount_ubifs(struct ubifs_info *c)
                        goto out_master;
        }
 
-       err = ubifs_lpt_init(c, 1, !mounted_read_only);
+       err = ubifs_lpt_init(c, 1, !c->ro_mount);
        if (err)
                goto out_lpt;
 
@@ -1285,11 +1285,11 @@ static int mount_ubifs(struct ubifs_info *c)
        /* Calculate 'min_idx_lebs' after journal replay */
        c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
 
-       err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
+       err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
        if (err)
                goto out_orphans;
 
-       if (!mounted_read_only) {
+       if (!c->ro_mount) {
                int lnum;
 
                err = check_free_space(c);
@@ -1351,7 +1351,7 @@ static int mount_ubifs(struct ubifs_info *c)
        spin_unlock(&ubifs_infos_lock);
 
        if (c->need_recovery) {
-               if (mounted_read_only)
+               if (c->ro_mount)
                        ubifs_msg("recovery deferred");
                else {
                        c->need_recovery = 0;
@@ -1378,7 +1378,7 @@ static int mount_ubifs(struct ubifs_info *c)
 
        ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
                  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
-       if (mounted_read_only)
+       if (c->ro_mount)
                ubifs_msg("mounted read-only");
        x = (long long)c->main_lebs * c->leb_size;
        ubifs_msg("file system size:   %lld bytes (%lld KiB, %lld MiB, %d "
@@ -1640,7 +1640,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        }
 
        dbg_gen("re-mounted read-write");
-       c->vfs_sb->s_flags &= ~MS_RDONLY;
+       c->ro_mount = 0;
        c->remounting_rw = 0;
        c->always_chk_crc = 0;
        err = dbg_check_space_info(c);
@@ -1676,7 +1676,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
        int i, err;
 
        ubifs_assert(!c->need_recovery);
-       ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
+       ubifs_assert(!c->ro_mount);
 
        mutex_lock(&c->umount_mutex);
        if (c->bgt) {
@@ -1686,10 +1686,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
 
        dbg_save_space_info(c);
 
-       for (i = 0; i < c->jhead_cnt; i++) {
+       for (i = 0; i < c->jhead_cnt; i++)
                ubifs_wbuf_sync(&c->jheads[i].wbuf);
-               hrtimer_cancel(&c->jheads[i].wbuf.timer);
-       }
 
        c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
        c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
@@ -1704,6 +1702,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
        vfree(c->ileb_buf);
        c->ileb_buf = NULL;
        ubifs_lpt_free(c, 1);
+       c->ro_mount = 1;
        err = dbg_check_space_info(c);
        if (err)
                ubifs_ro_mode(c, err);
@@ -1735,7 +1734,7 @@ static void ubifs_put_super(struct super_block *sb)
         * the mutex is locked.
         */
        mutex_lock(&c->umount_mutex);
-       if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
+       if (!c->ro_mount) {
                /*
                 * First of all kill the background thread to make sure it does
                 * not interfere with un-mounting and freeing resources.
@@ -1745,23 +1744,22 @@ static void ubifs_put_super(struct super_block *sb)
                        c->bgt = NULL;
                }
 
-               /* Synchronize write-buffers */
-               if (c->jheads)
-                       for (i = 0; i < c->jhead_cnt; i++)
-                               ubifs_wbuf_sync(&c->jheads[i].wbuf);
-
                /*
-                * On fatal errors c->ro_media is set to 1, in which case we do
+                * On fatal errors c->ro_error is set to 1, in which case we do
                 * not write the master node.
                 */
-               if (!c->ro_media) {
+               if (!c->ro_error) {
+                       int err;
+
+                       /* Synchronize write-buffers */
+                       for (i = 0; i < c->jhead_cnt; i++)
+                               ubifs_wbuf_sync(&c->jheads[i].wbuf);
+
                        /*
                         * We are being cleanly unmounted which means the
                         * orphans were killed - indicate this in the master
                         * node. Also save the reserved GC LEB number.
                         */
-                       int err;
-
                        c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
                        c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
                        c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
@@ -1774,6 +1772,10 @@ static void ubifs_put_super(struct super_block *sb)
                                 */
                                ubifs_err("failed to write master node, "
                                          "error %d", err);
+               } else {
+                       for (i = 0; i < c->jhead_cnt; i++)
+                               /* Make sure write-buffer timers are canceled */
+                               hrtimer_cancel(&c->jheads[i].wbuf.timer);
                }
        }
 
@@ -1797,17 +1799,21 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
                return err;
        }
 
-       if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+       if (c->ro_mount && !(*flags & MS_RDONLY)) {
+               if (c->ro_error) {
+                       ubifs_msg("cannot re-mount R/W due to prior errors");
+                       return -EROFS;
+               }
                if (c->ro_media) {
-                       ubifs_msg("cannot re-mount due to prior errors");
+                       ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
                        return -EROFS;
                }
                err = ubifs_remount_rw(c);
                if (err)
                        return err;
-       } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
-               if (c->ro_media) {
-                       ubifs_msg("cannot re-mount due to prior errors");
+       } else if (!c->ro_mount && (*flags & MS_RDONLY)) {
+               if (c->ro_error) {
+                       ubifs_msg("cannot re-mount R/O due to prior errors");
                        return -EROFS;
                }
                ubifs_remount_ro(c);
@@ -2049,8 +2055,8 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
         */
        ubi = open_ubi(name, UBI_READONLY);
        if (IS_ERR(ubi)) {
-               ubifs_err("cannot open \"%s\", error %d",
-                         name, (int)PTR_ERR(ubi));
+               dbg_err("cannot open \"%s\", error %d",
+                       name, (int)PTR_ERR(ubi));
                return PTR_ERR(ubi);
        }
        ubi_get_volume_info(ubi, &vi);
@@ -2064,9 +2070,11 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
        }
 
        if (sb->s_root) {
+               struct ubifs_info *c1 = sb->s_fs_info;
+
                /* A new mount point for already mounted UBIFS */
                dbg_gen("this ubi volume is already mounted");
-               if ((flags ^ sb->s_flags) & MS_RDONLY) {
+               if (!!(flags & MS_RDONLY) != c1->ro_mount) {
                        err = -EBUSY;
                        goto out_deact;
                }
index 2194915220e56c75bc9894724496dc19c797b908..ad9cf013362231b5c5622ce78e5c4c8a6472221d 100644 (file)
@@ -1177,6 +1177,7 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
        unsigned long time = get_seconds();
 
        dbg_tnc("search key %s", DBGKEY(key));
+       ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
 
        znode = c->zroot.znode;
        if (unlikely(!znode)) {
@@ -2966,7 +2967,7 @@ static struct ubifs_znode *right_znode(struct ubifs_info *c,
  *
  * This function searches an indexing node by its first key @key and its
  * address @lnum:@offs. It looks up the indexing tree by pulling all indexing
- * nodes it traverses to TNC. This function is called fro indexing nodes which
+ * nodes it traverses to TNC. This function is called for indexing nodes which
  * were found on the media by scanning, for example when garbage-collecting or
  * when doing in-the-gaps commit. This means that the indexing node which is
  * looked for does not have to have exactly the same leftmost key @key, because
@@ -2988,6 +2989,8 @@ static struct ubifs_znode *lookup_znode(struct ubifs_info *c,
        struct ubifs_znode *znode, *zn;
        int n, nn;
 
+       ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
+
        /*
         * The arguments have probably been read off flash, so don't assume
         * they are valid.
index 0c9876b396dd021f43c91dc77d27a244d5b95487..381d6b207a525f95e09f4dc5366de3738cfc5675 100644 (file)
  * in TNC. However, when replaying, it is handy to introduce fake "truncation"
  * keys for truncation nodes because the code becomes simpler. So we define
  * %UBIFS_TRUN_KEY type.
+ *
+ * But otherwise, out of the journal reply scope, the truncation keys are
+ * invalid.
  */
-#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+#define UBIFS_TRUN_KEY    UBIFS_KEY_TYPES_CNT
+#define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT
 
 /*
  * How much a directory entry/extended attribute entry adds to the parent/host
@@ -1028,6 +1032,8 @@ struct ubifs_debug_info;
  * @max_leb_cnt: maximum count of logical eraseblocks
  * @old_leb_cnt: count of logical eraseblocks before re-size
  * @ro_media: the underlying UBI volume is read-only
+ * @ro_mount: the file-system was mounted as read-only
+ * @ro_error: UBIFS switched to R/O mode because an error happened
  *
  * @dirty_pg_cnt: number of dirty pages (not used)
  * @dirty_zn_cnt: number of dirty znodes
@@ -1168,11 +1174,14 @@ struct ubifs_debug_info;
  * @replay_sqnum: sequence number of node currently being replayed
  * @need_recovery: file-system needs recovery
  * @replaying: set to %1 during journal replay
- * @unclean_leb_list: LEBs to recover when mounting ro to rw
- * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
+ * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
+ *                    mode
+ * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
+ *                  FS to R/W mode
  * @size_tree: inode size information for recovery
- * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
- * @always_chk_crc: always check CRCs (while mounting and remounting rw)
+ * @remounting_rw: set while re-mounting from R/O mode to R/W mode
+ * @always_chk_crc: always check CRCs (while mounting and remounting to R/W
+ *                  mode)
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg: debugging-related information
@@ -1268,7 +1277,9 @@ struct ubifs_info {
        int leb_cnt;
        int max_leb_cnt;
        int old_leb_cnt;
-       int ro_media;
+       unsigned int ro_media:1;
+       unsigned int ro_mount:1;
+       unsigned int ro_error:1;
 
        atomic_long_t dirty_pg_cnt;
        atomic_long_t dirty_zn_cnt;
index 0e0e99bd6bcefcb9c12c15485a3d0a43888e97db..f8def3c8ea4c49f9a3cd823b1af03c3264d4e2ef 100644 (file)
@@ -1,5 +1,6 @@
 config UDF_FS
        tristate "UDF file system support"
+       depends on BKL # needs serious work to remove
        select CRC_ITU_T
        help
          This is the new file system used on some CD-ROMs and DVDs. Say Y if
index 65412d84a45d7c5e6e8563111c7ca4b66cec32b7..76f3d6d97b402ea14c391c46b8a924af9888cc6c 100644 (file)
@@ -1880,6 +1880,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        struct kernel_lb_addr rootdir, fileset;
        struct udf_sb_info *sbi;
 
+       lock_kernel();
+
        uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
        uopt.uid = -1;
        uopt.gid = -1;
@@ -1888,8 +1890,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        uopt.dmode = UDF_INVALID_MODE;
 
        sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
-       if (!sbi)
+       if (!sbi) {
+               unlock_kernel();
                return -ENOMEM;
+       }
 
        sb->s_fs_info = sbi;
 
@@ -2035,6 +2039,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                goto error_out;
        }
        sb->s_maxbytes = MAX_LFS_FILESIZE;
+       unlock_kernel();
        return 0;
 
 error_out:
@@ -2055,6 +2060,7 @@ error_out:
        kfree(sbi);
        sb->s_fs_info = NULL;
 
+       unlock_kernel();
        return -EINVAL;
 }
 
index e4f10a40768a436d1b50a133c68b1668679d7541..30c8f223253d29f7b67f2c2e72a483b1ffdec7b9 100644 (file)
@@ -1,6 +1,7 @@
 config UFS_FS
        tristate "UFS file system support (read only)"
        depends on BLOCK
+       depends on BKL # probably fixable
        help
          BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
          OpenBSD and NeXTstep) use a file system called UFS. Some System V
index d510c1b91817c9543ea5da4f062af0cc7eb3ae4f..6b9be90dae7dd7affc1ccba35c02bd9fac193570 100644 (file)
@@ -696,6 +696,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        unsigned maxsymlen;
        int ret = -EINVAL;
 
+       lock_kernel();
+
        uspi = NULL;
        ubh = NULL;
        flags = 0;
@@ -1163,6 +1165,7 @@ magic_found:
                        goto failed;
 
        UFSD("EXIT\n");
+       unlock_kernel();
        return 0;
 
 dalloc_failed:
@@ -1174,10 +1177,12 @@ failed:
        kfree(sbi);
        sb->s_fs_info = NULL;
        UFSD("EXIT (FAILED)\n");
+       unlock_kernel();
        return ret;
 
 failed_nomem:
        UFSD("EXIT (NOMEM)\n");
+       unlock_kernel();
        return -ENOMEM;
 }
 
index 15412fe15c3a47f3cc744af36cecfe2b01e5a5a3..b552f816de15942095f82ad0302b8656f7db09ae 100644 (file)
@@ -852,8 +852,8 @@ xfs_convert_page(
                SetPageUptodate(page);
 
        if (count) {
-               wbc->nr_to_write--;
-               if (wbc->nr_to_write <= 0)
+               if (--wbc->nr_to_write <= 0 &&
+                   wbc->sync_mode == WB_SYNC_NONE)
                        done = 1;
        }
        xfs_start_page_writeback(page, !page_dirty, count);
@@ -1068,7 +1068,7 @@ xfs_vm_writepage(
         * by themselves.
         */
        if ((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == PF_MEMALLOC)
-               goto out_fail;
+               goto redirty;
 
        /*
         * We need a transaction if there are delalloc or unwritten buffers
@@ -1080,7 +1080,7 @@ xfs_vm_writepage(
         */
        xfs_count_page_state(page, &delalloc, &unwritten);
        if ((current->flags & PF_FSTRANS) && (delalloc || unwritten))
-               goto out_fail;
+               goto redirty;
 
        /* Is this page beyond the end of the file? */
        offset = i_size_read(inode);
@@ -1245,12 +1245,15 @@ error:
        if (iohead)
                xfs_cancel_ioend(iohead);
 
+       if (err == -EAGAIN)
+               goto redirty;
+
        xfs_aops_discard_page(page);
        ClearPageUptodate(page);
        unlock_page(page);
        return err;
 
-out_fail:
+redirty:
        redirty_page_for_writepage(wbc, page);
        unlock_page(page);
        return 0;
index ea79072f521012549c4c2673a6210340834202a4..286e36e21dae587672216d7b7722488e91b45758 100644 (file)
@@ -440,12 +440,7 @@ _xfs_buf_find(
                ASSERT(btp == bp->b_target);
                if (bp->b_file_offset == range_base &&
                    bp->b_buffer_length == range_length) {
-                       /*
-                        * If we look at something, bring it to the
-                        * front of the list for next time.
-                        */
                        atomic_inc(&bp->b_hold);
-                       list_move(&bp->b_hash_list, &hash->bh_list);
                        goto found;
                }
        }
@@ -1443,8 +1438,7 @@ xfs_alloc_bufhash(
 {
        unsigned int            i;
 
-       btp->bt_hashshift = external ? 3 : 8;   /* 8 or 256 buckets */
-       btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
+       btp->bt_hashshift = external ? 3 : 12;  /* 8 or 4096 buckets */
        btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
                                         sizeof(xfs_bufhash_t));
        for (i = 0; i < (1 << btp->bt_hashshift); i++) {
@@ -1938,7 +1932,8 @@ xfs_buf_init(void)
        if (!xfs_buf_zone)
                goto out;
 
-       xfslogd_workqueue = create_workqueue("xfslogd");
+       xfslogd_workqueue = alloc_workqueue("xfslogd",
+                                       WQ_RESCUER | WQ_HIGHPRI, 1);
        if (!xfslogd_workqueue)
                goto out_free_buf_zone;
 
index d072e5ff923b3e71eac4000bd432cd84d72e0d9b..2a05614f0b920c672a3d5950aef3701f91aab465 100644 (file)
@@ -137,7 +137,6 @@ typedef struct xfs_buftarg {
        size_t                  bt_smask;
 
        /* per device buffer hash table */
-       uint                    bt_hashmask;
        uint                    bt_hashshift;
        xfs_bufhash_t           *bt_hash;
 
index 237f5ffb2ee8ca067f6dc81ebc38a6de1f7b36ce..3b9e626f7cd1562877cc340d0c43c5a776dd2e35 100644 (file)
@@ -785,6 +785,8 @@ xfs_ioc_fsgetxattr(
 {
        struct fsxattr          fa;
 
+       memset(&fa, 0, sizeof(struct fsxattr));
+
        xfs_ilock(ip, XFS_ILOCK_SHARED);
        fa.fsx_xflags = xfs_ip2xflags(ip);
        fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
@@ -906,6 +908,13 @@ xfs_ioctl_setattr(
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
 
+       /*
+        * Disallow 32bit project ids because on-disk structure
+        * is 16bit only.
+        */
+       if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1))
+               return XFS_ERROR(EINVAL);
+
        /*
         * If disk quotas is on, we make sure that the dquots do exist on disk,
         * before we start any other transactions. Trying to do this later
index 68be25dcd301801506889f0f2ac23cd5e5ff420d..b1fc2a6bfe834667cefe95e9a842527ba886944d 100644 (file)
@@ -664,7 +664,7 @@ xfs_vn_fiemap(
                                        fieinfo->fi_extents_max + 1;
        bm.bmv_count = min_t(__s32, bm.bmv_count,
                             (PAGE_SIZE * 16 / sizeof(struct getbmapx)));
-       bm.bmv_iflags = BMV_IF_PREALLOC;
+       bm.bmv_iflags = BMV_IF_PREALLOC | BMV_IF_NO_HOLES;
        if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR)
                bm.bmv_iflags |= BMV_IF_ATTRFORK;
        if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC))
index 15c35b62ff14ba46e0dd31d09cb5b0dfb54cf195..a4e07974955be3025ebbbe3839264b9bb1acba74 100644 (file)
@@ -1226,6 +1226,7 @@ xfs_fs_statfs(
        struct xfs_inode        *ip = XFS_I(dentry->d_inode);
        __uint64_t              fakeinos, id;
        xfs_extlen_t            lsize;
+       __int64_t               ffree;
 
        statp->f_type = XFS_SB_MAGIC;
        statp->f_namelen = MAXNAMELEN - 1;
@@ -1249,7 +1250,11 @@ xfs_fs_statfs(
                statp->f_files = min_t(typeof(statp->f_files),
                                        statp->f_files,
                                        mp->m_maxicount);
-       statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+
+       /* make sure statp->f_ffree does not underflow */
+       ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+       statp->f_ffree = max_t(__int64_t, ffree, 0);
+
        spin_unlock(&mp->m_sb_lock);
 
        if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
@@ -1402,7 +1407,7 @@ xfs_fs_freeze(
 
        xfs_save_resvblks(mp);
        xfs_quiesce_attr(mp);
-       return -xfs_fs_log_dummy(mp);
+       return -xfs_fs_log_dummy(mp, SYNC_WAIT);
 }
 
 STATIC int
index dfcbd98d15997e62e7d8a433fa71e5b8a9912609..81976ffed7d6f031f1bef0d7a5995cbbebbed69b 100644 (file)
@@ -34,6 +34,7 @@
 #include "xfs_inode_item.h"
 #include "xfs_quota.h"
 #include "xfs_trace.h"
+#include "xfs_fsops.h"
 
 #include <linux/kthread.h>
 #include <linux/freezer.h>
@@ -340,38 +341,6 @@ xfs_sync_attr(
                                     XFS_ICI_NO_TAG, 0, NULL);
 }
 
-STATIC int
-xfs_commit_dummy_trans(
-       struct xfs_mount        *mp,
-       uint                    flags)
-{
-       struct xfs_inode        *ip = mp->m_rootip;
-       struct xfs_trans        *tp;
-       int                     error;
-
-       /*
-        * Put a dummy transaction in the log to tell recovery
-        * that all others are OK.
-        */
-       tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
-       error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
-       if (error) {
-               xfs_trans_cancel(tp, 0);
-               return error;
-       }
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-       xfs_trans_ijoin(tp, ip);
-       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       error = xfs_trans_commit(tp, 0);
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-       /* the log force ensures this transaction is pushed to disk */
-       xfs_log_force(mp, (flags & SYNC_WAIT) ? XFS_LOG_SYNC : 0);
-       return error;
-}
-
 STATIC int
 xfs_sync_fsdata(
        struct xfs_mount        *mp)
@@ -432,7 +401,7 @@ xfs_quiesce_data(
 
        /* mark the log as covered if needed */
        if (xfs_log_need_covered(mp))
-               error2 = xfs_commit_dummy_trans(mp, SYNC_WAIT);
+               error2 = xfs_fs_log_dummy(mp, SYNC_WAIT);
 
        /* flush data-only devices */
        if (mp->m_rtdev_targp)
@@ -563,7 +532,7 @@ xfs_flush_inodes(
 /*
  * Every sync period we need to unpin all items, reclaim inodes and sync
  * disk quotas.  We might need to cover the log to indicate that the
- * filesystem is idle.
+ * filesystem is idle and not frozen.
  */
 STATIC void
 xfs_sync_worker(
@@ -577,8 +546,9 @@ xfs_sync_worker(
                xfs_reclaim_inodes(mp, 0);
                /* dgc: errors ignored here */
                error = xfs_qm_sync(mp, SYNC_TRYLOCK);
-               if (xfs_log_need_covered(mp))
-                       error = xfs_commit_dummy_trans(mp, 0);
+               if (mp->m_super->s_frozen == SB_UNFROZEN &&
+                   xfs_log_need_covered(mp))
+                       error = xfs_fs_log_dummy(mp, 0);
        }
        mp->m_sync_seq++;
        wake_up(&mp->m_wait_single_sync_task);
@@ -698,14 +668,11 @@ xfs_inode_set_reclaim_tag(
        xfs_perag_put(pag);
 }
 
-void
-__xfs_inode_clear_reclaim_tag(
-       xfs_mount_t     *mp,
+STATIC void
+__xfs_inode_clear_reclaim(
        xfs_perag_t     *pag,
        xfs_inode_t     *ip)
 {
-       radix_tree_tag_clear(&pag->pag_ici_root,
-                       XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
        pag->pag_ici_reclaimable--;
        if (!pag->pag_ici_reclaimable) {
                /* clear the reclaim tag from the perag radix tree */
@@ -719,6 +686,17 @@ __xfs_inode_clear_reclaim_tag(
        }
 }
 
+void
+__xfs_inode_clear_reclaim_tag(
+       xfs_mount_t     *mp,
+       xfs_perag_t     *pag,
+       xfs_inode_t     *ip)
+{
+       radix_tree_tag_clear(&pag->pag_ici_root,
+                       XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+       __xfs_inode_clear_reclaim(pag, ip);
+}
+
 /*
  * Inodes in different states need to be treated differently, and the return
  * value of xfs_iflush is not sufficient to get this right. The following table
@@ -868,6 +846,7 @@ reclaim:
        if (!radix_tree_delete(&pag->pag_ici_root,
                                XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino)))
                ASSERT(0);
+       __xfs_inode_clear_reclaim(pag, ip);
        write_unlock(&pag->pag_ici_lock);
 
        /*
index 23f14e595c18cd3a8068796f5b73396fa9db98f9..f90dadd5a96877ff9975ecaaf2fb260863f7d089 100644 (file)
@@ -5533,12 +5533,24 @@ xfs_getbmap(
                                        map[i].br_startblock))
                                goto out_free_map;
 
-                       nexleft--;
                        bmv->bmv_offset =
                                out[cur_ext].bmv_offset +
                                out[cur_ext].bmv_length;
                        bmv->bmv_length =
                                max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
+
+                       /*
+                        * In case we don't want to return the hole,
+                        * don't increase cur_ext so that we can reuse
+                        * it in the next loop.
+                        */
+                       if ((iflags & BMV_IF_NO_HOLES) &&
+                           map[i].br_startblock == HOLESTARTBLOCK) {
+                               memset(&out[cur_ext], 0, sizeof(out[cur_ext]));
+                               continue;
+                       }
+
+                       nexleft--;
                        bmv->bmv_entries++;
                        cur_ext++;
                }
index 7cf7220e7d5fb30dfece1fe9aa4f2798f3e017fc..87c2e9d02288d6ff0eba2949d379e1d02546eb11 100644 (file)
@@ -114,8 +114,10 @@ struct getbmapx {
 #define BMV_IF_NO_DMAPI_READ   0x2     /* Do not generate DMAPI read event  */
 #define BMV_IF_PREALLOC                0x4     /* rtn status BMV_OF_PREALLOC if req */
 #define BMV_IF_DELALLOC                0x8     /* rtn status BMV_OF_DELALLOC if req */
+#define BMV_IF_NO_HOLES                0x10    /* Do not return holes */
 #define BMV_IF_VALID   \
-       (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC|BMV_IF_DELALLOC)
+       (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC|  \
+        BMV_IF_DELALLOC|BMV_IF_NO_HOLES)
 
 /*     bmv_oflags values - returned for each non-header segment */
 #define BMV_OF_PREALLOC                0x1     /* segment = unwritten pre-allocation */
index dbca5f5c37bad18fc220ce21f551d17b58f0c13a..43b1d56993350ba3af58c53757be99dfa936c017 100644 (file)
@@ -604,31 +604,36 @@ out:
        return 0;
 }
 
+/*
+ * Dump a transaction into the log that contains no real change. This is needed
+ * to be able to make the log dirty or stamp the current tail LSN into the log
+ * during the covering operation.
+ *
+ * We cannot use an inode here for this - that will push dirty state back up
+ * into the VFS and then periodic inode flushing will prevent log covering from
+ * making progress. Hence we log a field in the superblock instead.
+ */
 int
 xfs_fs_log_dummy(
-       xfs_mount_t     *mp)
+       xfs_mount_t     *mp,
+       int             flags)
 {
        xfs_trans_t     *tp;
-       xfs_inode_t     *ip;
        int             error;
 
        tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);
-       error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
+       error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+                                       XFS_DEFAULT_LOG_COUNT);
        if (error) {
                xfs_trans_cancel(tp, 0);
                return error;
        }
 
-       ip = mp->m_rootip;
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-       xfs_trans_ijoin(tp, ip);
-       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       xfs_trans_set_sync(tp);
-       error = xfs_trans_commit(tp, 0);
-
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-       return error;
+       /* log the UUID because it is an unchanging field */
+       xfs_mod_sb(tp, XFS_SB_UUID);
+       if (flags & SYNC_WAIT)
+               xfs_trans_set_sync(tp);
+       return xfs_trans_commit(tp, 0);
 }
 
 int
index 88435e0a77c9b2f67035344e8f3afc58532d4d5c..a786c5212c1e478677e46f2725105a010ebd1262 100644 (file)
@@ -25,6 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
 extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
                                xfs_fsop_resblks_t *outval);
 extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
-extern int xfs_fs_log_dummy(xfs_mount_t *mp);
+extern int xfs_fs_log_dummy(xfs_mount_t *mp, int flags);
 
 #endif /* __XFS_FSOPS_H__ */
index abf80ae1e95bed43db56f17dd8a7ffc06039a60a..5371d2dc360ebde33776d7f44d87e4c79afe210e 100644 (file)
@@ -1213,7 +1213,6 @@ xfs_imap_lookup(
        struct xfs_inobt_rec_incore rec;
        struct xfs_btree_cur    *cur;
        struct xfs_buf          *agbp;
-       xfs_agino_t             startino;
        int                     error;
        int                     i;
 
@@ -1227,13 +1226,13 @@ xfs_imap_lookup(
        }
 
        /*
-        * derive and lookup the exact inode record for the given agino. If the
-        * record cannot be found, then it's an invalid inode number and we
-        * should abort.
+        * Lookup the inode record for the given agino. If the record cannot be
+        * found, then it's an invalid inode number and we should abort. Once
+        * we have a record, we need to ensure it contains the inode number
+        * we are looking up.
         */
        cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
-       startino = agino & ~(XFS_IALLOC_INODES(mp) - 1);
-       error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i);
+       error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
        if (!error) {
                if (i)
                        error = xfs_inobt_get_rec(cur, &rec, &i);
@@ -1246,6 +1245,11 @@ xfs_imap_lookup(
        if (error)
                return error;
 
+       /* check that the returned record contains the required inode */
+       if (rec.ir_startino > agino ||
+           rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino)
+               return EINVAL;
+
        /* for untrusted inodes check it is allocated first */
        if ((flags & XFS_IGET_UNTRUSTED) &&
            (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
index 68415cb4f23cab39861119c68838b1b099029df2..34798f391c49349018f04a47d625c6aafa035bea 100644 (file)
@@ -1914,6 +1914,11 @@ xfs_iunlink_remove(
        return 0;
 }
 
+/*
+ * A big issue when freeing the inode cluster is is that we _cannot_ skip any
+ * inodes that are in memory - they all must be marked stale and attached to
+ * the cluster buffer.
+ */
 STATIC void
 xfs_ifree_cluster(
        xfs_inode_t     *free_ip,
@@ -1945,8 +1950,6 @@ xfs_ifree_cluster(
        }
 
        for (j = 0; j < nbufs; j++, inum += ninodes) {
-               int     found = 0;
-
                blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum),
                                         XFS_INO_TO_AGBNO(mp, inum));
 
@@ -1965,7 +1968,9 @@ xfs_ifree_cluster(
                /*
                 * Walk the inodes already attached to the buffer and mark them
                 * stale. These will all have the flush locks held, so an
-                * in-memory inode walk can't lock them.
+                * in-memory inode walk can't lock them. By marking them all
+                * stale first, we will not attempt to lock them in the loop
+                * below as the XFS_ISTALE flag will be set.
                 */
                lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
                while (lip) {
@@ -1977,11 +1982,11 @@ xfs_ifree_cluster(
                                                        &iip->ili_flush_lsn,
                                                        &iip->ili_item.li_lsn);
                                xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
-                               found++;
                        }
                        lip = lip->li_bio_list;
                }
 
+
                /*
                 * For each inode in memory attempt to add it to the inode
                 * buffer and set it up for being staled on buffer IO
@@ -1993,6 +1998,7 @@ xfs_ifree_cluster(
                 * even trying to lock them.
                 */
                for (i = 0; i < ninodes; i++) {
+retry:
                        read_lock(&pag->pag_ici_lock);
                        ip = radix_tree_lookup(&pag->pag_ici_root,
                                        XFS_INO_TO_AGINO(mp, (inum + i)));
@@ -2003,38 +2009,36 @@ xfs_ifree_cluster(
                                continue;
                        }
 
-                       /* don't try to lock/unlock the current inode */
+                       /*
+                        * Don't try to lock/unlock the current inode, but we
+                        * _cannot_ skip the other inodes that we did not find
+                        * in the list attached to the buffer and are not
+                        * already marked stale. If we can't lock it, back off
+                        * and retry.
+                        */
                        if (ip != free_ip &&
                            !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
                                read_unlock(&pag->pag_ici_lock);
-                               continue;
+                               delay(1);
+                               goto retry;
                        }
                        read_unlock(&pag->pag_ici_lock);
 
-                       if (!xfs_iflock_nowait(ip)) {
-                               if (ip != free_ip)
-                                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                               continue;
-                       }
-
+                       xfs_iflock(ip);
                        xfs_iflags_set(ip, XFS_ISTALE);
-                       if (xfs_inode_clean(ip)) {
-                               ASSERT(ip != free_ip);
-                               xfs_ifunlock(ip);
-                               xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                               continue;
-                       }
 
+                       /*
+                        * we don't need to attach clean inodes or those only
+                        * with unlogged changes (which we throw away, anyway).
+                        */
                        iip = ip->i_itemp;
-                       if (!iip) {
-                               /* inode with unlogged changes only */
+                       if (!iip || xfs_inode_clean(ip)) {
                                ASSERT(ip != free_ip);
                                ip->i_update_core = 0;
                                xfs_ifunlock(ip);
                                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                                continue;
                        }
-                       found++;
 
                        iip->ili_last_fields = iip->ili_format.ilf_fields;
                        iip->ili_format.ilf_fields = 0;
@@ -2049,8 +2053,7 @@ xfs_ifree_cluster(
                                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                }
 
-               if (found)
-                       xfs_trans_stale_inode_buf(tp, bp);
+               xfs_trans_stale_inode_buf(tp, bp);
                xfs_trans_binval(tp, bp);
        }
 
index 925d572bf0f405e9a94be11b74549c5f760b3ec4..33f718f92a4849df234880dfe190069791d7bcb6 100644 (file)
@@ -3015,7 +3015,8 @@ _xfs_log_force(
 
        XFS_STATS_INC(xs_log_force);
 
-       xlog_cil_push(log, 1);
+       if (log->l_cilp)
+               xlog_cil_force(log);
 
        spin_lock(&log->l_icloglock);
 
@@ -3167,7 +3168,7 @@ _xfs_log_force_lsn(
        XFS_STATS_INC(xs_log_force);
 
        if (log->l_cilp) {
-               lsn = xlog_cil_push_lsn(log, lsn);
+               lsn = xlog_cil_force_lsn(log, lsn);
                if (lsn == NULLCOMMITLSN)
                        return 0;
        }
@@ -3724,7 +3725,7 @@ xfs_log_force_umount(
         * call below.
         */
        if (!logerror && (mp->m_flags & XFS_MOUNT_DELAYLOG))
-               xlog_cil_push(log, 1);
+               xlog_cil_force(log);
 
        /*
         * We must hold both the GRANT lock and the LOG lock,
index 31e4ea2d19acfc08f069813dffa367e6b2420973..7e206fc1fa362ed4bb761a8f5ad11ef39c2dd5c0 100644 (file)
@@ -68,6 +68,7 @@ xlog_cil_init(
        ctx->sequence = 1;
        ctx->cil = cil;
        cil->xc_ctx = ctx;
+       cil->xc_current_sequence = ctx->sequence;
 
        cil->xc_log = log;
        log->l_cilp = cil;
@@ -269,15 +270,10 @@ xlog_cil_insert(
 static void
 xlog_cil_format_items(
        struct log              *log,
-       struct xfs_log_vec      *log_vector,
-       struct xlog_ticket      *ticket,
-       xfs_lsn_t               *start_lsn)
+       struct xfs_log_vec      *log_vector)
 {
        struct xfs_log_vec *lv;
 
-       if (start_lsn)
-               *start_lsn = log->l_cilp->xc_ctx->sequence;
-
        ASSERT(log_vector);
        for (lv = log_vector; lv; lv = lv->lv_next) {
                void    *ptr;
@@ -301,9 +297,24 @@ xlog_cil_format_items(
                        ptr += vec->i_len;
                }
                ASSERT(ptr == lv->lv_buf + lv->lv_buf_len);
+       }
+}
 
+static void
+xlog_cil_insert_items(
+       struct log              *log,
+       struct xfs_log_vec      *log_vector,
+       struct xlog_ticket      *ticket,
+       xfs_lsn_t               *start_lsn)
+{
+       struct xfs_log_vec *lv;
+
+       if (start_lsn)
+               *start_lsn = log->l_cilp->xc_ctx->sequence;
+
+       ASSERT(log_vector);
+       for (lv = log_vector; lv; lv = lv->lv_next)
                xlog_cil_insert(log, ticket, lv->lv_item, lv);
-       }
 }
 
 static void
@@ -320,80 +331,6 @@ xlog_cil_free_logvec(
        }
 }
 
-/*
- * Commit a transaction with the given vector to the Committed Item List.
- *
- * To do this, we need to format the item, pin it in memory if required and
- * account for the space used by the transaction. Once we have done that we
- * need to release the unused reservation for the transaction, attach the
- * transaction to the checkpoint context so we carry the busy extents through
- * to checkpoint completion, and then unlock all the items in the transaction.
- *
- * For more specific information about the order of operations in
- * xfs_log_commit_cil() please refer to the comments in
- * xfs_trans_commit_iclog().
- *
- * Called with the context lock already held in read mode to lock out
- * background commit, returns without it held once background commits are
- * allowed again.
- */
-int
-xfs_log_commit_cil(
-       struct xfs_mount        *mp,
-       struct xfs_trans        *tp,
-       struct xfs_log_vec      *log_vector,
-       xfs_lsn_t               *commit_lsn,
-       int                     flags)
-{
-       struct log              *log = mp->m_log;
-       int                     log_flags = 0;
-       int                     push = 0;
-
-       if (flags & XFS_TRANS_RELEASE_LOG_RES)
-               log_flags = XFS_LOG_REL_PERM_RESERV;
-
-       if (XLOG_FORCED_SHUTDOWN(log)) {
-               xlog_cil_free_logvec(log_vector);
-               return XFS_ERROR(EIO);
-       }
-
-       /* lock out background commit */
-       down_read(&log->l_cilp->xc_ctx_lock);
-       xlog_cil_format_items(log, log_vector, tp->t_ticket, commit_lsn);
-
-       /* check we didn't blow the reservation */
-       if (tp->t_ticket->t_curr_res < 0)
-               xlog_print_tic_res(log->l_mp, tp->t_ticket);
-
-       /* attach the transaction to the CIL if it has any busy extents */
-       if (!list_empty(&tp->t_busy)) {
-               spin_lock(&log->l_cilp->xc_cil_lock);
-               list_splice_init(&tp->t_busy,
-                                       &log->l_cilp->xc_ctx->busy_extents);
-               spin_unlock(&log->l_cilp->xc_cil_lock);
-       }
-
-       tp->t_commit_lsn = *commit_lsn;
-       xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
-       xfs_trans_unreserve_and_mod_sb(tp);
-
-       /* check for background commit before unlock */
-       if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log))
-               push = 1;
-       up_read(&log->l_cilp->xc_ctx_lock);
-
-       /*
-        * We need to push CIL every so often so we don't cache more than we
-        * can fit in the log. The limit really is that a checkpoint can't be
-        * more than half the log (the current checkpoint is not allowed to
-        * overwrite the previous checkpoint), but commit latency and memory
-        * usage limit this to a smaller size in most cases.
-        */
-       if (push)
-               xlog_cil_push(log, 0);
-       return 0;
-}
-
 /*
  * Mark all items committed and clear busy extents. We free the log vector
  * chains in a separate pass so that we unpin the log items as quickly as
@@ -427,13 +364,23 @@ xlog_cil_committed(
 }
 
 /*
- * Push the Committed Item List to the log. If the push_now flag is not set,
- * then it is a background flush and so we can chose to ignore it.
+ * Push the Committed Item List to the log. If @push_seq flag is zero, then it
+ * is a background flush and so we can chose to ignore it. Otherwise, if the
+ * current sequence is the same as @push_seq we need to do a flush. If
+ * @push_seq is less than the current sequence, then it has already been
+ * flushed and we don't need to do anything - the caller will wait for it to
+ * complete if necessary.
+ *
+ * @push_seq is a value rather than a flag because that allows us to do an
+ * unlocked check of the sequence number for a match. Hence we can allows log
+ * forces to run racily and not issue pushes for the same sequence twice. If we
+ * get a race between multiple pushes for the same sequence they will block on
+ * the first one and then abort, hence avoiding needless pushes.
  */
-int
+STATIC int
 xlog_cil_push(
        struct log              *log,
-       int                     push_now)
+       xfs_lsn_t               push_seq)
 {
        struct xfs_cil          *cil = log->l_cilp;
        struct xfs_log_vec      *lv;
@@ -453,12 +400,20 @@ xlog_cil_push(
        if (!cil)
                return 0;
 
+       ASSERT(!push_seq || push_seq <= cil->xc_ctx->sequence);
+
        new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS);
        new_ctx->ticket = xlog_cil_ticket_alloc(log);
 
-       /* lock out transaction commit, but don't block on background push */
+       /*
+        * Lock out transaction commit, but don't block for background pushes
+        * unless we are well over the CIL space limit. See the definition of
+        * XLOG_CIL_HARD_SPACE_LIMIT() for the full explanation of the logic
+        * used here.
+        */
        if (!down_write_trylock(&cil->xc_ctx_lock)) {
-               if (!push_now)
+               if (!push_seq &&
+                   cil->xc_ctx->space_used < XLOG_CIL_HARD_SPACE_LIMIT(log))
                        goto out_free_ticket;
                down_write(&cil->xc_ctx_lock);
        }
@@ -469,7 +424,11 @@ xlog_cil_push(
                goto out_skip;
 
        /* check for spurious background flush */
-       if (!push_now && cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log))
+       if (!push_seq && cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log))
+               goto out_skip;
+
+       /* check for a previously pushed seqeunce */
+       if (push_seq && push_seq < cil->xc_ctx->sequence)
                goto out_skip;
 
        /*
@@ -514,6 +473,13 @@ xlog_cil_push(
        new_ctx->cil = cil;
        cil->xc_ctx = new_ctx;
 
+       /*
+        * mirror the new sequence into the cil structure so that we can do
+        * unlocked checks against the current sequence in log forces without
+        * risking deferencing a freed context pointer.
+        */
+       cil->xc_current_sequence = new_ctx->sequence;
+
        /*
         * The switch is now done, so we can drop the context lock and move out
         * of a shared context. We can't just go straight to the commit record,
@@ -625,6 +591,102 @@ out_abort:
        return XFS_ERROR(EIO);
 }
 
+/*
+ * Commit a transaction with the given vector to the Committed Item List.
+ *
+ * To do this, we need to format the item, pin it in memory if required and
+ * account for the space used by the transaction. Once we have done that we
+ * need to release the unused reservation for the transaction, attach the
+ * transaction to the checkpoint context so we carry the busy extents through
+ * to checkpoint completion, and then unlock all the items in the transaction.
+ *
+ * For more specific information about the order of operations in
+ * xfs_log_commit_cil() please refer to the comments in
+ * xfs_trans_commit_iclog().
+ *
+ * Called with the context lock already held in read mode to lock out
+ * background commit, returns without it held once background commits are
+ * allowed again.
+ */
+int
+xfs_log_commit_cil(
+       struct xfs_mount        *mp,
+       struct xfs_trans        *tp,
+       struct xfs_log_vec      *log_vector,
+       xfs_lsn_t               *commit_lsn,
+       int                     flags)
+{
+       struct log              *log = mp->m_log;
+       int                     log_flags = 0;
+       int                     push = 0;
+
+       if (flags & XFS_TRANS_RELEASE_LOG_RES)
+               log_flags = XFS_LOG_REL_PERM_RESERV;
+
+       if (XLOG_FORCED_SHUTDOWN(log)) {
+               xlog_cil_free_logvec(log_vector);
+               return XFS_ERROR(EIO);
+       }
+
+       /*
+        * do all the hard work of formatting items (including memory
+        * allocation) outside the CIL context lock. This prevents stalling CIL
+        * pushes when we are low on memory and a transaction commit spends a
+        * lot of time in memory reclaim.
+        */
+       xlog_cil_format_items(log, log_vector);
+
+       /* lock out background commit */
+       down_read(&log->l_cilp->xc_ctx_lock);
+       xlog_cil_insert_items(log, log_vector, tp->t_ticket, commit_lsn);
+
+       /* check we didn't blow the reservation */
+       if (tp->t_ticket->t_curr_res < 0)
+               xlog_print_tic_res(log->l_mp, tp->t_ticket);
+
+       /* attach the transaction to the CIL if it has any busy extents */
+       if (!list_empty(&tp->t_busy)) {
+               spin_lock(&log->l_cilp->xc_cil_lock);
+               list_splice_init(&tp->t_busy,
+                                       &log->l_cilp->xc_ctx->busy_extents);
+               spin_unlock(&log->l_cilp->xc_cil_lock);
+       }
+
+       tp->t_commit_lsn = *commit_lsn;
+       xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
+       xfs_trans_unreserve_and_mod_sb(tp);
+
+       /*
+        * Once all the items of the transaction have been copied to the CIL,
+        * the items can be unlocked and freed.
+        *
+        * This needs to be done before we drop the CIL context lock because we
+        * have to update state in the log items and unlock them before they go
+        * to disk. If we don't, then the CIL checkpoint can race with us and
+        * we can run checkpoint completion before we've updated and unlocked
+        * the log items. This affects (at least) processing of stale buffers,
+        * inodes and EFIs.
+        */
+       xfs_trans_free_items(tp, *commit_lsn, 0);
+
+       /* check for background commit before unlock */
+       if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log))
+               push = 1;
+
+       up_read(&log->l_cilp->xc_ctx_lock);
+
+       /*
+        * We need to push CIL every so often so we don't cache more than we
+        * can fit in the log. The limit really is that a checkpoint can't be
+        * more than half the log (the current checkpoint is not allowed to
+        * overwrite the previous checkpoint), but commit latency and memory
+        * usage limit this to a smaller size in most cases.
+        */
+       if (push)
+               xlog_cil_push(log, 0);
+       return 0;
+}
+
 /*
  * Conditionally push the CIL based on the sequence passed in.
  *
@@ -639,39 +701,34 @@ out_abort:
  * commit lsn is there. It'll be empty, so this is broken for now.
  */
 xfs_lsn_t
-xlog_cil_push_lsn(
+xlog_cil_force_lsn(
        struct log      *log,
-       xfs_lsn_t       push_seq)
+       xfs_lsn_t       sequence)
 {
        struct xfs_cil          *cil = log->l_cilp;
        struct xfs_cil_ctx      *ctx;
        xfs_lsn_t               commit_lsn = NULLCOMMITLSN;
 
-restart:
-       down_write(&cil->xc_ctx_lock);
-       ASSERT(push_seq <= cil->xc_ctx->sequence);
-
-       /* check to see if we need to force out the current context */
-       if (push_seq == cil->xc_ctx->sequence) {
-               up_write(&cil->xc_ctx_lock);
-               xlog_cil_push(log, 1);
-               goto restart;
-       }
+       ASSERT(sequence <= cil->xc_current_sequence);
+
+       /*
+        * check to see if we need to force out the current context.
+        * xlog_cil_push() handles racing pushes for the same sequence,
+        * so no need to deal with it here.
+        */
+       if (sequence == cil->xc_current_sequence)
+               xlog_cil_push(log, sequence);
 
        /*
         * See if we can find a previous sequence still committing.
-        * We can drop the flush lock as soon as we have the cil lock
-        * because we are now only comparing contexts protected by
-        * the cil lock.
-        *
         * We need to wait for all previous sequence commits to complete
         * before allowing the force of push_seq to go ahead. Hence block
         * on commits for those as well.
         */
+restart:
        spin_lock(&cil->xc_cil_lock);
-       up_write(&cil->xc_ctx_lock);
        list_for_each_entry(ctx, &cil->xc_committing, committing) {
-               if (ctx->sequence > push_seq)
+               if (ctx->sequence > sequence)
                        continue;
                if (!ctx->commit_lsn) {
                        /*
@@ -681,7 +738,7 @@ restart:
                        sv_wait(&cil->xc_commit_wait, 0, &cil->xc_cil_lock, 0);
                        goto restart;
                }
-               if (ctx->sequence != push_seq)
+               if (ctx->sequence != sequence)
                        continue;
                /* found it! */
                commit_lsn = ctx->commit_lsn;
index 8c072618965caf80476a562e7e38cae026089f88..edcdfe01617f673bc1047caca3acc243f66a0658 100644 (file)
@@ -422,16 +422,17 @@ struct xfs_cil {
        struct rw_semaphore     xc_ctx_lock;
        struct list_head        xc_committing;
        sv_t                    xc_commit_wait;
+       xfs_lsn_t               xc_current_sequence;
 };
 
 /*
- * The amount of log space we should the CIL to aggregate is difficult to size.
- * Whatever we chose we have to make we can get a reservation for the log space
- * effectively, that it is large enough to capture sufficient relogging to
- * reduce log buffer IO significantly, but it is not too large for the log or
- * induces too much latency when writing out through the iclogs. We track both
- * space consumed and the number of vectors in the checkpoint context, so we
- * need to decide which to use for limiting.
+ * The amount of log space we allow the CIL to aggregate is difficult to size.
+ * Whatever we choose, we have to make sure we can get a reservation for the
+ * log space effectively, that it is large enough to capture sufficient
+ * relogging to reduce log buffer IO significantly, but it is not too large for
+ * the log or induces too much latency when writing out through the iclogs. We
+ * track both space consumed and the number of vectors in the checkpoint
+ * context, so we need to decide which to use for limiting.
  *
  * Every log buffer we write out during a push needs a header reserved, which
  * is at least one sector and more for v2 logs. Hence we need a reservation of
@@ -458,16 +459,21 @@ struct xfs_cil {
  * checkpoint transaction ticket is specific to the checkpoint context, rather
  * than the CIL itself.
  *
- * With dynamic reservations, we can basically make up arbitrary limits for the
- * checkpoint size so long as they don't violate any other size rules.  Hence
- * the initial maximum size for the checkpoint transaction will be set to a
- * quarter of the log or 8MB, which ever is smaller. 8MB is an arbitrary limit
- * right now based on the latency of writing out a large amount of data through
- * the circular iclog buffers.
+ * With dynamic reservations, we can effectively make up arbitrary limits for
+ * the checkpoint size so long as they don't violate any other size rules.
+ * Recovery imposes a rule that no transaction exceed half the log, so we are
+ * limited by that.  Furthermore, the log transaction reservation subsystem
+ * tries to keep 25% of the log free, so we need to keep below that limit or we
+ * risk running out of free log space to start any new transactions.
+ *
+ * In order to keep background CIL push efficient, we will set a lower
+ * threshold at which background pushing is attempted without blocking current
+ * transaction commits.  A separate, higher bound defines when CIL pushes are
+ * enforced to ensure we stay within our maximum checkpoint size bounds.
+ * threshold, yet give us plenty of space for aggregation on large logs.
  */
-
-#define XLOG_CIL_SPACE_LIMIT(log)      \
-       (min((log->l_logsize >> 2), (8 * 1024 * 1024)))
+#define XLOG_CIL_SPACE_LIMIT(log)      (log->l_logsize >> 3)
+#define XLOG_CIL_HARD_SPACE_LIMIT(log) (3 * (log->l_logsize >> 4))
 
 /*
  * The reservation head lsn is not made up of a cycle number and block number.
@@ -562,8 +568,16 @@ int        xlog_cil_init(struct log *log);
 void   xlog_cil_init_post_recovery(struct log *log);
 void   xlog_cil_destroy(struct log *log);
 
-int    xlog_cil_push(struct log *log, int push_now);
-xfs_lsn_t xlog_cil_push_lsn(struct log *log, xfs_lsn_t push_sequence);
+/*
+ * CIL force routines
+ */
+xfs_lsn_t xlog_cil_force_lsn(struct log *log, xfs_lsn_t sequence);
+
+static inline void
+xlog_cil_force(struct log *log)
+{
+       xlog_cil_force_lsn(log, log->l_cilp->xc_current_sequence);
+}
 
 /*
  * Unmount record type is used as a pseudo transaction type for the ticket.
index fdca7416c754636a26dae9a312003932f7306d9f..1c47edaea0d28f4def851e87f664bd9339ac19b7 100644 (file)
@@ -1167,7 +1167,7 @@ xfs_trans_del_item(
  * Unlock all of the items of a transaction and free all the descriptors
  * of that transaction.
  */
-STATIC void
+void
 xfs_trans_free_items(
        struct xfs_trans        *tp,
        xfs_lsn_t               commit_lsn,
@@ -1653,9 +1653,6 @@ xfs_trans_commit_cil(
                return error;
 
        current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
-
-       /* xfs_trans_free_items() unlocks them first */
-       xfs_trans_free_items(tp, *commit_lsn, 0);
        xfs_trans_free(tp);
        return 0;
 }
index e2d93d8ead7b68b9b6ab74b1869a3f8e10721981..62da86c90de53bb36b3fd2928d539ae9fc339478 100644 (file)
@@ -25,7 +25,8 @@ struct xfs_trans;
 
 void   xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
 void   xfs_trans_del_item(struct xfs_log_item *);
-
+void   xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn,
+                               int flags);
 void   xfs_trans_item_committed(struct xfs_log_item *lip,
                                xfs_lsn_t commit_lsn, int aborted);
 void   xfs_trans_unreserve_and_mod_sb(struct xfs_trans *tp);
index 66d585c6917cfd55e50447b8048a2adc3f60d68c..4c7c7bfb2b2fc0aa8cc3cb3c98334392eb902c00 100644 (file)
@@ -2299,15 +2299,22 @@ xfs_alloc_file_space(
                        e = allocatesize_fsb;
                }
 
+               /*
+                * The transaction reservation is limited to a 32-bit block
+                * count, hence we need to limit the number of blocks we are
+                * trying to reserve to avoid an overflow. We can't allocate
+                * more than @nimaps extents, and an extent is limited on disk
+                * to MAXEXTLEN (21 bits), so use that to enforce the limit.
+                */
+               resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
                if (unlikely(rt)) {
-                       resrtextents = qblocks = (uint)(e - s);
+                       resrtextents = qblocks = resblks;
                        resrtextents /= mp->m_sb.sb_rextsize;
                        resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
                        quota_flag = XFS_QMOPT_RES_RTBLKS;
                } else {
                        resrtextents = 0;
-                       resblks = qblocks = \
-                               XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
+                       resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
                        quota_flag = XFS_QMOPT_RES_REGBLKS;
                }
 
index baacd98e7cc6244b795b5db1b09b440292ee3dac..4de84ce3a927123f118861df950202a8dba1a536 100644 (file)
@@ -377,9 +377,6 @@ struct acpi_pci_root {
 
        u32 osc_support_set;    /* _OSC state of support bits */
        u32 osc_control_set;    /* _OSC state of control bits */
-       u32 osc_control_qry;    /* the latest _OSC query result */
-
-       u32 osc_queried:1;      /* has _OSC control been queried? */
 };
 
 /* helper */
index c0786d446a00b88adf144ab97f05af06679cccf7..984cdc62e30bc52da4cef907f3dd5094aa5ffd71 100644 (file)
@@ -55,7 +55,7 @@
 extern u8 acpi_gbl_permanent_mmap;
 
 /*
- * Globals that are publically available, allowing for
+ * Globals that are publicly available, allowing for
  * run time configuration
  */
 extern u32 acpi_dbg_level;
index e53347fbf1da6bdc85aa45ef66ed1c47bdb65a08..e994197f84b73de6432f8a849519ff332b4c6bde 100644 (file)
@@ -43,6 +43,7 @@
  */
 #define atomic_set(v, i) (((v)->counter) = (i))
 
+#include <linux/irqflags.h>
 #include <asm/system.h>
 
 /**
@@ -57,7 +58,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
        unsigned long flags;
        int temp;
 
-       raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+       raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
        temp = v->counter;
        temp += i;
        v->counter = temp;
@@ -78,7 +79,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
        unsigned long flags;
        int temp;
 
-       raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+       raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
        temp = v->counter;
        temp -= i;
        v->counter = temp;
@@ -119,14 +120,23 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_dec_and_test(v)         (atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)         (atomic_add_return(1, (v)) == 0)
 
-#define atomic_add_unless(v, a, u)                             \
-({                                                             \
-       int c, old;                                             \
-       c = atomic_read(v);                                     \
-       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-               c = old;                                        \
-       c != (u);                                               \
-})
+#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
+
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+  int c, old;
+  c = atomic_read(v);
+  while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
+    c = old;
+  return c != u;
+}
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
@@ -140,15 +150,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
        raw_local_irq_restore(flags);
 }
 
-#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
-#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
-
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
 /* Assume that atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
 #define smp_mb__after_atomic_dec()     barrier()
index 1914e9742512db6d9bd5e9be5bc9be30ad510c0f..110fa700f85380e29397287ef597734f2a366149 100644 (file)
@@ -1,15 +1,50 @@
 #ifndef _ASM_GENERIC_BITOPS_FIND_H_
 #define _ASM_GENERIC_BITOPS_FIND_H_
 
-#ifndef CONFIG_GENERIC_FIND_NEXT_BIT
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
 extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
                size, unsigned long offset);
 
+/**
+ * find_next_zero_bit - find the next cleared bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
 extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
                long size, unsigned long offset);
-#endif
+
+#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit.
+ */
+extern unsigned long find_first_bit(const unsigned long *addr,
+                                   unsigned long size);
+
+/**
+ * find_first_zero_bit - find the first cleared bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first cleared bit.
+ */
+extern unsigned long find_first_zero_bit(const unsigned long *addr,
+                                        unsigned long size);
+#else /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
 #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
 
+#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
+
 #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
index b2ba2fc8829a6a759d521e14bf1a3e1e80d64c78..2533fddd34a69d7b1f272895b980c750f39cfdd1 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_GENERIC_CMPXCHG_LOCAL_H
 
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
 
index a70b2d2bfc14f70940d08bcaef7fac4e185308c9..0fc16e3f0bfcc01e0f4e9016f82b0b5387d5317a 100644 (file)
 
 struct f_owner_ex {
        int     type;
-       pid_t   pid;
+       __kernel_pid_t  pid;
 };
 
 /* for F_[GET|SET]FL */
index c7376bf80b0604bf8f8b9394989178d6de45ecc2..8ca18e26d7e39fe429a8179d48f2f9f17f58a589 100644 (file)
  * While the GPIO programming interface defines valid GPIO numbers
  * to be in the range 0..MAX_INT, this library restricts them to the
  * smaller range 0..ARCH_NR_GPIOS-1.
+ *
+ * ARCH_NR_GPIOS is somewhat arbitrary; it usually reflects the sum of
+ * builtin/SoC GPIOs plus a number of GPIOs on expanders; the latter is
+ * actually an estimate of a board-specific value.
  */
 
 #ifndef ARCH_NR_GPIOS
 #define ARCH_NR_GPIOS          256
 #endif
 
+/*
+ * "valid" GPIO numbers are nonnegative and may be passed to
+ * setup routines like gpio_request().  only some valid numbers
+ * can successfully be requested and used.
+ *
+ * Invalid GPIO numbers are useful for indicating no-such-GPIO in
+ * platform data and other tables.
+ */
+
 static inline int gpio_is_valid(int number)
 {
-       /* only some non-negative numbers are valid */
        return ((unsigned)number) < ARCH_NR_GPIOS;
 }
 
index 62f59080e5cc215edb843f928763d9898055071f..04d0a977cd431fc5eb2c2f34cbd5390bfeb0db05 100644 (file)
@@ -3,13 +3,13 @@
 
 #include <linux/cache.h>
 #include <linux/threads.h>
-#include <linux/irq.h>
 
 typedef struct {
        unsigned int __softirq_pending;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
 
 #ifndef ack_bad_irq
 static inline void ack_bad_irq(unsigned int irq)
index 118601fce92d95a48ef7cbbaa6190bc575b6b609..3577ca11a0be7511d417433ddcc4636dc01c2a26 100644 (file)
@@ -19,7 +19,9 @@
 #include <asm-generic/iomap.h>
 #endif
 
+#ifndef mmiowb
 #define mmiowb() do {} while (0)
+#endif
 
 /*****************************************************************************/
 /*
  * differently. On the simple architectures, we just read/write the
  * memory location directly.
  */
+#ifndef __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
        return *(const volatile u8 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        return *(const volatile u16 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        return *(const volatile u32 __force *) addr;
 }
+#endif
 
 #define readb __raw_readb
 #define readw(addr) __le16_to_cpu(__raw_readw(addr))
 #define readl(addr) __le32_to_cpu(__raw_readl(addr))
 
+#ifndef __raw_writeb
 static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
 {
        *(volatile u8 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writew
 static inline void __raw_writew(u16 b, volatile void __iomem *addr)
 {
        *(volatile u16 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writel
 static inline void __raw_writel(u32 b, volatile void __iomem *addr)
 {
        *(volatile u32 __force *) addr = b;
 }
+#endif
 
 #define writeb __raw_writeb
 #define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
@@ -122,6 +136,7 @@ static inline void outl(u32 b, unsigned long addr)
 #define outw_p(x, addr)        outw((x), (addr))
 #define outl_p(x, addr)        outl((x), (addr))
 
+#ifndef insb
 static inline void insb(unsigned long addr, void *buffer, int count)
 {
        if (count) {
@@ -132,7 +147,9 @@ static inline void insb(unsigned long addr, void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
+#ifndef insw
 static inline void insw(unsigned long addr, void *buffer, int count)
 {
        if (count) {
@@ -143,7 +160,9 @@ static inline void insw(unsigned long addr, void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
+#ifndef insl
 static inline void insl(unsigned long addr, void *buffer, int count)
 {
        if (count) {
@@ -154,7 +173,9 @@ static inline void insl(unsigned long addr, void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
+#ifndef outsb
 static inline void outsb(unsigned long addr, const void *buffer, int count)
 {
        if (count) {
@@ -164,7 +185,9 @@ static inline void outsb(unsigned long addr, const void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
+#ifndef outsw
 static inline void outsw(unsigned long addr, const void *buffer, int count)
 {
        if (count) {
@@ -174,7 +197,9 @@ static inline void outsw(unsigned long addr, const void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
+#ifndef outsl
 static inline void outsl(unsigned long addr, const void *buffer, int count)
 {
        if (count) {
@@ -184,6 +209,7 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
                } while (--count);
        }
 }
+#endif
 
 #ifndef CONFIG_GENERIC_IOMAP
 #define ioread8(addr)          readb(addr)
index 9aebf618275af2e5bf519bb241661039f8e632d4..1f40d0024cf381d5c380f2a1c19b5c5ce3ae24e1 100644 (file)
@@ -5,68 +5,62 @@
  * All architectures should implement at least the first two functions,
  * usually inline assembly will be the best way.
  */
-#ifndef RAW_IRQ_DISABLED
-#define RAW_IRQ_DISABLED 0
-#define RAW_IRQ_ENABLED 1
+#ifndef ARCH_IRQ_DISABLED
+#define ARCH_IRQ_DISABLED 0
+#define ARCH_IRQ_ENABLED 1
 #endif
 
 /* read interrupt enabled status */
-#ifndef __raw_local_save_flags
-unsigned long __raw_local_save_flags(void);
+#ifndef arch_local_save_flags
+unsigned long arch_local_save_flags(void);
 #endif
 
 /* set interrupt enabled status */
-#ifndef raw_local_irq_restore
-void raw_local_irq_restore(unsigned long flags);
+#ifndef arch_local_irq_restore
+void arch_local_irq_restore(unsigned long flags);
 #endif
 
 /* get status and disable interrupts */
-#ifndef __raw_local_irq_save
-static inline unsigned long __raw_local_irq_save(void)
+#ifndef arch_local_irq_save
+static inline unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
-       flags = __raw_local_save_flags();
-       raw_local_irq_restore(RAW_IRQ_DISABLED);
+       flags = arch_local_save_flags();
+       arch_local_irq_restore(ARCH_IRQ_DISABLED);
        return flags;
 }
 #endif
 
 /* test flags */
-#ifndef raw_irqs_disabled_flags
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+#ifndef arch_irqs_disabled_flags
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-       return flags == RAW_IRQ_DISABLED;
+       return flags == ARCH_IRQ_DISABLED;
 }
 #endif
 
 /* unconditionally enable interrupts */
-#ifndef raw_local_irq_enable
-static inline void raw_local_irq_enable(void)
+#ifndef arch_local_irq_enable
+static inline void arch_local_irq_enable(void)
 {
-       raw_local_irq_restore(RAW_IRQ_ENABLED);
+       arch_local_irq_restore(ARCH_IRQ_ENABLED);
 }
 #endif
 
 /* unconditionally disable interrupts */
-#ifndef raw_local_irq_disable
-static inline void raw_local_irq_disable(void)
+#ifndef arch_local_irq_disable
+static inline void arch_local_irq_disable(void)
 {
-       raw_local_irq_restore(RAW_IRQ_DISABLED);
+       arch_local_irq_restore(ARCH_IRQ_DISABLED);
 }
 #endif
 
 /* test hardware interrupt enable bit */
-#ifndef raw_irqs_disabled
-static inline int raw_irqs_disabled(void)
+#ifndef arch_irqs_disabled
+static inline int arch_irqs_disabled(void)
 {
-       return raw_irqs_disabled_flags(__raw_local_save_flags());
+       return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 #endif
 
-#define raw_local_save_flags(flags) \
-       do { (flags) = __raw_local_save_flags(); } while (0)
-
-#define raw_local_irq_save(flags) \
-       do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* __ASM_GENERIC_IRQFLAGS_H */
index 11e57b6a85fcd78e451e88a34a14d20c8c1cc04d..d1814497bcdb050a0694453441b2722c7ce75898 100644 (file)
@@ -3,7 +3,7 @@
 
 enum die_val {
        DIE_UNUSED,
-       DIE_OOPS=1
+       DIE_OOPS = 1,
 };
 
 #endif /* _ASM_GENERIC_KDEBUG_H */
index b5043a9890d85a38d4e63d3ae40f546675639e30..08923b6847681f364557fd52a43b076eaf4d9a2e 100644 (file)
@@ -70,11 +70,16 @@ extern void setup_per_cpu_areas(void);
 
 #else /* ! SMP */
 
-#define per_cpu(var, cpu)                      (*((void)(cpu), &(var)))
-#define __get_cpu_var(var)                     (var)
-#define __raw_get_cpu_var(var)                 (var)
-#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)
-#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr)
+#define VERIFY_PERCPU_PTR(__p) ({                      \
+       __verify_pcpu_ptr((__p));                       \
+       (typeof(*(__p)) __kernel __force *)(__p);       \
+})
+
+#define per_cpu(var, cpu)      (*((void)(cpu), VERIFY_PERCPU_PTR(&(var))))
+#define __get_cpu_var(var)     (*VERIFY_PERCPU_PTR(&(var)))
+#define __raw_get_cpu_var(var) (*VERIFY_PERCPU_PTR(&(var)))
+#define this_cpu_ptr(ptr)      per_cpu_ptr(ptr, 0)
+#define __this_cpu_ptr(ptr)    this_cpu_ptr(ptr)
 
 #endif /* SMP */
 
index e2bd73e8f9c0b4db75755d1e4f0aadaaa0e20c2a..f4d4120e5128a8fe76580286151017ddb68c497b 100644 (file)
@@ -129,6 +129,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #define move_pte(pte, prot, old_addr, new_addr)        (pte)
 #endif
 
+#ifndef flush_tlb_fix_spurious_fault
+#define flush_tlb_fix_spurious_fault(vma, address) flush_tlb_page(vma, address)
+#endif
+
 #ifndef pgprot_noncached
 #define pgprot_noncached(prot) (prot)
 #endif
index efa403b5e121585298c5822edf26602abc70599e..4b0b9cbbfae5441eec5ada87d19351a53d7b2394 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/irqflags.h>
 
 #include <asm/cmpxchg-local.h>
+#include <asm/cmpxchg.h>
 
 struct task_struct;
 
@@ -136,25 +137,6 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 #define xchg(ptr, x) \
        ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
 
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                                     unsigned long old, unsigned long new)
-{
-       unsigned long retval;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       retval = *m;
-       if (retval == old)
-               *m = new;
-       local_irq_restore(flags);
-       return retval;
-}
-
-#define cmpxchg(ptr, o, n)                                     \
-       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-                                       (unsigned long)(o),     \
-                                       (unsigned long)(n)))
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 8a92a170fb7dfd87710bb26b3c7f384dd6801363..f4229fb315e1d7d81caddb7557cbcb6c65072fed 100644 (file)
                                                                        \
        BUG_TABLE                                                       \
                                                                        \
+       JUMP_TABLE                                                      \
+                                                                       \
        /* PCI quirks */                                                \
        .pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {        \
                VMLINUX_SYMBOL(__start_pci_fixups_early) = .;           \
 #define BUG_TABLE
 #endif
 
+#define JUMP_TABLE                                                     \
+       . = ALIGN(8);                                                   \
+       __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) {           \
+               VMLINUX_SYMBOL(__start___jump_table) = .;               \
+               *(__jump_table)                                         \
+               VMLINUX_SYMBOL(__stop___jump_table) = .;                \
+       }
+
 #ifdef CONFIG_PM_TRACE
 #define TRACEDATA                                                      \
        . = ALIGN(4);                                                   \
                                - LOAD_OFFSET) {                        \
                VMLINUX_SYMBOL(__per_cpu_start) = .;                    \
                *(.data..percpu..first)                                 \
+               . = ALIGN(PAGE_SIZE);                                   \
                *(.data..percpu..page_aligned)                          \
+               *(.data..percpu..readmostly)                            \
                *(.data..percpu)                                        \
                *(.data..percpu..shared_aligned)                        \
                VMLINUX_SYMBOL(__per_cpu_end) = .;                      \
                VMLINUX_SYMBOL(__per_cpu_load) = .;                     \
                VMLINUX_SYMBOL(__per_cpu_start) = .;                    \
                *(.data..percpu..first)                                 \
+               . = ALIGN(PAGE_SIZE);                                   \
                *(.data..percpu..page_aligned)                          \
+               *(.data..percpu..readmostly)                            \
                *(.data..percpu)                                        \
                *(.data..percpu..shared_aligned)                        \
                VMLINUX_SYMBOL(__per_cpu_end) = .;                      \
index 2a512bc0d4ab74f7c56bc9460b7df3e4e3c0f8d9..4c9461a4f9e67b4b3e67c5bb73192aed44695079 100644 (file)
@@ -305,14 +305,16 @@ struct drm_ioctl_desc {
        unsigned int cmd;
        int flags;
        drm_ioctl_t *func;
+       unsigned int cmd_drv;
 };
 
 /**
  * Creates a driver or general drm_ioctl_desc array entry for the given
  * ioctl, for use by drm_ioctl().
  */
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags}
+
+#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)                        \
+       [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl}
 
 struct drm_magic_entry {
        struct list_head head;
@@ -610,7 +612,7 @@ struct drm_gem_object {
        struct kref refcount;
 
        /** Handle count of this object. Each handle also holds a reference */
-       struct kref handlecount;
+       atomic_t handle_count; /* number of handles on this object */
 
        /** Related drm device */
        struct drm_device *dev;
@@ -806,7 +808,6 @@ struct drm_driver {
         */
        int (*gem_init_object) (struct drm_gem_object *obj);
        void (*gem_free_object) (struct drm_gem_object *obj);
-       void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1173,6 +1174,7 @@ extern int drm_release(struct inode *inode, struct file *filp);
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
 extern void drm_vm_open_locked(struct vm_area_struct *vma);
+extern void drm_vm_close_locked(struct vm_area_struct *vma);
 extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
 extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
 extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
@@ -1453,12 +1455,11 @@ int drm_gem_init(struct drm_device *dev);
 void drm_gem_destroy(struct drm_device *dev);
 void drm_gem_object_release(struct drm_gem_object *obj);
 void drm_gem_object_free(struct kref *kref);
-void drm_gem_object_free_unlocked(struct kref *kref);
 struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
                                            size_t size);
 int drm_gem_object_init(struct drm_device *dev,
                        struct drm_gem_object *obj, size_t size);
-void drm_gem_object_handle_free(struct kref *kref);
+void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -1481,8 +1482,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
 static inline void
 drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
 {
-       if (obj != NULL)
-               kref_put(&obj->refcount, drm_gem_object_free_unlocked);
+       if (obj != NULL) {
+               struct drm_device *dev = obj->dev;
+               mutex_lock(&dev->struct_mutex);
+               kref_put(&obj->refcount, drm_gem_object_free);
+               mutex_unlock(&dev->struct_mutex);
+       }
 }
 
 int drm_gem_handle_create(struct drm_file *file_priv,
@@ -1493,7 +1498,7 @@ static inline void
 drm_gem_object_handle_reference(struct drm_gem_object *obj)
 {
        drm_gem_object_reference(obj);
-       kref_get(&obj->handlecount);
+       atomic_inc(&obj->handle_count);
 }
 
 static inline void
@@ -1502,12 +1507,15 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj)
        if (obj == NULL)
                return;
 
+       if (atomic_read(&obj->handle_count) == 0)
+               return;
        /*
         * Must bump handle count first as this may be the last
         * ref, in which case the object would disappear before we
         * checked for a name
         */
-       kref_put(&obj->handlecount, drm_gem_object_handle_free);
+       if (atomic_dec_and_test(&obj->handle_count))
+               drm_gem_object_handle_free(obj);
        drm_gem_object_unreference(obj);
 }
 
@@ -1517,12 +1525,17 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
        if (obj == NULL)
                return;
 
+       if (atomic_read(&obj->handle_count) == 0)
+               return;
+
        /*
        * Must bump handle count first as this may be the last
        * ref, in which case the object would disappear before we
        * checked for a name
        */
-       kref_put(&obj->handlecount, drm_gem_object_handle_free);
+
+       if (atomic_dec_and_test(&obj->handle_count))
+               drm_gem_object_handle_free(obj);
        drm_gem_object_unreference_unlocked(obj);
 }
 
index c9f3cc5949a82eb0ae5ba4b463891df5f96806dd..3e5a51af757c76ba07f514d00265a5e7300b6627 100644 (file)
@@ -386,7 +386,15 @@ struct drm_connector_funcs {
        void (*dpms)(struct drm_connector *connector, int mode);
        void (*save)(struct drm_connector *connector);
        void (*restore)(struct drm_connector *connector);
-       enum drm_connector_status (*detect)(struct drm_connector *connector);
+
+       /* Check to see if anything is attached to the connector.
+        * @force is set to false whilst polling, true when checking the
+        * connector due to user request. @force can be used by the driver
+        * to avoid expensive, destructive operations during automated
+        * probing.
+        */
+       enum drm_connector_status (*detect)(struct drm_connector *connector,
+                                           bool force);
        int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
        int (*set_property)(struct drm_connector *connector, struct drm_property *property,
                             uint64_t val);
index 3a9940ef728bb5d2412c4cb54d84ed746e15d870..883c1d4398996d8ba807ca5d54940cec28c7809e 100644 (file)
@@ -85,7 +85,6 @@
        {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
        {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
index 4b00d2dd4f684f7dfde4256c84f09bf08844e2b6..61315c29b8f3d53dcb903487e13825bd507e48bf 100644 (file)
@@ -264,20 +264,20 @@ typedef struct _drm_i830_sarea {
 #define DRM_I830_GETPARAM      0x0c
 #define DRM_I830_SETPARAM      0x0d
 
-#define DRM_IOCTL_I830_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_INIT, drm_i830_init_t)
-#define DRM_IOCTL_I830_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_VERTEX, drm_i830_vertex_t)
-#define DRM_IOCTL_I830_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_CLEAR, drm_i830_clear_t)
-#define DRM_IOCTL_I830_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLUSH)
-#define DRM_IOCTL_I830_GETAGE          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_GETAGE)
-#define DRM_IOCTL_I830_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETBUF, drm_i830_dma_t)
-#define DRM_IOCTL_I830_SWAP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_SWAP)
-#define DRM_IOCTL_I830_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_COPY, drm_i830_copy_t)
-#define DRM_IOCTL_I830_DOCOPY          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_DOCOPY)
-#define DRM_IOCTL_I830_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLIP)
-#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_EMIT, drm_i830_irq_emit_t)
-#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_WAIT, drm_i830_irq_wait_t)
-#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETPARAM, drm_i830_getparam_t)
-#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_SETPARAM, drm_i830_setparam_t)
+#define DRM_IOCTL_I830_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I830_INIT, drm_i830_init_t)
+#define DRM_IOCTL_I830_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_I830_VERTEX, drm_i830_vertex_t)
+#define DRM_IOCTL_I830_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_I830_CLEAR, drm_i830_clear_t)
+#define DRM_IOCTL_I830_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I830_FLUSH)
+#define DRM_IOCTL_I830_GETAGE          DRM_IO ( DRM_COMMAND_BASE + DRM_I830_GETAGE)
+#define DRM_IOCTL_I830_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_GETBUF, drm_i830_dma_t)
+#define DRM_IOCTL_I830_SWAP            DRM_IO ( DRM_COMMAND_BASE + DRM_I830_SWAP)
+#define DRM_IOCTL_I830_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_I830_COPY, drm_i830_copy_t)
+#define DRM_IOCTL_I830_DOCOPY          DRM_IO ( DRM_COMMAND_BASE + DRM_I830_DOCOPY)
+#define DRM_IOCTL_I830_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_I830_FLIP)
+#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_IRQ_EMIT, drm_i830_irq_emit_t)
+#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I830_IRQ_WAIT, drm_i830_irq_wait_t)
+#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_GETPARAM, drm_i830_getparam_t)
+#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_SETPARAM, drm_i830_setparam_t)
 
 typedef struct _drm_i830_clear {
        int clear_color;
index 8f8b072c4c7b6013e12c10e35bbf1da24f6a9d79..e41c74facb6a3e41e84e3c66df6395d1a94add76 100644 (file)
@@ -215,6 +215,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
+#define DRM_IOCTL_I915_HWS_ADDR                DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init)
 #define DRM_IOCTL_I915_GEM_INIT                DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
 #define DRM_IOCTL_I915_GEM_EXECBUFFER  DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
 #define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
index 3ffbc4798afacaec3f521eac11b607269cfd7c20..c16097f99be090f557d21405f8eeee1446be0324 100644 (file)
@@ -248,7 +248,7 @@ typedef struct _drm_mga_sarea {
 #define DRM_MGA_DMA_BOOTSTRAP  0x0c
 
 #define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
-#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
+#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock)
 #define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
 #define DRM_IOCTL_MGA_SWAP     DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_SWAP)
 #define DRM_IOCTL_MGA_CLEAR    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
index fe917dee723a7357f44c285626189ae7acd5e863..01a7141195068c8e0fd384c0dde661adfb9601b6 100644 (file)
@@ -197,4 +197,17 @@ struct drm_nouveau_sarea {
 #define DRM_NOUVEAU_GEM_CPU_FINI       0x43
 #define DRM_NOUVEAU_GEM_INFO           0x44
 
+#define DRM_IOCTL_NOUVEAU_GETPARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam)
+#define DRM_IOCTL_NOUVEAU_SETPARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SETPARAM, struct drm_nouveau_setparam)
+#define DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC      DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_ALLOC, struct drm_nouveau_channel_alloc)
+#define DRM_IOCTL_NOUVEAU_CHANNEL_FREE       DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_FREE, struct drm_nouveau_channel_free)
+#define DRM_IOCTL_NOUVEAU_GROBJ_ALLOC        DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GROBJ_ALLOC, struct drm_nouveau_grobj_alloc)
+#define DRM_IOCTL_NOUVEAU_NOTIFIEROBJ_ALLOC  DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, struct drm_nouveau_notifierobj_alloc)
+#define DRM_IOCTL_NOUVEAU_GPUOBJ_FREE        DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GPUOBJ_FREE, struct drm_nouveau_gpuobj_free)
+#define DRM_IOCTL_NOUVEAU_GEM_NEW            DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new)
+#define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF        DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
+#define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP       DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
+#define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI       DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini)
+#define DRM_IOCTL_NOUVEAU_GEM_INFO           DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info)
+
 #endif /* __NOUVEAU_DRM_H__ */
index 0acaf8f9143751791f54b3a2da0be0c40653ad19..10f8b53bdd404d47c80cd8d9ee876c57b1c2b8a5 100644 (file)
@@ -547,8 +547,8 @@ typedef struct {
 #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle)
 #define DRM_IOCTL_RADEON_CS            DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
 #define DRM_IOCTL_RADEON_INFO          DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
-#define DRM_IOCTL_RADEON_SET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling)
-#define DRM_IOCTL_RADEON_GET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
+#define DRM_IOCTL_RADEON_GEM_SET_TILING        DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling)
+#define DRM_IOCTL_RADEON_GEM_GET_TILING        DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
 #define DRM_IOCTL_RADEON_GEM_BUSY      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy)
 
 typedef struct drm_radeon_init {
index 8a576ef01821715099d7f16ef991571f290749ce..4863cf6bf96fb23c96d3eab9d7cde5d794fe89bc 100644 (file)
@@ -63,10 +63,10 @@ typedef struct _drm_savage_sarea {
 #define DRM_SAVAGE_BCI_EVENT_EMIT      0x02
 #define DRM_SAVAGE_BCI_EVENT_WAIT      0x03
 
-#define DRM_IOCTL_SAVAGE_INIT          DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
-#define DRM_IOCTL_SAVAGE_CMDBUF                DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
-#define DRM_IOCTL_SAVAGE_EVENT_EMIT    DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
-#define DRM_IOCTL_SAVAGE_EVENT_WAIT    DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
+#define DRM_IOCTL_SAVAGE_BCI_INIT              DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
+#define DRM_IOCTL_SAVAGE_BCI_CMDBUF            DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
+#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT        DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
+#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT        DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
 
 #define SAVAGE_DMA_PCI 1
 #define SAVAGE_DMA_AGP 3
index 267a86c74e2e5cc089dfb5c72a1f1da3dbdae721..2040e6c4f1729a7de3001d5077277b8521427fb9 100644 (file)
@@ -246,9 +246,11 @@ struct ttm_buffer_object {
 
        atomic_t reserved;
 
-
        /**
         * Members protected by the bo::lock
+        * In addition, setting sync_obj to anything else
+        * than NULL requires bo::reserved to be held. This allows for
+        * checking NULL while reserved but not holding bo::lock.
         */
 
        void *sync_obj_arg;
index 626b629429ff2fc3f30fcf63b25fb52211f184c0..4e8ea8c8ec1e7f6fc04ebf992294b63cb23b1bbb 100644 (file)
@@ -118,7 +118,6 @@ header-y += eventpoll.h
 header-y += ext2_fs.h
 header-y += fadvise.h
 header-y += falloc.h
-header-y += fanotify.h
 header-y += fb.h
 header-y += fcntl.h
 header-y += fd.h
index ccf94dc5acdf0ba8cc4f836968f103f542ff43b6..c227757feb06b4c22eb15ca3faf82c1dfa9f107e 100644 (file)
@@ -304,8 +304,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
                                OSC_PCI_EXPRESS_PME_CONTROL |           \
                                OSC_PCI_EXPRESS_AER_CONTROL |           \
                                OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
-
-extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags);
+extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
+                                            u32 *mask, u32 req);
 extern void acpi_early_init(void);
 
 #else  /* !CONFIG_ACPI */
index 7e3d2859be50230b9b2755288a53d8fb693145b0..1d0ef1ae80362d50f1b620b54c01313d6c46b936 100644 (file)
@@ -25,8 +25,6 @@ static inline u32 acpi_pm_read_early(void)
        return acpi_pm_read_verified() & ACPI_PM_MASK;
 }
 
-extern void pmtimer_wait(unsigned);
-
 #else
 
 static inline u32 acpi_pm_read_early(void)
index b0c1740124365979f9e6e50a0671bf217206bdda..c6454cca044787f65965369d92837f4649297a93 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/resource.h>
 
 #define AMBA_NR_IRQS   2
+#define AMBA_CID       0xb105f00d
 
 struct clk;
 
@@ -70,9 +71,15 @@ void amba_release_regions(struct amba_device *);
 #define amba_pclk_disable(d)   \
        do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
-#define amba_config(d) (((d)->periphid >> 24) & 0xff)
-#define amba_rev(d)    (((d)->periphid >> 20) & 0x0f)
-#define amba_manf(d)   (((d)->periphid >> 12) & 0xff)
-#define amba_part(d)   ((d)->periphid & 0xfff)
+/* Some drivers don't use the struct amba_device */
+#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
+#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
+#define AMBA_MANF_BITS(a) (((a) >> 12) & 0xff)
+#define AMBA_PART_BITS(a) ((a) & 0xfff)
+
+#define amba_config(d) AMBA_CONFIG_BITS((d)->periphid)
+#define amba_rev(d)    AMBA_REV_BITS((d)->periphid)
+#define amba_manf(d)   AMBA_MANF_BITS((d)->periphid)
+#define amba_part(d)   AMBA_PART_BITS((d)->periphid)
 
 #endif
index ca84ce70d5d5fca84b7de66533ba06cab54e5298..f4ee9acc97213b72f36f984ce31b57fd4ba1a784 100644 (file)
@@ -24,6 +24,7 @@
  * whether a card is present in the MMC slot or not
  * @gpio_wp: read this GPIO pin to see if the card is write protected
  * @gpio_cd: read this GPIO pin to detect card insertion
+ * @cd_invert: true if the gpio_cd pin value is active low
  * @capabilities: the capabilities of the block as implemented in
  * this platform, signify anything MMC_CAP_* from mmc/host.h
  */
@@ -35,6 +36,7 @@ struct mmci_platform_data {
        unsigned int (*status)(struct device *);
        int     gpio_wp;
        int     gpio_cd;
+       bool    cd_invert;
        unsigned long capabilities;
 };
 
index abf26cc47a2bc19ff0238a71128d2505c9acc156..4ce98f54186b4fe0a215fa47ddd49fe1ef83152a 100644 (file)
@@ -228,6 +228,7 @@ enum ssp_chip_select {
 };
 
 
+struct dma_chan;
 /**
  * struct pl022_ssp_master - device.platform_data for SPI controller devices.
  * @num_chipselect: chipselects are used to distinguish individual
@@ -235,11 +236,16 @@ enum ssp_chip_select {
  *     each slave has a chipselect signal, but it's common that not
  *     every chipselect is connected to a slave.
  * @enable_dma: if true enables DMA driven transfers.
+ * @dma_rx_param: parameter to locate an RX DMA channel.
+ * @dma_tx_param: parameter to locate a TX DMA channel.
  */
 struct pl022_ssp_controller {
        u16 bus_id;
        u8 num_chipselect;
        u8 enable_dma:1;
+       bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+       void *dma_rx_param;
+       void *dma_tx_param;
 };
 
 /**
@@ -270,20 +276,13 @@ struct pl022_ssp_controller {
  * @dma_config: DMA configuration for SSP controller and peripheral
  */
 struct pl022_config_chip {
-       struct device *dev;
-       enum ssp_loopback lbm;
        enum ssp_interface iface;
        enum ssp_hierarchy hierarchy;
        bool slave_tx_disable;
        struct ssp_clock_params clk_freq;
-       enum ssp_rx_endian endian_rx;
-       enum ssp_tx_endian endian_tx;
-       enum ssp_data_size data_size;
        enum ssp_mode com_mode;
        enum ssp_rx_level_trig rx_lev_trig;
        enum ssp_tx_level_trig tx_lev_trig;
-       enum ssp_spi_clk_phase clk_phase;
-       enum ssp_spi_clk_pol clk_pol;
        enum ssp_microwire_ctrl_len ctrl_len;
        enum ssp_microwire_wait_state wait_state;
        enum ssp_duplex duplex;
index e1b634b635f2a3df5e8a0787c76ea371ae9d8f1a..6021588ba0a87ea14ab1cb4620bef7aeea3d3ab9 100644 (file)
@@ -32,7 +32,9 @@
 #define UART01x_RSR            0x04    /* Receive status register (Read). */
 #define UART01x_ECR            0x04    /* Error clear register (Write). */
 #define UART010_LCRH           0x08    /* Line control register, high byte. */
+#define ST_UART011_DMAWM       0x08    /* DMA watermark configure register. */
 #define UART010_LCRM           0x0C    /* Line control register, middle byte. */
+#define ST_UART011_TIMEOUT     0x0C    /* Timeout period register. */
 #define UART010_LCRL           0x10    /* Line control register, low byte. */
 #define UART010_CR             0x14    /* Control register. */
 #define UART01x_FR             0x18    /* Flag register (Read only). */
 #define UART011_MIS            0x40    /* Masked interrupt status. */
 #define UART011_ICR            0x44    /* Interrupt clear register. */
 #define UART011_DMACR          0x48    /* DMA control register. */
+#define ST_UART011_XFCR                0x50    /* XON/XOFF control register. */
+#define ST_UART011_XON1                0x54    /* XON1 register. */
+#define ST_UART011_XON2                0x58    /* XON2 register. */
+#define ST_UART011_XOFF1       0x5C    /* XON1 register. */
+#define ST_UART011_XOFF2       0x60    /* XON2 register. */
+#define ST_UART011_ITCR                0x80    /* Integration test control register. */
+#define ST_UART011_ITIP                0x84    /* Integration test input register. */
+#define ST_UART011_ABCR                0x100   /* Autobaud control register. */
+#define ST_UART011_ABIMSC      0x15C   /* Autobaud interrupt mask/clear register. */
 
 #define UART011_DR_OE          (1 << 11)
 #define UART011_DR_BE          (1 << 10)
index fe6e681a9d742788be67c16003662b9a7a218e89..0c4929fa34d31da64a79bd22dbfdccd8aaba33dc 100644 (file)
@@ -89,6 +89,7 @@ enum {
        ATA_ID_SPG              = 98,
        ATA_ID_LBA_CAPACITY_2   = 100,
        ATA_ID_SECTOR_SIZE      = 106,
+       ATA_ID_LOGICAL_SECTOR_SIZE      = 117,  /* and 118 */
        ATA_ID_LAST_LUN         = 126,
        ATA_ID_DLF              = 128,
        ATA_ID_CSFO             = 129,
@@ -640,16 +641,49 @@ static inline int ata_id_flush_ext_enabled(const u16 *id)
        return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400;
 }
 
-static inline int ata_id_has_large_logical_sectors(const u16 *id)
+static inline u32 ata_id_logical_sector_size(const u16 *id)
 {
-       if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000)
-               return 0;
-       return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
+       /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+        * IDENTIFY DEVICE data, word 117-118.
+        * 0xd000 ignores bit 13 (logical:physical > 1)
+        */
+       if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000)
+               return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16)
+                        + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ;
+       return ATA_SECT_SIZE;
+}
+
+static inline u8 ata_id_log2_per_physical_sector(const u16 *id)
+{
+       /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+        * IDENTIFY DEVICE data, word 106.
+        * 0xe000 ignores bit 12 (logical sector > 512 bytes)
+        */
+       if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000)
+               return (id[ATA_ID_SECTOR_SIZE] & 0xf);
+       return 0;
 }
 
-static inline u16 ata_id_logical_per_physical_sectors(const u16 *id)
+/* Offset of logical sectors relative to physical sectors.
+ *
+ * If device has more than one logical sector per physical sector
+ * (aka 512 byte emulation), vendors might offset the "sector 0" address
+ * so sector 63 is "naturally aligned" - e.g. FAT partition table.
+ * This avoids Read/Mod/Write penalties when using FAT partition table
+ * and updating "well aligned" (FS perspective) physical sectors on every
+ * transaction.
+ */
+static inline u16 ata_id_logical_sector_offset(const u16 *id,
+        u8 log2_per_phys)
 {
-       return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf);
+       u16 word_209 = id[209];
+
+       if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) {
+               u16 first = word_209 & 0x3fff;
+               if (first > 0)
+                       return (1 << log2_per_phys) - first;
+       }
+       return 0;
 }
 
 static inline int ata_id_has_lba48(const u16 *id)
index fc68053378ce276d5d2d038115e12dbb6b31c27e..827cc95711ef82563e0f7a1718f364ce8adfd451 100644 (file)
@@ -136,28 +136,6 @@ static inline unsigned long __ffs64(u64 word)
 }
 
 #ifdef __KERNEL__
-#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first set bit.
- */
-extern unsigned long find_first_bit(const unsigned long *addr,
-                                   unsigned long size);
-
-/**
- * find_first_zero_bit - find the first cleared bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first cleared bit.
- */
-extern unsigned long find_first_zero_bit(const unsigned long *addr,
-                                        unsigned long size);
-#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #ifdef CONFIG_GENERIC_FIND_LAST_BIT
 /**
@@ -171,28 +149,5 @@ extern unsigned long find_last_bit(const unsigned long *addr,
                                   unsigned long size);
 #endif /* CONFIG_GENERIC_FIND_LAST_BIT */
 
-#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The bitmap size in bits
- */
-extern unsigned long find_next_bit(const unsigned long *addr,
-                                  unsigned long size, unsigned long offset);
-
-/**
- * find_next_zero_bit - find the next cleared bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The bitmap size in bits
- */
-
-extern unsigned long find_next_zero_bit(const unsigned long *addr,
-                                       unsigned long size,
-                                       unsigned long offset);
-
-#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
 #endif /* __KERNEL__ */
 #endif
similarity index 97%
rename from fs/ceph/auth.h
rename to include/linux/ceph/auth.h
index d38a2fb4a13762fc6e37578f840b166ee85efd16..7fff521d7eb5e00741fcf2fc97f7ce8c40fdbfc8 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef _FS_CEPH_AUTH_H
 #define _FS_CEPH_AUTH_H
 
-#include "types.h"
-#include "buffer.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/buffer.h>
 
 /*
  * Abstract interface for communicating with the authenticate module.
similarity index 100%
rename from fs/ceph/buffer.h
rename to include/linux/ceph/buffer.h
similarity index 86%
rename from fs/ceph/ceph_debug.h
rename to include/linux/ceph/ceph_debug.h
index 1818c2305610e28f6dbb7d3e126e7137d28c1365..aa2e19182d990eedda70de69bf638db5856811d1 100644 (file)
@@ -3,7 +3,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#ifdef CONFIG_CEPH_FS_PRETTYDEBUG
+#ifdef CONFIG_CEPH_LIB_PRETTYDEBUG
 
 /*
  * wrap pr_debug to include a filename:lineno prefix on each line.
@@ -14,7 +14,8 @@
 # if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
 extern const char *ceph_file_part(const char *s, int len);
 #  define dout(fmt, ...)                                               \
-       pr_debug(" %12.12s:%-4d : " fmt,                                \
+       pr_debug("%.*s %12.12s:%-4d : " fmt,                            \
+                8 - (int)sizeof(KBUILD_MODNAME), "    ",               \
                 ceph_file_part(__FILE__, sizeof(__FILE__)),            \
                 __LINE__, ##__VA_ARGS__)
 # else
similarity index 99%
rename from fs/ceph/ceph_fs.h
rename to include/linux/ceph/ceph_fs.h
index d5619ac86711a6b41c56a00da7660099352d5327..c3c74aef289d0d34afb2758392ef144d82b59cc6 100644 (file)
@@ -299,6 +299,7 @@ enum {
        CEPH_MDS_OP_SETATTR    = 0x01108,
        CEPH_MDS_OP_SETFILELOCK= 0x01109,
        CEPH_MDS_OP_GETFILELOCK= 0x00110,
+       CEPH_MDS_OP_SETDIRLAYOUT=0x0110a,
 
        CEPH_MDS_OP_MKNOD      = 0x01201,
        CEPH_MDS_OP_LINK       = 0x01202,
diff --git a/include/linux/ceph/debugfs.h b/include/linux/ceph/debugfs.h
new file mode 100644 (file)
index 0000000..2a79702
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _FS_CEPH_DEBUGFS_H
+#define _FS_CEPH_DEBUGFS_H
+
+#include "ceph_debug.h"
+#include "types.h"
+
+#define CEPH_DEFINE_SHOW_FUNC(name)                                    \
+static int name##_open(struct inode *inode, struct file *file)         \
+{                                                                      \
+       struct seq_file *sf;                                            \
+       int ret;                                                        \
+                                                                       \
+       ret = single_open(file, name, NULL);                            \
+       sf = file->private_data;                                        \
+       sf->private = inode->i_private;                                 \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static const struct file_operations name##_fops = {                    \
+       .open           = name##_open,                                  \
+       .read           = seq_read,                                     \
+       .llseek         = seq_lseek,                                    \
+       .release        = single_release,                               \
+};
+
+/* debugfs.c */
+extern int ceph_debugfs_init(void);
+extern void ceph_debugfs_cleanup(void);
+extern int ceph_debugfs_client_init(struct ceph_client *client);
+extern void ceph_debugfs_client_cleanup(struct ceph_client *client);
+
+#endif
+
similarity index 96%
rename from fs/ceph/decode.h
rename to include/linux/ceph/decode.h
index 3d25415afe6368debff12c405463e52c7683edc6..c5b6939fb32af578501a280f73f2aa7b4276ac37 100644 (file)
@@ -191,6 +191,11 @@ static inline void ceph_encode_string(void **p, void *end,
                ceph_encode_need(p, end, n, bad);               \
                ceph_encode_copy(p, pv, n);                     \
        } while (0)
+#define ceph_encode_string_safe(p, end, s, n, bad)             \
+       do {                                                    \
+               ceph_encode_need(p, end, n, bad);               \
+               ceph_encode_string(p, end, s, n);               \
+       } while (0)
 
 
 #endif
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
new file mode 100644 (file)
index 0000000..f22b2e9
--- /dev/null
@@ -0,0 +1,249 @@
+#ifndef _FS_CEPH_LIBCEPH_H
+#define _FS_CEPH_LIBCEPH_H
+
+#include "ceph_debug.h"
+
+#include <asm/unaligned.h>
+#include <linux/backing-dev.h>
+#include <linux/completion.h>
+#include <linux/exportfs.h>
+#include <linux/fs.h>
+#include <linux/mempool.h>
+#include <linux/pagemap.h>
+#include <linux/wait.h>
+#include <linux/writeback.h>
+#include <linux/slab.h>
+
+#include "types.h"
+#include "messenger.h"
+#include "msgpool.h"
+#include "mon_client.h"
+#include "osd_client.h"
+#include "ceph_fs.h"
+
+/*
+ * Supported features
+ */
+#define CEPH_FEATURE_SUPPORTED_DEFAULT CEPH_FEATURE_NOSRCADDR
+#define CEPH_FEATURE_REQUIRED_DEFAULT  CEPH_FEATURE_NOSRCADDR
+
+/*
+ * mount options
+ */
+#define CEPH_OPT_FSID             (1<<0)
+#define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
+#define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
+#define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes */
+
+#define CEPH_OPT_DEFAULT   (0);
+
+#define ceph_set_opt(client, opt) \
+       (client)->options->flags |= CEPH_OPT_##opt;
+#define ceph_test_opt(client, opt) \
+       (!!((client)->options->flags & CEPH_OPT_##opt))
+
+struct ceph_options {
+       int flags;
+       struct ceph_fsid fsid;
+       struct ceph_entity_addr my_addr;
+       int mount_timeout;
+       int osd_idle_ttl;
+       int osd_timeout;
+       int osd_keepalive_timeout;
+
+       /*
+        * any type that can't be simply compared or doesn't need need
+        * to be compared should go beyond this point,
+        * ceph_compare_options() should be updated accordingly
+        */
+
+       struct ceph_entity_addr *mon_addr; /* should be the first
+                                             pointer type of args */
+       int num_mon;
+       char *name;
+       char *secret;
+};
+
+/*
+ * defaults
+ */
+#define CEPH_MOUNT_TIMEOUT_DEFAULT  60
+#define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
+#define CEPH_OSD_KEEPALIVE_DEFAULT  5
+#define CEPH_OSD_IDLE_TTL_DEFAULT    60
+#define CEPH_MOUNT_RSIZE_DEFAULT    (512*1024) /* readahead */
+
+#define CEPH_MSG_MAX_FRONT_LEN (16*1024*1024)
+#define CEPH_MSG_MAX_DATA_LEN  (16*1024*1024)
+
+#define CEPH_AUTH_NAME_DEFAULT   "guest"
+
+/*
+ * Delay telling the MDS we no longer want caps, in case we reopen
+ * the file.  Delay a minimum amount of time, even if we send a cap
+ * message for some other reason.  Otherwise, take the oppotunity to
+ * update the mds to avoid sending another message later.
+ */
+#define CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT      5  /* cap release delay */
+#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
+
+#define CEPH_CAP_RELEASE_SAFETY_DEFAULT        (CEPH_CAPS_PER_RELEASE * 4)
+
+/* mount state */
+enum {
+       CEPH_MOUNT_MOUNTING,
+       CEPH_MOUNT_MOUNTED,
+       CEPH_MOUNT_UNMOUNTING,
+       CEPH_MOUNT_UNMOUNTED,
+       CEPH_MOUNT_SHUTDOWN,
+};
+
+/*
+ * subtract jiffies
+ */
+static inline unsigned long time_sub(unsigned long a, unsigned long b)
+{
+       BUG_ON(time_after(b, a));
+       return (long)a - (long)b;
+}
+
+struct ceph_mds_client;
+
+/*
+ * per client state
+ *
+ * possibly shared by multiple mount points, if they are
+ * mounting the same ceph filesystem/cluster.
+ */
+struct ceph_client {
+       struct ceph_fsid fsid;
+       bool have_fsid;
+
+       void *private;
+
+       struct ceph_options *options;
+
+       struct mutex mount_mutex;      /* serialize mount attempts */
+       wait_queue_head_t auth_wq;
+       int auth_err;
+
+       int (*extra_mon_dispatch)(struct ceph_client *, struct ceph_msg *);
+
+       u32 supported_features;
+       u32 required_features;
+
+       struct ceph_messenger *msgr;   /* messenger instance */
+       struct ceph_mon_client monc;
+       struct ceph_osd_client osdc;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs_dir;
+       struct dentry *debugfs_monmap;
+       struct dentry *debugfs_osdmap;
+#endif
+};
+
+
+
+/*
+ * snapshots
+ */
+
+/*
+ * A "snap context" is the set of existing snapshots when we
+ * write data.  It is used by the OSD to guide its COW behavior.
+ *
+ * The ceph_snap_context is refcounted, and attached to each dirty
+ * page, indicating which context the dirty data belonged when it was
+ * dirtied.
+ */
+struct ceph_snap_context {
+       atomic_t nref;
+       u64 seq;
+       int num_snaps;
+       u64 snaps[];
+};
+
+static inline struct ceph_snap_context *
+ceph_get_snap_context(struct ceph_snap_context *sc)
+{
+       /*
+       printk("get_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
+              atomic_read(&sc->nref)+1);
+       */
+       if (sc)
+               atomic_inc(&sc->nref);
+       return sc;
+}
+
+static inline void ceph_put_snap_context(struct ceph_snap_context *sc)
+{
+       if (!sc)
+               return;
+       /*
+       printk("put_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
+              atomic_read(&sc->nref)-1);
+       */
+       if (atomic_dec_and_test(&sc->nref)) {
+               /*printk(" deleting snap_context %p\n", sc);*/
+               kfree(sc);
+       }
+}
+
+/*
+ * calculate the number of pages a given length and offset map onto,
+ * if we align the data.
+ */
+static inline int calc_pages_for(u64 off, u64 len)
+{
+       return ((off+len+PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT) -
+               (off >> PAGE_CACHE_SHIFT);
+}
+
+/* ceph_common.c */
+extern const char *ceph_msg_type_name(int type);
+extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
+extern struct kmem_cache *ceph_inode_cachep;
+extern struct kmem_cache *ceph_cap_cachep;
+extern struct kmem_cache *ceph_dentry_cachep;
+extern struct kmem_cache *ceph_file_cachep;
+
+extern int ceph_parse_options(struct ceph_options **popt, char *options,
+                             const char *dev_name, const char *dev_name_end,
+                             int (*parse_extra_token)(char *c, void *private),
+                             void *private);
+extern void ceph_destroy_options(struct ceph_options *opt);
+extern int ceph_compare_options(struct ceph_options *new_opt,
+                               struct ceph_client *client);
+extern struct ceph_client *ceph_create_client(struct ceph_options *opt,
+                                             void *private);
+extern u64 ceph_client_id(struct ceph_client *client);
+extern void ceph_destroy_client(struct ceph_client *client);
+extern int __ceph_open_session(struct ceph_client *client,
+                              unsigned long started);
+extern int ceph_open_session(struct ceph_client *client);
+
+/* pagevec.c */
+extern void ceph_release_page_vector(struct page **pages, int num_pages);
+
+extern struct page **ceph_get_direct_page_vector(const char __user *data,
+                                           int num_pages,
+                                           loff_t off, size_t len);
+extern void ceph_put_page_vector(struct page **pages, int num_pages);
+extern void ceph_release_page_vector(struct page **pages, int num_pages);
+extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
+extern int ceph_copy_user_to_page_vector(struct page **pages,
+                                        const char __user *data,
+                                        loff_t off, size_t len);
+extern int ceph_copy_to_page_vector(struct page **pages,
+                                   const char *data,
+                                   loff_t off, size_t len);
+extern int ceph_copy_from_page_vector(struct page **pages,
+                                   char *data,
+                                   loff_t off, size_t len);
+extern int ceph_copy_page_vector_to_user(struct page **pages, char __user *data,
+                                   loff_t off, size_t len);
+extern void ceph_zero_page_vector_range(int off, int len, struct page **pages);
+
+
+#endif /* _FS_CEPH_SUPER_H */
similarity index 100%
rename from fs/ceph/mdsmap.h
rename to include/linux/ceph/mdsmap.h
similarity index 95%
rename from fs/ceph/messenger.h
rename to include/linux/ceph/messenger.h
index 76fbc957bc137dab063cdd69abcc1b432800aa51..5956d62c3057139ac6634df8e13556659d07725e 100644 (file)
@@ -65,6 +65,9 @@ struct ceph_messenger {
         */
        u32 global_seq;
        spinlock_t global_seq_lock;
+
+       u32 supported_features;
+       u32 required_features;
 };
 
 /*
@@ -82,6 +85,10 @@ struct ceph_msg {
        struct ceph_pagelist *pagelist; /* instead of pages */
        struct list_head list_head;
        struct kref kref;
+       struct bio  *bio;               /* instead of pages/pagelist */
+       struct bio  *bio_iter;          /* bio iterator */
+       int bio_seg;                    /* current bio segment */
+       struct ceph_pagelist *trail;    /* the trailing part of the data */
        bool front_is_vmalloc;
        bool more_to_follow;
        bool needs_out_seq;
@@ -205,7 +212,7 @@ struct ceph_connection {
 };
 
 
-extern const char *pr_addr(const struct sockaddr_storage *ss);
+extern const char *ceph_pr_addr(const struct sockaddr_storage *ss);
 extern int ceph_parse_ips(const char *c, const char *end,
                          struct ceph_entity_addr *addr,
                          int max_count, int *count);
@@ -216,7 +223,8 @@ extern void ceph_msgr_exit(void);
 extern void ceph_msgr_flush(void);
 
 extern struct ceph_messenger *ceph_messenger_create(
-       struct ceph_entity_addr *myaddr);
+       struct ceph_entity_addr *myaddr,
+       u32 features, u32 required);
 extern void ceph_messenger_destroy(struct ceph_messenger *);
 
 extern void ceph_con_init(struct ceph_messenger *msgr,
similarity index 99%
rename from fs/ceph/mon_client.h
rename to include/linux/ceph/mon_client.h
index 8e396f2c09637f29d0a82311244d036441a51c1c..545f85917780ab3cd65a314553f7011b655dbb50 100644 (file)
@@ -79,6 +79,7 @@ struct ceph_mon_client {
        u64 last_tid;
 
        /* mds/osd map */
+       int want_mdsmap;
        int want_next_osdmap; /* 1 = want, 2 = want+asked */
        u32 have_osdmap, have_mdsmap;
 
similarity index 100%
rename from fs/ceph/msgr.h
rename to include/linux/ceph/msgr.h
similarity index 76%
rename from fs/ceph/osd_client.h
rename to include/linux/ceph/osd_client.h
index ce776989ef6a76d73d1475ce2335ce558b653e2d..6c91fb032c39cd907a3ac509db75a3a860e564c1 100644 (file)
@@ -15,6 +15,7 @@ struct ceph_snap_context;
 struct ceph_osd_request;
 struct ceph_osd_client;
 struct ceph_authorizer;
+struct ceph_pagelist;
 
 /*
  * completion callback for async writepages
@@ -68,6 +69,7 @@ struct ceph_osd_request {
        struct list_head  r_unsafe_item;
 
        struct inode *r_inode;                /* for use by callbacks */
+       void *r_priv;                         /* ditto */
 
        char              r_oid[40];          /* object name */
        int               r_oid_len;
@@ -80,6 +82,11 @@ struct ceph_osd_request {
        struct page     **r_pages;            /* pages for data payload */
        int               r_pages_from_pool;
        int               r_own_pages;        /* if true, i own page list */
+#ifdef CONFIG_BLOCK
+       struct bio       *r_bio;              /* instead of pages */
+#endif
+
+       struct ceph_pagelist *r_trail;        /* trailing part of the data */
 };
 
 struct ceph_osd_client {
@@ -110,6 +117,42 @@ struct ceph_osd_client {
        struct ceph_msgpool     msgpool_op_reply;
 };
 
+struct ceph_osd_req_op {
+       u16 op;           /* CEPH_OSD_OP_* */
+       u32 flags;        /* CEPH_OSD_FLAG_* */
+       union {
+               struct {
+                       u64 offset, length;
+                       u64 truncate_size;
+                       u32 truncate_seq;
+               } extent;
+               struct {
+                       const char *name;
+                       u32 name_len;
+                       const char  *val;
+                       u32 value_len;
+                       __u8 cmp_op;       /* CEPH_OSD_CMPXATTR_OP_* */
+                       __u8 cmp_mode;     /* CEPH_OSD_CMPXATTR_MODE_* */
+               } xattr;
+               struct {
+                       const char *class_name;
+                       __u8 class_len;
+                       const char *method_name;
+                       __u8 method_len;
+                       __u8 argc;
+                       const char *indata;
+                       u32 indata_len;
+               } cls;
+               struct {
+                       u64 cookie, count;
+               } pgls;
+               struct {
+                       u64 snapid;
+               } snap;
+       };
+       u32 payload_len;
+};
+
 extern int ceph_osdc_init(struct ceph_osd_client *osdc,
                          struct ceph_client *client);
 extern void ceph_osdc_stop(struct ceph_osd_client *osdc);
@@ -119,6 +162,30 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
 extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
                                 struct ceph_msg *msg);
 
+extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+                       struct ceph_file_layout *layout,
+                       u64 snapid,
+                       u64 off, u64 *plen, u64 *bno,
+                       struct ceph_osd_request *req,
+                       struct ceph_osd_req_op *op);
+
+extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
+                                              int flags,
+                                              struct ceph_snap_context *snapc,
+                                              struct ceph_osd_req_op *ops,
+                                              bool use_mempool,
+                                              gfp_t gfp_flags,
+                                              struct page **pages,
+                                              struct bio *bio);
+
+extern void ceph_osdc_build_request(struct ceph_osd_request *req,
+                                   u64 off, u64 *plen,
+                                   struct ceph_osd_req_op *src_ops,
+                                   struct ceph_snap_context *snapc,
+                                   struct timespec *mtime,
+                                   const char *oid,
+                                   int oid_len);
+
 extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
                                      struct ceph_file_layout *layout,
                                      struct ceph_vino vino,
similarity index 97%
rename from fs/ceph/osdmap.h
rename to include/linux/ceph/osdmap.h
index 970b547e510dbd0edb8ba8c2ec95c45932be6106..ba4c205cbb016a141495e2e872ee6a3cfd57253a 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/rbtree.h>
 #include "types.h"
 #include "ceph_fs.h"
-#include "crush/crush.h"
+#include <linux/crush/crush.h>
 
 /*
  * The osd map describes the current membership of the osd cluster and
@@ -125,4 +125,6 @@ extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
 extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
                                struct ceph_pg pgid);
 
+extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
+
 #endif
similarity index 62%
rename from fs/ceph/pagelist.h
rename to include/linux/ceph/pagelist.h
index e8a4187e1087aa7fbc86a2620764f87f234dfe0a..9660d6b0a35d780dbe0806edf6193d1f7d5ef8f5 100644 (file)
@@ -8,6 +8,14 @@ struct ceph_pagelist {
        void *mapped_tail;
        size_t length;
        size_t room;
+       struct list_head free_list;
+       size_t num_pages_free;
+};
+
+struct ceph_pagelist_cursor {
+       struct ceph_pagelist *pl;   /* pagelist, for error checking */
+       struct list_head *page_lru; /* page in list */
+       size_t room;                /* room remaining to reset to */
 };
 
 static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
@@ -16,10 +24,23 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
        pl->mapped_tail = NULL;
        pl->length = 0;
        pl->room = 0;
+       INIT_LIST_HEAD(&pl->free_list);
+       pl->num_pages_free = 0;
 }
+
 extern int ceph_pagelist_release(struct ceph_pagelist *pl);
 
-extern int ceph_pagelist_append(struct ceph_pagelist *pl, void *d, size_t l);
+extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l);
+
+extern int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space);
+
+extern int ceph_pagelist_free_reserve(struct ceph_pagelist *pl);
+
+extern void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
+                                    struct ceph_pagelist_cursor *c);
+
+extern int ceph_pagelist_truncate(struct ceph_pagelist *pl,
+                                 struct ceph_pagelist_cursor *c);
 
 static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v)
 {
similarity index 100%
rename from fs/ceph/rados.h
rename to include/linux/ceph/rados.h
similarity index 100%
rename from fs/ceph/types.h
rename to include/linux/ceph/types.h
index ed3e92e41c6e5683ad3dbb823e48259f5150ac33..709dfb901d1124c75656fb0f7591826683bd2c5d 100644 (file)
@@ -75,7 +75,7 @@ struct cgroup_subsys_state {
 
        unsigned long flags;
        /* ID for this css, if possible */
-       struct css_id *id;
+       struct css_id __rcu *id;
 };
 
 /* bits in struct cgroup_subsys_state flags field */
@@ -205,7 +205,7 @@ struct cgroup {
        struct list_head children;      /* my children */
 
        struct cgroup *parent;          /* my parent */
-       struct dentry *dentry;          /* cgroup fs entry, RCU protected */
+       struct dentry __rcu *dentry;    /* cgroup fs entry, RCU protected */
 
        /* Private pointers for each registered subsystem */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
@@ -578,7 +578,12 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
 void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it);
 int cgroup_scan_tasks(struct cgroup_scanner *scan);
 int cgroup_attach_task(struct cgroup *, struct task_struct *);
-int cgroup_attach_task_current_cg(struct task_struct *);
+int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
+
+static inline int cgroup_attach_task_current_cg(struct task_struct *tsk)
+{
+       return cgroup_attach_task_all(current, tsk);
+}
 
 /*
  * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works
@@ -636,6 +641,11 @@ static inline int cgroupstats_build(struct cgroupstats *stats,
 }
 
 /* No cgroups - nothing to do */
+static inline int cgroup_attach_task_all(struct task_struct *from,
+                                        struct task_struct *t)
+{
+       return 0;
+}
 static inline int cgroup_attach_task_current_cg(struct task_struct *t)
 {
        return 0;
index 9ddc8780e8db7bfe45496587bc47e5fb00d12073..5778b559d59c3222ee825897b7430523aa96c353 100644 (file)
@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type,
                const struct compat_iovec __user *uvector, unsigned long nr_segs,
                unsigned long fast_segs, struct iovec *fast_pointer,
                struct iovec **ret_pointer);
+
+extern void __user *compat_alloc_user_space(unsigned long len);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
index c1a62c56a660226b1592bc6bc269087adac58649..320d6c94ff848d5db94fb1fd76576501a88e9a3a 100644 (file)
 # define __release(x)  __context__(x,-1)
 # define __cond_lock(x,c)      ((c) ? ({ __acquire(x); 1; }) : 0)
 # define __percpu      __attribute__((noderef, address_space(3)))
+#ifdef CONFIG_SPARSE_RCU_POINTER
+# define __rcu         __attribute__((noderef, address_space(4)))
+#else
 # define __rcu
+#endif
 extern void __chk_user_ptr(const volatile void __user *);
 extern void __chk_io_ptr(const volatile void __iomem *);
 #else
index 8ba66a9d9022c7d0ddbbcb984b8839dabb2b91f8..ba4b85a6d9b8bc71853de37df2a36b865707b745 100644 (file)
@@ -9,37 +9,7 @@
  * These are the only things you should do on a core-file: use only these
  * functions to write out all the necessary info.
  */
-static inline int dump_write(struct file *file, const void *addr, int nr)
-{
-       return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static inline int dump_seek(struct file *file, loff_t off)
-{
-       int ret = 1;
-
-       if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-               if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
-                       return 0;
-       } else {
-               char *buf = (char *)get_zeroed_page(GFP_KERNEL);
-
-               if (!buf)
-                       return 0;
-               while (off > 0) {
-                       unsigned long n = off;
-
-                       if (n > PAGE_SIZE)
-                               n = PAGE_SIZE;
-                       if (!dump_write(file, buf, n)) {
-                               ret = 0;
-                               break;
-                       }
-                       off -= n;
-               }
-               free_page((unsigned long)buf);
-       }
-       return ret;
-}
+extern int dump_write(struct file *file, const void *addr, int nr);
+extern int dump_seek(struct file *file, loff_t off);
 
 #endif /* _LINUX_COREDUMP_H */
index 36ca9721a0c28a0150b05153b4f442d2c558d6d4..1be416bbbb82540802a0a742ba2c22934a9a6659 100644 (file)
@@ -53,6 +53,7 @@ struct cpuidle_state {
 #define CPUIDLE_FLAG_BALANCED  (0x40) /* medium latency, moderate savings */
 #define CPUIDLE_FLAG_DEEP      (0x80) /* high latency, large savings */
 #define CPUIDLE_FLAG_IGNORE    (0x100) /* ignore during this idle period */
+#define CPUIDLE_FLAG_TLB_FLUSHED (0x200) /* tlb will be flushed */
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
index 4d2c39573f3694cdeef07d83c6f141b4804a5f36..4aaeab3764469961f1106d988e57e58a91e1a16e 100644 (file)
@@ -84,7 +84,7 @@ struct thread_group_cred {
        atomic_t        usage;
        pid_t           tgid;                   /* thread group process ID */
        spinlock_t      lock;
-       struct key      *session_keyring;       /* keyring inherited over fork */
+       struct key __rcu *session_keyring;      /* keyring inherited over fork */
        struct key      *process_keyring;       /* keyring private to this process */
        struct rcu_head rcu;                    /* RCU deletion hook */
 };
index 29b3ce3f2a1d0cd948523d8890c0bb8420834e09..2833452ea01c8ecec5207a7a8631da3f2b439fa3 100644 (file)
@@ -49,7 +49,6 @@ struct task_struct;
 
 #ifdef CONFIG_LOCKDEP
 extern void debug_show_all_locks(void);
-extern void __debug_show_held_locks(struct task_struct *task);
 extern void debug_show_held_locks(struct task_struct *task);
 extern void debug_check_no_locks_freed(const void *from, unsigned long len);
 extern void debug_check_no_locks_held(struct task_struct *task);
@@ -58,10 +57,6 @@ static inline void debug_show_all_locks(void)
 {
 }
 
-static inline void __debug_show_held_locks(struct task_struct *task)
-{
-}
-
 static inline void debug_show_held_locks(struct task_struct *task)
 {
 }
index ce29b8151198b6c0d40b8f420efe9c2c920d9b4f..ba8319ae5fcc3e75edc0d52240da0b16e18da68d 100644 (file)
@@ -102,6 +102,9 @@ static inline u64 dma_get_mask(struct device *dev)
        return DMA_BIT_MASK(32);
 }
 
+#ifdef ARCH_HAS_DMA_SET_COHERENT_MASK
+int dma_set_coherent_mask(struct device *dev, u64 mask);
+#else
 static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
 {
        if (!dma_supported(dev, mask))
@@ -109,6 +112,7 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
        dev->coherent_dma_mask = mask;
        return 0;
 }
+#endif
 
 extern u64 dma_get_required_mask(struct device *dev);
 
index c61d4ca27bcc26906699101b4f8eee7ce8e8525b..e2106495cc11383ad9a14d7ac119400b18a8f83a 100644 (file)
@@ -548,7 +548,7 @@ static inline bool dma_dev_has_pq_continue(struct dma_device *dma)
        return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE;
 }
 
-static unsigned short dma_dev_to_maxpq(struct dma_device *dma)
+static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma)
 {
        return dma->max_pq & ~DMA_HAS_PQ_CONTINUE;
 }
index d7cecc90ed34069f99c92692b17ed7d91aac2a20..a7d9dc21391d276e94c7a008107d31a0c56d8dc6 100644 (file)
@@ -57,15 +57,15 @@ extern int dmar_table_init(void);
 extern int dmar_dev_scope_init(void);
 
 /* Intel IOMMU detection */
-extern void detect_intel_iommu(void);
+extern int detect_intel_iommu(void);
 extern int enable_drhd_fault_handling(void);
 
 extern int parse_ioapics_under_ir(void);
 extern int alloc_iommu(struct dmar_drhd_unit *);
 #else
-static inline void detect_intel_iommu(void)
+static inline int detect_intel_iommu(void)
 {
-       return;
+       return -ENODEV;
 }
 
 static inline int dmar_table_init(void)
@@ -106,6 +106,7 @@ struct irte {
                __u64 high;
        };
 };
+
 #ifdef CONFIG_INTR_REMAP
 extern int intr_remapping_enabled;
 extern int intr_remapping_supported(void);
@@ -119,11 +120,8 @@ extern int alloc_irte(struct intel_iommu *iommu, int irq, u16 count);
 extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
                        u16 sub_handle);
 extern int map_irq_to_irte_handle(int irq, u16 *sub_handle);
-extern int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index);
-extern int flush_irte(int irq);
 extern int free_irte(int irq);
 
-extern int irq_remapped(int irq);
 extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
 extern struct intel_iommu *map_ioapic_to_ir(int apic);
 extern struct intel_iommu *map_hpet_to_ir(u8 id);
@@ -177,7 +175,6 @@ static inline int set_msi_sid(struct irte *irte, struct pci_dev *dev)
        return 0;
 }
 
-#define irq_remapped(irq)              (0)
 #define enable_intr_remapping(mode)    (-1)
 #define disable_intr_remapping()       (0)
 #define reenable_intr_remapping(mode)  (0)
@@ -187,8 +184,9 @@ static inline int set_msi_sid(struct irte *irte, struct pci_dev *dev)
 /* Can't use the common MSI interrupt functions
  * since DMAR is not a pci device
  */
-extern void dmar_msi_unmask(unsigned int irq);
-extern void dmar_msi_mask(unsigned int irq);
+struct irq_data;
+extern void dmar_msi_unmask(struct irq_data *data);
+extern void dmar_msi_mask(struct irq_data *data);
 extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
index 52c0da4bdd18fe5969fbf9c583652c0f7f00ba07..bef3cda44c4c4bb54570600a99fb0003db7038e7 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _DYNAMIC_DEBUG_H
 #define _DYNAMIC_DEBUG_H
 
+#include <linux/jump_label.h>
+
 /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
  * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
  * use independent hash functions, to reduce the chance of false positives.
@@ -22,8 +24,6 @@ struct _ddebug {
        const char *function;
        const char *filename;
        const char *format;
-       char primary_hash;
-       char secondary_hash;
        unsigned int lineno:24;
        /*
         * The flags field controls the behaviour at the callsite.
@@ -33,6 +33,7 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */
 #define _DPRINTK_FLAGS_DEFAULT 0
        unsigned int flags:8;
+       char enabled;
 } __attribute__((aligned(8)));
 
 
@@ -42,33 +43,35 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 #if defined(CONFIG_DYNAMIC_DEBUG)
 extern int ddebug_remove_module(const char *mod_name);
 
-#define __dynamic_dbg_enabled(dd)  ({       \
-       int __ret = 0;                                                       \
-       if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&        \
-                       (dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \
-                               if (unlikely(dd.flags))                      \
-                                       __ret = 1;                           \
-       __ret; })
-
 #define dynamic_pr_debug(fmt, ...) do {                                        \
+       __label__ do_printk;                                            \
+       __label__ out;                                                  \
        static struct _ddebug descriptor                                \
        __used                                                          \
        __attribute__((section("__verbose"), aligned(8))) =             \
-       { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,  \
-               DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };        \
-       if (__dynamic_dbg_enabled(descriptor))                          \
-               printk(KERN_DEBUG pr_fmt(fmt),  ##__VA_ARGS__);         \
+       { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__,            \
+               _DPRINTK_FLAGS_DEFAULT };                               \
+       JUMP_LABEL(&descriptor.enabled, do_printk);                     \
+       goto out;                                                       \
+do_printk:                                                             \
+       printk(KERN_DEBUG pr_fmt(fmt),  ##__VA_ARGS__);                 \
+out:   ;                                                               \
        } while (0)
 
 
 #define dynamic_dev_dbg(dev, fmt, ...) do {                            \
+       __label__ do_printk;                                            \
+       __label__ out;                                                  \
        static struct _ddebug descriptor                                \
        __used                                                          \
        __attribute__((section("__verbose"), aligned(8))) =             \
-       { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,  \
-               DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };        \
-       if (__dynamic_dbg_enabled(descriptor))                          \
-               dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);        \
+       { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__,            \
+               _DPRINTK_FLAGS_DEFAULT };                               \
+       JUMP_LABEL(&descriptor.enabled, do_printk);                     \
+       goto out;                                                       \
+do_printk:                                                             \
+       dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);                \
+out:   ;                                                               \
        } while (0)
 
 #else
diff --git a/include/linux/early_res.h b/include/linux/early_res.h
deleted file mode 100644 (file)
index 29c09f5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _LINUX_EARLY_RES_H
-#define _LINUX_EARLY_RES_H
-#ifdef __KERNEL__
-
-extern void reserve_early(u64 start, u64 end, char *name);
-extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
-extern void free_early(u64 start, u64 end);
-void free_early_partial(u64 start, u64 end);
-extern void early_res_to_bootmem(u64 start, u64 end);
-
-void reserve_early_without_check(u64 start, u64 end, char *name);
-u64 find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
-                        u64 size, u64 align);
-u64 find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
-                        u64 *sizep, u64 align);
-u64 find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align);
-u64 get_max_mapped(void);
-#include <linux/range.h>
-int get_free_all_memory_range(struct range **rangep, int nodeid);
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_EARLY_RES_H */
index 7cf92e8a4196c0f6a38257cec095b1aa6d04939f..36c66443bdfd260def7dd6e9724f751dd17c7cc6 100644 (file)
@@ -13,6 +13,7 @@
 #define _LINUX_EDAC_H_
 
 #include <asm/atomic.h>
+#include <linux/sysdev.h>
 
 #define EDAC_OPSTATE_INVAL     -1
 #define EDAC_OPSTATE_POLL      0
 extern int edac_op_state;
 extern int edac_err_assert;
 extern atomic_t edac_handlers;
+extern struct sysdev_class edac_class;
 
 extern int edac_handler_set(void);
 extern void edac_atomic_assert_error(void);
+extern struct sysdev_class *edac_get_sysfs_class(void);
+extern void edac_put_sysfs_class(void);
 
 static inline void opstate_init(void)
 {
index df1ee866d71567dfe522bd8cfbe53c3a7f2ce2e7..80a0ece8f7e47e8479c6d8fadb6cc2dae7de05e1 100644 (file)
@@ -93,6 +93,7 @@ struct elevator_queue
        struct elevator_type *elevator_type;
        struct mutex sysfs_lock;
        struct hlist_head *hash;
+       unsigned int registered:1;
 };
 
 /*
@@ -138,6 +139,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
 
 extern int elevator_init(struct request_queue *, char *);
 extern void elevator_exit(struct elevator_queue *);
+extern int elevator_change(struct request_queue *, const char *);
 extern int elv_rq_merge_ok(struct request *, struct bio *);
 
 /*
index f0949a57ca9d72cc7cb47df5717ab6fef250427b..63531a6b4d2a0e42759dbe1a224a103afec1327a 100644 (file)
                                 FAN_ALL_PERM_EVENTS |\
                                 FAN_Q_OVERFLOW)
 
-#define FANOTIFY_METADATA_VERSION      1
+#define FANOTIFY_METADATA_VERSION      2
 
 struct fanotify_event_metadata {
        __u32 event_len;
        __u32 vers;
-       __s32 fd;
        __u64 mask;
-       __s64 pid;
+       __s32 fd;
+       __s32 pid;
 } __attribute__ ((packed));
 
 struct fanotify_response {
@@ -95,11 +95,4 @@ struct fanotify_response {
                                (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
                                (long)(meta)->event_len <= (long)(len))
 
-#ifdef __KERNEL__
-
-struct fanotify_wait {
-       struct fsnotify_event *event;
-       __s32 fd;
-};
-#endif /* __KERNEL__ */
 #endif /* _LINUX_FANOTIFY_H */
index f59ed297b661fceb086a6ca188b54c3ff0006f85..133c0ba25e306a68199d399cf26fc15c242d347a 100644 (file)
@@ -31,7 +31,7 @@ struct embedded_fd_set {
 
 struct fdtable {
        unsigned int max_fds;
-       struct file ** fd;      /* current fd array */
+       struct file __rcu **fd;      /* current fd array */
        fd_set *close_on_exec;
        fd_set *open_fds;
        struct rcu_head rcu;
@@ -46,7 +46,7 @@ struct files_struct {
    * read mostly part
    */
        atomic_t count;
-       struct fdtable *fdt;
+       struct fdtable __rcu *fdt;
        struct fdtable fdtab;
   /*
    * written part on a separate cache line in SMP
@@ -55,7 +55,7 @@ struct files_struct {
        int next_fd;
        struct embedded_fd_set close_on_exec_init;
        struct embedded_fd_set open_fds_init;
-       struct file * fd_array[NR_OPEN_DEFAULT];
+       struct file __rcu * fd_array[NR_OPEN_DEFAULT];
 };
 
 #define rcu_dereference_check_fdtable(files, fdtfd) \
index 76041b6147582ef62eb0daedafbf1771a8e844c6..0a81b87ea15813902fbb64108fa8931ffc80cce0 100644 (file)
@@ -1131,6 +1131,8 @@ extern int vfs_setlease(struct file *, long, struct file_lock **);
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void lock_flocks(void);
+extern void unlock_flocks(void);
 #else /* !CONFIG_FILE_LOCKING */
 static inline int fcntl_getlk(struct file *file, struct flock __user *user)
 {
@@ -1273,6 +1275,14 @@ static inline int lock_may_write(struct inode *inode, loff_t start,
        return 1;
 }
 
+static inline void lock_flocks(void)
+{
+}
+
+static inline void unlock_flocks(void)
+{
+}
+
 #endif /* !CONFIG_FILE_LOCKING */
 
 
@@ -1380,7 +1390,7 @@ struct super_block {
         * Saved mount options for lazy filesystems using
         * generic_show_options()
         */
-       char *s_options;
+       char __rcu *s_options;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
@@ -2374,6 +2384,8 @@ extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
 
 extern int generic_file_fsync(struct file *, int);
 
+extern int generic_check_addressable(unsigned, u64);
+
 #ifdef CONFIG_MIGRATION
 extern int buffer_migrate_page(struct address_space *,
                                struct page *, struct page *);
@@ -2450,6 +2462,7 @@ static const struct file_operations __fops = {                            \
        .release = simple_attr_release,                                 \
        .read    = simple_attr_read,                                    \
        .write   = simple_attr_write,                                   \
+       .llseek  = generic_file_llseek,                                 \
 };
 
 static inline void __attribute__((format(printf, 1, 2)))
index ed36fb57c426b13ce2b9ec3df0574779607949f5..e40190d1687813d5c86e2a1b9e414e48fcf22595 100644 (file)
@@ -156,6 +156,7 @@ struct fsnotify_group {
                        struct mutex access_mutex;
                        struct list_head access_list;
                        wait_queue_head_t access_waitq;
+                       bool bypass_perm; /* protected by access_mutex */
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                } fanotify_data;
index 02b8b24f8f51f0e37156731ba94da19ba2d19131..8beabb958f61d5147c8893f1e780415a91fcb2e6 100644 (file)
@@ -191,8 +191,8 @@ struct ftrace_event_call {
        unsigned int            flags;
 
 #ifdef CONFIG_PERF_EVENTS
-       int                     perf_refcount;
-       struct hlist_head       *perf_events;
+       int                             perf_refcount;
+       struct hlist_head __percpu      *perf_events;
 #endif
 };
 
@@ -252,8 +252,8 @@ DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
 
 extern int  perf_trace_init(struct perf_event *event);
 extern void perf_trace_destroy(struct perf_event *event);
-extern int  perf_trace_enable(struct perf_event *event);
-extern void perf_trace_disable(struct perf_event *event);
+extern int  perf_trace_add(struct perf_event *event, int flags);
+extern void perf_trace_del(struct perf_event *event, int flags);
 extern int  ftrace_profile_set_filter(struct perf_event *event, int event_id,
                                     char *filter_str);
 extern void ftrace_profile_free_filter(struct perf_event *event);
index 57647ecfc1bd634da5f7dfede07f6958256db8e3..557c3927e70f5637c3bef45a019e9f6fc257c3a4 100644 (file)
@@ -139,9 +139,9 @@ struct blk_scsi_cmd_filter {
 struct disk_part_tbl {
        struct rcu_head rcu_head;
        int len;
-       struct hd_struct *last_lookup;
+       struct hd_struct __rcu *last_lookup;
        struct gendisk *disk;
-       struct hd_struct *part[];
+       struct hd_struct __rcu *part[];
 };
 
 struct gendisk {
@@ -160,7 +160,7 @@ struct gendisk {
         * non-critical accesses use RCU.  Always access through
         * helpers.
         */
-       struct disk_part_tbl *part_tbl;
+       struct disk_part_tbl __rcu *part_tbl;
        struct hd_struct part0;
 
        const struct block_device_operations *fops;
index 03f616b78cfa8b857e727ea220a60c05a87bb89f..e41f7dd1ae676eb778a00c0f7cdced047312eff7 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/errno.h>
 
 struct device;
+struct gpio_chip;
 
 /*
  * Some platforms don't support the GPIO programming interface.
index d5b387669dab1f044406826847fdfa7646ab829d..8a389b608ce3b568e85d14dcbfb71f8f98cf0c13 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/lockdep.h>
 #include <linux/ftrace_irq.h>
 #include <asm/hardirq.h>
-#include <asm/system.h>
 
 /*
  * We put the hardirq and softirq counter into the preemption
@@ -64,6 +63,8 @@
 #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
 #define NMI_OFFSET     (1UL << NMI_SHIFT)
 
+#define SOFTIRQ_DISABLE_OFFSET (2 * SOFTIRQ_OFFSET)
+
 #ifndef PREEMPT_ACTIVE
 #define PREEMPT_ACTIVE_BITS    1
 #define PREEMPT_ACTIVE_SHIFT   (NMI_SHIFT + NMI_BITS)
 /*
  * Are we doing bottom half or hardware interrupt processing?
  * Are we in a softirq context? Interrupt context?
+ * in_softirq - Are we currently processing softirq or have bh disabled?
+ * in_serving_softirq - Are we currently processing softirq?
  */
 #define in_irq()               (hardirq_count())
 #define in_softirq()           (softirq_count())
 #define in_interrupt()         (irq_count())
+#define in_serving_softirq()   (softirq_count() & SOFTIRQ_OFFSET)
 
 /*
  * Are we in NMI context?
@@ -132,14 +136,16 @@ extern void synchronize_irq(unsigned int irq);
 
 struct task_struct;
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING)
 static inline void account_system_vtime(struct task_struct *tsk)
 {
 }
+#else
+extern void account_system_vtime(struct task_struct *tsk);
 #endif
 
 #if defined(CONFIG_NO_HZ)
-#if defined(CONFIG_TINY_RCU)
+#if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
 extern void rcu_enter_nohz(void);
 extern void rcu_exit_nohz(void);
 
index c96ea46737d03067afeeeeb4191c29c3ec438d6f..70a1dbbf209350836f97743363fadfe4f6f95b36 100644 (file)
@@ -9,8 +9,9 @@ struct ht_irq_msg {
 /* Helper functions.. */
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
-void mask_ht_irq(unsigned int irq);
-void unmask_ht_irq(unsigned int irq);
+struct irq_data;
+void mask_ht_irq(struct irq_data *data);
+void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
index ee3049cb9ba5782e27447d3984a914a2d39ae87b..52baa79d69a763f7f94f728b115fe0337190addd 100644 (file)
@@ -63,6 +63,9 @@
  *            IRQ lines will appear.  Similarly to gpio_base, the expander
  *            will create a block of irqs beginning at this number.
  *            This value is ignored if irq_summary is < 0.
+ * @reset_during_probe: If set to true, the driver will trigger a full
+ *                      reset of the chip at the beginning of the probe
+ *                      in order to place it in a known state.
  */
 struct sx150x_platform_data {
        unsigned gpio_base;
@@ -73,6 +76,7 @@ struct sx150x_platform_data {
        u16      io_polarity;
        int      irq_summary;
        unsigned irq_base;
+       bool     reset_during_probe;
 };
 
 #endif /* __LINUX_I2C_SX150X_H */
index e968db71e33a94548160cb38c216289ab1577c30..cdb715e58e3e6de8b2e60485e31ce79ea99da8f4 100644 (file)
 
 struct idr_layer {
        unsigned long            bitmap; /* A zero bit means "space here" */
-       struct idr_layer        *ary[1<<IDR_BITS];
+       struct idr_layer __rcu  *ary[1<<IDR_BITS];
        int                      count;  /* When zero, we can release it */
        int                      layer;  /* distance from leaf */
        struct rcu_head          rcu_head;
 };
 
 struct idr {
-       struct idr_layer *top;
+       struct idr_layer __rcu *top;
        struct idr_layer *id_free;
        int               layers; /* only valid without concurrent changes */
        int               id_free_cnt;
index c831467774d0e71963ccf774d310bd4f6dd91b8e..bed7a4682b90734935e3dd6680d5e646b0b895c0 100644 (file)
@@ -119,7 +119,7 @@ struct ethhdr {
        unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
        unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
        __be16          h_proto;                /* packet type ID field */
-} __packed;
+} __attribute__((packed));
 
 #ifdef __KERNEL__
 #include <linux/skbuff.h>
index 9947c39e62f6fa49ea95505d0afc8053a27fbebb..e6dc11e7f9a54613f3700af8fe9d6557d8bd6135 100644 (file)
@@ -67,7 +67,7 @@ struct fddi_8022_1_hdr {
        __u8    dsap;                                   /* destination service access point */
        __u8    ssap;                                   /* source service access point */
        __u8    ctrl;                                   /* control byte #1 */
-} __packed;
+} __attribute__((packed));
 
 /* Define 802.2 Type 2 header */
 struct fddi_8022_2_hdr {
@@ -75,7 +75,7 @@ struct fddi_8022_2_hdr {
        __u8    ssap;                                   /* source service access point */
        __u8    ctrl_1;                                 /* control byte #1 */
        __u8    ctrl_2;                                 /* control byte #2 */
-} __packed;
+} __attribute__((packed));
 
 /* Define 802.2 SNAP header */
 #define FDDI_K_OUI_LEN 3
@@ -85,7 +85,7 @@ struct fddi_snap_hdr {
        __u8    ctrl;                                   /* always 0x03 */
        __u8    oui[FDDI_K_OUI_LEN];    /* organizational universal id */
        __be16  ethertype;                              /* packet type ID field */
-} __packed;
+} __attribute__((packed));
 
 /* Define FDDI LLC frame header */
 struct fddihdr {
@@ -98,7 +98,7 @@ struct fddihdr {
                struct fddi_8022_2_hdr          llc_8022_2;
                struct fddi_snap_hdr            llc_snap;
                } hdr;
-} __packed;
+} __attribute__((packed));
 
 #ifdef __KERNEL__
 #include <linux/netdevice.h>
index 5fe5f307c6f560f424f16252ad61a1a9bf4b7b45..cdc049f1829a8ca6ccc9aabb2103b1aacd3fb990 100644 (file)
@@ -104,7 +104,7 @@ struct hippi_fp_hdr {
        __be32          fixed;
 #endif
        __be32          d2_size;
-} __packed;
+} __attribute__((packed));
 
 struct hippi_le_hdr {
 #if defined (__BIG_ENDIAN_BITFIELD)
@@ -129,7 +129,7 @@ struct hippi_le_hdr {
        __u8            daddr[HIPPI_ALEN];
        __u16           locally_administered;
        __u8            saddr[HIPPI_ALEN];
-} __packed;
+} __attribute__((packed));
 
 #define HIPPI_OUI_LEN  3
 /*
@@ -142,12 +142,12 @@ struct hippi_snap_hdr {
        __u8    ctrl;                   /* always 0x03 */
        __u8    oui[HIPPI_OUI_LEN];     /* organizational universal id (zero)*/
        __be16  ethertype;              /* packet type ID field */
-} __packed;
+} __attribute__((packed));
 
 struct hippi_hdr {
        struct hippi_fp_hdr     fp;
        struct hippi_le_hdr     le;
        struct hippi_snap_hdr   snap;
-} __packed;
+} __attribute__((packed));
 
 #endif /* _LINUX_IF_HIPPI_H */
index 1925e0c3f1623e0d515a22ac6cbc01074fd83e68..27741e05446f97dfad3e5f35e83f328d02520588 100644 (file)
@@ -59,7 +59,7 @@ struct sockaddr_pppox {
        union{ 
                struct pppoe_addr       pppoe; 
        }sa_addr; 
-} __packed;
+} __attribute__((packed));
 
 /* The use of the above union isn't viable because the size of this
  * struct must stay fixed over time -- applications use sizeof(struct
@@ -70,7 +70,7 @@ struct sockaddr_pppol2tp {
        sa_family_t     sa_family;      /* address family, AF_PPPOX */
        unsigned int    sa_protocol;    /* protocol identifier */
        struct pppol2tp_addr pppol2tp;
-} __packed;
+} __attribute__((packed));
 
 /* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
  * bits. So we need a different sockaddr structure.
@@ -79,7 +79,7 @@ struct sockaddr_pppol2tpv3 {
        sa_family_t     sa_family;      /* address family, AF_PPPOX */
        unsigned int    sa_protocol;    /* protocol identifier */
        struct pppol2tpv3_addr pppol2tp;
-} __packed;
+} __attribute__((packed));
 
 /*********************************************************************
  *
@@ -101,7 +101,7 @@ struct pppoe_tag {
        __be16 tag_type;
        __be16 tag_len;
        char tag_data[0];
-} __attribute ((packed));
+} __attribute__ ((packed));
 
 /* Tag identifiers */
 #define PTT_EOL                __cpu_to_be16(0x0000)
@@ -129,7 +129,7 @@ struct pppoe_hdr {
        __be16 sid;
        __be16 length;
        struct pppoe_tag tag[0];
-} __packed;
+} __attribute__((packed));
 
 /* Length of entire PPPoE + PPP header */
 #define PPPOE_SES_HLEN 8
index 1f43fa56f6001f821736e4b66e9fac5e6e0375ed..2fea6c8ef6babea0564ccf3b061698cacba1d14e 100644 (file)
@@ -82,11 +82,17 @@ extern struct group_info init_groups;
 # define CAP_INIT_BSET  CAP_FULL_SET
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
+#define INIT_TASK_RCU_TREE_PREEMPT()                                   \
+       .rcu_blocked_node = NULL,
+#else
+#define INIT_TASK_RCU_TREE_PREEMPT(tsk)
+#endif
+#ifdef CONFIG_PREEMPT_RCU
 #define INIT_TASK_RCU_PREEMPT(tsk)                                     \
        .rcu_read_lock_nesting = 0,                                     \
        .rcu_read_unlock_special = 0,                                   \
-       .rcu_blocked_node = NULL,                                       \
-       .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry),
+       .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry),           \
+       INIT_TASK_RCU_TREE_PREEMPT()
 #else
 #define INIT_TASK_RCU_PREEMPT(tsk)
 #endif
@@ -137,8 +143,8 @@ extern struct cred init_cred;
        .children       = LIST_HEAD_INIT(tsk.children),                 \
        .sibling        = LIST_HEAD_INIT(tsk.sibling),                  \
        .group_leader   = &tsk,                                         \
-       .real_cred      = &init_cred,                                   \
-       .cred           = &init_cred,                                   \
+       RCU_INIT_POINTER(.real_cred, &init_cred),                       \
+       RCU_INIT_POINTER(.cred, &init_cred),                            \
        .cred_guard_mutex =                                             \
                 __MUTEX_INITIALIZER(tsk.cred_guard_mutex),             \
        .comm           = "swapper",                                    \
index 896a92227bc429a9abdd27da5e3b0d77be122d95..d6ae1761be97fae4cbbc66602d19d9bdd60f3bdd 100644 (file)
@@ -1196,7 +1196,7 @@ struct input_dev {
        int (*flush)(struct input_dev *dev, struct file *file);
        int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 
-       struct input_handle *grab;
+       struct input_handle __rcu *grab;
 
        spinlock_t event_lock;
        struct mutex mutex;
diff --git a/include/linux/intel-gtt.h b/include/linux/intel-gtt.h
new file mode 100644 (file)
index 0000000..1d19ab2
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Common Intel AGPGART and GTT definitions.
+ */
+#ifndef _INTEL_GTT_H
+#define _INTEL_GTT_H
+
+#include <linux/agp_backend.h>
+
+/* This is for Intel only GTT controls.
+ *
+ * Sandybridge: AGP_USER_CACHED_MEMORY default to LLC only
+ */
+
+#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
+#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)
+
+/* flag for GFDT type */
+#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
+
+#endif
index a0384a4d1e6f4da4d39a02c0f8ba6634842dd236..414328577cedcdb0c67ccdee0c4c4d06661e2aa5 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <trace/events/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+       trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+       or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
@@ -641,11 +647,8 @@ static inline void init_irq_proc(void)
 struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
 
-struct irq_desc;
-
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
 extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int node);
 
 #endif
index 0a6b3d5c490ccfcd3ab9a3dbdba9b41f88e1c4b8..7fb59279373823339f6fdda86158952e3e6fac45 100644 (file)
@@ -79,7 +79,7 @@ io_mapping_free(struct io_mapping *mapping)
 }
 
 /* Atomic map/unmap */
-static inline void *
+static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
                         unsigned long offset,
                         int slot)
@@ -94,12 +94,12 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping,
 }
 
 static inline void
-io_mapping_unmap_atomic(void *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
 {
        iounmap_atomic(vaddr, slot);
 }
 
-static inline void *
+static inline void __iomem *
 io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 {
        resource_size_t phys_addr;
@@ -111,7 +111,7 @@ io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 }
 
 static inline void
-io_mapping_unmap(void *vaddr)
+io_mapping_unmap(void __iomem *vaddr)
 {
        iounmap(vaddr);
 }
@@ -125,38 +125,38 @@ struct io_mapping;
 static inline struct io_mapping *
 io_mapping_create_wc(resource_size_t base, unsigned long size)
 {
-       return (struct io_mapping *) ioremap_wc(base, size);
+       return (struct io_mapping __force *) ioremap_wc(base, size);
 }
 
 static inline void
 io_mapping_free(struct io_mapping *mapping)
 {
-       iounmap(mapping);
+       iounmap((void __force __iomem *) mapping);
 }
 
 /* Atomic map/unmap */
-static inline void *
+static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
                         unsigned long offset,
                         int slot)
 {
-       return ((char *) mapping) + offset;
+       return ((char __force __iomem *) mapping) + offset;
 }
 
 static inline void
-io_mapping_unmap_atomic(void *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
 {
 }
 
 /* Non-atomic map/unmap */
-static inline void *
+static inline void __iomem *
 io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 {
-       return ((char *) mapping) + offset;
+       return ((char __force __iomem *) mapping) + offset;
 }
 
 static inline void
-io_mapping_unmap(void *vaddr)
+io_mapping_unmap(void __iomem *vaddr)
 {
 }
 
index 64d5291330312ac718ba7f649e3d428063127f39..3e70b21884a948880f90e28684e5d5778e7a3d35 100644 (file)
@@ -53,7 +53,7 @@ struct io_context {
 
        struct radix_tree_root radix_root;
        struct hlist_head cic_list;
-       void *ioc_data;
+       void __rcu *ioc_data;
 };
 
 static inline struct io_context *ioc_task_link(struct io_context *ioc)
index ab9e9e89e4074318405a595c1147642e344255c0..e62683ba88e6824e72b3e8c81c7315998868f606 100644 (file)
@@ -58,7 +58,7 @@ struct ipv6_opt_hdr {
        /* 
         * TLV encoded option data follows.
         */
-} __packed;    /* required for some archs */
+} __attribute__((packed));     /* required for some archs */
 
 #define ipv6_destopt_hdr ipv6_opt_hdr
 #define ipv6_hopopt_hdr  ipv6_opt_hdr
@@ -99,7 +99,7 @@ struct ipv6_destopt_hao {
        __u8                    type;
        __u8                    length;
        struct in6_addr         addr;
-} __packed;
+} __attribute__((packed));
 
 /*
  *     IPv6 fixed header
index c03243ad84b46b220324d499b18e0805e9fb827b..e9639115dff1b920095b79b92202767cd0ed0537 100644 (file)
@@ -72,6 +72,10 @@ typedef      void (*irq_flow_handler_t)(unsigned int irq,
 #define IRQ_ONESHOT            0x08000000      /* IRQ is not unmasked after hardirq */
 #define IRQ_NESTED_THREAD      0x10000000      /* IRQ is nested into another, no own handler thread */
 
+#define IRQF_MODIFY_MASK       \
+       (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
+        IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL)
+
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
 # define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
@@ -80,36 +84,77 @@ typedef     void (*irq_flow_handler_t)(unsigned int irq,
 # define IRQ_NO_BALANCING_MASK IRQ_NO_BALANCING
 #endif
 
-struct proc_dir_entry;
 struct msi_desc;
 
+/**
+ * struct irq_data - per irq and irq chip data passed down to chip functions
+ * @irq:               interrupt number
+ * @node:              node index useful for balancing
+ * @chip:              low level interrupt hardware access
+ * @handler_data:      per-IRQ data for the irq_chip methods
+ * @chip_data:         platform-specific per-chip private data for the chip
+ *                     methods, to allow shared chip implementations
+ * @msi_desc:          MSI descriptor
+ * @affinity:          IRQ affinity on SMP
+ *
+ * The fields here need to overlay the ones in irq_desc until we
+ * cleaned up the direct references and switched everything over to
+ * irq_data.
+ */
+struct irq_data {
+       unsigned int            irq;
+       unsigned int            node;
+       struct irq_chip         *chip;
+       void                    *handler_data;
+       void                    *chip_data;
+       struct msi_desc         *msi_desc;
+#ifdef CONFIG_SMP
+       cpumask_var_t           affinity;
+#endif
+};
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
  * @name:              name for /proc/interrupts
- * @startup:           start up the interrupt (defaults to ->enable if NULL)
- * @shutdown:          shut down the interrupt (defaults to ->disable if NULL)
- * @enable:            enable the interrupt (defaults to chip->unmask if NULL)
- * @disable:           disable the interrupt
- * @ack:               start of a new interrupt
- * @mask:              mask an interrupt source
- * @mask_ack:          ack and mask an interrupt source
- * @unmask:            unmask an interrupt source
- * @eoi:               end of interrupt - chip level
- * @end:               end of interrupt - flow level
- * @set_affinity:      set the CPU affinity on SMP machines
- * @retrigger:         resend an IRQ to the CPU
- * @set_type:          set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
- * @set_wake:          enable/disable power-management wake-on of an IRQ
+ * @startup:           deprecated, replaced by irq_startup
+ * @shutdown:          deprecated, replaced by irq_shutdown
+ * @enable:            deprecated, replaced by irq_enable
+ * @disable:           deprecated, replaced by irq_disable
+ * @ack:               deprecated, replaced by irq_ack
+ * @mask:              deprecated, replaced by irq_mask
+ * @mask_ack:          deprecated, replaced by irq_mask_ack
+ * @unmask:            deprecated, replaced by irq_unmask
+ * @eoi:               deprecated, replaced by irq_eoi
+ * @end:               deprecated, will go away with __do_IRQ()
+ * @set_affinity:      deprecated, replaced by irq_set_affinity
+ * @retrigger:         deprecated, replaced by irq_retrigger
+ * @set_type:          deprecated, replaced by irq_set_type
+ * @set_wake:          deprecated, replaced by irq_wake
+ * @bus_lock:          deprecated, replaced by irq_bus_lock
+ * @bus_sync_unlock:   deprecated, replaced by irq_bus_sync_unlock
  *
- * @bus_lock:          function to lock access to slow bus (i2c) chips
- * @bus_sync_unlock:   function to sync and unlock slow bus (i2c) chips
+ * @irq_startup:       start up the interrupt (defaults to ->enable if NULL)
+ * @irq_shutdown:      shut down the interrupt (defaults to ->disable if NULL)
+ * @irq_enable:                enable the interrupt (defaults to chip->unmask if NULL)
+ * @irq_disable:       disable the interrupt
+ * @irq_ack:           start of a new interrupt
+ * @irq_mask:          mask an interrupt source
+ * @irq_mask_ack:      ack and mask an interrupt source
+ * @irq_unmask:                unmask an interrupt source
+ * @irq_eoi:           end of interrupt
+ * @irq_set_affinity:  set the CPU affinity on SMP machines
+ * @irq_retrigger:     resend an IRQ to the CPU
+ * @irq_set_type:      set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
+ * @irq_set_wake:      enable/disable power-management wake-on of an IRQ
+ * @irq_bus_lock:      function to lock access to slow bus (i2c) chips
+ * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
  *
  * @release:           release function solely used by UML
- * @typename:          obsoleted by name, kept as migration helper
  */
 struct irq_chip {
        const char      *name;
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
        unsigned int    (*startup)(unsigned int irq);
        void            (*shutdown)(unsigned int irq);
        void            (*enable)(unsigned int irq);
@@ -130,154 +175,66 @@ struct irq_chip {
 
        void            (*bus_lock)(unsigned int irq);
        void            (*bus_sync_unlock)(unsigned int irq);
+#endif
+       unsigned int    (*irq_startup)(struct irq_data *data);
+       void            (*irq_shutdown)(struct irq_data *data);
+       void            (*irq_enable)(struct irq_data *data);
+       void            (*irq_disable)(struct irq_data *data);
+
+       void            (*irq_ack)(struct irq_data *data);
+       void            (*irq_mask)(struct irq_data *data);
+       void            (*irq_mask_ack)(struct irq_data *data);
+       void            (*irq_unmask)(struct irq_data *data);
+       void            (*irq_eoi)(struct irq_data *data);
+
+       int             (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
+       int             (*irq_retrigger)(struct irq_data *data);
+       int             (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
+       int             (*irq_set_wake)(struct irq_data *data, unsigned int on);
+
+       void            (*irq_bus_lock)(struct irq_data *data);
+       void            (*irq_bus_sync_unlock)(struct irq_data *data);
 
        /* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
        void            (*release)(unsigned int irq, void *dev_id);
 #endif
-       /*
-        * For compatibility, ->typename is copied into ->name.
-        * Will disappear.
-        */
-       const char      *typename;
 };
 
-struct timer_rand_state;
-struct irq_2_iommu;
-/**
- * struct irq_desc - interrupt descriptor
- * @irq:               interrupt number for this descriptor
- * @timer_rand_state:  pointer to timer rand state struct
- * @kstat_irqs:                irq stats per cpu
- * @irq_2_iommu:       iommu with this irq
- * @handle_irq:                highlevel irq-events handler [if NULL, __do_IRQ()]
- * @chip:              low level interrupt hardware access
- * @msi_desc:          MSI descriptor
- * @handler_data:      per-IRQ data for the irq_chip methods
- * @chip_data:         platform-specific per-chip private data for the chip
- *                     methods, to allow shared chip implementations
- * @action:            the irq action chain
- * @status:            status information
- * @depth:             disable-depth, for nested irq_disable() calls
- * @wake_depth:                enable depth, for multiple set_irq_wake() callers
- * @irq_count:         stats field to detect stalled irqs
- * @last_unhandled:    aging timer for unhandled count
- * @irqs_unhandled:    stats field for spurious unhandled interrupts
- * @lock:              locking for SMP
- * @affinity:          IRQ affinity on SMP
- * @node:              node index useful for balancing
- * @pending_mask:      pending rebalanced interrupts
- * @threads_active:    number of irqaction threads currently running
- * @wait_for_threads:  wait queue for sync_irq to wait for threaded handlers
- * @dir:               /proc/irq/ procfs entry
- * @name:              flow handler name for /proc/interrupts output
- */
-struct irq_desc {
-       unsigned int            irq;
-       struct timer_rand_state *timer_rand_state;
-       unsigned int            *kstat_irqs;
-#ifdef CONFIG_INTR_REMAP
-       struct irq_2_iommu      *irq_2_iommu;
-#endif
-       irq_flow_handler_t      handle_irq;
-       struct irq_chip         *chip;
-       struct msi_desc         *msi_desc;
-       void                    *handler_data;
-       void                    *chip_data;
-       struct irqaction        *action;        /* IRQ action list */
-       unsigned int            status;         /* IRQ status */
-
-       unsigned int            depth;          /* nested irq disables */
-       unsigned int            wake_depth;     /* nested wake enables */
-       unsigned int            irq_count;      /* For detecting broken IRQs */
-       unsigned long           last_unhandled; /* Aging timer for unhandled count */
-       unsigned int            irqs_unhandled;
-       raw_spinlock_t          lock;
-#ifdef CONFIG_SMP
-       cpumask_var_t           affinity;
-       const struct cpumask    *affinity_hint;
-       unsigned int            node;
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_var_t           pending_mask;
-#endif
-#endif
-       atomic_t                threads_active;
-       wait_queue_head_t       wait_for_threads;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry   *dir;
-#endif
-       const char              *name;
-} ____cacheline_internodealigned_in_smp;
+/* This include will go away once we isolated irq_desc usage to core code */
+#include <linux/irqdesc.h>
 
-extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
-                                       struct irq_desc *desc, int node);
-extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
+/*
+ * Pick up the arch-dependent methods:
+ */
+#include <asm/hw_irq.h>
 
-#ifndef CONFIG_SPARSE_IRQ
-extern struct irq_desc irq_desc[NR_IRQS];
+#ifndef NR_IRQS_LEGACY
+# define NR_IRQS_LEGACY 0
 #endif
 
-#ifdef CONFIG_NUMA_IRQ_DESC
-extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
-#else
-static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
-{
-       return desc;
-}
+#ifndef ARCH_IRQ_INIT_FLAGS
+# define ARCH_IRQ_INIT_FLAGS   0
 #endif
 
-extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
-
-/*
- * Pick up the arch-dependent methods:
- */
-#include <asm/hw_irq.h>
+#define IRQ_DEFAULT_INIT_FLAGS (IRQ_DISABLED | ARCH_IRQ_INIT_FLAGS)
 
+struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
-#ifdef CONFIG_SMP
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
 void move_native_irq(int irq);
 void move_masked_irq(int irq);
-
-#else /* CONFIG_GENERIC_PENDING_IRQ */
-
-static inline void move_irq(int irq)
-{
-}
-
-static inline void move_native_irq(int irq)
-{
-}
-
-static inline void move_masked_irq(int irq)
-{
-}
-
-#endif /* CONFIG_GENERIC_PENDING_IRQ */
-
-#else /* CONFIG_SMP */
-
-#define move_native_irq(x)
-#define move_masked_irq(x)
-
-#endif /* CONFIG_SMP */
+#else
+static inline void move_native_irq(int irq) { }
+static inline void move_masked_irq(int irq) { }
+#endif
 
 extern int no_irq_affinity;
 
-static inline int irq_balancing_disabled(unsigned int irq)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       return desc->status & IRQ_NO_BALANCING_MASK;
-}
-
 /* Handle irq action chains: */
 extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
@@ -293,42 +250,10 @@ extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
-/*
- * Monolithic do_IRQ implementation.
- */
-#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern unsigned int __do_IRQ(unsigned int irq);
-#endif
-
-/*
- * Architectures call this to let the generic IRQ layer
- * handle an interrupt. If the descriptor is attached to an
- * irqchip-style controller then we call the ->handle_irq() handler,
- * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
- */
-static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-       desc->handle_irq(irq, desc);
-#else
-       if (likely(desc->handle_irq))
-               desc->handle_irq(irq, desc);
-       else
-               __do_IRQ(irq);
-#endif
-}
-
-static inline void generic_handle_irq(unsigned int irq)
-{
-       generic_handle_irq_desc(irq, irq_to_desc(irq));
-}
-
 /* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
                           irqreturn_t action_ret);
 
-/* Resending of interrupts :*/
-void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
 /* Enable/disable irq debugging output: */
 extern int noirqdebug_setup(char *str);
@@ -351,16 +276,6 @@ extern void
 __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                  const char *name);
 
-/* caller has locked the irq_desc and both params are valid */
-static inline void __set_irq_handler_unlocked(int irq,
-                                             irq_flow_handler_t handler)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       desc->handle_irq = handler;
-}
-
 /*
  * Set a highlevel flow handler for a given IRQ:
  */
@@ -384,141 +299,121 @@ set_irq_chained_handler(unsigned int irq,
 
 extern void set_irq_nested_thread(unsigned int irq, int nest);
 
-extern void set_irq_noprobe(unsigned int irq);
-extern void set_irq_probe(unsigned int irq);
+void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
+
+static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
+{
+       irq_modify_status(irq, 0, set);
+}
+
+static inline void irq_clear_status_flags(unsigned int irq, unsigned long clr)
+{
+       irq_modify_status(irq, clr, 0);
+}
+
+static inline void set_irq_noprobe(unsigned int irq)
+{
+       irq_modify_status(irq, 0, IRQ_NOPROBE);
+}
+
+static inline void set_irq_probe(unsigned int irq)
+{
+       irq_modify_status(irq, IRQ_NOPROBE, 0);
+}
 
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
 
-/* Test to see if a driver has successfully requested an irq */
-static inline int irq_has_action(unsigned int irq)
+/*
+ * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and
+ * irq_free_desc instead.
+ */
+extern void dynamic_irq_cleanup(unsigned int irq);
+static inline void dynamic_irq_init(unsigned int irq)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       return desc->action != NULL;
+       dynamic_irq_cleanup(irq);
 }
 
-/* Dynamic irq helper functions */
-extern void dynamic_irq_init(unsigned int irq);
-void dynamic_irq_init_keep_chip_data(unsigned int irq);
-extern void dynamic_irq_cleanup(unsigned int irq);
-void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
-
 /* Set/get chip/data for an IRQ: */
 extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
 extern int set_irq_data(unsigned int irq, void *data);
 extern int set_irq_chip_data(unsigned int irq, void *data);
 extern int set_irq_type(unsigned int irq, unsigned int type);
 extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
+extern struct irq_data *irq_get_irq_data(unsigned int irq);
 
-#define get_irq_chip(irq)      (irq_to_desc(irq)->chip)
-#define get_irq_chip_data(irq) (irq_to_desc(irq)->chip_data)
-#define get_irq_data(irq)      (irq_to_desc(irq)->handler_data)
-#define get_irq_msi(irq)       (irq_to_desc(irq)->msi_desc)
-
-#define get_irq_desc_chip(desc)                ((desc)->chip)
-#define get_irq_desc_chip_data(desc)   ((desc)->chip_data)
-#define get_irq_desc_data(desc)                ((desc)->handler_data)
-#define get_irq_desc_msi(desc)         ((desc)->msi_desc)
-
-#endif /* CONFIG_GENERIC_HARDIRQS */
-
-#endif /* !CONFIG_S390 */
-
-#ifdef CONFIG_SMP
-/**
- * alloc_desc_masks - allocate cpumasks for irq_desc
- * @desc:      pointer to irq_desc struct
- * @node:      node which will be handling the cpumasks
- * @boot:      true if need bootmem
- *
- * Allocates affinity and pending_mask cpumask if required.
- * Returns true if successful (or not required).
- */
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-                                                       bool boot)
+static inline struct irq_chip *get_irq_chip(unsigned int irq)
 {
-       gfp_t gfp = GFP_ATOMIC;
-
-       if (boot)
-               gfp = GFP_NOWAIT;
-
-#ifdef CONFIG_CPUMASK_OFFSTACK
-       if (!alloc_cpumask_var_node(&desc->affinity, gfp, node))
-               return false;
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->chip : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       if (!alloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
-               free_cpumask_var(desc->affinity);
-               return false;
-       }
-#endif
-#endif
-       return true;
+static inline struct irq_chip *irq_data_get_irq_chip(struct irq_data *d)
+{
+       return d->chip;
 }
 
-static inline void init_desc_masks(struct irq_desc *desc)
+static inline void *get_irq_chip_data(unsigned int irq)
 {
-       cpumask_setall(desc->affinity);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_clear(desc->pending_mask);
-#endif
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->chip_data : NULL;
 }
 
-/**
- * init_copy_desc_masks - copy cpumasks for irq_desc
- * @old_desc:  pointer to old irq_desc struct
- * @new_desc:  pointer to new irq_desc struct
- *
- * Insures affinity and pending_masks are copied to new irq_desc.
- * If !CONFIG_CPUMASKS_OFFSTACK the cpumasks are embedded in the
- * irq_desc struct so the copy is redundant.
- */
+static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
+{
+       return d->chip_data;
+}
 
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-                                       struct irq_desc *new_desc)
+static inline void *get_irq_data(unsigned int irq)
 {
-#ifdef CONFIG_CPUMASK_OFFSTACK
-       cpumask_copy(new_desc->affinity, old_desc->affinity);
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->handler_data : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_copy(new_desc->pending_mask, old_desc->pending_mask);
-#endif
-#endif
+static inline void *irq_data_get_irq_data(struct irq_data *d)
+{
+       return d->handler_data;
 }
 
-static inline void free_desc_masks(struct irq_desc *old_desc,
-                                  struct irq_desc *new_desc)
+static inline struct msi_desc *get_irq_msi(unsigned int irq)
 {
-       free_cpumask_var(old_desc->affinity);
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->msi_desc : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       free_cpumask_var(old_desc->pending_mask);
-#endif
+static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
+{
+       return d->msi_desc;
 }
 
-#else /* !CONFIG_SMP */
+int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
+void irq_free_descs(unsigned int irq, unsigned int cnt);
+int irq_reserve_irqs(unsigned int from, unsigned int cnt);
 
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-                                                               bool boot)
+static inline int irq_alloc_desc(int node)
 {
-       return true;
+       return irq_alloc_descs(-1, 0, 1, node);
 }
 
-static inline void init_desc_masks(struct irq_desc *desc)
+static inline int irq_alloc_desc_at(unsigned int at, int node)
 {
+       return irq_alloc_descs(at, at, 1, node);
 }
 
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-                                       struct irq_desc *new_desc)
+static inline int irq_alloc_desc_from(unsigned int from, int node)
 {
+       return irq_alloc_descs(-1, from, 1, node);
 }
 
-static inline void free_desc_masks(struct irq_desc *old_desc,
-                                  struct irq_desc *new_desc)
+static inline void irq_free_desc(unsigned int irq)
 {
+       irq_free_descs(irq, 1);
 }
-#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
+#endif /* !CONFIG_S390 */
 
 #endif /* _LINUX_IRQ_H */
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
new file mode 100644 (file)
index 0000000..4fa09d4
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LINUX_IRQ_WORK_H
+#define _LINUX_IRQ_WORK_H
+
+struct irq_work {
+       struct irq_work *next;
+       void (*func)(struct irq_work *);
+};
+
+static inline
+void init_irq_work(struct irq_work *entry, void (*func)(struct irq_work *))
+{
+       entry->next = NULL;
+       entry->func = func;
+}
+
+bool irq_work_queue(struct irq_work *entry);
+void irq_work_run(void);
+void irq_work_sync(struct irq_work *entry);
+
+#endif /* _LINUX_IRQ_WORK_H */
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
new file mode 100644 (file)
index 0000000..979c68c
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef _LINUX_IRQDESC_H
+#define _LINUX_IRQDESC_H
+
+/*
+ * Core internal functions to deal with irq descriptors
+ *
+ * This include will move to kernel/irq once we cleaned up the tree.
+ * For now it's included from <linux/irq.h>
+ */
+
+struct proc_dir_entry;
+struct timer_rand_state;
+/**
+ * struct irq_desc - interrupt descriptor
+ * @irq_data:          per irq and chip data passed down to chip functions
+ * @timer_rand_state:  pointer to timer rand state struct
+ * @kstat_irqs:                irq stats per cpu
+ * @handle_irq:                highlevel irq-events handler [if NULL, __do_IRQ()]
+ * @action:            the irq action chain
+ * @status:            status information
+ * @depth:             disable-depth, for nested irq_disable() calls
+ * @wake_depth:                enable depth, for multiple set_irq_wake() callers
+ * @irq_count:         stats field to detect stalled irqs
+ * @last_unhandled:    aging timer for unhandled count
+ * @irqs_unhandled:    stats field for spurious unhandled interrupts
+ * @lock:              locking for SMP
+ * @pending_mask:      pending rebalanced interrupts
+ * @threads_active:    number of irqaction threads currently running
+ * @wait_for_threads:  wait queue for sync_irq to wait for threaded handlers
+ * @dir:               /proc/irq/ procfs entry
+ * @name:              flow handler name for /proc/interrupts output
+ */
+struct irq_desc {
+
+#ifdef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+       struct irq_data         irq_data;
+#else
+       /*
+        * This union will go away, once we fixed the direct access to
+        * irq_desc all over the place. The direct fields are a 1:1
+        * overlay of irq_data.
+        */
+       union {
+               struct irq_data         irq_data;
+               struct {
+                       unsigned int            irq;
+                       unsigned int            node;
+                       struct irq_chip         *chip;
+                       void                    *handler_data;
+                       void                    *chip_data;
+                       struct msi_desc         *msi_desc;
+#ifdef CONFIG_SMP
+                       cpumask_var_t           affinity;
+#endif
+               };
+       };
+#endif
+
+       struct timer_rand_state *timer_rand_state;
+       unsigned int            *kstat_irqs;
+       irq_flow_handler_t      handle_irq;
+       struct irqaction        *action;        /* IRQ action list */
+       unsigned int            status;         /* IRQ status */
+
+       unsigned int            depth;          /* nested irq disables */
+       unsigned int            wake_depth;     /* nested wake enables */
+       unsigned int            irq_count;      /* For detecting broken IRQs */
+       unsigned long           last_unhandled; /* Aging timer for unhandled count */
+       unsigned int            irqs_unhandled;
+       raw_spinlock_t          lock;
+#ifdef CONFIG_SMP
+       const struct cpumask    *affinity_hint;
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+       cpumask_var_t           pending_mask;
+#endif
+#endif
+       atomic_t                threads_active;
+       wait_queue_head_t       wait_for_threads;
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry   *dir;
+#endif
+       const char              *name;
+} ____cacheline_internodealigned_in_smp;
+
+#ifndef CONFIG_SPARSE_IRQ
+extern struct irq_desc irq_desc[NR_IRQS];
+#endif
+
+/* Will be removed once the last users in power and sh are gone */
+extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
+static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
+{
+       return desc;
+}
+
+#ifdef CONFIG_GENERIC_HARDIRQS
+
+#define get_irq_desc_chip(desc)                ((desc)->irq_data.chip)
+#define get_irq_desc_chip_data(desc)   ((desc)->irq_data.chip_data)
+#define get_irq_desc_data(desc)                ((desc)->irq_data.handler_data)
+#define get_irq_desc_msi(desc)         ((desc)->irq_data.msi_desc)
+
+/*
+ * Monolithic do_IRQ implementation.
+ */
+#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+extern unsigned int __do_IRQ(unsigned int irq);
+#endif
+
+/*
+ * Architectures call this to let the generic IRQ layer
+ * handle an interrupt. If the descriptor is attached to an
+ * irqchip-style controller then we call the ->handle_irq() handler,
+ * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
+ */
+static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
+{
+#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+       desc->handle_irq(irq, desc);
+#else
+       if (likely(desc->handle_irq))
+               desc->handle_irq(irq, desc);
+       else
+               __do_IRQ(irq);
+#endif
+}
+
+static inline void generic_handle_irq(unsigned int irq)
+{
+       generic_handle_irq_desc(irq, irq_to_desc(irq));
+}
+
+/* Test to see if a driver has successfully requested an irq */
+static inline int irq_has_action(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+       return desc->action != NULL;
+}
+
+static inline int irq_balancing_disabled(unsigned int irq)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+       return desc->status & IRQ_NO_BALANCING_MASK;
+}
+
+/* caller has locked the irq_desc and both params are valid */
+static inline void __set_irq_handler_unlocked(int irq,
+                                             irq_flow_handler_t handler)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+       desc->handle_irq = handler;
+}
+#endif
+
+#endif
index 006bf45eae30e5777ece188a997736cd5ff509cf..d176d658fe25dd6b09b3d03936a4b60ce324367c 100644 (file)
@@ -12,6 +12,7 @@
 #define _LINUX_TRACE_IRQFLAGS_H
 
 #include <linux/typecheck.h>
+#include <asm/irqflags.h>
 
 #ifdef CONFIG_TRACE_IRQFLAGS
   extern void trace_softirqs_on(unsigned long ip);
 # define start_critical_timings() do { } while (0)
 #endif
 
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-
-#include <asm/irqflags.h>
+/*
+ * Wrap the arch provided IRQ routines to provide appropriate checks.
+ */
+#define raw_local_irq_disable()                arch_local_irq_disable()
+#define raw_local_irq_enable()         arch_local_irq_enable()
+#define raw_local_irq_save(flags)                      \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               flags = arch_local_irq_save();          \
+       } while (0)
+#define raw_local_irq_restore(flags)                   \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               arch_local_irq_restore(flags);          \
+       } while (0)
+#define raw_local_save_flags(flags)                    \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               flags = arch_local_save_flags();        \
+       } while (0)
+#define raw_irqs_disabled_flags(flags)                 \
+       ({                                              \
+               typecheck(unsigned long, flags);        \
+               arch_irqs_disabled_flags(flags);        \
+       })
+#define raw_irqs_disabled()            (arch_irqs_disabled())
+#define raw_safe_halt()                        arch_safe_halt()
 
+/*
+ * The local_irq_*() APIs are equal to the raw_local_irq*()
+ * if !TRACE_IRQFLAGS.
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
 #define local_irq_enable() \
        do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
 #define local_irq_disable() \
        do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
 #define local_irq_save(flags)                          \
        do {                                            \
-               typecheck(unsigned long, flags);        \
                raw_local_irq_save(flags);              \
                trace_hardirqs_off();                   \
        } while (0)
@@ -70,7 +99,6 @@
 
 #define local_irq_restore(flags)                       \
        do {                                            \
-               typecheck(unsigned long, flags);        \
                if (raw_irqs_disabled_flags(flags)) {   \
                        raw_local_irq_restore(flags);   \
                        trace_hardirqs_off();           \
                        raw_local_irq_restore(flags);   \
                }                                       \
        } while (0)
-#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
-/*
- * The local_irq_*() APIs are equal to the raw_local_irq*()
- * if !TRACE_IRQFLAGS.
- */
-# define raw_local_irq_disable()       local_irq_disable()
-# define raw_local_irq_enable()                local_irq_enable()
-# define raw_local_irq_save(flags)                     \
-       do {                                            \
-               typecheck(unsigned long, flags);        \
-               local_irq_save(flags);                  \
-       } while (0)
-# define raw_local_irq_restore(flags)                  \
+#define local_save_flags(flags)                                \
        do {                                            \
-               typecheck(unsigned long, flags);        \
-               local_irq_restore(flags);               \
+               raw_local_save_flags(flags);            \
        } while (0)
-#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-#define safe_halt()                                            \
-       do {                                                    \
-               trace_hardirqs_on();                            \
-               raw_safe_halt();                                \
-       } while (0)
+#define irqs_disabled_flags(flags)                     \
+       ({                                              \
+               raw_irqs_disabled_flags(flags);         \
+       })
 
-#define local_save_flags(flags)                                \
-       do {                                            \
-               typecheck(unsigned long, flags);        \
-               raw_local_save_flags(flags);            \
+#define irqs_disabled()                                        \
+       ({                                              \
+               unsigned long _flags;                   \
+               raw_local_save_flags(_flags);           \
+               raw_irqs_disabled_flags(_flags);        \
+       })
+
+#define safe_halt()                            \
+       do {                                    \
+               trace_hardirqs_on();            \
+               raw_safe_halt();                \
        } while (0)
 
-#define irqs_disabled()                                                \
-({                                                             \
-       unsigned long _flags;                                   \
-                                                               \
-       raw_local_save_flags(_flags);                           \
-       raw_irqs_disabled_flags(_flags);                        \
-})
 
-#define irqs_disabled_flags(flags)             \
-({                                             \
-       typecheck(unsigned long, flags);        \
-       raw_irqs_disabled_flags(flags);         \
-})
+#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
+
+#define local_irq_enable()     do { raw_local_irq_enable(); } while (0)
+#define local_irq_disable()    do { raw_local_irq_disable(); } while (0)
+#define local_irq_save(flags)                                  \
+       do {                                                    \
+               raw_local_irq_save(flags);                      \
+       } while (0)
+#define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
+#define local_save_flags(flags)        do { raw_local_save_flags(flags); } while (0)
+#define irqs_disabled()                (raw_irqs_disabled())
+#define irqs_disabled_flags(flags) (raw_irqs_disabled_flags(flags))
+#define safe_halt()            do { raw_safe_halt(); } while (0)
+
 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
 #endif
index 7bf89bc8cbca32762d082664c1839d8d642f8782..05aa8c23483ff502bdf94e76365236fa44ff9721 100644 (file)
@@ -25,6 +25,7 @@
 
 extern int nr_irqs;
 extern struct irq_desc *irq_to_desc(unsigned int irq);
+unsigned int irq_get_next_irq(unsigned int offset);
 
 # define for_each_irq_desc(irq, desc)                                  \
        for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs;           \
@@ -47,6 +48,10 @@ extern struct irq_desc *irq_to_desc(unsigned int irq);
 #define irq_node(irq)  0
 #endif
 
+# define for_each_active_irq(irq)                      \
+       for (irq = irq_get_next_irq(0); irq < nr_irqs;  \
+            irq = irq_get_next_irq(irq + 1))
+
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
 #define for_each_irq_nr(irq)                   \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
new file mode 100644 (file)
index 0000000..b67cb18
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _LINUX_JUMP_LABEL_H
+#define _LINUX_JUMP_LABEL_H
+
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_HAVE_ARCH_JUMP_LABEL)
+# include <asm/jump_label.h>
+# define HAVE_JUMP_LABEL
+#endif
+
+enum jump_label_type {
+       JUMP_LABEL_ENABLE,
+       JUMP_LABEL_DISABLE
+};
+
+struct module;
+
+#ifdef HAVE_JUMP_LABEL
+
+extern struct jump_entry __start___jump_table[];
+extern struct jump_entry __stop___jump_table[];
+
+extern void arch_jump_label_transform(struct jump_entry *entry,
+                                enum jump_label_type type);
+extern void arch_jump_label_text_poke_early(jump_label_t addr);
+extern void jump_label_update(unsigned long key, enum jump_label_type type);
+extern void jump_label_apply_nops(struct module *mod);
+extern int jump_label_text_reserved(void *start, void *end);
+
+#define jump_label_enable(key) \
+       jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE);
+
+#define jump_label_disable(key) \
+       jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE);
+
+#else
+
+#define JUMP_LABEL(key, label)                 \
+do {                                           \
+       if (unlikely(*key))                     \
+               goto label;                     \
+} while (0)
+
+#define jump_label_enable(cond_var)    \
+do {                                   \
+       *(cond_var) = 1;                        \
+} while (0)
+
+#define jump_label_disable(cond_var)   \
+do {                                   \
+       *(cond_var) = 0;                        \
+} while (0)
+
+static inline int jump_label_apply_nops(struct module *mod)
+{
+       return 0;
+}
+
+static inline int jump_label_text_reserved(void *start, void *end)
+{
+       return 0;
+}
+
+#endif
+
+#define COND_STMT(key, stmt)                                   \
+do {                                                           \
+       __label__ jl_enabled;                                   \
+       JUMP_LABEL(key, jl_enabled);                            \
+       if (0) {                                                \
+jl_enabled:                                                    \
+               stmt;                                           \
+       }                                                       \
+} while (0)
+
+#endif
diff --git a/include/linux/jump_label_ref.h b/include/linux/jump_label_ref.h
new file mode 100644 (file)
index 0000000..e5d012a
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _LINUX_JUMP_LABEL_REF_H
+#define _LINUX_JUMP_LABEL_REF_H
+
+#include <linux/jump_label.h>
+#include <asm/atomic.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+static inline void jump_label_inc(atomic_t *key)
+{
+       if (atomic_add_return(1, key) == 1)
+               jump_label_enable(key);
+}
+
+static inline void jump_label_dec(atomic_t *key)
+{
+       if (atomic_dec_and_test(key))
+               jump_label_disable(key);
+}
+
+#else /* !HAVE_JUMP_LABEL */
+
+static inline void jump_label_inc(atomic_t *key)
+{
+       atomic_inc(key);
+}
+
+static inline void jump_label_dec(atomic_t *key)
+{
+       atomic_dec(key);
+}
+
+#undef JUMP_LABEL
+#define JUMP_LABEL(key, label)                                         \
+do {                                                                   \
+       if (unlikely(__builtin_choose_expr(                             \
+             __builtin_types_compatible_p(typeof(key), atomic_t *),    \
+             atomic_read((atomic_t *)(key)), *(key))))                 \
+               goto label;                                             \
+} while (0)
+
+#endif /* HAVE_JUMP_LABEL */
+
+#endif /* _LINUX_JUMP_LABEL_REF_H */
index f5df2f4acb0d38a9e3061b196c122bbad4927b6a..edef168a04064b61161cff70e9e8d803aa2ed1a4 100644 (file)
@@ -58,7 +58,18 @@ extern const char linux_proc_banner[];
 
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define roundup(x, y) (                                        \
+{                                                      \
+       typeof(y) __y = y;                              \
+       (((x) + (__y - 1)) / __y) * __y;                \
+}                                                      \
+)
+#define rounddown(x, y) (                              \
+{                                                      \
+       typeof(x) __x = (x);                            \
+       __x - (__x % (y));                              \
+}                                                      \
+)
 #define DIV_ROUND_CLOSEST(x, divisor)(                 \
 {                                                      \
        typeof(divisor) __divisor = divisor;            \
index cd50dfa1d4c224de2a26e2d8ef3926d7fc74435e..3db0adce1fdabd00d034ad2e111b9d3411146dfd 100644 (file)
@@ -178,8 +178,9 @@ struct key {
         */
        union {
                unsigned long           value;
+               void __rcu              *rcudata;
                void                    *data;
-               struct keyring_list     *subscriptions;
+               struct keyring_list __rcu *subscriptions;
        } payload;
 };
 
index 4aa95f203f3ee773a6ab4bbdbb632efaf970785e..62dbee554f608c91fe7b2b3bf01f390260821c52 100644 (file)
@@ -214,7 +214,7 @@ __kfifo_must_check_helper(unsigned int val)
  */
 #define kfifo_reset(fifo) \
 (void)({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        __tmp->kfifo.in = __tmp->kfifo.out = 0; \
 })
 
@@ -228,7 +228,7 @@ __kfifo_must_check_helper(unsigned int val)
  */
 #define kfifo_reset_out(fifo)  \
 (void)({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        __tmp->kfifo.out = __tmp->kfifo.in; \
 })
 
@@ -238,7 +238,7 @@ __kfifo_must_check_helper(unsigned int val)
  */
 #define kfifo_len(fifo) \
 ({ \
-       typeof(fifo + 1) __tmpl = (fifo); \
+       typeof((fifo) + 1) __tmpl = (fifo); \
        __tmpl->kfifo.in - __tmpl->kfifo.out; \
 })
 
@@ -248,7 +248,7 @@ __kfifo_must_check_helper(unsigned int val)
  */
 #define        kfifo_is_empty(fifo) \
 ({ \
-       typeof(fifo + 1) __tmpq = (fifo); \
+       typeof((fifo) + 1) __tmpq = (fifo); \
        __tmpq->kfifo.in == __tmpq->kfifo.out; \
 })
 
@@ -258,7 +258,7 @@ __kfifo_must_check_helper(unsigned int val)
  */
 #define        kfifo_is_full(fifo) \
 ({ \
-       typeof(fifo + 1) __tmpq = (fifo); \
+       typeof((fifo) + 1) __tmpq = (fifo); \
        kfifo_len(__tmpq) > __tmpq->kfifo.mask; \
 })
 
@@ -269,7 +269,7 @@ __kfifo_must_check_helper(unsigned int val)
 #define        kfifo_avail(fifo) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmpq = (fifo); \
+       typeof((fifo) + 1) __tmpq = (fifo); \
        const size_t __recsize = sizeof(*__tmpq->rectype); \
        unsigned int __avail = kfifo_size(__tmpq) - kfifo_len(__tmpq); \
        (__recsize) ? ((__avail <= __recsize) ? 0 : \
@@ -284,7 +284,7 @@ __kfifo_must_check_helper( \
  */
 #define        kfifo_skip(fifo) \
 (void)({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
        if (__recsize) \
@@ -302,7 +302,7 @@ __kfifo_must_check_helper( \
 #define kfifo_peek_len(fifo) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
        (!__recsize) ? kfifo_len(__tmp) * sizeof(*__tmp->type) : \
@@ -325,7 +325,7 @@ __kfifo_must_check_helper( \
 #define kfifo_alloc(fifo, size, gfp_mask) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
        __is_kfifo_ptr(__tmp) ? \
        __kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \
@@ -339,7 +339,7 @@ __kfifo_must_check_helper( \
  */
 #define kfifo_free(fifo) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
        if (__is_kfifo_ptr(__tmp)) \
                __kfifo_free(__kfifo); \
@@ -358,7 +358,7 @@ __kfifo_must_check_helper( \
  */
 #define kfifo_init(fifo, buffer, size) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
        __is_kfifo_ptr(__tmp) ? \
        __kfifo_init(__kfifo, buffer, size, sizeof(*__tmp->type)) : \
@@ -379,8 +379,8 @@ __kfifo_must_check_helper( \
  */
 #define        kfifo_put(fifo, val) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(val + 1) __val = (val); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((val) + 1) __val = (val); \
        unsigned int __ret; \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -421,8 +421,8 @@ __kfifo_must_check_helper( \
 #define        kfifo_get(fifo, val) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(val + 1) __val = (val); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((val) + 1) __val = (val); \
        unsigned int __ret; \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -462,8 +462,8 @@ __kfifo_must_check_helper( \
 #define        kfifo_peek(fifo, val) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(val + 1) __val = (val); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((val) + 1) __val = (val); \
        unsigned int __ret; \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -501,8 +501,8 @@ __kfifo_must_check_helper( \
  */
 #define        kfifo_in(fifo, buf, n) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(buf + 1) __buf = (buf); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((buf) + 1) __buf = (buf); \
        unsigned long __n = (n); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -554,8 +554,8 @@ __kfifo_must_check_helper( \
 #define        kfifo_out(fifo, buf, n) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(buf + 1) __buf = (buf); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((buf) + 1) __buf = (buf); \
        unsigned long __n = (n); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -611,7 +611,7 @@ __kfifo_must_check_helper( \
 #define        kfifo_from_user(fifo, from, len, copied) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        const void __user *__from = (from); \
        unsigned int __len = (len); \
        unsigned int *__copied = (copied); \
@@ -639,7 +639,7 @@ __kfifo_must_check_helper( \
 #define        kfifo_to_user(fifo, to, len, copied) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        void __user *__to = (to); \
        unsigned int __len = (len); \
        unsigned int *__copied = (copied); \
@@ -666,7 +666,7 @@ __kfifo_must_check_helper( \
  */
 #define        kfifo_dma_in_prepare(fifo, sgl, nents, len) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        struct scatterlist *__sgl = (sgl); \
        int __nents = (nents); \
        unsigned int __len = (len); \
@@ -690,7 +690,7 @@ __kfifo_must_check_helper( \
  */
 #define kfifo_dma_in_finish(fifo, len) \
 (void)({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        unsigned int __len = (len); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -717,7 +717,7 @@ __kfifo_must_check_helper( \
  */
 #define        kfifo_dma_out_prepare(fifo, sgl, nents, len) \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo);  \
        struct scatterlist *__sgl = (sgl); \
        int __nents = (nents); \
        unsigned int __len = (len); \
@@ -741,7 +741,7 @@ __kfifo_must_check_helper( \
  */
 #define kfifo_dma_out_finish(fifo, len) \
 (void)({ \
-       typeof(fifo + 1) __tmp = (fifo); \
+       typeof((fifo) + 1) __tmp = (fifo); \
        unsigned int __len = (len); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
@@ -766,8 +766,8 @@ __kfifo_must_check_helper( \
 #define        kfifo_out_peek(fifo, buf, n) \
 __kfifo_must_check_helper( \
 ({ \
-       typeof(fifo + 1) __tmp = (fifo); \
-       typeof(buf + 1) __buf = (buf); \
+       typeof((fifo) + 1) __tmp = (fifo); \
+       typeof((buf) + 1) __buf = (buf); \
        unsigned long __n = (n); \
        const size_t __recsize = sizeof(*__tmp->rectype); \
        struct __kfifo *__kfifo = &__tmp->kfifo; \
index cf343a852534bee2f3ed02ffd9cce21210caac8f..7950a37a71466b773ac72d1880e834d20b1d0c14 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/kref.h>
+#include <linux/kobject_ns.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <asm/atomic.h>
@@ -136,42 +137,8 @@ struct kobj_attribute {
 
 extern const struct sysfs_ops kobj_sysfs_ops;
 
-/*
- * Namespace types which are used to tag kobjects and sysfs entries.
- * Network namespace will likely be the first.
- */
-enum kobj_ns_type {
-       KOBJ_NS_TYPE_NONE = 0,
-       KOBJ_NS_TYPE_NET,
-       KOBJ_NS_TYPES
-};
-
 struct sock;
 
-/*
- * Callbacks so sysfs can determine namespaces
- *   @current_ns: return calling task's namespace
- *   @netlink_ns: return namespace to which a sock belongs (right?)
- *   @initial_ns: return the initial namespace (i.e. init_net_ns)
- */
-struct kobj_ns_type_operations {
-       enum kobj_ns_type type;
-       const void *(*current_ns)(void);
-       const void *(*netlink_ns)(struct sock *sk);
-       const void *(*initial_ns)(void);
-};
-
-int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
-int kobj_ns_type_registered(enum kobj_ns_type type);
-const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
-const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
-
-const void *kobj_ns_current(enum kobj_ns_type type);
-const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk);
-const void *kobj_ns_initial(enum kobj_ns_type type);
-void kobj_ns_exit(enum kobj_ns_type type, const void *ns);
-
-
 /**
  * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
  *
diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h
new file mode 100644 (file)
index 0000000..82cb5bf
--- /dev/null
@@ -0,0 +1,56 @@
+/* Kernel object name space definitions
+ *
+ * Copyright (c) 2002-2003 Patrick Mochel
+ * Copyright (c) 2002-2003 Open Source Development Labs
+ * Copyright (c) 2006-2008 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (c) 2006-2008 Novell Inc.
+ *
+ * Split from kobject.h by David Howells (dhowells@redhat.com)
+ *
+ * This file is released under the GPLv2.
+ *
+ * Please read Documentation/kobject.txt before using the kobject
+ * interface, ESPECIALLY the parts about reference counts and object
+ * destructors.
+ */
+
+#ifndef _LINUX_KOBJECT_NS_H
+#define _LINUX_KOBJECT_NS_H
+
+struct sock;
+struct kobject;
+
+/*
+ * Namespace types which are used to tag kobjects and sysfs entries.
+ * Network namespace will likely be the first.
+ */
+enum kobj_ns_type {
+       KOBJ_NS_TYPE_NONE = 0,
+       KOBJ_NS_TYPE_NET,
+       KOBJ_NS_TYPES
+};
+
+/*
+ * Callbacks so sysfs can determine namespaces
+ *   @current_ns: return calling task's namespace
+ *   @netlink_ns: return namespace to which a sock belongs (right?)
+ *   @initial_ns: return the initial namespace (i.e. init_net_ns)
+ */
+struct kobj_ns_type_operations {
+       enum kobj_ns_type type;
+       const void *(*current_ns)(void);
+       const void *(*netlink_ns)(struct sock *sk);
+       const void *(*initial_ns)(void);
+};
+
+int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
+int kobj_ns_type_registered(enum kobj_ns_type type);
+const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
+const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
+
+const void *kobj_ns_current(enum kobj_ns_type type);
+const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk);
+const void *kobj_ns_initial(enum kobj_ns_type type);
+void kobj_ns_exit(enum kobj_ns_type type, const void *ns);
+
+#endif /* _LINUX_KOBJECT_NS_H */
index 74d691ee9121c5bb3aa8336d7eeffcc03d88cc46..3319a6967626e02f91c340080b21950a8310a67f 100644 (file)
@@ -16,6 +16,9 @@
 struct stable_node;
 struct mem_cgroup;
 
+struct page *ksm_does_need_to_copy(struct page *page,
+                       struct vm_area_struct *vma, unsigned long address);
+
 #ifdef CONFIG_KSM
 int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
                unsigned long end, int advice, unsigned long *vm_flags);
@@ -70,19 +73,14 @@ static inline void set_page_stable_node(struct page *page,
  * We'd like to make this conditional on vma->vm_flags & VM_MERGEABLE,
  * but what if the vma was unmerged while the page was swapped out?
  */
-struct page *ksm_does_need_to_copy(struct page *page,
-                       struct vm_area_struct *vma, unsigned long address);
-static inline struct page *ksm_might_need_to_copy(struct page *page,
+static inline int ksm_might_need_to_copy(struct page *page,
                        struct vm_area_struct *vma, unsigned long address)
 {
        struct anon_vma *anon_vma = page_anon_vma(page);
 
-       if (!anon_vma ||
-           (anon_vma->root == vma->anon_vma->root &&
-            page->index == linear_page_index(vma, address)))
-               return page;
-
-       return ksm_does_need_to_copy(page, vma, address);
+       return anon_vma &&
+               (anon_vma->root != vma->anon_vma->root ||
+                page->index != linear_page_index(vma, address));
 }
 
 int page_referenced_ksm(struct page *page,
@@ -115,10 +113,10 @@ static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
        return 0;
 }
 
-static inline struct page *ksm_might_need_to_copy(struct page *page,
+static inline int ksm_might_need_to_copy(struct page *page,
                        struct vm_area_struct *vma, unsigned long address)
 {
-       return page;
+       return 0;
 }
 
 static inline int page_referenced_ksm(struct page *page,
index c13cc48697aa73d2f8daa55dcbaf94204ff3db38..ac740b26eb1071950a26ce64ddca68f8212e8742 100644 (file)
@@ -205,7 +205,7 @@ struct kvm {
 
        struct mutex irq_lock;
 #ifdef CONFIG_HAVE_KVM_IRQCHIP
-       struct kvm_irq_routing_table *irq_routing;
+       struct kvm_irq_routing_table __rcu *irq_routing;
        struct hlist_head mask_notifier_list;
        struct hlist_head irq_ack_notifier_list;
 #endif
index b288cb713b902182cca71156e5d9f75c7452a117..f549056fb20bd5533555918cc1b1f9805c2cdcc3 100644 (file)
        int i;                                                          \
        preempt_disable();                                              \
        rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_);           \
-       for_each_online_cpu(i) {                                        \
+       for_each_possible_cpu(i) {                                      \
                arch_spinlock_t *lock;                                  \
                lock = &per_cpu(name##_lock, i);                        \
                arch_spin_lock(lock);                                   \
  void name##_global_unlock(void) {                                     \
        int i;                                                          \
        rwlock_release(&name##_lock_dep_map, 1, _RET_IP_);              \
-       for_each_online_cpu(i) {                                        \
+       for_each_possible_cpu(i) {                                      \
                arch_spinlock_t *lock;                                  \
                lock = &per_cpu(name##_lock, i);                        \
                arch_spin_unlock(lock);                                 \
index f010f18a0f863f39e139d65469debae94232b259..15b77b8dc7e11f529b93cc9ba629f464627d3a74 100644 (file)
@@ -37,6 +37,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/acpi.h>
 #include <linux/cdrom.h>
+#include <linux/sched.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -172,6 +173,7 @@ enum {
        ATA_LFLAG_NO_RETRY      = (1 << 5), /* don't retry this link */
        ATA_LFLAG_DISABLED      = (1 << 6), /* link is disabled */
        ATA_LFLAG_SW_ACTIVITY   = (1 << 7), /* keep activity stats */
+       ATA_LFLAG_NO_LPM        = (1 << 8), /* disable LPM on this link */
 
        /* struct ata_port flags */
        ATA_FLAG_SLAVE_POSS     = (1 << 0), /* host supports slave dev */
@@ -196,7 +198,7 @@ enum {
        ATA_FLAG_ACPI_SATA      = (1 << 17), /* need native SATA ACPI layout */
        ATA_FLAG_AN             = (1 << 18), /* controller supports AN */
        ATA_FLAG_PMP            = (1 << 19), /* controller supports PMP */
-       ATA_FLAG_IPM            = (1 << 20), /* driver can handle IPM */
+       ATA_FLAG_LPM            = (1 << 20), /* driver can handle LPM */
        ATA_FLAG_EM             = (1 << 21), /* driver supports enclosure
                                              * management */
        ATA_FLAG_SW_ACTIVITY    = (1 << 22), /* driver supports sw activity
@@ -324,23 +326,23 @@ enum {
        ATA_EH_HARDRESET        = (1 << 2), /* meaningful only in ->prereset */
        ATA_EH_RESET            = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
        ATA_EH_ENABLE_LINK      = (1 << 3),
-       ATA_EH_LPM              = (1 << 4),  /* link power management action */
        ATA_EH_PARK             = (1 << 5), /* unload heads and stop I/O */
 
        ATA_EH_PERDEV_MASK      = ATA_EH_REVALIDATE | ATA_EH_PARK,
        ATA_EH_ALL_ACTIONS      = ATA_EH_REVALIDATE | ATA_EH_RESET |
-                                 ATA_EH_ENABLE_LINK | ATA_EH_LPM,
+                                 ATA_EH_ENABLE_LINK,
 
        /* ata_eh_info->flags */
        ATA_EHI_HOTPLUGGED      = (1 << 0),  /* could have been hotplugged */
        ATA_EHI_NO_AUTOPSY      = (1 << 2),  /* no autopsy */
        ATA_EHI_QUIET           = (1 << 3),  /* be quiet */
+       ATA_EHI_NO_RECOVERY     = (1 << 4),  /* no recovery */
 
        ATA_EHI_DID_SOFTRESET   = (1 << 16), /* already soft-reset this port */
        ATA_EHI_DID_HARDRESET   = (1 << 17), /* already soft-reset this port */
        ATA_EHI_PRINTINFO       = (1 << 18), /* print configuration info */
        ATA_EHI_SETMODE         = (1 << 19), /* configure transfer mode */
-       ATA_EHI_POST_SETMODE    = (1 << 20), /* revaildating after setmode */
+       ATA_EHI_POST_SETMODE    = (1 << 20), /* revalidating after setmode */
 
        ATA_EHI_DID_RESET       = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
 
@@ -376,7 +378,6 @@ enum {
        ATA_HORKAGE_BROKEN_HPA  = (1 << 4),     /* Broken HPA */
        ATA_HORKAGE_DISABLE     = (1 << 5),     /* Disable it */
        ATA_HORKAGE_HPA_SIZE    = (1 << 6),     /* native size off by one */
-       ATA_HORKAGE_IPM         = (1 << 7),     /* Link PM problems */
        ATA_HORKAGE_IVB         = (1 << 8),     /* cbl det validity bit bugs */
        ATA_HORKAGE_STUCK_ERR   = (1 << 9),     /* stuck ERR on next PACKET */
        ATA_HORKAGE_BRIDGE_OK   = (1 << 10),    /* no bridge limits */
@@ -463,6 +464,22 @@ enum ata_completion_errors {
        AC_ERR_NCQ              = (1 << 10), /* marker for offending NCQ qc */
 };
 
+/*
+ * Link power management policy: If you alter this, you also need to
+ * alter libata-scsi.c (for the ascii descriptions)
+ */
+enum ata_lpm_policy {
+       ATA_LPM_UNKNOWN,
+       ATA_LPM_MAX_POWER,
+       ATA_LPM_MED_POWER,
+       ATA_LPM_MIN_POWER,
+};
+
+enum ata_lpm_hints {
+       ATA_LPM_EMPTY           = (1 << 0), /* port empty/probing */
+       ATA_LPM_HIPM            = (1 << 1), /* may use HIPM */
+};
+
 /* forward declarations */
 struct scsi_device;
 struct ata_port_operations;
@@ -477,16 +494,6 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes,
                              unsigned long deadline);
 typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
 
-/*
- * host pm policy: If you alter this, you also need to alter libata-scsi.c
- * (for the ascii descriptions)
- */
-enum link_pm {
-       NOT_AVAILABLE,
-       MIN_POWER,
-       MAX_PERFORMANCE,
-       MEDIUM_POWER,
-};
 extern struct device_attribute dev_attr_link_power_management_policy;
 extern struct device_attribute dev_attr_unload_heads;
 extern struct device_attribute dev_attr_em_message_type;
@@ -529,6 +536,10 @@ struct ata_host {
        void                    *private_data;
        struct ata_port_operations *ops;
        unsigned long           flags;
+
+       struct mutex            eh_mutex;
+       struct task_struct      *eh_owner;
+
 #ifdef CONFIG_ATA_ACPI
        acpi_handle             acpi_handle;
 #endif
@@ -559,13 +570,13 @@ struct ata_queued_cmd {
        unsigned int            extrabytes;
        unsigned int            curbytes;
 
-       struct scatterlist      *cursg;
-       unsigned int            cursg_ofs;
-
        struct scatterlist      sgent;
 
        struct scatterlist      *sg;
 
+       struct scatterlist      *cursg;
+       unsigned int            cursg_ofs;
+
        unsigned int            err_mask;
        struct ata_taskfile     result_tf;
        ata_qc_cb_t             complete_fn;
@@ -603,6 +614,7 @@ struct ata_device {
        union acpi_object       *gtf_cache;
        unsigned int            gtf_filter;
 #endif
+       struct device           tdev;
        /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
        u64                     n_sectors;      /* size of device, if ATA */
        u64                     n_native_sectors; /* native size, if ATA */
@@ -689,6 +701,7 @@ struct ata_link {
        struct ata_port         *ap;
        int                     pmp;            /* port multiplier port # */
 
+       struct device           tdev;
        unsigned int            active_tag;     /* active tag on this link */
        u32                     sactive;        /* active NCQ commands */
 
@@ -698,6 +711,7 @@ struct ata_link {
        unsigned int            hw_sata_spd_limit;
        unsigned int            sata_spd_limit;
        unsigned int            sata_spd;       /* current SATA PHY speed */
+       enum ata_lpm_policy     lpm_policy;
 
        /* record runtime error info, protected by host_set lock */
        struct ata_eh_info      eh_info;
@@ -706,6 +720,8 @@ struct ata_link {
 
        struct ata_device       device[ATA_MAX_DEVICES];
 };
+#define ATA_LINK_CLEAR_BEGIN           offsetof(struct ata_link, active_tag)
+#define ATA_LINK_CLEAR_END             offsetof(struct ata_link, device[0])
 
 struct ata_port {
        struct Scsi_Host        *scsi_host; /* our co-allocated scsi host */
@@ -723,6 +739,7 @@ struct ata_port {
        struct ata_ioports      ioaddr; /* ATA cmd/ctl/dma register blocks */
        u8                      ctl;    /* cache of ATA control register */
        u8                      last_ctl;       /* Cache last written value */
+       struct ata_link*        sff_pio_task_link; /* link currently used */
        struct delayed_work     sff_pio_task;
 #ifdef CONFIG_ATA_BMDMA
        struct ata_bmdma_prd    *bmdma_prd;     /* BMDMA SG list */
@@ -750,6 +767,7 @@ struct ata_port {
        struct ata_port_stats   stats;
        struct ata_host         *host;
        struct device           *dev;
+       struct device           tdev;
 
        struct mutex            scsi_scan_mutex;
        struct delayed_work     hotplug_task;
@@ -765,7 +783,7 @@ struct ata_port {
 
        pm_message_t            pm_mesg;
        int                     *pm_result;
-       enum link_pm            pm_policy;
+       enum ata_lpm_policy     target_lpm_policy;
 
        struct timer_list       fastdrain_timer;
        unsigned long           fastdrain_cnt;
@@ -831,8 +849,8 @@ struct ata_port_operations {
        int  (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val);
        void (*pmp_attach)(struct ata_port *ap);
        void (*pmp_detach)(struct ata_port *ap);
-       int  (*enable_pm)(struct ata_port *ap, enum link_pm policy);
-       void (*disable_pm)(struct ata_port *ap);
+       int  (*set_lpm)(struct ata_link *link, enum ata_lpm_policy policy,
+                       unsigned hints);
 
        /*
         * Start, stop, suspend and resume
@@ -944,6 +962,8 @@ extern int sata_link_debounce(struct ata_link *link,
                        const unsigned long *params, unsigned long deadline);
 extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
                            unsigned long deadline);
+extern int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+                            bool spm_wakeup);
 extern int sata_link_hardreset(struct ata_link *link,
                        const unsigned long *timing, unsigned long deadline,
                        bool *online, int (*check_ready)(struct ata_link *));
@@ -989,8 +1009,9 @@ extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
 extern void ata_host_resume(struct ata_host *host);
 #endif
 extern int ata_ratelimit(void);
-extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
-                            unsigned long interval, unsigned long timeout);
+extern void ata_msleep(struct ata_port *ap, unsigned int msecs);
+extern u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask,
+                       u32 val, unsigned long interval, unsigned long timeout);
 extern int atapi_cmd_type(u8 opcode);
 extern void ata_tf_to_fis(const struct ata_taskfile *tf,
                          u8 pmp, int is_cmd, u8 *fis);
@@ -1594,7 +1615,7 @@ extern void ata_sff_irq_on(struct ata_port *ap);
 extern void ata_sff_irq_clear(struct ata_port *ap);
 extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
                            u8 status, int in_wq);
-extern void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay);
+extern void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay);
 extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
 extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
 extern unsigned int ata_sff_port_intr(struct ata_port *ap,
index d167b5d7c0ac0844d9b42fab6a16d486793878c5..88a000617d775fb74333a5f54aceac8460cb5008 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/stddef.h>
 #include <linux/poison.h>
 #include <linux/prefetch.h>
-#include <asm/system.h>
 
 /*
  * Simple doubly linked list implementation.
index 06aed8305bf3bc38061dc42c168c3b9d83f29492..71c09b26c7592ff4a1f6351fd226c9442ef66e5d 100644 (file)
@@ -31,6 +31,17 @@ extern int lock_stat;
 
 #define MAX_LOCKDEP_SUBCLASSES         8UL
 
+/*
+ * NR_LOCKDEP_CACHING_CLASSES ... Number of classes
+ * cached in the instance of lockdep_map
+ *
+ * Currently main class (subclass == 0) and signle depth subclass
+ * are cached in lockdep_map. This optimization is mainly targeting
+ * on rq->lock. double_rq_lock() acquires this highly competitive with
+ * single depth.
+ */
+#define NR_LOCKDEP_CACHING_CLASSES     2
+
 /*
  * Lock-classes are keyed via unique addresses, by embedding the
  * lockclass-key into the kernel (or module) .data section. (For
@@ -138,7 +149,7 @@ void clear_lock_stats(struct lock_class *class);
  */
 struct lockdep_map {
        struct lock_class_key           *key;
-       struct lock_class               *class_cache;
+       struct lock_class               *class_cache[NR_LOCKDEP_CACHING_CLASSES];
        const char                      *name;
 #ifdef CONFIG_LOCK_STAT
        int                             cpu;
@@ -424,14 +435,6 @@ do {                                                               \
 
 #endif /* CONFIG_LOCKDEP */
 
-#ifdef CONFIG_GENERIC_HARDIRQS
-extern void early_init_irq_lock_class(void);
-#else
-static inline void early_init_irq_lock_class(void)
-{
-}
-#endif
-
 #ifdef CONFIG_TRACE_IRQFLAGS
 extern void early_boot_irqs_off(void);
 extern void early_boot_irqs_on(void);
index a59faf2b5edd15faa6b408de6cc75fcfb069d840..62a10c2a11f2dc6a68f5bf4b1e30bbb23149ce6a 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_MEMBLOCK_H
 #ifdef __KERNEL__
 
+#ifdef CONFIG_HAVE_MEMBLOCK
 /*
  * Logical memory blocks.
  *
 #include <linux/init.h>
 #include <linux/mm.h>
 
-#define MAX_MEMBLOCK_REGIONS 128
+#include <asm/memblock.h>
 
-struct memblock_property {
-       u64 base;
-       u64 size;
-};
+#define INIT_MEMBLOCK_REGIONS  128
+#define MEMBLOCK_ERROR         0
 
 struct memblock_region {
-       unsigned long cnt;
-       u64 size;
-       struct memblock_property region[MAX_MEMBLOCK_REGIONS+1];
+       phys_addr_t base;
+       phys_addr_t size;
+};
+
+struct memblock_type {
+       unsigned long cnt;      /* number of regions */
+       unsigned long max;      /* size of the allocated array */
+       struct memblock_region *regions;
 };
 
 struct memblock {
-       unsigned long debug;
-       u64 rmo_size;
-       struct memblock_region memory;
-       struct memblock_region reserved;
+       phys_addr_t current_limit;
+       phys_addr_t memory_size;        /* Updated by memblock_analyze() */
+       struct memblock_type memory;
+       struct memblock_type reserved;
 };
 
 extern struct memblock memblock;
+extern int memblock_debug;
+extern int memblock_can_resize;
 
-extern void __init memblock_init(void);
-extern void __init memblock_analyze(void);
-extern long memblock_add(u64 base, u64 size);
-extern long memblock_remove(u64 base, u64 size);
-extern long __init memblock_free(u64 base, u64 size);
-extern long __init memblock_reserve(u64 base, u64 size);
-extern u64 __init memblock_alloc_nid(u64 size, u64 align, int nid,
-                               u64 (*nid_range)(u64, u64, int *));
-extern u64 __init memblock_alloc(u64 size, u64 align);
-extern u64 __init memblock_alloc_base(u64 size,
-               u64, u64 max_addr);
-extern u64 __init __memblock_alloc_base(u64 size,
-               u64 align, u64 max_addr);
-extern u64 __init memblock_phys_mem_size(void);
-extern u64 memblock_end_of_DRAM(void);
-extern void __init memblock_enforce_memory_limit(u64 memory_limit);
-extern int __init memblock_is_reserved(u64 addr);
-extern int memblock_is_region_reserved(u64 base, u64 size);
-extern int memblock_find(struct memblock_property *res);
+#define memblock_dbg(fmt, ...) \
+       if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+
+u64 memblock_find_in_range(u64 start, u64 end, u64 size, u64 align);
+int memblock_free_reserved_regions(void);
+int memblock_reserve_reserved_regions(void);
+
+extern void memblock_init(void);
+extern void memblock_analyze(void);
+extern long memblock_add(phys_addr_t base, phys_addr_t size);
+extern long memblock_remove(phys_addr_t base, phys_addr_t size);
+extern long memblock_free(phys_addr_t base, phys_addr_t size);
+extern long memblock_reserve(phys_addr_t base, phys_addr_t size);
+
+/* The numa aware allocator is only available if
+ * CONFIG_ARCH_POPULATES_NODE_MAP is set
+ */
+extern phys_addr_t memblock_alloc_nid(phys_addr_t size, phys_addr_t align,
+                                       int nid);
+extern phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
+                                           int nid);
+
+extern phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
+
+/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
+#define MEMBLOCK_ALLOC_ANYWHERE        (~(phys_addr_t)0)
+#define MEMBLOCK_ALLOC_ACCESSIBLE      0
+
+extern phys_addr_t memblock_alloc_base(phys_addr_t size,
+                                        phys_addr_t align,
+                                        phys_addr_t max_addr);
+extern phys_addr_t __memblock_alloc_base(phys_addr_t size,
+                                          phys_addr_t align,
+                                          phys_addr_t max_addr);
+extern phys_addr_t memblock_phys_mem_size(void);
+extern phys_addr_t memblock_end_of_DRAM(void);
+extern void memblock_enforce_memory_limit(phys_addr_t memory_limit);
+extern int memblock_is_memory(phys_addr_t addr);
+extern int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
+extern int memblock_is_reserved(phys_addr_t addr);
+extern int memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
 
 extern void memblock_dump_all(void);
 
-static inline u64
-memblock_size_bytes(struct memblock_region *type, unsigned long region_nr)
+/* Provided by the architecture */
+extern phys_addr_t memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid);
+extern int memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
+                                  phys_addr_t addr2, phys_addr_t size2);
+
+/**
+ * memblock_set_current_limit - Set the current allocation limit to allow
+ *                         limiting allocations to what is currently
+ *                         accessible during boot
+ * @limit: New limit value (physical address)
+ */
+extern void memblock_set_current_limit(phys_addr_t limit);
+
+
+/*
+ * pfn conversion functions
+ *
+ * While the memory MEMBLOCKs should always be page aligned, the reserved
+ * MEMBLOCKs may not be. This accessor attempt to provide a very clear
+ * idea of what they return for such non aligned MEMBLOCKs.
+ */
+
+/**
+ * memblock_region_memory_base_pfn - Return the lowest pfn intersecting with the memory region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
 {
-       return type->region[region_nr].size;
+       return PFN_UP(reg->base);
 }
-static inline u64
-memblock_size_pages(struct memblock_region *type, unsigned long region_nr)
+
+/**
+ * memblock_region_memory_end_pfn - Return the end_pfn this region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
 {
-       return memblock_size_bytes(type, region_nr) >> PAGE_SHIFT;
+       return PFN_DOWN(reg->base + reg->size);
 }
-static inline u64
-memblock_start_pfn(struct memblock_region *type, unsigned long region_nr)
+
+/**
+ * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
 {
-       return type->region[region_nr].base >> PAGE_SHIFT;
+       return PFN_DOWN(reg->base);
 }
-static inline u64
-memblock_end_pfn(struct memblock_region *type, unsigned long region_nr)
+
+/**
+ * memblock_region_reserved_end_pfn - Return the end_pfn this region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
 {
-       return memblock_start_pfn(type, region_nr) +
-              memblock_size_pages(type, region_nr);
+       return PFN_UP(reg->base + reg->size);
 }
 
-#include <asm/memblock.h>
+#define for_each_memblock(memblock_type, region)                                       \
+       for (region = memblock.memblock_type.regions;                           \
+            region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);    \
+            region++)
+
+
+#ifdef ARCH_DISCARD_MEMBLOCK
+#define __init_memblock __init
+#define __initdata_memblock __initdata
+#else
+#define __init_memblock
+#define __initdata_memblock
+#endif
+
+#endif /* CONFIG_HAVE_MEMBLOCK */
 
 #endif /* __KERNEL__ */
 
index e47f770d30684df3f164f2689debe335923b062a..eff3094ca84e0d1c1eaf8b183303c33d6d5cdf76 100644 (file)
@@ -111,9 +111,13 @@ extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val);
  * struct tc35892_gpio_platform_data - TC35892 GPIO platform data
  * @gpio_base: first gpio number assigned to TC35892.  A maximum of
  *            %TC35892_NR_GPIOS GPIOs will be allocated.
+ * @setup: callback for board-specific initialization
+ * @remove: callback for board-specific teardown
  */
 struct tc35892_gpio_platform_data {
        int gpio_base;
+       void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
+       void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
 };
 
 /**
index bafffc737903971934037fc334f7d4158d9eda48..18fd13028ba1aab8207a1baa9c5b1527435d3a01 100644 (file)
@@ -33,6 +33,7 @@
 #define MWAVE_MINOR            219     /* ACP/Mwave Modem */
 #define MPT_MINOR              220
 #define MPT2SAS_MINOR          221
+#define UINPUT_MINOR           223
 #define HPET_MINOR             228
 #define FUSE_MINOR             229
 #define KVM_MINOR              232
index 709f6728fc90e223c9f41092d626b7b7fc4458bd..7687228dd3b7d16530cf28087ea71f07155ee3ba 100644 (file)
@@ -78,7 +78,11 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_MAYSHARE    0x00000080
 
 #define VM_GROWSDOWN   0x00000100      /* general info on the segment */
+#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64)
 #define VM_GROWSUP     0x00000200
+#else
+#define VM_GROWSUP     0x00000000
+#endif
 #define VM_PFNMAP      0x00000400      /* Page-ranges managed without "struct page", just pure PFN */
 #define VM_DENYWRITE   0x00000800      /* ETXTBSY on write attempts.. */
 
@@ -860,6 +864,12 @@ int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
+/* Is the vma a continuation of the stack vma above it? */
+static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
+{
+       return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
+}
+
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
                unsigned long old_addr, struct vm_area_struct *new_vma,
                unsigned long new_addr, unsigned long len);
@@ -1165,6 +1175,8 @@ extern void free_bootmem_with_active_regions(int nid,
                                                unsigned long max_low_pfn);
 int add_from_early_node_map(struct range *range, int az,
                                   int nr_range, int nid);
+u64 __init find_memory_core_early(int nid, u64 size, u64 align,
+                                       u64 goal, u64 limit);
 void *__alloc_memory_core_early(int nodeid, u64 size, u64 align,
                                 u64 goal, u64 limit);
 typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
@@ -1330,8 +1342,10 @@ unsigned long ra_submit(struct file_ra_state *ra,
 
 /* Do stack extension */
 extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
-#ifdef CONFIG_IA64
+#if VM_GROWSUP
 extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
+#else
+  #define expand_upwards(vma, address) do { } while (0)
 #endif
 extern int expand_stack_downwards(struct vm_area_struct *vma,
                                  unsigned long address);
@@ -1357,7 +1371,15 @@ static inline unsigned long vma_pages(struct vm_area_struct *vma)
        return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 }
 
+#ifdef CONFIG_MMU
 pgprot_t vm_get_page_prot(unsigned long vm_flags);
+#else
+static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
+{
+       return __pgprot(0);
+}
+#endif
+
 struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
                        unsigned long pfn, unsigned long size, pgprot_t);
index ee7e258627f9f5b9999e4c3033f7fa78c5927b48..cb57d657ce4d2643c58e21eb23b2b1434f0f7a2f 100644 (file)
@@ -299,7 +299,7 @@ struct mm_struct {
         * new_owner->mm == mm
         * new_owner->alloc_lock is held
         */
-       struct task_struct *owner;
+       struct task_struct __rcu *owner;
 #endif
 
 #ifdef CONFIG_PROC_FS
index 329a8faa6e37bb32bd6e65f1b8fd758ac45baa36..245cdacee5443791eb5418d10bde3daa190351a9 100644 (file)
@@ -38,6 +38,8 @@
  *      [8:0] Byte/block count
  */
 
+#define R4_MEMORY_PRESENT (1 << 27)
+
 /*
   SDIO status in R5
   Type
index 6e6e62648a4d4a6d792fe207d42105563b112aaa..3984c4eb41fdc9c85759dbffe308df5a806391f4 100644 (file)
@@ -283,6 +283,13 @@ struct zone {
        /* zone watermarks, access with *_wmark_pages(zone) macros */
        unsigned long watermark[NR_WMARK];
 
+       /*
+        * When free pages are below this point, additional steps are taken
+        * when reading the number of free pages to avoid per-cpu counter
+        * drift allowing watermarks to be breached
+        */
+       unsigned long percpu_drift_mark;
+
        /*
         * We don't know if the memory that we're going to allocate will be freeable
         * or/and it will be released eventually, so to avoid totally wasting several
@@ -441,6 +448,12 @@ static inline int zone_is_oom_locked(const struct zone *zone)
        return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 }
 
+#ifdef CONFIG_SMP
+unsigned long zone_nr_free_pages(struct zone *zone);
+#else
+#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES)
+#endif /* CONFIG_SMP */
+
 /*
  * The "priority" of VM scanning is how much of the queues we will scan in one
  * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
index 8a6b9fdc7ffae0c20335b8a2c73726396a934ee2..b29e7458b96642b2f36162aa755b10ff76b15abe 100644 (file)
@@ -350,7 +350,10 @@ struct module
        struct tracepoint *tracepoints;
        unsigned int num_tracepoints;
 #endif
-
+#ifdef HAVE_JUMP_LABEL
+       struct jump_entry *jump_entries;
+       unsigned int num_jump_entries;
+#endif
 #ifdef CONFIG_TRACING
        const char **trace_bprintk_fmt_start;
        unsigned int num_trace_bprintk_fmt;
@@ -686,17 +689,16 @@ extern int module_sysfs_initialized;
 
 
 #ifdef CONFIG_GENERIC_BUG
-int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
+void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
                         struct module *);
 void module_bug_cleanup(struct module *);
 
 #else  /* !CONFIG_GENERIC_BUG */
 
-static inline int  module_bug_finalize(const Elf_Ehdr *hdr,
+static inline void module_bug_finalize(const Elf_Ehdr *hdr,
                                        const Elf_Shdr *sechdrs,
                                        struct module *mod)
 {
-       return 0;
 }
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif /* CONFIG_GENERIC_BUG */
index 91b05c171854f12488e92c8fe2d23812bb1f03e5..05acced439a38ec1faf822200740d032778e9022 100644 (file)
@@ -10,12 +10,13 @@ struct msi_msg {
 };
 
 /* Helper functions */
-struct irq_desc;
-extern void mask_msi_irq(unsigned int irq);
-extern void unmask_msi_irq(unsigned int irq);
-extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
-extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
-extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
+struct irq_data;
+struct msi_desc;
+extern void mask_msi_irq(struct irq_data *data);
+extern void unmask_msi_irq(struct irq_data *data);
+extern void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+extern void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+extern void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
index 878cab4f5fcc5db95585184c22aea5d905a34295..f363bc8fdc74c821c99aa59d5bfcb9554c012c9a 100644 (file)
@@ -78,6 +78,14 @@ struct mutex_waiter {
 # include <linux/mutex-debug.h>
 #else
 # define __DEBUG_MUTEX_INITIALIZER(lockname)
+/**
+ * mutex_init - initialize the mutex
+ * @mutex: the mutex to be initialized
+ *
+ * Initialize the mutex to unlocked state.
+ *
+ * It is not allowed to initialize an already locked mutex.
+ */
 # define mutex_init(mutex) \
 do {                                                   \
        static struct lock_class_key __key;             \
index bb58854a806196d8dea6ab9599daa244012ef5d8..d146ca10c0f52449dd528e9fec61be47e0c85221 100644 (file)
@@ -88,7 +88,7 @@ struct nbd_request {
        char handle[8];
        __be64 from;
        __be32 len;
-} __packed;
+} __attribute__((packed));
 
 /*
  * This is the reply packet that nbd-server sends back to the client after
index 3ace8370e61e9855cfda5d7237362c1538c701a6..99f0adeeb3f348e58c65312133217055a6ccf3c0 100644 (file)
@@ -27,7 +27,7 @@ struct ncp_request_header {
        __u8 conn_high;
        __u8 function;
        __u8 data[0];
-} __packed;
+} __attribute__((packed));
 
 #define NCP_REPLY                (0x3333)
 #define NCP_WATCHDOG            (0x3E3E)
@@ -42,7 +42,7 @@ struct ncp_reply_header {
        __u8 completion_code;
        __u8 connection_state;
        __u8 data[0];
-} __packed;
+} __attribute__((packed));
 
 #define NCP_VOLNAME_LEN (16)
 #define NCP_NUMBER_OF_VOLUMES (256)
@@ -158,7 +158,7 @@ struct nw_info_struct {
 #ifdef __KERNEL__
        struct nw_nfs_info nfs;
 #endif
-} __packed;
+} __attribute__((packed));
 
 /* modify mask - use with MODIFY_DOS_INFO structure */
 #define DM_ATTRIBUTES            (cpu_to_le32(0x02))
@@ -190,12 +190,12 @@ struct nw_modify_dos_info {
        __u16 inheritanceGrantMask;
        __u16 inheritanceRevokeMask;
        __u32 maximumSpace;
-} __packed;
+} __attribute__((packed));
 
 struct nw_search_sequence {
        __u8 volNumber;
        __u32 dirBase;
        __u32 sequence;
-} __packed;
+} __attribute__((packed));
 
 #endif                         /* _LINUX_NCP_H */
index 4522aed00906c81f885eae6ed5c0ecd9f399bde8..ef663061d5ac5e3725b87ff11cc9bd3309a4db8c 100644 (file)
@@ -241,34 +241,6 @@ int ncp_mmap(struct file *, struct vm_area_struct *);
 /* linux/fs/ncpfs/ncplib_kernel.c */
 int ncp_make_closed(struct inode *);
 
-#define ncp_namespace(i)       (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
-
-static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
-{
-#ifdef CONFIG_NCPFS_SMALLDOS
-       int ns = ncp_namespace(i);
-
-       if ((ns == NW_NS_DOS)
-#ifdef CONFIG_NCPFS_OS2_NS
-               || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
-#endif /* CONFIG_NCPFS_OS2_NS */
-                               )
-               return 0;
-#endif /* CONFIG_NCPFS_SMALLDOS */
-       return 1;
-}
-
-#define ncp_preserve_case(i)   (ncp_namespace(i) != NW_NS_DOS)
-
-static inline int ncp_case_sensitive(struct inode *i)
-{
-#ifdef CONFIG_NCPFS_NFS_NS
-       return ncp_namespace(i) == NW_NS_NFS;
-#else
-       return 0;
-#endif /* CONFIG_NCPFS_NFS_NS */
-} 
-
 #endif                         /* __KERNEL__ */
 
 #endif                         /* _LINUX_NCP_FS_H */
index 8da05bc098ca86b2ba5758af8b0b7885c7894dd3..d64b0e89433691bf532577a4b193781c4e0516b6 100644 (file)
@@ -62,6 +62,7 @@ struct ncp_server {
        int ncp_reply_size;
 
        int root_setuped;
+       struct mutex root_setup_lock;
 
        /* info for packet signing */
        int sign_wanted;        /* 1=Server needs signed packets */
@@ -81,13 +82,14 @@ struct ncp_server {
                size_t  len;
                void*   data;
        } priv;
+       struct rw_semaphore auth_rwsem;
 
        /* nls info: codepage for volume and charset for I/O */
        struct nls_table *nls_vol;
        struct nls_table *nls_io;
 
        /* maximum age in jiffies */
-       int dentry_ttl;
+       atomic_t dentry_ttl;
 
        /* miscellaneous */
        unsigned int flags;
index 9ed534c991b9312d84876c9162ed63e5ef2b5c66..70cd0603911c97b865bc576a3f4490f523e2fc08 100644 (file)
@@ -39,8 +39,9 @@ enum ctattr_type {
        CTA_TUPLE_MASTER,
        CTA_NAT_SEQ_ADJ_ORIG,
        CTA_NAT_SEQ_ADJ_REPLY,
-       CTA_SECMARK,
+       CTA_SECMARK,            /* obsolete */
        CTA_ZONE,
+       CTA_SECCTX,
        __CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -172,4 +173,11 @@ enum ctattr_help {
 };
 #define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
 
+enum ctattr_secctx {
+       CTA_SECCTX_UNSPEC,
+       CTA_SECCTX_NAME,
+       __CTA_SECCTX_MAX
+};
+#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1)
+
 #endif /* _IPCONNTRACK_NETLINK_H */
index 3e1aa1be942ef2297637d0bf4a778eec605d7040..208ae938733143ce0ba2117378423d443a3d8312 100644 (file)
@@ -39,7 +39,7 @@ struct idletimer_tg_info {
        char label[MAX_IDLETIMER_LABEL_SIZE];
 
        /* for kernel module internal use only */
-       struct idletimer_tg *timer __attribute((aligned(8)));
+       struct idletimer_tg *timer __attribute__((aligned(8)));
 };
 
 #endif
index 6fcd3448b18631f04e081cde470f85218dd7f9b8..989092bd6274b44585ccc0faf4f005a0d7b909b7 100644 (file)
  * packets are being marked for.
  */
 #define SECMARK_MODE_SEL       0x01            /* SELinux */
-#define SECMARK_SELCTX_MAX     256
-
-struct xt_secmark_target_selinux_info {
-       __u32 selsid;
-       char selctx[SECMARK_SELCTX_MAX];
-};
+#define SECMARK_SECCTX_MAX     256
 
 struct xt_secmark_target_info {
        __u8 mode;
-       union {
-               struct xt_secmark_target_selinux_info sel;
-       } u;
+       __u32 secid;
+       char secctx[SECMARK_SECCTX_MAX];
 };
 
 #endif /*_XT_SECMARK_H_target */
index 1167aeb7a34793ff288aff2b7190a966378e5080..eff34ac1880883f70d88282a8ac881a1e8bff8a5 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _XT_IPVS_H
 #define _XT_IPVS_H
 
+#include <linux/types.h>
+
 enum {
        XT_IPVS_IPVS_PROPERTY = 1 << 0, /* all other options imply this one */
        XT_IPVS_PROTO =         1 << 1,
index 59d066936ab9e0414d2cddc5123a9b7e0ac3c3ad..123566912d7312f276bf975cd1a48c97b2ffa830 100644 (file)
@@ -27,8 +27,6 @@
 
 #define MAX_LINKS 32           
 
-struct net;
-
 struct sockaddr_nl {
        sa_family_t     nl_family;      /* AF_NETLINK   */
        unsigned short  nl_pad;         /* zero         */
@@ -151,6 +149,8 @@ struct nlattr {
 #include <linux/capability.h>
 #include <linux/skbuff.h>
 
+struct net;
+
 static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
 {
        return (struct nlmsghdr *)skb->data;
index 791d5109f34c12207de65f06cca05fa4b35b44b8..50d8009be86c023cbee9607cb728927ba86fb531 100644 (file)
@@ -63,20 +63,20 @@ static inline bool netpoll_rx(struct sk_buff *skb)
        unsigned long flags;
        bool ret = false;
 
-       rcu_read_lock_bh();
+       local_irq_save(flags);
        npinfo = rcu_dereference_bh(skb->dev->npinfo);
 
        if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags))
                goto out;
 
-       spin_lock_irqsave(&npinfo->rx_lock, flags);
+       spin_lock(&npinfo->rx_lock);
        /* check rx_flags again with the lock held */
        if (npinfo->rx_flags && __netpoll_rx(skb))
                ret = true;
-       spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+       spin_unlock(&npinfo->rx_lock);
 
 out:
-       rcu_read_unlock_bh();
+       local_irq_restore(flags);
        return ret;
 }
 
index 508f8cf6da379bc7179b5c8f22d534a63a539ad0..d0edf7d823ae3ef60ec2ba6c6daa3ff0b34643cd 100644 (file)
@@ -185,7 +185,7 @@ struct nfs_inode {
        struct nfs4_cached_acl  *nfs4_acl;
         /* NFSv4 state */
        struct list_head        open_states;
-       struct nfs_delegation   *delegation;
+       struct nfs_delegation __rcu *delegation;
        fmode_t                  delegation_state;
        struct rw_semaphore     rwsem;
 #endif /* CONFIG_NFS_V4*/
index b2f1a4d835506b7d0d8fdce8831d608fa28759bd..2026f9e1ceb8e5cb5d6a9f3a2a1b4c4ff02d5953 100644 (file)
 
 struct notifier_block {
        int (*notifier_call)(struct notifier_block *, unsigned long, void *);
-       struct notifier_block *next;
+       struct notifier_block __rcu *next;
        int priority;
 };
 
 struct atomic_notifier_head {
        spinlock_t lock;
-       struct notifier_block *head;
+       struct notifier_block __rcu *head;
 };
 
 struct blocking_notifier_head {
        struct rw_semaphore rwsem;
-       struct notifier_block *head;
+       struct notifier_block __rcu *head;
 };
 
 struct raw_notifier_head {
-       struct notifier_block *head;
+       struct notifier_block __rcu *head;
 };
 
 struct srcu_notifier_head {
        struct mutex mutex;
        struct srcu_struct srcu;
-       struct notifier_block *head;
+       struct notifier_block __rcu *head;
 };
 
 #define ATOMIC_INIT_NOTIFIER_HEAD(name) do {   \
diff --git a/include/linux/opp.h b/include/linux/opp.h
new file mode 100644 (file)
index 0000000..5449945
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *     Nishanth Menon
+ *     Romit Dasgupta
+ *     Kevin Hilman
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+struct opp;
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long opp_get_voltage(struct opp *opp);
+
+unsigned long opp_get_freq(struct opp *opp);
+
+int opp_get_opp_count(struct device *dev);
+
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+                               bool available);
+
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
+
+int opp_enable(struct device *dev, unsigned long freq);
+
+int opp_disable(struct device *dev, unsigned long freq);
+
+#else
+static inline unsigned long opp_get_voltage(struct opp *opp)
+{
+       return 0;
+}
+
+static inline unsigned long opp_get_freq(struct opp *opp)
+{
+       return 0;
+}
+
+static inline int opp_get_opp_count(struct device *dev)
+{
+       return 0;
+}
+
+static inline struct opp *opp_find_freq_exact(struct device *dev,
+                                       unsigned long freq, bool available)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_floor(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_ceil(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline int opp_add(struct device *dev, unsigned long freq,
+                                       unsigned long u_volt)
+{
+       return -EINVAL;
+}
+
+static inline int opp_enable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+
+static inline int opp_disable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+#endif         /* CONFIG_PM */
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table);
+#else
+static inline int opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table)
+{
+       return -EINVAL;
+}
+#endif         /* CONFIG_CPU_FREQ */
+
+#endif         /* __LINUX_OPP_H__ */
index 5171639ecf0ff070e74d884deb8c969e3b88132d..32fb81212fd153c0a71ba347ead6429d0a8dcd06 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/atomic.h>
  
 /* Each escaped entry is prefixed by ESCAPE_CODE
@@ -185,4 +186,10 @@ int oprofile_add_data(struct op_entry *entry, unsigned long val);
 int oprofile_add_data64(struct op_entry *entry, u64 val);
 int oprofile_write_commit(struct op_entry *entry);
 
+#ifdef CONFIG_PERF_EVENTS
+int __init oprofile_perf_init(struct oprofile_operations *ops);
+void oprofile_perf_exit(void);
+char *op_name_from_perf_id(void);
+#endif /* CONFIG_PERF_EVENTS */
+
 #endif /* OPROFILE_H */
index b1d17956a1536ff9f1e913cc6f33410f2e54cfa8..c8d95e369ff441fe54760192ce4a0d9922f0508a 100644 (file)
@@ -1214,6 +1214,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
                                                unsigned int devfn)
 { return NULL; }
 
+static inline int pci_domain_nr(struct pci_bus *bus)
+{ return 0; }
+
 #define dev_is_pci(d) (false)
 #define dev_is_pf(d) (false)
 #define dev_num_vf(d) (0)
index f6a3b2d36cadde8e1a6684d1c9fdc408eebef9b2..dad30734432ac3a0a0ee4523d443c9e29880bc4c 100644 (file)
 #define PCI_DEVICE_ID_VLSI_82C147      0x0105
 #define PCI_DEVICE_ID_VLSI_VAS96011    0x0702
 
+/* AMD RD890 Chipset */
+#define PCI_DEVICE_ID_RD890_IOMMU      0x5a23
+
 #define PCI_VENDOR_ID_ADL              0x1005
 #define PCI_DEVICE_ID_ADL_2301         0x2301
 
 #define PCI_DEVICE_ID_AMD_11H_NB_DRAM  0x1302
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
+#define PCI_DEVICE_ID_AMD_15H_NB_MISC  0x1603
 #define PCI_DEVICE_ID_AMD_LANCE                0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME   0x2001
 #define PCI_DEVICE_ID_AMD_SCSI         0x2020
 #define PCI_DEVICE_ID_P2010            0x0079
 #define PCI_DEVICE_ID_P1020E           0x0100
 #define PCI_DEVICE_ID_P1020            0x0101
+#define PCI_DEVICE_ID_P1021E           0x0102
+#define PCI_DEVICE_ID_P1021            0x0103
 #define PCI_DEVICE_ID_P1011E           0x0108
 #define PCI_DEVICE_ID_P1011            0x0109
 #define PCI_DEVICE_ID_P1022E           0x0110
 #define PCI_DEVICE_ID_P4080            0x0401
 #define PCI_DEVICE_ID_P4040E           0x0408
 #define PCI_DEVICE_ID_P4040            0x0409
+#define PCI_DEVICE_ID_P2040E           0x0410
+#define PCI_DEVICE_ID_P2040            0x0411
+#define PCI_DEVICE_ID_P3041E           0x041E
+#define PCI_DEVICE_ID_P3041            0x041F
+#define PCI_DEVICE_ID_P5020E           0x0420
+#define PCI_DEVICE_ID_P5020            0x0421
+#define PCI_DEVICE_ID_P5010E           0x0428
+#define PCI_DEVICE_ID_P5010            0x0429
 #define PCI_DEVICE_ID_MPC8641          0x7010
 #define PCI_DEVICE_ID_MPC8641D         0x7011
 #define PCI_DEVICE_ID_MPC8610          0x7018
index ce2dc655cd1d40a6765acc2dd3f49e104bca4f5c..018db9a62ffe7b08ea64a967ab0b0a0a5caedf44 100644 (file)
        DEFINE_PER_CPU_SECTION(type, name, "..page_aligned")            \
        __aligned(PAGE_SIZE)
 
+/*
+ * Declaration/definition used for per-CPU variables that must be read mostly.
+ */
+#define DECLARE_PER_CPU_READ_MOSTLY(type, name)                        \
+       DECLARE_PER_CPU_SECTION(type, name, "..readmostly")
+
+#define DEFINE_PER_CPU_READ_MOSTLY(type, name)                         \
+       DEFINE_PER_CPU_SECTION(type, name, "..readmostly")
+
+/*
+ * Declaration/definition used for large per-CPU variables that must be
+ * aligned to something larger than the pagesize.
+ */
+#define DECLARE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)            \
+       DECLARE_PER_CPU_SECTION(type, name, "..page_aligned")           \
+       __aligned(size)
+
+#define DEFINE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)             \
+       DEFINE_PER_CPU_SECTION(type, name, "..page_aligned")            \
+       __aligned(size)
+
 /*
  * Intermodule exports for per-CPU variables.  sparse forgets about
  * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
index b8b9084527b18029f602c02fe9db5d7c5754364b..0eb50832aa00fd1bbc31cc23837abfc698412402 100644 (file)
        preempt_enable();                               \
 } while (0)
 
+#define get_cpu_ptr(var) ({                            \
+       preempt_disable();                              \
+       this_cpu_ptr(var); })
+
+#define put_cpu_ptr(var) do {                          \
+       (void)(var);                                    \
+       preempt_enable();                               \
+} while (0)
+
 #ifdef CONFIG_SMP
 
 /* minimum unit size, also is the maximum supported allocation size */
@@ -149,7 +158,7 @@ extern void __init percpu_init_late(void);
 
 #else /* CONFIG_SMP */
 
-#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
+#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); })
 
 /* can't distinguish from other static vars, always false */
 static inline bool is_kernel_percpu_address(unsigned long addr)
index 716f99b682c1a57fb3b6f1f72e90aec3982ca5fd..057bf22a8323463a6bd9279d6928d3fea7ed8eb8 100644 (file)
@@ -486,6 +486,8 @@ struct perf_guest_info_callbacks {
 #include <linux/workqueue.h>
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
+#include <linux/irq_work.h>
+#include <linux/jump_label_ref.h>
 #include <asm/atomic.h>
 #include <asm/local.h>
 
@@ -529,16 +531,22 @@ struct hw_perf_event {
                        int             last_cpu;
                };
                struct { /* software */
-                       s64             remaining;
                        struct hrtimer  hrtimer;
                };
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
                struct { /* breakpoint */
                        struct arch_hw_breakpoint       info;
                        struct list_head                bp_list;
+                       /*
+                        * Crufty hack to avoid the chicken and egg
+                        * problem hw_breakpoint has with context
+                        * creation and event initalization.
+                        */
+                       struct task_struct              *bp_target;
                };
 #endif
        };
+       int                             state;
        local64_t                       prev_count;
        u64                             sample_period;
        u64                             last_period;
@@ -550,6 +558,13 @@ struct hw_perf_event {
 #endif
 };
 
+/*
+ * hw_perf_event::state flags
+ */
+#define PERF_HES_STOPPED       0x01 /* the counter is stopped */
+#define PERF_HES_UPTODATE      0x02 /* event->count up-to-date */
+#define PERF_HES_ARCH          0x04
+
 struct perf_event;
 
 /*
@@ -561,36 +576,70 @@ struct perf_event;
  * struct pmu - generic performance monitoring unit
  */
 struct pmu {
-       int (*enable)                   (struct perf_event *event);
-       void (*disable)                 (struct perf_event *event);
-       int (*start)                    (struct perf_event *event);
-       void (*stop)                    (struct perf_event *event);
-       void (*read)                    (struct perf_event *event);
-       void (*unthrottle)              (struct perf_event *event);
+       struct list_head                entry;
+
+       int * __percpu                  pmu_disable_count;
+       struct perf_cpu_context * __percpu pmu_cpu_context;
+       int                             task_ctx_nr;
+
+       /*
+        * Fully disable/enable this PMU, can be used to protect from the PMI
+        * as well as for lazy/batch writing of the MSRs.
+        */
+       void (*pmu_enable)              (struct pmu *pmu); /* optional */
+       void (*pmu_disable)             (struct pmu *pmu); /* optional */
 
        /*
-        * Group events scheduling is treated as a transaction, add group
-        * events as a whole and perform one schedulability test. If the test
-        * fails, roll back the whole group
+        * Try and initialize the event for this PMU.
+        * Should return -ENOENT when the @event doesn't match this PMU.
         */
+       int (*event_init)               (struct perf_event *event);
+
+#define PERF_EF_START  0x01            /* start the counter when adding    */
+#define PERF_EF_RELOAD 0x02            /* reload the counter when starting */
+#define PERF_EF_UPDATE 0x04            /* update the counter when stopping */
 
        /*
-        * Start the transaction, after this ->enable() doesn't need
-        * to do schedulability tests.
+        * Adds/Removes a counter to/from the PMU, can be done inside
+        * a transaction, see the ->*_txn() methods.
         */
-       void (*start_txn)       (const struct pmu *pmu);
+       int  (*add)                     (struct perf_event *event, int flags);
+       void (*del)                     (struct perf_event *event, int flags);
+
        /*
-        * If ->start_txn() disabled the ->enable() schedulability test
+        * Starts/Stops a counter present on the PMU. The PMI handler
+        * should stop the counter when perf_event_overflow() returns
+        * !0. ->start() will be used to continue.
+        */
+       void (*start)                   (struct perf_event *event, int flags);
+       void (*stop)                    (struct perf_event *event, int flags);
+
+       /*
+        * Updates the counter value of the event.
+        */
+       void (*read)                    (struct perf_event *event);
+
+       /*
+        * Group events scheduling is treated as a transaction, add
+        * group events as a whole and perform one schedulability test.
+        * If the test fails, roll back the whole group
+        *
+        * Start the transaction, after this ->add() doesn't need to
+        * do schedulability tests.
+        */
+       void (*start_txn)       (struct pmu *pmu); /* optional */
+       /*
+        * If ->start_txn() disabled the ->add() schedulability test
         * then ->commit_txn() is required to perform one. On success
         * the transaction is closed. On error the transaction is kept
         * open until ->cancel_txn() is called.
         */
-       int  (*commit_txn)      (const struct pmu *pmu);
+       int  (*commit_txn)      (struct pmu *pmu); /* optional */
        /*
-        * Will cancel the transaction, assumes ->disable() is called for
-        * each successfull ->enable() during the transaction.
+        * Will cancel the transaction, assumes ->del() is called
+        * for each successfull ->add() during the transaction.
         */
-       void (*cancel_txn)      (const struct pmu *pmu);
+       void (*cancel_txn)      (struct pmu *pmu); /* optional */
 };
 
 /**
@@ -631,11 +680,6 @@ struct perf_buffer {
        void                            *data_pages[0];
 };
 
-struct perf_pending_entry {
-       struct perf_pending_entry *next;
-       void (*func)(struct perf_pending_entry *);
-};
-
 struct perf_sample_data;
 
 typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
@@ -656,6 +700,7 @@ struct swevent_hlist {
 
 #define PERF_ATTACH_CONTEXT    0x01
 #define PERF_ATTACH_GROUP      0x02
+#define PERF_ATTACH_TASK       0x04
 
 /**
  * struct perf_event - performance event kernel representation:
@@ -669,7 +714,7 @@ struct perf_event {
        int                             nr_siblings;
        int                             group_flags;
        struct perf_event               *group_leader;
-       const struct pmu                *pmu;
+       struct pmu                      *pmu;
 
        enum perf_event_active_state    state;
        unsigned int                    attach_state;
@@ -743,7 +788,7 @@ struct perf_event {
        int                             pending_wakeup;
        int                             pending_kill;
        int                             pending_disable;
-       struct perf_pending_entry       pending;
+       struct irq_work                 pending;
 
        atomic_t                        event_limit;
 
@@ -763,12 +808,19 @@ struct perf_event {
 #endif /* CONFIG_PERF_EVENTS */
 };
 
+enum perf_event_context_type {
+       task_context,
+       cpu_context,
+};
+
 /**
  * struct perf_event_context - event context structure
  *
  * Used as a container for task events and CPU events as well:
  */
 struct perf_event_context {
+       enum perf_event_context_type    type;
+       struct pmu                      *pmu;
        /*
         * Protect the states of the events in the list,
         * nr_active, and the list:
@@ -808,6 +860,12 @@ struct perf_event_context {
        struct rcu_head                 rcu_head;
 };
 
+/*
+ * Number of contexts where an event can trigger:
+ *     task, softirq, hardirq, nmi.
+ */
+#define PERF_NR_CONTEXTS       4
+
 /**
  * struct perf_event_cpu_context - per cpu event context structure
  */
@@ -815,18 +873,9 @@ struct perf_cpu_context {
        struct perf_event_context       ctx;
        struct perf_event_context       *task_ctx;
        int                             active_oncpu;
-       int                             max_pertask;
        int                             exclusive;
-       struct swevent_hlist            *swevent_hlist;
-       struct mutex                    hlist_mutex;
-       int                             hlist_refcount;
-
-       /*
-        * Recursion avoidance:
-        *
-        * task, softirq, irq, nmi context
-        */
-       int                             recursion[4];
+       struct list_head                rotation_list;
+       int                             jiffies_interval;
 };
 
 struct perf_output_handle {
@@ -842,26 +891,34 @@ struct perf_output_handle {
 
 #ifdef CONFIG_PERF_EVENTS
 
-/*
- * Set by architecture code:
- */
-extern int perf_max_events;
+extern int perf_pmu_register(struct pmu *pmu);
+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 const struct pmu *hw_perf_event_init(struct perf_event *event);
+extern atomic_t perf_task_events;
+
+static inline void perf_event_task_sched_in(struct task_struct *task)
+{
+       COND_STMT(&perf_task_events, __perf_event_task_sched_in(task));
+}
+
+static inline
+void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
+{
+       COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
+}
 
-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_tick(struct task_struct *task);
 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);
-extern void set_perf_event_pending(void);
-extern void perf_event_do_pending(void);
+extern void perf_event_delayed_put(struct task_struct *task);
 extern void perf_event_print_debug(void);
-extern void __perf_disable(void);
-extern bool __perf_enable(void);
-extern void perf_disable(void);
-extern void perf_enable(void);
+extern void perf_pmu_disable(struct pmu *pmu);
+extern void perf_pmu_enable(struct pmu *pmu);
 extern int perf_event_task_disable(void);
 extern int perf_event_task_enable(void);
 extern void perf_event_update_userpage(struct perf_event *event);
@@ -869,7 +926,7 @@ extern int perf_event_release_kernel(struct perf_event *event);
 extern struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr,
                                int cpu,
-                               pid_t pid,
+                               struct task_struct *task,
                                perf_overflow_handler_t callback);
 extern u64 perf_event_read_value(struct perf_event *event,
                                 u64 *enabled, u64 *running);
@@ -920,14 +977,7 @@ extern int perf_event_overflow(struct perf_event *event, int nmi,
  */
 static inline int is_software_event(struct perf_event *event)
 {
-       switch (event->attr.type) {
-       case PERF_TYPE_SOFTWARE:
-       case PERF_TYPE_TRACEPOINT:
-       /* for now the breakpoint stuff also works as software event */
-       case PERF_TYPE_BREAKPOINT:
-               return 1;
-       }
-       return 0;
+       return event->pmu->task_ctx_nr == perf_sw_context;
 }
 
 extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
@@ -954,18 +1004,20 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs)
        perf_arch_fetch_caller_regs(regs, CALLER_ADDR0);
 }
 
-static inline void
+static __always_inline void
 perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
 {
-       if (atomic_read(&perf_swevent_enabled[event_id])) {
-               struct pt_regs hot_regs;
-
-               if (!regs) {
-                       perf_fetch_caller_regs(&hot_regs);
-                       regs = &hot_regs;
-               }
-               __perf_sw_event(event_id, nr, nmi, regs, addr);
+       struct pt_regs hot_regs;
+
+       JUMP_LABEL(&perf_swevent_enabled[event_id], have_event);
+       return;
+
+have_event:
+       if (!regs) {
+               perf_fetch_caller_regs(&hot_regs);
+               regs = &hot_regs;
        }
+       __perf_sw_event(event_id, nr, nmi, regs, addr);
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
@@ -976,7 +1028,21 @@ extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks
 extern void perf_event_comm(struct task_struct *tsk);
 extern void perf_event_fork(struct task_struct *tsk);
 
-extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs);
+/* Callchains */
+DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry);
+
+extern void perf_callchain_user(struct perf_callchain_entry *entry,
+                               struct pt_regs *regs);
+extern void perf_callchain_kernel(struct perf_callchain_entry *entry,
+                                 struct pt_regs *regs);
+
+
+static inline void
+perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)
+{
+       if (entry->nr < PERF_MAX_STACK_DEPTH)
+               entry->ip[entry->nr++] = ip;
+}
 
 extern int sysctl_perf_event_paranoid;
 extern int sysctl_perf_event_mlock;
@@ -1019,21 +1085,18 @@ extern int perf_swevent_get_recursion_context(void);
 extern void perf_swevent_put_recursion_context(int rctx);
 extern void perf_event_enable(struct perf_event *event);
 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)                     { }
 static inline void
 perf_event_task_sched_out(struct task_struct *task,
                            struct task_struct *next)                   { }
-static inline void
-perf_event_task_tick(struct task_struct *task)                         { }
 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)      { }
-static inline void perf_event_do_pending(void)                         { }
+static inline void perf_event_delayed_put(struct task_struct *task)    { }
 static inline void perf_event_print_debug(void)                                { }
-static inline void perf_disable(void)                                  { }
-static inline void perf_enable(void)                                   { }
 static inline int perf_event_task_disable(void)                                { return -EINVAL; }
 static inline int perf_event_task_enable(void)                         { return -EINVAL; }
 
@@ -1056,6 +1119,7 @@ static inline int  perf_swevent_get_recursion_context(void)               { return -1; }
 static inline void perf_swevent_put_recursion_context(int rctx)                { }
 static inline void perf_event_enable(struct perf_event *event)         { }
 static inline void perf_event_disable(struct perf_event *event)                { }
+static inline void perf_event_task_tick(void)                          { }
 #endif
 
 #define perf_output_put(handle, x) \
index 24426c3d6b5ab34a463cf3ee650b497d9e545522..76edadf046d3d3b68215c23ef2a30ce18a86992a 100644 (file)
@@ -56,7 +56,7 @@ struct phonethdr {
        __be16  pn_length;
        __u8    pn_robj;
        __u8    pn_sobj;
-} __packed;
+} __attribute__((packed));
 
 /* Common Phonet payload header */
 struct phonetmsg {
@@ -98,7 +98,7 @@ struct sockaddr_pn {
        __u8 spn_dev;
        __u8 spn_resource;
        __u8 spn_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - 3];
-} __packed;
+} __attribute__((packed));
 
 /* Well known address */
 #define PN_DEV_PC      0x10
index 52e8c55ff314ce9ffa92b14b11ff5603a4e77eb6..40f3f45702bac82a8e454812b67a4419b7d36362 100644 (file)
@@ -41,6 +41,12 @@ extern void (*pm_power_off_prepare)(void);
 
 struct device;
 
+#ifdef CONFIG_PM
+extern const char power_group_name[];          /* = "power" */
+#else
+#define power_group_name       NULL
+#endif
+
 typedef struct pm_message {
        int event;
 } pm_message_t;
@@ -438,6 +444,9 @@ enum rpm_status {
  *
  * RPM_REQ_SUSPEND     Run the device bus type's ->runtime_suspend() callback
  *
+ * RPM_REQ_AUTOSUSPEND Same as RPM_REQ_SUSPEND, but not until the device has
+ *                     been inactive for as long as power.autosuspend_delay
+ *
  * RPM_REQ_RESUME      Run the device bus type's ->runtime_resume() callback
  */
 
@@ -445,26 +454,28 @@ enum rpm_request {
        RPM_REQ_NONE = 0,
        RPM_REQ_IDLE,
        RPM_REQ_SUSPEND,
+       RPM_REQ_AUTOSUSPEND,
        RPM_REQ_RESUME,
 };
 
+struct wakeup_source;
+
 struct dev_pm_info {
        pm_message_t            power_state;
        unsigned int            can_wakeup:1;
-       unsigned int            should_wakeup:1;
        unsigned                async_suspend:1;
        enum dpm_state          status;         /* Owned by the PM core */
+       spinlock_t              lock;
 #ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
        struct completion       completion;
-       unsigned long           wakeup_count;
+       struct wakeup_source    *wakeup;
 #endif
 #ifdef CONFIG_PM_RUNTIME
        struct timer_list       suspend_timer;
        unsigned long           timer_expires;
        struct work_struct      work;
        wait_queue_head_t       wait_queue;
-       spinlock_t              lock;
        atomic_t                usage_count;
        atomic_t                child_count;
        unsigned int            disable_depth:3;
@@ -474,9 +485,14 @@ struct dev_pm_info {
        unsigned int            deferred_resume:1;
        unsigned int            run_wake:1;
        unsigned int            runtime_auto:1;
+       unsigned int            no_callbacks:1;
+       unsigned int            use_autosuspend:1;
+       unsigned int            timer_autosuspends:1;
        enum rpm_request        request;
        enum rpm_status         runtime_status;
        int                     runtime_error;
+       int                     autosuspend_delay;
+       unsigned long           last_busy;
        unsigned long           active_jiffies;
        unsigned long           suspended_jiffies;
        unsigned long           accounting_timestamp;
@@ -558,12 +574,7 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
                __suspend_report_result(__func__, fn, ret);             \
        } while (0)
 
-extern void device_pm_wait_for_dev(struct device *sub, struct device *dev);
-
-/* drivers/base/power/wakeup.c */
-extern void pm_wakeup_event(struct device *dev, unsigned int msec);
-extern void pm_stay_awake(struct device *dev);
-extern void pm_relax(void);
+extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
 #else /* !CONFIG_PM_SLEEP */
 
 #define device_pm_lock() do {} while (0)
@@ -576,11 +587,10 @@ static inline int dpm_suspend_start(pm_message_t state)
 
 #define suspend_report_result(fn, ret)         do {} while (0)
 
-static inline void device_pm_wait_for_dev(struct device *a, struct device *b) {}
-
-static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
-static inline void pm_stay_awake(struct device *dev) {}
-static inline void pm_relax(void) {}
+static inline int device_pm_wait_for_dev(struct device *a, struct device *b)
+{
+       return 0;
+}
 #endif /* !CONFIG_PM_SLEEP */
 
 /* How to reorder dpm_list after device_move() */
index 6e81888c62225f99217ab356dd0f3c46a3a45715..3ec2358f8692d11027e6af927402fcbc0f039da2 100644 (file)
 #include <linux/device.h>
 #include <linux/pm.h>
 
+#include <linux/jiffies.h>
+
+/* Runtime PM flag argument bits */
+#define RPM_ASYNC              0x01    /* Request is asynchronous */
+#define RPM_NOWAIT             0x02    /* Don't wait for concurrent
+                                           state change */
+#define RPM_GET_PUT            0x04    /* Increment/decrement the
+                                           usage_count */
+#define RPM_AUTO               0x08    /* Use autosuspend_delay */
+
 #ifdef CONFIG_PM_RUNTIME
 
 extern struct workqueue_struct *pm_wq;
 
-extern int pm_runtime_idle(struct device *dev);
-extern int pm_runtime_suspend(struct device *dev);
-extern int pm_runtime_resume(struct device *dev);
-extern int pm_request_idle(struct device *dev);
+extern int __pm_runtime_idle(struct device *dev, int rpmflags);
+extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
+extern int __pm_runtime_resume(struct device *dev, int rpmflags);
 extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
-extern int pm_request_resume(struct device *dev);
-extern int __pm_runtime_get(struct device *dev, bool sync);
-extern int __pm_runtime_put(struct device *dev, bool sync);
 extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
 extern int pm_runtime_barrier(struct device *dev);
 extern void pm_runtime_enable(struct device *dev);
@@ -33,6 +39,10 @@ extern void pm_runtime_forbid(struct device *dev);
 extern int pm_generic_runtime_idle(struct device *dev);
 extern int pm_generic_runtime_suspend(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
+extern void pm_runtime_no_callbacks(struct device *dev);
+extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
+extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
 
 static inline bool pm_children_suspended(struct device *dev)
 {
@@ -70,19 +80,29 @@ static inline bool pm_runtime_suspended(struct device *dev)
        return dev->power.runtime_status == RPM_SUSPENDED;
 }
 
+static inline void pm_runtime_mark_last_busy(struct device *dev)
+{
+       ACCESS_ONCE(dev->power.last_busy) = jiffies;
+}
+
 #else /* !CONFIG_PM_RUNTIME */
 
-static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
-static inline int pm_runtime_suspend(struct device *dev) { return -ENOSYS; }
-static inline int pm_runtime_resume(struct device *dev) { return 0; }
-static inline int pm_request_idle(struct device *dev) { return -ENOSYS; }
+static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
+{
+       return -ENOSYS;
+}
+static inline int __pm_runtime_suspend(struct device *dev, int rpmflags)
+{
+       return -ENOSYS;
+}
+static inline int __pm_runtime_resume(struct device *dev, int rpmflags)
+{
+       return 1;
+}
 static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        return -ENOSYS;
 }
-static inline int pm_request_resume(struct device *dev) { return 0; }
-static inline int __pm_runtime_get(struct device *dev, bool sync) { return 1; }
-static inline int __pm_runtime_put(struct device *dev, bool sync) { return 0; }
 static inline int __pm_runtime_set_status(struct device *dev,
                                            unsigned int status) { return 0; }
 static inline int pm_runtime_barrier(struct device *dev) { return 0; }
@@ -102,27 +122,82 @@ static inline bool pm_runtime_suspended(struct device *dev) { return false; }
 static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
 static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
 static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+static inline void pm_runtime_no_callbacks(struct device *dev) {}
+
+static inline void pm_runtime_mark_last_busy(struct device *dev) {}
+static inline void __pm_runtime_use_autosuspend(struct device *dev,
+                                               bool use) {}
+static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
+                                               int delay) {}
+static inline unsigned long pm_runtime_autosuspend_expiration(
+                               struct device *dev) { return 0; }
 
 #endif /* !CONFIG_PM_RUNTIME */
 
+static inline int pm_runtime_idle(struct device *dev)
+{
+       return __pm_runtime_idle(dev, 0);
+}
+
+static inline int pm_runtime_suspend(struct device *dev)
+{
+       return __pm_runtime_suspend(dev, 0);
+}
+
+static inline int pm_runtime_autosuspend(struct device *dev)
+{
+       return __pm_runtime_suspend(dev, RPM_AUTO);
+}
+
+static inline int pm_runtime_resume(struct device *dev)
+{
+       return __pm_runtime_resume(dev, 0);
+}
+
+static inline int pm_request_idle(struct device *dev)
+{
+       return __pm_runtime_idle(dev, RPM_ASYNC);
+}
+
+static inline int pm_request_resume(struct device *dev)
+{
+       return __pm_runtime_resume(dev, RPM_ASYNC);
+}
+
+static inline int pm_request_autosuspend(struct device *dev)
+{
+       return __pm_runtime_suspend(dev, RPM_ASYNC | RPM_AUTO);
+}
+
 static inline int pm_runtime_get(struct device *dev)
 {
-       return __pm_runtime_get(dev, false);
+       return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC);
 }
 
 static inline int pm_runtime_get_sync(struct device *dev)
 {
-       return __pm_runtime_get(dev, true);
+       return __pm_runtime_resume(dev, RPM_GET_PUT);
 }
 
 static inline int pm_runtime_put(struct device *dev)
 {
-       return __pm_runtime_put(dev, false);
+       return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
+}
+
+static inline int pm_runtime_put_autosuspend(struct device *dev)
+{
+       return __pm_runtime_suspend(dev,
+           RPM_GET_PUT | RPM_ASYNC | RPM_AUTO);
 }
 
 static inline int pm_runtime_put_sync(struct device *dev)
 {
-       return __pm_runtime_put(dev, true);
+       return __pm_runtime_idle(dev, RPM_GET_PUT);
+}
+
+static inline int pm_runtime_put_sync_autosuspend(struct device *dev)
+{
+       return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO);
 }
 
 static inline int pm_runtime_set_active(struct device *dev)
@@ -140,4 +215,14 @@ static inline void pm_runtime_disable(struct device *dev)
        __pm_runtime_disable(dev, true);
 }
 
+static inline void pm_runtime_use_autosuspend(struct device *dev)
+{
+       __pm_runtime_use_autosuspend(dev, true);
+}
+
+static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
+{
+       __pm_runtime_use_autosuspend(dev, false);
+}
+
 #endif
index 76aca48722aeb116556b36d478e1e114834c8446..9cff00dd6b63a031d02e59b797fcf2c5fe94f082 100644 (file)
@@ -2,6 +2,7 @@
  *  pm_wakeup.h - Power management wakeup interface
  *
  *  Copyright (C) 2008 Alan Stern
+ *  Copyright (C) 2010 Rafael J. Wysocki, Novell Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 
 #include <linux/types.h>
 
-#ifdef CONFIG_PM
-
-/* Changes to device_may_wakeup take effect on the next pm state change.
+/**
+ * struct wakeup_source - Representation of wakeup sources
  *
- * By default, most devices should leave wakeup disabled.  The exceptions
- * are devices that everyone expects to be wakeup sources: keyboards,
- * power buttons, possibly network interfaces, etc.
+ * @total_time: Total time this wakeup source has been active.
+ * @max_time: Maximum time this wakeup source has been continuously active.
+ * @last_time: Monotonic clock when the wakeup source's was activated last time.
+ * @event_count: Number of signaled wakeup events.
+ * @active_count: Number of times the wakeup sorce was activated.
+ * @relax_count: Number of times the wakeup sorce was deactivated.
+ * @hit_count: Number of times the wakeup sorce might abort system suspend.
+ * @active: Status of the wakeup source.
  */
-static inline void device_init_wakeup(struct device *dev, bool val)
+struct wakeup_source {
+       char                    *name;
+       struct list_head        entry;
+       spinlock_t              lock;
+       struct timer_list       timer;
+       unsigned long           timer_expires;
+       ktime_t total_time;
+       ktime_t max_time;
+       ktime_t last_time;
+       unsigned long           event_count;
+       unsigned long           active_count;
+       unsigned long           relax_count;
+       unsigned long           hit_count;
+       unsigned int            active:1;
+};
+
+#ifdef CONFIG_PM_SLEEP
+
+/*
+ * Changes to device_may_wakeup take effect on the next pm state change.
+ */
+
+static inline void device_set_wakeup_capable(struct device *dev, bool capable)
+{
+       dev->power.can_wakeup = capable;
+}
+
+static inline bool device_can_wakeup(struct device *dev)
+{
+       return dev->power.can_wakeup;
+}
+
+
+
+static inline bool device_may_wakeup(struct device *dev)
 {
-       dev->power.can_wakeup = dev->power.should_wakeup = val;
+       return dev->power.can_wakeup && !!dev->power.wakeup;
 }
 
+/* drivers/base/power/wakeup.c */
+extern struct wakeup_source *wakeup_source_create(const char *name);
+extern void wakeup_source_destroy(struct wakeup_source *ws);
+extern void wakeup_source_add(struct wakeup_source *ws);
+extern void wakeup_source_remove(struct wakeup_source *ws);
+extern struct wakeup_source *wakeup_source_register(const char *name);
+extern void wakeup_source_unregister(struct wakeup_source *ws);
+extern int device_wakeup_enable(struct device *dev);
+extern int device_wakeup_disable(struct device *dev);
+extern int device_init_wakeup(struct device *dev, bool val);
+extern int device_set_wakeup_enable(struct device *dev, bool enable);
+extern void __pm_stay_awake(struct wakeup_source *ws);
+extern void pm_stay_awake(struct device *dev);
+extern void __pm_relax(struct wakeup_source *ws);
+extern void pm_relax(struct device *dev);
+extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);
+extern void pm_wakeup_event(struct device *dev, unsigned int msec);
+
+#else /* !CONFIG_PM_SLEEP */
+
 static inline void device_set_wakeup_capable(struct device *dev, bool capable)
 {
        dev->power.can_wakeup = capable;
@@ -50,43 +109,63 @@ static inline bool device_can_wakeup(struct device *dev)
        return dev->power.can_wakeup;
 }
 
-static inline void device_set_wakeup_enable(struct device *dev, bool enable)
+static inline bool device_may_wakeup(struct device *dev)
 {
-       dev->power.should_wakeup = enable;
+       return false;
 }
 
-static inline bool device_may_wakeup(struct device *dev)
+static inline struct wakeup_source *wakeup_source_create(const char *name)
 {
-       return dev->power.can_wakeup && dev->power.should_wakeup;
+       return NULL;
 }
 
-#else /* !CONFIG_PM */
+static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
+
+static inline void wakeup_source_add(struct wakeup_source *ws) {}
 
-/* For some reason the following routines work even without CONFIG_PM */
-static inline void device_init_wakeup(struct device *dev, bool val)
+static inline void wakeup_source_remove(struct wakeup_source *ws) {}
+
+static inline struct wakeup_source *wakeup_source_register(const char *name)
 {
-       dev->power.can_wakeup = val;
+       return NULL;
 }
 
-static inline void device_set_wakeup_capable(struct device *dev, bool capable)
+static inline void wakeup_source_unregister(struct wakeup_source *ws) {}
+
+static inline int device_wakeup_enable(struct device *dev)
 {
-       dev->power.can_wakeup = capable;
+       return -EINVAL;
 }
 
-static inline bool device_can_wakeup(struct device *dev)
+static inline int device_wakeup_disable(struct device *dev)
 {
-       return dev->power.can_wakeup;
+       return 0;
 }
 
-static inline void device_set_wakeup_enable(struct device *dev, bool enable)
+static inline int device_init_wakeup(struct device *dev, bool val)
 {
+       dev->power.can_wakeup = val;
+       return val ? -EINVAL : 0;
 }
 
-static inline bool device_may_wakeup(struct device *dev)
+
+static inline int device_set_wakeup_enable(struct device *dev, bool enable)
 {
-       return false;
+       return -EINVAL;
 }
 
-#endif /* !CONFIG_PM */
+static inline void __pm_stay_awake(struct wakeup_source *ws) {}
+
+static inline void pm_stay_awake(struct device *dev) {}
+
+static inline void __pm_relax(struct wakeup_source *ws) {}
+
+static inline void pm_relax(struct device *dev) {}
+
+static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {}
+
+static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
+
+#endif /* !CONFIG_PM_SLEEP */
 
 #endif /* _LINUX_PM_WAKEUP_H */
diff --git a/include/linux/pxa168_eth.h b/include/linux/pxa168_eth.h
new file mode 100644 (file)
index 0000000..18d75e7
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *pxa168 ethernet platform device data definition file.
+ */
+#ifndef __LINUX_PXA168_ETH_H
+#define __LINUX_PXA168_ETH_H
+
+struct pxa168_eth_platform_data {
+       int     port_number;
+       int     phy_addr;
+
+       /*
+        * If speed is 0, then speed and duplex are autonegotiated.
+        */
+       int     speed;          /* 0, SPEED_10, SPEED_100 */
+       int     duplex;         /* DUPLEX_HALF or DUPLEX_FULL */
+
+       /*
+        * Override default RX/TX queue sizes if nonzero.
+        */
+       int     rx_queue_size;
+       int     tx_queue_size;
+
+       /*
+        * init callback is used for board specific initialization
+        * e.g on Aspenite its used to initialize the PHY transceiver.
+        */
+       int (*init)(void);
+};
+
+#endif /* __LINUX_PXA168_ETH_H */
index d50ba858cfe0c15325ff5fcf410d7a18f1a8aad3..d1a9193960f17601d4637bfae03f3c9a3ac5bc83 100644 (file)
@@ -274,8 +274,14 @@ static inline int dquot_alloc_space(struct inode *inode, qsize_t nr)
        int ret;
 
        ret = dquot_alloc_space_nodirty(inode, nr);
-       if (!ret)
-               mark_inode_dirty_sync(inode);
+       if (!ret) {
+               /*
+                * Mark inode fully dirty. Since we are allocating blocks, inode
+                * would become fully dirty soon anyway and it reportedly
+                * reduces inode_lock contention.
+                */
+               mark_inode_dirty(inode);
+       }
        return ret;
 }
 
index 634b8e674ac578e2916b110a28b992bf2e8dfd22..a39cbed9ee17a5d771f7c3e7ca129e3a05171220 100644 (file)
@@ -47,6 +47,8 @@ static inline void *radix_tree_indirect_to_ptr(void *ptr)
 {
        return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
 }
+#define radix_tree_indirect_to_ptr(ptr) \
+       radix_tree_indirect_to_ptr((void __force *)(ptr))
 
 static inline int radix_tree_is_indirect_ptr(void *ptr)
 {
@@ -61,7 +63,7 @@ static inline int radix_tree_is_indirect_ptr(void *ptr)
 struct radix_tree_root {
        unsigned int            height;
        gfp_t                   gfp_mask;
-       struct radix_tree_node  *rnode;
+       struct radix_tree_node  __rcu *rnode;
 };
 
 #define RADIX_TREE_INIT(mask)  {                                       \
index 4ec3b38ce9c584049229b71bbf537770d6fbe263..f31ef61f1c650b585bd6faf969f7cec754dffe2d 100644 (file)
@@ -9,6 +9,21 @@
 #include <linux/list.h>
 #include <linux/rcupdate.h>
 
+/*
+ * Why is there no list_empty_rcu()?  Because list_empty() serves this
+ * purpose.  The list_empty() function fetches the RCU-protected pointer
+ * and compares it to the address of the list head, but neither dereferences
+ * this pointer itself nor provides this pointer to the caller.  Therefore,
+ * it is not necessary to use rcu_dereference(), so that list_empty() can
+ * be used anywhere you would want to use a list_empty_rcu().
+ */
+
+/*
+ * return the ->next pointer of a list_head in an rcu safe
+ * way, we must not access it directly
+ */
+#define list_next_rcu(list)    (*((struct list_head __rcu **)(&(list)->next)))
+
 /*
  * Insert a new entry between two known consecutive entries.
  *
@@ -20,7 +35,7 @@ static inline void __list_add_rcu(struct list_head *new,
 {
        new->next = next;
        new->prev = prev;
-       rcu_assign_pointer(prev->next, new);
+       rcu_assign_pointer(list_next_rcu(prev), new);
        next->prev = new;
 }
 
@@ -138,7 +153,7 @@ static inline void list_replace_rcu(struct list_head *old,
 {
        new->next = old->next;
        new->prev = old->prev;
-       rcu_assign_pointer(new->prev->next, new);
+       rcu_assign_pointer(list_next_rcu(new->prev), new);
        new->next->prev = new;
        old->prev = LIST_POISON2;
 }
@@ -193,7 +208,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
         */
 
        last->next = at;
-       rcu_assign_pointer(head->next, first);
+       rcu_assign_pointer(list_next_rcu(head), first);
        first->prev = head;
        at->prev = last;
 }
@@ -208,7 +223,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_entry_rcu(ptr, type, member) \
-       container_of(rcu_dereference_raw(ptr), type, member)
+       ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
+        container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
+       })
 
 /**
  * list_first_entry_rcu - get the first element from a list
@@ -225,9 +242,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
        list_entry_rcu((ptr)->next, type, member)
 
 #define __list_for_each_rcu(pos, head) \
-       for (pos = rcu_dereference_raw((head)->next); \
+       for (pos = rcu_dereference_raw(list_next_rcu(head)); \
                pos != (head); \
-               pos = rcu_dereference_raw(pos->next))
+               pos = rcu_dereference_raw(list_next_rcu((pos)))
 
 /**
  * list_for_each_entry_rcu     -       iterate over rcu list of given type
@@ -257,9 +274,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * as long as the traversal is guarded by rcu_read_lock().
  */
 #define list_for_each_continue_rcu(pos, head) \
-       for ((pos) = rcu_dereference_raw((pos)->next); \
+       for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
                prefetch((pos)->next), (pos) != (head); \
-               (pos) = rcu_dereference_raw((pos)->next))
+               (pos) = rcu_dereference_raw(list_next_rcu(pos)))
 
 /**
  * list_for_each_entry_continue_rcu - continue iteration over list of given type
@@ -314,12 +331,19 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
 
        new->next = next;
        new->pprev = old->pprev;
-       rcu_assign_pointer(*new->pprev, new);
+       rcu_assign_pointer(*(struct hlist_node __rcu **)new->pprev, new);
        if (next)
                new->next->pprev = &new->next;
        old->pprev = LIST_POISON2;
 }
 
+/*
+ * return the first or the next element in an RCU protected hlist
+ */
+#define hlist_first_rcu(head)  (*((struct hlist_node __rcu **)(&(head)->first)))
+#define hlist_next_rcu(node)   (*((struct hlist_node __rcu **)(&(node)->next)))
+#define hlist_pprev_rcu(node)  (*((struct hlist_node __rcu **)((node)->pprev)))
+
 /**
  * hlist_add_head_rcu
  * @n: the element to add to the hash list.
@@ -346,7 +370,7 @@ static inline void hlist_add_head_rcu(struct hlist_node *n,
 
        n->next = first;
        n->pprev = &h->first;
-       rcu_assign_pointer(h->first, n);
+       rcu_assign_pointer(hlist_first_rcu(h), n);
        if (first)
                first->pprev = &n->next;
 }
@@ -374,7 +398,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n,
 {
        n->pprev = next->pprev;
        n->next = next;
-       rcu_assign_pointer(*(n->pprev), n);
+       rcu_assign_pointer(hlist_pprev_rcu(n), n);
        next->pprev = &n->next;
 }
 
@@ -401,15 +425,15 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
 {
        n->next = prev->next;
        n->pprev = &prev->next;
-       rcu_assign_pointer(prev->next, n);
+       rcu_assign_pointer(hlist_next_rcu(prev), n);
        if (n->next)
                n->next->pprev = &n->next;
 }
 
-#define __hlist_for_each_rcu(pos, head)                        \
-       for (pos = rcu_dereference((head)->first);      \
-            pos && ({ prefetch(pos->next); 1; });      \
-            pos = rcu_dereference(pos->next))
+#define __hlist_for_each_rcu(pos, head)                                \
+       for (pos = rcu_dereference(hlist_first_rcu(head));      \
+            pos && ({ prefetch(pos->next); 1; });              \
+            pos = rcu_dereference(hlist_next_rcu(pos)))
 
 /**
  * hlist_for_each_entry_rcu - iterate over rcu list of given type
@@ -422,11 +446,11 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
  * the _rcu list-mutation primitives such as hlist_add_head_rcu()
  * as long as the traversal is guarded by rcu_read_lock().
  */
-#define hlist_for_each_entry_rcu(tpos, pos, head, member)               \
-       for (pos = rcu_dereference_raw((head)->first);                   \
+#define hlist_for_each_entry_rcu(tpos, pos, head, member)              \
+       for (pos = rcu_dereference_raw(hlist_first_rcu(head));          \
                pos && ({ prefetch(pos->next); 1; }) &&                  \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-               pos = rcu_dereference_raw(pos->next))
+               pos = rcu_dereference_raw(hlist_next_rcu(pos)))
 
 /**
  * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type
index b70ffe53cb9fe77a668f57c2bc584216f90f95b6..2ae13714828bc42568e77684fedfc2cf929c291d 100644 (file)
@@ -37,6 +37,12 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n)
        }
 }
 
+#define hlist_nulls_first_rcu(head) \
+       (*((struct hlist_nulls_node __rcu __force **)&(head)->first))
+
+#define hlist_nulls_next_rcu(node) \
+       (*((struct hlist_nulls_node __rcu __force **)&(node)->next))
+
 /**
  * hlist_nulls_del_rcu - deletes entry from hash list without re-initialization
  * @n: the element to delete from the hash list.
@@ -88,7 +94,7 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
 
        n->next = first;
        n->pprev = &h->first;
-       rcu_assign_pointer(h->first, n);
+       rcu_assign_pointer(hlist_nulls_first_rcu(h), n);
        if (!is_a_nulls(first))
                first->pprev = &n->next;
 }
@@ -100,11 +106,11 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
  * @member:    the name of the hlist_nulls_node within the struct.
  *
  */
-#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \
-       for (pos = rcu_dereference_raw((head)->first);                   \
-               (!is_a_nulls(pos)) &&                   \
+#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member)                        \
+       for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
+               (!is_a_nulls(pos)) &&                                           \
                ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \
-               pos = rcu_dereference_raw(pos->next))
+               pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)))
 
 #endif
 #endif
index 9fbc54a2585d42cb9276adf2c2d168f53e883f63..03cda7bed98587b128c5a9953316644a8debb4d2 100644 (file)
 #include <linux/lockdep.h>
 #include <linux/completion.h>
 #include <linux/debugobjects.h>
+#include <linux/compiler.h>
 
 #ifdef CONFIG_RCU_TORTURE_TEST
 extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 
+#define ULONG_CMP_GE(a, b)     (ULONG_MAX / 2 >= (a) - (b))
+#define ULONG_CMP_LT(a, b)     (ULONG_MAX / 2 < (a) - (b))
+
 /**
  * struct rcu_head - callback structure for use with RCU
  * @next: next update requests in a list
@@ -57,29 +61,94 @@ struct rcu_head {
 };
 
 /* Exported common interfaces */
-extern void rcu_barrier(void);
+extern void call_rcu_sched(struct rcu_head *head,
+                          void (*func)(struct rcu_head *rcu));
+extern void synchronize_sched(void);
 extern void rcu_barrier_bh(void);
 extern void rcu_barrier_sched(void);
 extern void synchronize_sched_expedited(void);
 extern int sched_expedited_torture_stats(char *page);
 
+static inline void __rcu_read_lock_bh(void)
+{
+       local_bh_disable();
+}
+
+static inline void __rcu_read_unlock_bh(void)
+{
+       local_bh_enable();
+}
+
+#ifdef CONFIG_PREEMPT_RCU
+
+extern void __rcu_read_lock(void);
+extern void __rcu_read_unlock(void);
+void synchronize_rcu(void);
+
+/*
+ * Defined as a macro as it is a very low level header included from
+ * areas that don't even know about current.  This gives the rcu_read_lock()
+ * nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other
+ * types of kernel builds, the rcu_read_lock() nesting depth is unknowable.
+ */
+#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
+
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+static inline void __rcu_read_lock(void)
+{
+       preempt_disable();
+}
+
+static inline void __rcu_read_unlock(void)
+{
+       preempt_enable();
+}
+
+static inline void synchronize_rcu(void)
+{
+       synchronize_sched();
+}
+
+static inline int rcu_preempt_depth(void)
+{
+       return 0;
+}
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
 /* Internal to kernel */
 extern void rcu_init(void);
+extern void rcu_sched_qs(int cpu);
+extern void rcu_bh_qs(int cpu);
+extern void rcu_check_callbacks(int cpu, int user);
+struct notifier_block;
+
+#ifdef CONFIG_NO_HZ
+
+extern void rcu_enter_nohz(void);
+extern void rcu_exit_nohz(void);
+
+#else /* #ifdef CONFIG_NO_HZ */
+
+static inline void rcu_enter_nohz(void)
+{
+}
+
+static inline void rcu_exit_nohz(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_NO_HZ */
 
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
 #include <linux/rcutree.h>
-#elif defined(CONFIG_TINY_RCU)
+#elif defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
 #include <linux/rcutiny.h>
 #else
 #error "Unknown RCU implementation specified to kernel configuration"
 #endif
 
-#define RCU_HEAD_INIT  { .next = NULL, .func = NULL }
-#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT
-#define INIT_RCU_HEAD(ptr) do { \
-       (ptr)->next = NULL; (ptr)->func = NULL; \
-} while (0)
-
 /*
  * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic
  * initialization and destruction of rcu_head on the stack. rcu_head structures
@@ -120,14 +189,15 @@ extern struct lockdep_map rcu_sched_lock_map;
 extern int debug_lockdep_rcu_enabled(void);
 
 /**
- * rcu_read_lock_held - might we be in RCU read-side critical section?
+ * rcu_read_lock_held() - might we be in RCU read-side critical section?
  *
  * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU
  * read-side critical section.  In absence of CONFIG_DEBUG_LOCK_ALLOC,
  * this assumes we are in an RCU read-side critical section unless it can
- * prove otherwise.
+ * prove otherwise.  This is useful for debug checks in functions that
+ * require that they be called within an RCU read-side critical section.
  *
- * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
+ * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
  */
 static inline int rcu_read_lock_held(void)
@@ -144,14 +214,16 @@ static inline int rcu_read_lock_held(void)
 extern int rcu_read_lock_bh_held(void);
 
 /**
- * rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section?
+ * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
  *
  * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
  * RCU-sched read-side critical section.  In absence of
  * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
  * critical section unless it can prove otherwise.  Note that disabling
  * of preemption (including disabling irqs) counts as an RCU-sched
- * read-side critical section.
+ * read-side critical section.  This is useful for debug checks in functions
+ * that required that they be called within an RCU-sched read-side
+ * critical section.
  *
  * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
@@ -211,7 +283,11 @@ static inline int rcu_read_lock_sched_held(void)
 
 extern int rcu_my_thread_group_empty(void);
 
-#define __do_rcu_dereference_check(c)                                  \
+/**
+ * rcu_lockdep_assert - emit lockdep splat if specified condition not met
+ * @c: condition to check
+ */
+#define rcu_lockdep_assert(c)                                          \
        do {                                                            \
                static bool __warned;                                   \
                if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
@@ -220,41 +296,163 @@ extern int rcu_my_thread_group_empty(void);
                }                                                       \
        } while (0)
 
+#else /* #ifdef CONFIG_PROVE_RCU */
+
+#define rcu_lockdep_assert(c) do { } while (0)
+
+#endif /* #else #ifdef CONFIG_PROVE_RCU */
+
+/*
+ * Helper functions for rcu_dereference_check(), rcu_dereference_protected()
+ * and rcu_assign_pointer().  Some of these could be folded into their
+ * callers, but they are left separate in order to ease introduction of
+ * multiple flavors of pointers to match the multiple flavors of RCU
+ * (e.g., __rcu_bh, * __rcu_sched, and __srcu), should this make sense in
+ * the future.
+ */
+
+#ifdef __CHECKER__
+#define rcu_dereference_sparse(p, space) \
+       ((void)(((typeof(*p) space *)p) == p))
+#else /* #ifdef __CHECKER__ */
+#define rcu_dereference_sparse(p, space)
+#endif /* #else #ifdef __CHECKER__ */
+
+#define __rcu_access_pointer(p, space) \
+       ({ \
+               typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+               rcu_dereference_sparse(p, space); \
+               ((typeof(*p) __force __kernel *)(_________p1)); \
+       })
+#define __rcu_dereference_check(p, c, space) \
+       ({ \
+               typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+               rcu_lockdep_assert(c); \
+               rcu_dereference_sparse(p, space); \
+               smp_read_barrier_depends(); \
+               ((typeof(*p) __force __kernel *)(_________p1)); \
+       })
+#define __rcu_dereference_protected(p, c, space) \
+       ({ \
+               rcu_lockdep_assert(c); \
+               rcu_dereference_sparse(p, space); \
+               ((typeof(*p) __force __kernel *)(p)); \
+       })
+
+#define __rcu_dereference_index_check(p, c) \
+       ({ \
+               typeof(p) _________p1 = ACCESS_ONCE(p); \
+               rcu_lockdep_assert(c); \
+               smp_read_barrier_depends(); \
+               (_________p1); \
+       })
+#define __rcu_assign_pointer(p, v, space) \
+       ({ \
+               if (!__builtin_constant_p(v) || \
+                   ((v) != NULL)) \
+                       smp_wmb(); \
+               (p) = (typeof(*v) __force space *)(v); \
+       })
+
+
+/**
+ * rcu_access_pointer() - fetch RCU pointer with no dereferencing
+ * @p: The pointer to read
+ *
+ * Return the value of the specified RCU-protected pointer, but omit the
+ * smp_read_barrier_depends() and keep the ACCESS_ONCE().  This is useful
+ * when the value of this pointer is accessed, but the pointer is not
+ * dereferenced, for example, when testing an RCU-protected pointer against
+ * NULL.  Although rcu_access_pointer() may also be used in cases where
+ * update-side locks prevent the value of the pointer from changing, you
+ * should instead use rcu_dereference_protected() for this use case.
+ */
+#define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu)
+
 /**
- * rcu_dereference_check - rcu_dereference with debug checking
+ * rcu_dereference_check() - rcu_dereference with debug checking
  * @p: The pointer to read, prior to dereferencing
  * @c: The conditions under which the dereference will take place
  *
  * Do an rcu_dereference(), but check that the conditions under which the
- * dereference will take place are correct.  Typically the conditions indicate
- * the various locking conditions that should be held at that point.  The check
- * should return true if the conditions are satisfied.
+ * dereference will take place are correct.  Typically the conditions
+ * indicate the various locking conditions that should be held at that
+ * point.  The check should return true if the conditions are satisfied.
+ * An implicit check for being in an RCU read-side critical section
+ * (rcu_read_lock()) is included.
  *
  * For example:
  *
- *     bar = rcu_dereference_check(foo->bar, rcu_read_lock_held() ||
- *                                           lockdep_is_held(&foo->lock));
+ *     bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock));
  *
  * could be used to indicate to lockdep that foo->bar may only be dereferenced
- * if either the RCU read lock is held, or that the lock required to replace
+ * if either rcu_read_lock() is held, or that the lock required to replace
  * the bar struct at foo->bar is held.
  *
  * Note that the list of conditions may also include indications of when a lock
  * need not be held, for example during initialisation or destruction of the
  * target struct:
  *
- *     bar = rcu_dereference_check(foo->bar, rcu_read_lock_held() ||
- *                                           lockdep_is_held(&foo->lock) ||
+ *     bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock) ||
  *                                           atomic_read(&foo->usage) == 0);
+ *
+ * Inserts memory barriers on architectures that require them
+ * (currently only the Alpha), prevents the compiler from refetching
+ * (and from merging fetches), and, more importantly, documents exactly
+ * which pointers are protected by RCU and checks that the pointer is
+ * annotated as __rcu.
  */
 #define rcu_dereference_check(p, c) \
-       ({ \
-               __do_rcu_dereference_check(c); \
-               rcu_dereference_raw(p); \
-       })
+       __rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
+
+/**
+ * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-bh counterpart to rcu_dereference_check().
+ */
+#define rcu_dereference_bh_check(p, c) \
+       __rcu_dereference_check((p), rcu_read_lock_bh_held() || (c), __rcu)
 
 /**
- * rcu_dereference_protected - fetch RCU pointer when updates prevented
+ * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-sched counterpart to rcu_dereference_check().
+ */
+#define rcu_dereference_sched_check(p, c) \
+       __rcu_dereference_check((p), rcu_read_lock_sched_held() || (c), \
+                               __rcu)
+
+#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
+
+/**
+ * rcu_dereference_index_check() - rcu_dereference for indices with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * Similar to rcu_dereference_check(), but omits the sparse checking.
+ * This allows rcu_dereference_index_check() to be used on integers,
+ * which can then be used as array indices.  Attempting to use
+ * rcu_dereference_check() on an integer will give compiler warnings
+ * because the sparse address-space mechanism relies on dereferencing
+ * the RCU-protected pointer.  Dereferencing integers is not something
+ * that even gcc will put up with.
+ *
+ * Note that this function does not implicitly check for RCU read-side
+ * critical sections.  If this function gains lots of uses, it might
+ * make sense to provide versions for each flavor of RCU, but it does
+ * not make sense as of early 2010.
+ */
+#define rcu_dereference_index_check(p, c) \
+       __rcu_dereference_index_check((p), (c))
+
+/**
+ * rcu_dereference_protected() - fetch RCU pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
  *
  * Return the value of the specified RCU-protected pointer, but omit
  * both the smp_read_barrier_depends() and the ACCESS_ONCE().  This
@@ -263,35 +461,61 @@ extern int rcu_my_thread_group_empty(void);
  * prevent the compiler from repeating this reference or combining it
  * with other references, so it should not be used without protection
  * of appropriate locks.
+ *
+ * This function is only for update-side use.  Using this function
+ * when protected only by rcu_read_lock() will result in infrequent
+ * but very ugly failures.
  */
 #define rcu_dereference_protected(p, c) \
-       ({ \
-               __do_rcu_dereference_check(c); \
-               (p); \
-       })
+       __rcu_dereference_protected((p), (c), __rcu)
 
-#else /* #ifdef CONFIG_PROVE_RCU */
+/**
+ * rcu_dereference_bh_protected() - fetch RCU-bh pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-bh counterpart to rcu_dereference_protected().
+ */
+#define rcu_dereference_bh_protected(p, c) \
+       __rcu_dereference_protected((p), (c), __rcu)
 
-#define rcu_dereference_check(p, c)    rcu_dereference_raw(p)
-#define rcu_dereference_protected(p, c) (p)
+/**
+ * rcu_dereference_sched_protected() - fetch RCU-sched pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-sched counterpart to rcu_dereference_protected().
+ */
+#define rcu_dereference_sched_protected(p, c) \
+       __rcu_dereference_protected((p), (c), __rcu)
 
-#endif /* #else #ifdef CONFIG_PROVE_RCU */
 
 /**
- * rcu_access_pointer - fetch RCU pointer with no dereferencing
+ * rcu_dereference() - fetch RCU-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
  *
- * Return the value of the specified RCU-protected pointer, but omit the
- * smp_read_barrier_depends() and keep the ACCESS_ONCE().  This is useful
- * when the value of this pointer is accessed, but the pointer is not
- * dereferenced, for example, when testing an RCU-protected pointer against
- * NULL.  This may also be used in cases where update-side locks prevent
- * the value of the pointer from changing, but rcu_dereference_protected()
- * is a lighter-weight primitive for this use case.
+ * This is a simple wrapper around rcu_dereference_check().
+ */
+#define rcu_dereference(p) rcu_dereference_check(p, 0)
+
+/**
+ * rcu_dereference_bh() - fetch an RCU-bh-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Makes rcu_dereference_check() do the dirty work.
+ */
+#define rcu_dereference_bh(p) rcu_dereference_bh_check(p, 0)
+
+/**
+ * rcu_dereference_sched() - fetch RCU-sched-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Makes rcu_dereference_check() do the dirty work.
  */
-#define rcu_access_pointer(p)  ACCESS_ONCE(p)
+#define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0)
 
 /**
- * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+ * rcu_read_lock() - mark the beginning of an RCU read-side critical section
  *
  * When synchronize_rcu() is invoked on one CPU while other CPUs
  * are within RCU read-side critical sections, then the
@@ -302,7 +526,7 @@ extern int rcu_my_thread_group_empty(void);
  * until after the all the other CPUs exit their critical sections.
  *
  * Note, however, that RCU callbacks are permitted to run concurrently
- * with RCU read-side critical sections.  One way that this can happen
+ * with new RCU read-side critical sections.  One way that this can happen
  * is via the following sequence of events: (1) CPU 0 enters an RCU
  * read-side critical section, (2) CPU 1 invokes call_rcu() to register
  * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
@@ -317,7 +541,20 @@ extern int rcu_my_thread_group_empty(void);
  * will be deferred until the outermost RCU read-side critical section
  * completes.
  *
- * It is illegal to block while in an RCU read-side critical section.
+ * You can avoid reading and understanding the next paragraph by
+ * following this rule: don't put anything in an rcu_read_lock() RCU
+ * read-side critical section that would block in a !PREEMPT kernel.
+ * But if you want the full story, read on!
+ *
+ * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU), it
+ * is illegal to block while in an RCU read-side critical section.  In
+ * preemptible RCU implementations (TREE_PREEMPT_RCU and TINY_PREEMPT_RCU)
+ * in CONFIG_PREEMPT kernel builds, RCU read-side critical sections may
+ * be preempted, but explicit blocking is illegal.  Finally, in preemptible
+ * RCU implementations in real-time (CONFIG_PREEMPT_RT) kernel builds,
+ * RCU read-side critical sections may be preempted and they may also
+ * block, but only when acquiring spinlocks that are subject to priority
+ * inheritance.
  */
 static inline void rcu_read_lock(void)
 {
@@ -337,7 +574,7 @@ static inline void rcu_read_lock(void)
  */
 
 /**
- * rcu_read_unlock - marks the end of an RCU read-side critical section.
+ * rcu_read_unlock() - marks the end of an RCU read-side critical section.
  *
  * See rcu_read_lock() for more information.
  */
@@ -349,15 +586,16 @@ static inline void rcu_read_unlock(void)
 }
 
 /**
- * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical section
+ * rcu_read_lock_bh() - mark the beginning of an RCU-bh critical section
  *
  * This is equivalent of rcu_read_lock(), but to be used when updates
- * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
- * consider completion of a softirq handler to be a quiescent state,
- * a process in RCU read-side critical section must be protected by
- * disabling softirqs. Read-side critical sections in interrupt context
- * can use just rcu_read_lock().
- *
+ * are being done using call_rcu_bh() or synchronize_rcu_bh(). Since
+ * both call_rcu_bh() and synchronize_rcu_bh() consider completion of a
+ * softirq handler to be a quiescent state, a process in RCU read-side
+ * critical section must be protected by disabling softirqs. Read-side
+ * critical sections in interrupt context can use just rcu_read_lock(),
+ * though this should at least be commented to avoid confusing people
+ * reading the code.
  */
 static inline void rcu_read_lock_bh(void)
 {
@@ -379,13 +617,12 @@ static inline void rcu_read_unlock_bh(void)
 }
 
 /**
- * rcu_read_lock_sched - mark the beginning of a RCU-classic critical section
+ * rcu_read_lock_sched() - mark the beginning of a RCU-sched critical section
  *
- * Should be used with either
- * - synchronize_sched()
- * or
- * - call_rcu_sched() and rcu_barrier_sched()
- * on the write-side to insure proper synchronization.
+ * This is equivalent of rcu_read_lock(), but to be used when updates
+ * are being done using call_rcu_sched() or synchronize_rcu_sched().
+ * Read-side critical sections can also be introduced by anything that
+ * disables preemption, including local_irq_disable() and friends.
  */
 static inline void rcu_read_lock_sched(void)
 {
@@ -420,54 +657,14 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
        preempt_enable_notrace();
 }
 
-
 /**
- * rcu_dereference_raw - fetch an RCU-protected pointer
+ * rcu_assign_pointer() - assign to RCU-protected pointer
+ * @p: pointer to assign to
+ * @v: value to assign (publish)
  *
- * The caller must be within some flavor of RCU read-side critical
- * section, or must be otherwise preventing the pointer from changing,
- * for example, by holding an appropriate lock.  This pointer may later
- * be safely dereferenced.  It is the caller's responsibility to have
- * done the right thing, as this primitive does no checking of any kind.
- *
- * Inserts memory barriers on architectures that require them
- * (currently only the Alpha), and, more importantly, documents
- * exactly which pointers are protected by RCU.
- */
-#define rcu_dereference_raw(p) ({ \
-                               typeof(p) _________p1 = ACCESS_ONCE(p); \
-                               smp_read_barrier_depends(); \
-                               (_________p1); \
-                               })
-
-/**
- * rcu_dereference - fetch an RCU-protected pointer, checking for RCU
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference(p) \
-       rcu_dereference_check(p, rcu_read_lock_held())
-
-/**
- * rcu_dereference_bh - fetch an RCU-protected pointer, checking for RCU-bh
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference_bh(p) \
-               rcu_dereference_check(p, rcu_read_lock_bh_held())
-
-/**
- * rcu_dereference_sched - fetch RCU-protected pointer, checking for RCU-sched
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference_sched(p) \
-               rcu_dereference_check(p, rcu_read_lock_sched_held())
-
-/**
- * rcu_assign_pointer - assign (publicize) a pointer to a newly
- * initialized structure that will be dereferenced by RCU read-side
- * critical sections.  Returns the value assigned.
+ * Assigns the specified value to the specified RCU-protected
+ * pointer, ensuring that any concurrent RCU readers will see
+ * any prior initialization.  Returns the value assigned.
  *
  * Inserts memory barriers on architectures that require them
  * (pretty much all of them other than x86), and also prevents
@@ -476,14 +673,17 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * call documents which pointers will be dereferenced by RCU read-side
  * code.
  */
-
 #define rcu_assign_pointer(p, v) \
-       ({ \
-               if (!__builtin_constant_p(v) || \
-                   ((v) != NULL)) \
-                       smp_wmb(); \
-               (p) = (v); \
-       })
+       __rcu_assign_pointer((p), (v), __rcu)
+
+/**
+ * RCU_INIT_POINTER() - initialize an RCU protected pointer
+ *
+ * Initialize an RCU-protected pointer in such a way to avoid RCU-lockdep
+ * splats.
+ */
+#define RCU_INIT_POINTER(p, v) \
+               p = (typeof(*v) __force __rcu *)(v)
 
 /* Infrastructure to implement the synchronize_() primitives. */
 
@@ -494,26 +694,37 @@ struct rcu_synchronize {
 
 extern void wakeme_after_rcu(struct rcu_head  *head);
 
+#ifdef CONFIG_PREEMPT_RCU
+
 /**
- * call_rcu - Queue an RCU callback for invocation after a grace period.
+ * call_rcu() - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
- * @func: actual update function to be invoked after the grace period
+ * @func: actual callback function to be invoked after the grace period
  *
- * The update function will be invoked some time after a full grace
- * period elapses, in other words after all currently executing RCU
- * read-side critical sections have completed.  RCU read-side critical
+ * The callback function will be invoked some time after a full grace
+ * period elapses, in other words after all pre-existing RCU read-side
+ * critical sections have completed.  However, the callback function
+ * might well execute concurrently with RCU read-side critical sections
+ * that started after call_rcu() was invoked.  RCU read-side critical
  * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
  * and may be nested.
  */
 extern void call_rcu(struct rcu_head *head,
                              void (*func)(struct rcu_head *head));
 
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+/* In classic RCU, call_rcu() is just call_rcu_sched(). */
+#define        call_rcu        call_rcu_sched
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
 /**
- * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
+ * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
  * @head: structure to be used for queueing the RCU updates.
- * @func: actual update function to be invoked after the grace period
+ * @func: actual callback function to be invoked after the grace period
  *
- * The update function will be invoked some time after a full grace
+ * The callback function will be invoked some time after a full grace
  * period elapses, in other words after all currently executing RCU
  * read-side critical sections have completed. call_rcu_bh() assumes
  * that the read-side critical sections end on completion of a softirq
@@ -566,37 +777,4 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
 }
 #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
-#ifndef CONFIG_PROVE_RCU
-#define __do_rcu_dereference_check(c) do { } while (0)
-#endif /* #ifdef CONFIG_PROVE_RCU */
-
-#define __rcu_dereference_index_check(p, c) \
-       ({ \
-               typeof(p) _________p1 = ACCESS_ONCE(p); \
-               __do_rcu_dereference_check(c); \
-               smp_read_barrier_depends(); \
-               (_________p1); \
-       })
-
-/**
- * rcu_dereference_index_check() - rcu_dereference for indices with debug checking
- * @p: The pointer to read, prior to dereferencing
- * @c: The conditions under which the dereference will take place
- *
- * Similar to rcu_dereference_check(), but omits the sparse checking.
- * This allows rcu_dereference_index_check() to be used on integers,
- * which can then be used as array indices.  Attempting to use
- * rcu_dereference_check() on an integer will give compiler warnings
- * because the sparse address-space mechanism relies on dereferencing
- * the RCU-protected pointer.  Dereferencing integers is not something
- * that even gcc will put up with.
- *
- * Note that this function does not implicitly check for RCU read-side
- * critical sections.  If this function gains lots of uses, it might
- * make sense to provide versions for each flavor of RCU, but it does
- * not make sense as of early 2010.
- */
-#define rcu_dereference_index_check(p, c) \
-       __rcu_dereference_index_check((p), (c))
-
 #endif /* __LINUX_RCUPDATE_H */
index e2e893144a8450848cf50f8672368aa79c0a0001..13877cb93a6000043f11a6704f2d90b0cc04552d 100644 (file)
 
 #include <linux/cache.h>
 
-void rcu_sched_qs(int cpu);
-void rcu_bh_qs(int cpu);
-static inline void rcu_note_context_switch(int cpu)
-{
-       rcu_sched_qs(cpu);
-}
+#define rcu_init_sched()       do { } while (0)
 
-#define __rcu_read_lock()      preempt_disable()
-#define __rcu_read_unlock()    preempt_enable()
-#define __rcu_read_lock_bh()   local_bh_disable()
-#define __rcu_read_unlock_bh() local_bh_enable()
-#define call_rcu_sched         call_rcu
+#ifdef CONFIG_TINY_RCU
 
-#define rcu_init_sched()       do { } while (0)
-extern void rcu_check_callbacks(int cpu, int user);
+static inline void synchronize_rcu_expedited(void)
+{
+       synchronize_sched();    /* Only one CPU, so pretty fast anyway!!! */
+}
 
-static inline int rcu_needs_cpu(int cpu)
+static inline void rcu_barrier(void)
 {
-       return 0;
+       rcu_barrier_sched();  /* Only one CPU, so only one list of callbacks! */
 }
 
-/*
- * Return the number of grace periods.
- */
-static inline long rcu_batches_completed(void)
+#else /* #ifdef CONFIG_TINY_RCU */
+
+void rcu_barrier(void);
+void synchronize_rcu_expedited(void);
+
+#endif /* #else #ifdef CONFIG_TINY_RCU */
+
+static inline void synchronize_rcu_bh(void)
 {
-       return 0;
+       synchronize_sched();
 }
 
-/*
- * Return the number of bottom-half grace periods.
- */
-static inline long rcu_batches_completed_bh(void)
+static inline void synchronize_rcu_bh_expedited(void)
 {
-       return 0;
+       synchronize_sched();
 }
 
-static inline void rcu_force_quiescent_state(void)
+#ifdef CONFIG_TINY_RCU
+
+static inline void rcu_preempt_note_context_switch(void)
 {
 }
 
-static inline void rcu_bh_force_quiescent_state(void)
+static inline void exit_rcu(void)
 {
 }
 
-static inline void rcu_sched_force_quiescent_state(void)
+static inline int rcu_needs_cpu(int cpu)
 {
+       return 0;
 }
 
-extern void synchronize_sched(void);
+#else /* #ifdef CONFIG_TINY_RCU */
+
+void rcu_preempt_note_context_switch(void);
+extern void exit_rcu(void);
+int rcu_preempt_needs_cpu(void);
 
-static inline void synchronize_rcu(void)
+static inline int rcu_needs_cpu(int cpu)
 {
-       synchronize_sched();
+       return rcu_preempt_needs_cpu();
 }
 
-static inline void synchronize_rcu_bh(void)
+#endif /* #else #ifdef CONFIG_TINY_RCU */
+
+static inline void rcu_note_context_switch(int cpu)
 {
-       synchronize_sched();
+       rcu_sched_qs(cpu);
+       rcu_preempt_note_context_switch();
 }
 
-static inline void synchronize_rcu_expedited(void)
+/*
+ * Return the number of grace periods.
+ */
+static inline long rcu_batches_completed(void)
 {
-       synchronize_sched();
+       return 0;
 }
 
-static inline void synchronize_rcu_bh_expedited(void)
+/*
+ * Return the number of bottom-half grace periods.
+ */
+static inline long rcu_batches_completed_bh(void)
 {
-       synchronize_sched();
+       return 0;
 }
 
-struct notifier_block;
-
-#ifdef CONFIG_NO_HZ
-
-extern void rcu_enter_nohz(void);
-extern void rcu_exit_nohz(void);
-
-#else /* #ifdef CONFIG_NO_HZ */
-
-static inline void rcu_enter_nohz(void)
+static inline void rcu_force_quiescent_state(void)
 {
 }
 
-static inline void rcu_exit_nohz(void)
+static inline void rcu_bh_force_quiescent_state(void)
 {
 }
 
-#endif /* #else #ifdef CONFIG_NO_HZ */
-
-static inline void exit_rcu(void)
+static inline void rcu_sched_force_quiescent_state(void)
 {
 }
 
-static inline int rcu_preempt_depth(void)
+static inline void rcu_cpu_stall_reset(void)
 {
-       return 0;
 }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
index c0ed1c056f290701def0e0116b6aad72ada30c91..95518e6287946177e0eceb5cbf201ebfcaf0e072 100644 (file)
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
-struct notifier_block;
-
-extern void rcu_sched_qs(int cpu);
-extern void rcu_bh_qs(int cpu);
 extern void rcu_note_context_switch(int cpu);
 extern int rcu_needs_cpu(int cpu);
+extern void rcu_cpu_stall_reset(void);
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
-extern void __rcu_read_lock(void);
-extern void __rcu_read_unlock(void);
-extern void synchronize_rcu(void);
 extern void exit_rcu(void);
 
-/*
- * Defined as macro as it is a very low level header
- * included from areas that don't even know about current
- */
-#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
-
 #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
-static inline void __rcu_read_lock(void)
-{
-       preempt_disable();
-}
-
-static inline void __rcu_read_unlock(void)
-{
-       preempt_enable();
-}
-
-#define synchronize_rcu synchronize_sched
-
 static inline void exit_rcu(void)
 {
 }
 
-static inline int rcu_preempt_depth(void)
-{
-       return 0;
-}
-
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
-static inline void __rcu_read_lock_bh(void)
-{
-       local_bh_disable();
-}
-static inline void __rcu_read_unlock_bh(void)
-{
-       local_bh_enable();
-}
-
-extern void call_rcu_sched(struct rcu_head *head,
-                          void (*func)(struct rcu_head *rcu));
 extern void synchronize_rcu_bh(void);
-extern void synchronize_sched(void);
 extern void synchronize_rcu_expedited(void);
 
 static inline void synchronize_rcu_bh_expedited(void)
@@ -95,7 +54,7 @@ static inline void synchronize_rcu_bh_expedited(void)
        synchronize_sched_expedited();
 }
 
-extern void rcu_check_callbacks(int cpu, int user);
+extern void rcu_barrier(void);
 
 extern long rcu_batches_completed(void);
 extern long rcu_batches_completed_bh(void);
@@ -104,18 +63,6 @@ extern void rcu_force_quiescent_state(void);
 extern void rcu_bh_force_quiescent_state(void);
 extern void rcu_sched_force_quiescent_state(void);
 
-#ifdef CONFIG_NO_HZ
-void rcu_enter_nohz(void);
-void rcu_exit_nohz(void);
-#else /* CONFIG_NO_HZ */
-static inline void rcu_enter_nohz(void)
-{
-}
-static inline void rcu_exit_nohz(void)
-{
-}
-#endif /* CONFIG_NO_HZ */
-
 /* A context switch is a grace period for RCU-sched and RCU-bh. */
 static inline int rcu_blocking_is_gp(void)
 {
index bc8c3881c729fb29128b373b8fb6e0ad68feac45..f31db23687828da2e209696c8612cb3f7a195801 100644 (file)
@@ -3,6 +3,7 @@
 
 #ifdef CONFIG_PM_TRACE
 #include <asm/resume-trace.h>
+#include <linux/types.h>
 
 extern int pm_trace_enabled;
 
@@ -14,6 +15,7 @@ static inline int pm_trace_is_enabled(void)
 struct device;
 extern void set_trace_device(struct device *);
 extern void generate_resume_trace(const void *tracedata, unsigned int user);
+extern int show_trace_dev_match(char *buf, size_t size);
 
 #define TRACE_DEVICE(dev) do { \
        if (pm_trace_enabled) \
index 4f82326eb2945f2cd275bbcff64151a06ca6ccb4..08c32e4f261aca004ac06d895a1a8bbd73cfd887 100644 (file)
@@ -81,7 +81,7 @@ struct rfkill_event {
        __u8  type;
        __u8  op;
        __u8  soft, hard;
-} __packed;
+} __attribute__((packed));
 
 /*
  * We are planning to be backward and forward compatible with changes
index dbafa9e34a2d6ed90c4f7f86016eddde957c44e1..56154bbb8da9cf012f990d31448f741538201bcb 100644 (file)
@@ -878,6 +878,7 @@ enum sched_domain_level {
        SD_LV_NONE = 0,
        SD_LV_SIBLING,
        SD_LV_MC,
+       SD_LV_BOOK,
        SD_LV_CPU,
        SD_LV_NODE,
        SD_LV_ALLNODES,
@@ -1163,6 +1164,13 @@ struct sched_rt_entity {
 
 struct rcu_node;
 
+enum perf_event_task_context {
+       perf_invalid_context = -1,
+       perf_hw_context = 0,
+       perf_sw_context,
+       perf_nr_task_contexts,
+};
+
 struct task_struct {
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
        void *stack;
@@ -1205,11 +1213,13 @@ struct task_struct {
        unsigned int policy;
        cpumask_t cpus_allowed;
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
        int rcu_read_lock_nesting;
        char rcu_read_unlock_special;
-       struct rcu_node *rcu_blocked_node;
        struct list_head rcu_node_entry;
+#endif /* #ifdef CONFIG_PREEMPT_RCU */
+#ifdef CONFIG_TREE_PREEMPT_RCU
+       struct rcu_node *rcu_blocked_node;
 #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
@@ -1291,9 +1301,9 @@ struct task_struct {
        struct list_head cpu_timers[3];
 
 /* process credentials */
-       const struct cred *real_cred;   /* objective and real subjective task
+       const struct cred __rcu *real_cred; /* objective and real subjective task
                                         * credentials (COW) */
-       const struct cred *cred;        /* effective (overridable) subjective task
+       const struct cred __rcu *cred;  /* effective (overridable) subjective task
                                         * credentials (COW) */
        struct mutex cred_guard_mutex;  /* guard against foreign influences on
                                         * credential calculations
@@ -1421,7 +1431,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_CGROUPS
        /* Control Group info protected by css_set_lock */
-       struct css_set *cgroups;
+       struct css_set __rcu *cgroups;
        /* cg_list protected by css_set_lock and tsk->alloc_lock */
        struct list_head cg_list;
 #endif
@@ -1434,7 +1444,7 @@ struct task_struct {
        struct futex_pi_state *pi_state_cache;
 #endif
 #ifdef CONFIG_PERF_EVENTS
-       struct perf_event_context *perf_event_ctxp;
+       struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts];
        struct mutex perf_event_mutex;
        struct list_head perf_event_list;
 #endif
@@ -1684,8 +1694,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 /*
  * Per process flags
  */
-#define PF_ALIGNWARN   0x00000001      /* Print alignment warning msgs */
-                                       /* Not implemented yet, only for 486*/
+#define PF_KSOFTIRQD   0x00000001      /* I am ksoftirqd */
 #define PF_STARTING    0x00000002      /* being created */
 #define PF_EXITING     0x00000004      /* getting shut down */
 #define PF_EXITPIDONE  0x00000008      /* pi exit done on shut down */
@@ -1743,7 +1752,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 #define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
 #define used_math() tsk_used_math(current)
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 
 #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */
 #define RCU_READ_UNLOCK_NEED_QS (1 << 1) /* RCU core needs CPU response. */
@@ -1752,7 +1761,9 @@ static inline void rcu_copy_process(struct task_struct *p)
 {
        p->rcu_read_lock_nesting = 0;
        p->rcu_read_unlock_special = 0;
+#ifdef CONFIG_TREE_PREEMPT_RCU
        p->rcu_blocked_node = NULL;
+#endif
        INIT_LIST_HEAD(&p->rcu_node_entry);
 }
 
@@ -1829,6 +1840,19 @@ extern void sched_clock_idle_sleep_event(void);
 extern void sched_clock_idle_wakeup_event(u64 delta_ns);
 #endif
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+/*
+ * An i/f to runtime opt-in for irq time accounting based off of sched_clock.
+ * The reason for this explicit opt-in is not to have perf penalty with
+ * slow sched_clocks.
+ */
+extern void enable_sched_clock_irqtime(void);
+extern void disable_sched_clock_irqtime(void);
+#else
+static inline void enable_sched_clock_irqtime(void) {}
+static inline void disable_sched_clock_irqtime(void) {}
+#endif
+
 extern unsigned long long
 task_sched_runtime(struct task_struct *task);
 extern unsigned long long thread_group_sched_runtime(struct task_struct *task);
@@ -2370,9 +2394,9 @@ extern int __cond_resched_lock(spinlock_t *lock);
 
 extern int __cond_resched_softirq(void);
 
-#define cond_resched_softirq() ({                              \
-       __might_sleep(__FILE__, __LINE__, SOFTIRQ_OFFSET);      \
-       __cond_resched_softirq();                               \
+#define cond_resched_softirq() ({                                      \
+       __might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET);      \
+       __cond_resched_softirq();                                       \
 })
 
 /*
index a22219afff092952bbe276cb9da1d0509ddf196c..b8246a8df7d2dc2ecc864ac192d694b369dd12d6 100644 (file)
@@ -74,7 +74,7 @@ extern int cap_file_mmap(struct file *file, unsigned long reqprot,
 extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
 extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                          unsigned long arg4, unsigned long arg5);
-extern int cap_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp);
+extern int cap_task_setscheduler(struct task_struct *p);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
 extern int cap_syslog(int type, bool from_file);
@@ -959,6 +959,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     Sets the new child socket's sid to the openreq sid.
  * @inet_conn_established:
  *     Sets the connection's peersid to the secmark on skb.
+ * @secmark_relabel_packet:
+ *     check if the process should be allowed to relabel packets to the given secid
+ * @security_secmark_refcount_inc
+ *     tells the LSM to increment the number of secmark labeling rules loaded
+ * @security_secmark_refcount_dec
+ *     tells the LSM to decrement the number of secmark labeling rules loaded
  * @req_classify_flow:
  *     Sets the flow's sid to the openreq sid.
  * @tun_dev_create:
@@ -1279,9 +1285,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     Return 0 if permission is granted.
  *
  * @secid_to_secctx:
- *     Convert secid to security context.
+ *     Convert secid to security context.  If secdata is NULL the length of
+ *     the result will be returned in seclen, but no secdata will be returned.
+ *     This does mean that the length could change between calls to check the
+ *     length and the next call which actually allocates and returns the secdata.
  *     @secid contains the security ID.
  *     @secdata contains the pointer that stores the converted security context.
+ *     @seclen pointer which contains the length of the data
  * @secctx_to_secid:
  *     Convert security context to secid.
  *     @secid contains the pointer to the generated security ID.
@@ -1501,8 +1511,7 @@ struct security_operations {
        int (*task_getioprio) (struct task_struct *p);
        int (*task_setrlimit) (struct task_struct *p, unsigned int resource,
                        struct rlimit *new_rlim);
-       int (*task_setscheduler) (struct task_struct *p, int policy,
-                                 struct sched_param *lp);
+       int (*task_setscheduler) (struct task_struct *p);
        int (*task_getscheduler) (struct task_struct *p);
        int (*task_movememory) (struct task_struct *p);
        int (*task_kill) (struct task_struct *p,
@@ -1594,6 +1603,9 @@ struct security_operations {
                                  struct request_sock *req);
        void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
        void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
+       int (*secmark_relabel_packet) (u32 secid);
+       void (*secmark_refcount_inc) (void);
+       void (*secmark_refcount_dec) (void);
        void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
        int (*tun_dev_create)(void);
        void (*tun_dev_post_create)(struct sock *sk);
@@ -1752,8 +1764,7 @@ int security_task_setioprio(struct task_struct *p, int ioprio);
 int security_task_getioprio(struct task_struct *p);
 int security_task_setrlimit(struct task_struct *p, unsigned int resource,
                struct rlimit *new_rlim);
-int security_task_setscheduler(struct task_struct *p,
-                               int policy, struct sched_param *lp);
+int security_task_setscheduler(struct task_struct *p);
 int security_task_getscheduler(struct task_struct *p);
 int security_task_movememory(struct task_struct *p);
 int security_task_kill(struct task_struct *p, struct siginfo *info,
@@ -2320,11 +2331,9 @@ static inline int security_task_setrlimit(struct task_struct *p,
        return 0;
 }
 
-static inline int security_task_setscheduler(struct task_struct *p,
-                                            int policy,
-                                            struct sched_param *lp)
+static inline int security_task_setscheduler(struct task_struct *p)
 {
-       return cap_task_setscheduler(p, policy, lp);
+       return cap_task_setscheduler(p);
 }
 
 static inline int security_task_getscheduler(struct task_struct *p)
@@ -2551,6 +2560,9 @@ void security_inet_csk_clone(struct sock *newsk,
                        const struct request_sock *req);
 void security_inet_conn_established(struct sock *sk,
                        struct sk_buff *skb);
+int security_secmark_relabel_packet(u32 secid);
+void security_secmark_refcount_inc(void);
+void security_secmark_refcount_dec(void);
 int security_tun_dev_create(void);
 void security_tun_dev_post_create(struct sock *sk);
 int security_tun_dev_attach(struct sock *sk);
@@ -2705,6 +2717,19 @@ static inline void security_inet_conn_established(struct sock *sk,
 {
 }
 
+static inline int security_secmark_relabel_packet(u32 secid)
+{
+       return 0;
+}
+
+static inline void security_secmark_refcount_inc(void)
+{
+}
+
+static inline void security_secmark_refcount_dec(void)
+{
+}
+
 static inline int security_tun_dev_create(void)
 {
        return 0;
index 82e0f26a12996a1bcce6efddd07e734313162c19..44f4596126904f7d0357654c999ed2ae13258c82 100644 (file)
@@ -20,75 +20,12 @@ struct kern_ipc_perm;
 
 #ifdef CONFIG_SECURITY_SELINUX
 
-/**
- *     selinux_string_to_sid - map a security context string to a security ID
- *     @str: the security context string to be mapped
- *     @sid: ID value returned via this.
- *
- *     Returns 0 if successful, with the SID stored in sid.  A value
- *     of zero for sid indicates no SID could be determined (but no error
- *     occurred).
- */
-int selinux_string_to_sid(char *str, u32 *sid);
-
-/**
- *     selinux_secmark_relabel_packet_permission - secmark permission check
- *     @sid: SECMARK ID value to be applied to network packet
- *
- *     Returns 0 if the current task is allowed to set the SECMARK label of
- *     packets with the supplied security ID.  Note that it is implicit that
- *     the packet is always being relabeled from the default unlabeled value,
- *     and that the access control decision is made in the AVC.
- */
-int selinux_secmark_relabel_packet_permission(u32 sid);
-
-/**
- *     selinux_secmark_refcount_inc - increments the secmark use counter
- *
- *     SELinux keeps track of the current SECMARK targets in use so it knows
- *     when to apply SECMARK label access checks to network packets.  This
- *     function incements this reference count to indicate that a new SECMARK
- *     target has been configured.
- */
-void selinux_secmark_refcount_inc(void);
-
-/**
- *     selinux_secmark_refcount_dec - decrements the secmark use counter
- *
- *     SELinux keeps track of the current SECMARK targets in use so it knows
- *     when to apply SECMARK label access checks to network packets.  This
- *     function decements this reference count to indicate that one of the
- *     existing SECMARK targets has been removed/flushed.
- */
-void selinux_secmark_refcount_dec(void);
-
 /**
  * selinux_is_enabled - is SELinux enabled?
  */
 bool selinux_is_enabled(void);
 #else
 
-static inline int selinux_string_to_sid(const char *str, u32 *sid)
-{
-       *sid = 0;
-       return 0;
-}
-
-static inline int selinux_secmark_relabel_packet_permission(u32 sid)
-{
-       return 0;
-}
-
-static inline void selinux_secmark_refcount_inc(void)
-{
-       return;
-}
-
-static inline void selinux_secmark_refcount_dec(void)
-{
-       return;
-}
-
 static inline bool selinux_is_enabled(void)
 {
        return false;
index 7415839ac890f538b88611f7843b5b770e73292f..5310d27abd2a503ad523059ea4832f34ecfbb194 100644 (file)
@@ -26,6 +26,9 @@ struct semaphore {
        .wait_list      = LIST_HEAD_INIT((name).wait_list),             \
 }
 
+#define DEFINE_SEMAPHORE(name) \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
+
 #define DECLARE_MUTEX(name)    \
        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
 
index 1ebc694a6d521575165ad8443a472e0268e36dff..ef914061511ec833c706a38ddf47cac8ad52d93a 100644 (file)
@@ -77,8 +77,7 @@ struct serial_struct {
 #define PORT_16654     11
 #define PORT_16850     12
 #define PORT_RSA       13      /* RSA-DV II/S card */
-#define PORT_U6_16550A 14
-#define PORT_MAX       14
+#define PORT_MAX       13
 
 #define SERIAL_IO_PORT 0
 #define SERIAL_IO_HUB6 1
index 3c2ad99fed347e282d913ea2ad43082b6606b248..563e234009130ec557d1d6cb7d58b1875488d035 100644 (file)
@@ -44,7 +44,8 @@
 #define PORT_RM9000    16      /* PMC-Sierra RM9xxx internal UART */
 #define PORT_OCTEON    17      /* Cavium OCTEON internal UART */
 #define PORT_AR7       18      /* Texas Instruments AR7 internal UART */
-#define PORT_MAX_8250  18      /* max port ID */
+#define PORT_U6_16550A 19      /* ST-Ericsson U6xxx internal UART */
+#define PORT_MAX_8250  19      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
@@ -465,7 +466,7 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
 #ifdef SUPPORT_SYSRQ
        if (port->sysrq) {
                if (ch && time_before(jiffies, port->sysrq)) {
-                       handle_sysrq(ch, port->state->port.tty);
+                       handle_sysrq(ch);
                        port->sysrq = 0;
                        return 1;
                }
index 2ea1dd1ba21cedc1cdf7f9f0c74d939641d0e5b1..291f721144c2e23c51e4fbb92288f89e6b68dc11 100644 (file)
@@ -54,12 +54,15 @@ static inline void cycle_kernel_lock(void)
 
 #else
 
+#ifdef CONFIG_BKL /* provoke build bug if not set */
 #define lock_kernel()
 #define unlock_kernel()
-#define release_kernel_lock(task)              do { } while(0)
 #define cycle_kernel_lock()                    do { } while(0)
-#define reacquire_kernel_lock(task)            0
 #define kernel_locked()                                1
+#endif /* CONFIG_BKL */
+
+#define release_kernel_lock(task)              do { } while(0)
+#define reacquire_kernel_lock(task)            0
 
 #endif /* CONFIG_LOCK_KERNEL */
 #endif /* __LINUX_SMPLOCK_H */
index a2fada9becb60c47fcbf8143b3b3c67d291731b8..a8f56e1ec7602705d70ca326e620f1a8927e3925 100644 (file)
@@ -322,7 +322,7 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
                                          int offset, 
                                          unsigned int len, __wsum *csump);
 
-extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
+extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
 extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
                             int offset, int len);
index cc813f95a2f2b6a4ddf19d04ed1b60fc321c9712..c91302f3a25789b8045b34d9c0a9fa814c29b0ae 100644 (file)
@@ -14,7 +14,9 @@
 #define SPI_MODE_OFFSET                        6
 #define SPI_SCPH_OFFSET                        6
 #define SPI_SCOL_OFFSET                        7
+
 #define SPI_TMOD_OFFSET                        8
+#define SPI_TMOD_MASK                  (0x3 << SPI_TMOD_OFFSET)
 #define        SPI_TMOD_TR                     0x0             /* xmit & recv */
 #define SPI_TMOD_TO                    0x1             /* xmit only */
 #define SPI_TMOD_RO                    0x2             /* recv only */
index f8854655860e3a10f5d708b9b749c43ead2bd48d..80e535897de6ce85d26627144875a4914ff2aacc 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/preempt.h>
 #include <linux/linkage.h>
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <linux/thread_info.h>
 #include <linux/kernel.h>
 #include <linux/stringify.h>
index 4d5d2f546dbff11ee6a4abb6ad2cc53770d45aeb..58971e891f489950102d41f75bea118a22604f23 100644 (file)
@@ -108,19 +108,43 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 /**
- * srcu_dereference - fetch SRCU-protected pointer with checking
+ * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
+ * @p: the pointer to fetch and protect for later dereferencing
+ * @sp: pointer to the srcu_struct, which is used to check that we
+ *     really are in an SRCU read-side critical section.
+ * @c: condition to check for update-side use
  *
- * Makes rcu_dereference_check() do the dirty work.
+ * If PROVE_RCU is enabled, invoking this outside of an RCU read-side
+ * critical section will result in an RCU-lockdep splat, unless @c evaluates
+ * to 1.  The @c argument will normally be a logical expression containing
+ * lockdep_is_held() calls.
  */
-#define srcu_dereference(p, sp) \
-               rcu_dereference_check(p, srcu_read_lock_held(sp))
+#define srcu_dereference_check(p, sp, c) \
+       __rcu_dereference_check((p), srcu_read_lock_held(sp) || (c), __rcu)
+
+/**
+ * srcu_dereference - fetch SRCU-protected pointer for later dereferencing
+ * @p: the pointer to fetch and protect for later dereferencing
+ * @sp: pointer to the srcu_struct, which is used to check that we
+ *     really are in an SRCU read-side critical section.
+ *
+ * Makes rcu_dereference_check() do the dirty work.  If PROVE_RCU
+ * is enabled, invoking this outside of an RCU read-side critical
+ * section will result in an RCU-lockdep splat.
+ */
+#define srcu_dereference(p, sp) srcu_dereference_check((p), (sp), 0)
 
 /**
  * srcu_read_lock - register a new reader for an SRCU-protected structure.
  * @sp: srcu_struct in which to register the new reader.
  *
  * Enter an SRCU read-side critical section.  Note that SRCU read-side
- * critical sections may be nested.
+ * critical sections may be nested.  However, it is illegal to
+ * call anything that waits on an SRCU grace period for the same
+ * srcu_struct, whether directly or indirectly.  Please note that
+ * one way to indirectly wait on an SRCU grace period is to acquire
+ * a mutex that is held elsewhere while calling synchronize_srcu() or
+ * synchronize_srcu_expedited().
  */
 static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
 {
index 6b524a0d02e42b14419c5ae75133360a1f4874a5..1808960c50595908935455ca90a80fc02e421ef0 100644 (file)
@@ -126,8 +126,8 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
 
 #else   /* CONFIG_STOP_MACHINE && CONFIG_SMP */
 
-static inline int stop_machine(int (*fn)(void *), void *data,
-                              const struct cpumask *cpus)
+static inline int __stop_machine(int (*fn)(void *), void *data,
+                                const struct cpumask *cpus)
 {
        int ret;
        local_irq_disable();
@@ -136,5 +136,11 @@ static inline int stop_machine(int (*fn)(void *), void *data,
        return ret;
 }
 
+static inline int stop_machine(int (*fn)(void *), void *data,
+                              const struct cpumask *cpus)
+{
+       return __stop_machine(fn, data, cpus);
+}
+
 #endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */
 #endif /* _LINUX_STOP_MACHINE */
index 671538d25bc15b623155f2b7b7fd269ce394b5d6..8eee9dbbfe7aaddbdb5aaebfbaf5ad82669f846d 100644 (file)
@@ -69,7 +69,7 @@ struct gss_cl_ctx {
        enum rpc_gss_proc       gc_proc;
        u32                     gc_seq;
        spinlock_t              gc_seq_lock;
-       struct gss_ctx          *gc_gss_ctx;
+       struct gss_ctx __rcu    *gc_gss_ctx;
        struct xdr_netobj       gc_wire_ctx;
        u32                     gc_win;
        unsigned long           gc_expiry;
@@ -80,7 +80,7 @@ struct gss_upcall_msg;
 struct gss_cred {
        struct rpc_cred         gc_base;
        enum rpc_gss_svc        gc_service;
-       struct gss_cl_ctx       *gc_ctx;
+       struct gss_cl_ctx __rcu *gc_ctx;
        struct gss_upcall_msg   *gc_upcall;
        unsigned long           gc_upcall_timestamp;
        unsigned char           gc_machine_cred : 1;
index 569dc722a600d55834055cf22474858ef69f5bae..85f38a63f098a2c55989f1e5d4e070595e525a99 100644 (file)
@@ -30,7 +30,7 @@ struct rpc_inode;
  * The high-level client handle
  */
 struct rpc_clnt {
-       struct kref             cl_kref;        /* Number of references */
+       atomic_t                cl_count;       /* Number of references */
        struct list_head        cl_clients;     /* Global list of clients */
        struct list_head        cl_tasks;       /* List of tasks */
        spinlock_t              cl_lock;        /* spinlock */
index 4af270ec2204424db83ee330a74e891adb99959b..26697514c5ece07d72f6e07022f43ee86d187de0 100644 (file)
@@ -293,8 +293,8 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
 extern bool events_check_enabled;
 
 extern bool pm_check_wakeup_events(void);
-extern bool pm_get_wakeup_count(unsigned long *count);
-extern bool pm_save_wakeup_count(unsigned long count);
+extern bool pm_get_wakeup_count(unsigned int *count);
+extern bool pm_save_wakeup_count(unsigned int count);
 #else /* !CONFIG_PM_SLEEP */
 
 static inline int register_pm_notifier(struct notifier_block *nb)
@@ -308,6 +308,8 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
 }
 
 #define pm_notifier(fn, pri)   do { (void)(fn); } while (0)
+
+static inline bool pm_check_wakeup_events(void) { return true; }
 #endif /* !CONFIG_PM_SLEEP */
 
 extern struct mutex pm_mutex;
index 2fee51a11b7399aea7ea7427ae32777b45cf8903..7cdd63366f883a164a7f5d5b74ff8882c62b4f8c 100644 (file)
@@ -19,6 +19,7 @@ struct bio;
 #define SWAP_FLAG_PREFER       0x8000  /* set if swap priority specified */
 #define SWAP_FLAG_PRIO_MASK    0x7fff
 #define SWAP_FLAG_PRIO_SHIFT   0
+#define SWAP_FLAG_DISCARD      0x10000 /* discard swap cluster after use */
 
 static inline int current_is_kswapd(void)
 {
@@ -142,7 +143,7 @@ struct swap_extent {
 enum {
        SWP_USED        = (1 << 0),     /* is slot in swap_info[] used? */
        SWP_WRITEOK     = (1 << 1),     /* ok to write to this swap?    */
-       SWP_DISCARDABLE = (1 << 2),     /* blkdev supports discard */
+       SWP_DISCARDABLE = (1 << 2),     /* swapon+blkdev support discard */
        SWP_DISCARDING  = (1 << 3),     /* now discarding a free cluster */
        SWP_SOLIDSTATE  = (1 << 4),     /* blkdev seeks are cheap */
        SWP_CONTINUED   = (1 << 5),     /* swap_map has count continuation */
@@ -315,6 +316,7 @@ extern long nr_swap_pages;
 extern long total_swap_pages;
 extern void si_swapinfo(struct sysinfo *);
 extern swp_entry_t get_swap_page(void);
+extern swp_entry_t get_swap_page_of_type(int);
 extern int valid_swaphandles(swp_entry_t, unsigned long *);
 extern int add_swap_count_continuation(swp_entry_t, gfp_t);
 extern void swap_shmem_alloc(swp_entry_t);
@@ -331,13 +333,6 @@ extern int reuse_swap_page(struct page *);
 extern int try_to_free_swap(struct page *);
 struct backing_dev_info;
 
-#ifdef CONFIG_HIBERNATION
-void hibernation_freeze_swap(void);
-void hibernation_thaw_swap(void);
-swp_entry_t get_swap_for_hibernation(int type);
-void swap_free_for_hibernation(swp_entry_t val);
-#endif
-
 /* linux/mm/thrash.c */
 extern struct mm_struct *swap_token_mm;
 extern void grab_swap_token(struct mm_struct *);
index 3c92121ba9afb3f75700e540e24c52f3aae8b974..30b881555fa576fc4a0fb9a82f8418fac72aefa2 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/lockdep.h>
+#include <linux/kobject_ns.h>
 #include <asm/atomic.h>
 
 struct kobject;
@@ -163,6 +164,10 @@ int sysfs_add_file_to_group(struct kobject *kobj,
                        const struct attribute *attr, const char *group);
 void sysfs_remove_file_from_group(struct kobject *kobj,
                        const struct attribute *attr, const char *group);
+int sysfs_merge_group(struct kobject *kobj,
+                      const struct attribute_group *grp);
+void sysfs_unmerge_group(struct kobject *kobj,
+                      const struct attribute_group *grp);
 
 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
 void sysfs_notify_dirent(struct sysfs_dirent *sd);
@@ -301,6 +306,17 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
 {
 }
 
+static inline int sysfs_merge_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+       return 0;
+}
+
+static inline void sysfs_unmerge_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+}
+
 static inline void sysfs_notify(struct kobject *kobj, const char *dir,
                                const char *attr)
 {
index 609e8ca5f53429bddfc2c29aee5e0411cfe464af..387fa7d05c982b758942f83395e328949324fc1a 100644 (file)
@@ -15,9 +15,7 @@
 #define _LINUX_SYSRQ_H
 
 #include <linux/errno.h>
-
-struct pt_regs;
-struct tty_struct;
+#include <linux/types.h>
 
 /* Possible values of bitmask for enabling sysrq functions */
 /* 0x0001 is reserved for enable everything */
@@ -31,7 +29,7 @@ struct tty_struct;
 #define SYSRQ_ENABLE_RTNICE    0x0100
 
 struct sysrq_key_op {
-       void (*handler)(int, struct tty_struct *);
+       void (*handler)(int);
        char *help_msg;
        char *action_msg;
        int enable_mask;
@@ -44,8 +42,8 @@ struct sysrq_key_op {
  * are available -- else NULL's).
  */
 
-void handle_sysrq(int key, struct tty_struct *tty);
-void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
+void handle_sysrq(int key);
+void __handle_sysrq(int key, bool check_mask);
 int register_sysrq_key(int key, struct sysrq_key_op *op);
 int unregister_sysrq_key(int key, struct sysrq_key_op *op);
 struct sysrq_key_op *__sysrq_get_key_op(int key);
@@ -54,7 +52,11 @@ int sysrq_toggle_support(int enable_mask);
 
 #else
 
-static inline void handle_sysrq(int key, struct tty_struct *tty)
+static inline void handle_sysrq(int key)
+{
+}
+
+static inline void __handle_sysrq(int key, bool check_mask)
 {
 }
 
index a8cc4e13434c4261ae8ab536566b23fcd777286a..c90696544176902262699186b32dc1c515311a15 100644 (file)
@@ -23,12 +23,12 @@ struct restart_block {
                };
                /* For futex_wait and futex_wait_requeue_pi */
                struct {
-                       u32 *uaddr;
+                       u32 __user *uaddr;
                        u32 val;
                        u32 flags;
                        u32 bitset;
                        u64 time;
-                       u32 *uaddr2;
+                       u32 __user *uaddr2;
                } futex;
                /* For nanosleep */
                struct {
index 64e084ff5e5c9a6e68257068821b79110a760f02..b91a40e847d236d9046dc3154a7e7a58ea594776 100644 (file)
@@ -201,6 +201,12 @@ int arch_update_cpu_topology(void);
        .balance_interval       = 64,                                   \
 }
 
+#ifdef CONFIG_SCHED_BOOK
+#ifndef SD_BOOK_INIT
+#error Please define an appropriate SD_BOOK_INIT in include/asm/topology.h!!!
+#endif
+#endif /* CONFIG_SCHED_BOOK */
+
 #ifdef CONFIG_NUMA
 #ifndef SD_NODE_INIT
 #error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
index 103d1b61aacba635bb7c81cef9e32b70fe220bb7..a4a90b6726ce6129b43174609fb3e35a2bd088ae 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
+#include <linux/jump_label.h>
 
 struct module;
 struct tracepoint;
@@ -145,7 +146,9 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
        extern struct tracepoint __tracepoint_##name;                   \
        static inline void trace_##name(proto)                          \
        {                                                               \
-               if (unlikely(__tracepoint_##name.state))                \
+               JUMP_LABEL(&__tracepoint_##name.state, do_trace);       \
+               return;                                                 \
+do_trace:                                                              \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TP_PROTO(data_proto),                   \
                                TP_ARGS(data_args));                    \
index 01a082f56ef423065adb66f621b11db2bd1d88f1..357dbc19606f8920f0b060ad04fb1d4fb2dfca00 100644 (file)
@@ -121,7 +121,15 @@ typedef            __u64           u_int64_t;
 typedef                __s64           int64_t;
 #endif
 
-/* this is a special 64bit data type that is 8-byte aligned */
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
 #define aligned_u64 __u64 __attribute__((aligned(8)))
 #define aligned_be64 __be64 __attribute__((aligned(8)))
 #define aligned_le64 __le64 __attribute__((aligned(8)))
@@ -178,6 +186,11 @@ typedef __u64 __bitwise __be64;
 typedef __u16 __bitwise __sum16;
 typedef __u32 __bitwise __wsum;
 
+/* this is a special 64bit data type that is 8-byte aligned */
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
 #ifdef __KERNEL__
 typedef unsigned __bitwise__ gfp_t;
 typedef unsigned __bitwise__ fmode_t;
index 60c81da77f0f36b94bde7d83562db55dfa707d92..05f7fed2b173eb8205b0754ee3a00de730215e8e 100644 (file)
@@ -37,7 +37,6 @@
 #define UINPUT_VERSION         3
 
 #ifdef __KERNEL__
-#define UINPUT_MINOR           223
 #define UINPUT_NAME            "uinput"
 #define UINPUT_BUFFER_SIZE     16
 #define UINPUT_NUM_REQUESTS    16
index 890bc1472190f2189026e17792750f0f14706ff3..617068134ae8a91cadc1f7ccf42761cf212b5adf 100644 (file)
@@ -247,6 +247,7 @@ int usb_add_config(struct usb_composite_dev *,
  *     value; it should return zero on successful initialization.
  * @unbind: Reverses @bind(); called as a side effect of unregistering
  *     this driver.
+ * @disconnect: optional driver disconnect method
  * @suspend: Notifies when the host stops sending USB traffic,
  *     after function notifications
  * @resume: Notifies configuration when the host restarts USB traffic,
index 84a4c44c208b78a7eb9602091bc5a1401afdab8d..55675b1efb28659b37ff7b165fc6aa6ab0835fd7 100644 (file)
@@ -342,8 +342,7 @@ extern int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
 extern void usb_serial_generic_process_read_urb(struct urb *urb);
 extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
                                                void *dest, size_t size);
-extern int usb_serial_handle_sysrq_char(struct tty_struct *tty,
-                                       struct usb_serial_port *port,
+extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port,
                                        unsigned int ch);
 extern int usb_serial_handle_break(struct usb_serial_port *port);
 
index 6228b5b77d35860019adcf84747819e0e9e43ea6..e9e1524b582cbde9b1988107d9c50a86a68f08ae 100644 (file)
@@ -93,8 +93,11 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
  *     Nested calls are supported (a per-resource counter is maintained)
  */
 
-extern int vga_get(struct pci_dev *pdev, unsigned int rsrc,
-                                                                                       int interruptible);
+#if defined(CONFIG_VGA_ARB)
+extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
+#else
+static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) { return 0; }
+#endif
 
 /**
  *     vga_get_interruptible
@@ -131,7 +134,11 @@ static inline int vga_get_uninterruptible(struct pci_dev *pdev,
  *     are already locked by another card. It can be called in any context
  */
 
+#if defined(CONFIG_VGA_ARB)
 extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc);
+#else
+static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; }
+#endif
 
 /**
  *     vga_put         - release lock on legacy VGA resources
@@ -146,7 +153,11 @@ extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc);
  *     released if the counter reaches 0.
  */
 
+#if defined(CONFIG_VGA_ARB)
 extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
+#else
+#define vga_put(pdev, rsrc)
+#endif
 
 
 /**
index 7f43ccdc1d38c0eb919efe4891e1b91ec19c3705..eaaea37b3b75dd64b73a34a0e3beb31417bdd0d6 100644 (file)
@@ -170,6 +170,28 @@ static inline unsigned long zone_page_state(struct zone *zone,
        return x;
 }
 
+/*
+ * More accurate version that also considers the currently pending
+ * deltas. For that we need to loop over all cpus to find the current
+ * deltas. There is no synchronization so the result cannot be
+ * exactly accurate either.
+ */
+static inline unsigned long zone_page_state_snapshot(struct zone *zone,
+                                       enum zone_stat_item item)
+{
+       long x = atomic_long_read(&zone->vm_stat[item]);
+
+#ifdef CONFIG_SMP
+       int cpu;
+       for_each_online_cpu(cpu)
+               x += per_cpu_ptr(zone->pageset, cpu)->vm_stat_diff[item];
+
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
+}
+
 extern unsigned long global_reclaimable_pages(void);
 extern unsigned long zone_reclaimable_pages(struct zone *zone);
 
index 0836ccc5712146f87d13e9e35a9480e980708392..3efc9f3f43a0862cad51aa325e08c9f24d129f8e 100644 (file)
@@ -614,6 +614,7 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
                (wait)->private = current;                              \
                (wait)->func = autoremove_wake_function;                \
                INIT_LIST_HEAD(&(wait)->task_list);                     \
+               (wait)->flags = 0;                                      \
        } while (0)
 
 /**
index 4f9d277bcd9a5cd32ef35bc304bdbe3f6339a38a..25e02c941bac34a5322510f0461998b1054259fc 100644 (file)
@@ -25,18 +25,20 @@ typedef void (*work_func_t)(struct work_struct *work);
 
 enum {
        WORK_STRUCT_PENDING_BIT = 0,    /* work item is pending execution */
-       WORK_STRUCT_CWQ_BIT     = 1,    /* data points to cwq */
-       WORK_STRUCT_LINKED_BIT  = 2,    /* next work is linked to this one */
+       WORK_STRUCT_DELAYED_BIT = 1,    /* work item is delayed */
+       WORK_STRUCT_CWQ_BIT     = 2,    /* data points to cwq */
+       WORK_STRUCT_LINKED_BIT  = 3,    /* next work is linked to this one */
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
-       WORK_STRUCT_STATIC_BIT  = 3,    /* static initializer (debugobjects) */
-       WORK_STRUCT_COLOR_SHIFT = 4,    /* color for workqueue flushing */
+       WORK_STRUCT_STATIC_BIT  = 4,    /* static initializer (debugobjects) */
+       WORK_STRUCT_COLOR_SHIFT = 5,    /* color for workqueue flushing */
 #else
-       WORK_STRUCT_COLOR_SHIFT = 3,    /* color for workqueue flushing */
+       WORK_STRUCT_COLOR_SHIFT = 4,    /* color for workqueue flushing */
 #endif
 
        WORK_STRUCT_COLOR_BITS  = 4,
 
        WORK_STRUCT_PENDING     = 1 << WORK_STRUCT_PENDING_BIT,
+       WORK_STRUCT_DELAYED     = 1 << WORK_STRUCT_DELAYED_BIT,
        WORK_STRUCT_CWQ         = 1 << WORK_STRUCT_CWQ_BIT,
        WORK_STRUCT_LINKED      = 1 << WORK_STRUCT_LINKED_BIT,
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
@@ -59,8 +61,8 @@ enum {
 
        /*
         * Reserve 7 bits off of cwq pointer w/ debugobjects turned
-        * off.  This makes cwqs aligned to 128 bytes which isn't too
-        * excessive while allowing 15 workqueue flush colors.
+        * off.  This makes cwqs aligned to 256 bytes and allows 15
+        * workqueue flush colors.
         */
        WORK_STRUCT_FLAG_BITS   = WORK_STRUCT_COLOR_SHIFT +
                                  WORK_STRUCT_COLOR_BITS,
@@ -233,6 +235,10 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
 #define work_clear_pending(work) \
        clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))
 
+/*
+ * Workqueue flags and constants.  For details, please refer to
+ * Documentation/workqueue.txt.
+ */
 enum {
        WQ_NON_REENTRANT        = 1 << 0, /* guarantee non-reentrance */
        WQ_UNBOUND              = 1 << 1, /* not bound to any cpu */
@@ -241,6 +247,8 @@ enum {
        WQ_HIGHPRI              = 1 << 4, /* high priority */
        WQ_CPU_INTENSIVE        = 1 << 5, /* cpu instensive workqueue */
 
+       WQ_DYING                = 1 << 6, /* internal: workqueue is dying */
+
        WQ_MAX_ACTIVE           = 512,    /* I like 512, better ideas? */
        WQ_MAX_UNBOUND_PER_CPU  = 4,      /* 4 * #cpus for unbound wq */
        WQ_DFL_ACTIVE           = WQ_MAX_ACTIVE / 2,
index 97e07f46a0fae22f1cba1eb3073f5661cc97b95a..aa4ebb42a5652b2261b1a2dbbbe133cbd5fbfe51 100644 (file)
@@ -48,6 +48,7 @@ struct videobuf_dmabuf {
 
        /* for userland buffer */
        int                 offset;
+       size_t              size;
        struct page         **pages;
 
        /* for kernel buffers */
index 45375b41a2a0d44e62a370813ab4fdcbe046e3b3..4d40c4d0230baeffbafcb57cb6fac99a1f0174b3 100644 (file)
@@ -121,6 +121,7 @@ static inline int addrconf_finite_timeout(unsigned long timeout)
  *     IPv6 Address Label subsystem (addrlabel.c)
  */
 extern int                     ipv6_addr_label_init(void);
+extern void                    ipv6_addr_label_cleanup(void);
 extern void                    ipv6_addr_label_rtnl_register(void);
 extern u32                     ipv6_addr_label(struct net *net,
                                                const struct in6_addr *addr,
index 27a902d9b3a9a431c6b3162a4c6fe479aa99504c..30fce0128dd72fa0281795bc0ae03809b85bc9d0 100644 (file)
@@ -161,12 +161,30 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long l
 {
        struct sk_buff *skb;
 
+       release_sock(sk);
        if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
                skb_reserve(skb, BT_SKB_RESERVE);
                bt_cb(skb)->incoming  = 0;
        }
+       lock_sock(sk);
+
+       if (!skb && *err)
+               return NULL;
+
+       *err = sock_error(sk);
+       if (*err)
+               goto out;
+
+       if (sk->sk_shutdown) {
+               *err = -ECONNRESET;
+               goto out;
+       }
 
        return skb;
+
+out:
+       kfree_skb(skb);
+       return NULL;
 }
 
 int bt_err(__u16 code);
index 726cc353640988bd6fed9361f74cb8ef6dfbb9ce..a4dc5b027bd9cc7731b7fab1146508896c0b215c 100644 (file)
@@ -27,11 +27,17 @@ struct cgroup_cls_state
 #ifdef CONFIG_NET_CLS_CGROUP
 static inline u32 task_cls_classid(struct task_struct *p)
 {
+       int classid;
+
        if (in_interrupt())
                return 0;
 
-       return container_of(task_subsys_state(p, net_cls_subsys_id),
-                           struct cgroup_cls_state, css)->classid;
+       rcu_read_lock();
+       classid = container_of(task_subsys_state(p, net_cls_subsys_id),
+                              struct cgroup_cls_state, css)->classid;
+       rcu_read_unlock();
+
+       return classid;
 }
 #else
 extern int net_cls_subsys_id;
@@ -45,7 +51,8 @@ static inline u32 task_cls_classid(struct task_struct *p)
                return 0;
 
        rcu_read_lock();
-       id = rcu_dereference(net_cls_subsys_id);
+       id = rcu_dereference_index_check(net_cls_subsys_id,
+                                        rcu_read_lock_held());
        if (id >= 0)
                classid = container_of(task_subsys_state(p, id),
                                       struct cgroup_cls_state, css)->classid;
index 81d1413a87010967684febe7344169baa7d828ef..02386505033d975e666cd924a3bafe3ca02bb100 100644 (file)
@@ -242,6 +242,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
        dev->stats.rx_packets++;
        dev->stats.rx_bytes += skb->len;
        skb->rxhash = 0;
+       skb_set_queue_mapping(skb, 0);
        skb_dst_drop(skb);
        nf_reset(skb);
 }
index a4747a0f7303ab73b1dffa7cd9a66740c0ef0ffe..f976885f686f67f593d2928175e9f06de1c94f56 100644 (file)
@@ -955,6 +955,9 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
        return csum_partial(diff, sizeof(diff), oldsum);
 }
 
+extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
+                                  int outin);
+
 #endif /* __KERNEL__ */
 
 #endif /* _NET_IP_VS_H */
index e624dae54fa49b7d713b78641c7f18c2e3cfbae2..caf17db87dbc8983f4aeef52a54c2424a7d21054 100644 (file)
@@ -75,7 +75,7 @@ struct nf_conntrack_helper;
 /* nf_conn feature for connections that have a helper */
 struct nf_conn_help {
        /* Helper. if any */
-       struct nf_conntrack_helper *helper;
+       struct nf_conntrack_helper __rcu *helper;
 
        union nf_conntrack_help help;
 
index bd732d62e1c3a3181c7c324d695b02e1548970e0..7e5e73bfa4dec8e2d45c834507f74d86484b8715 100644 (file)
@@ -199,6 +199,8 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
                fl.fl_ip_sport = sport;
                fl.fl_ip_dport = dport;
                fl.proto = protocol;
+               if (inet_sk(sk)->transparent)
+                       fl.flags |= FLOWI_FLAG_ANYSRC;
                ip_rt_put(*rp);
                *rp = NULL;
                security_sk_classify_flow(sk, &fl);
index ac53bfbdfe16b57038cf6c0b7f88cc88f5221594..adab9dc5818355c603a699101c4787c99434eb12 100644 (file)
@@ -752,6 +752,7 @@ struct proto {
        /* Keeping track of sk's, looking them up, and port selection methods. */
        void                    (*hash)(struct sock *sk);
        void                    (*unhash)(struct sock *sk);
+       void                    (*rehash)(struct sock *sk);
        int                     (*get_port)(struct sock *sk, unsigned short snum);
 
        /* Keeping track of sockets in use */
index df6a2eb20193f935bc72204ca22c7f2f21b5070f..3e4b33e36602caade361654d0561a65b3fba2224 100644 (file)
@@ -268,11 +268,21 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
        return seq3 - seq2 >= seq1 - seq2;
 }
 
-static inline int tcp_too_many_orphans(struct sock *sk, int num)
+static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
 {
-       return (num > sysctl_tcp_max_orphans) ||
-               (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-                atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]);
+       struct percpu_counter *ocp = sk->sk_prot->orphan_count;
+       int orphans = percpu_counter_read_positive(ocp);
+
+       if (orphans << shift > sysctl_tcp_max_orphans) {
+               orphans = percpu_counter_sum_positive(ocp);
+               if (orphans << shift > sysctl_tcp_max_orphans)
+                       return true;
+       }
+
+       if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+           atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
+               return true;
+       return false;
 }
 
 /* syncookies: remember time of last synqueue overflow */
@@ -465,8 +475,22 @@ extern unsigned int tcp_current_mss(struct sock *sk);
 /* Bound MSS / TSO packet size with the half of the window */
 static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
 {
-       if (tp->max_window && pktsize > (tp->max_window >> 1))
-               return max(tp->max_window >> 1, 68U - tp->tcp_header_len);
+       int cutoff;
+
+       /* When peer uses tiny windows, there is no use in packetizing
+        * to sub-MSS pieces for the sake of SWS or making sure there
+        * are enough packets in the pipe for fast recovery.
+        *
+        * On the other hand, for extremely large MSS devices, handling
+        * smaller than MSS windows in this way does make sense.
+        */
+       if (tp->max_window >= 512)
+               cutoff = (tp->max_window >> 1);
+       else
+               cutoff = tp->max_window;
+
+       if (cutoff && pktsize > cutoff)
+               return max_t(int, cutoff, 68U - tp->tcp_header_len);
        else
                return pktsize;
 }
index 7abdf305da50fad63880b12c2c76a69b6b74a5fd..a184d3496b1369deefd62aba376f04320f76a773 100644 (file)
@@ -151,6 +151,7 @@ static inline void udp_lib_hash(struct sock *sk)
 }
 
 extern void udp_lib_unhash(struct sock *sk);
+extern void udp_lib_rehash(struct sock *sk, u16 new_hash);
 
 static inline void udp_lib_close(struct sock *sk, long timeout)
 {
index fc8f36dd0f5c5145932c45aa8e9f441697dcb0ec..4f53532d4c2f0f6e20d200fabafe1ac51dd1632c 100644 (file)
@@ -298,8 +298,8 @@ struct xfrm_state_afinfo {
        const struct xfrm_type  *type_map[IPPROTO_MAX];
        struct xfrm_mode        *mode_map[XFRM_MODE_MAX];
        int                     (*init_flags)(struct xfrm_state *x);
-       void                    (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
-                                               struct xfrm_tmpl *tmpl,
+       void                    (*init_tempsel)(struct xfrm_selector *sel, struct flowi *fl);
+       void                    (*init_temprop)(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
                                                xfrm_address_t *daddr, xfrm_address_t *saddr);
        int                     (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
        int                     (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
deleted file mode 100644 (file)
index 68d8bde..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * cs.h
- *
- * 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.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * (C) 1999             David A. Hinds
- */
-
-#ifndef _LINUX_CS_H
-#define _LINUX_CS_H
-
-#ifdef __KERNEL__
-#include <linux/interrupt.h>
-#endif
-
-/* ModifyConfiguration */
-typedef struct modconf_t {
-    u_int      Attributes;
-    u_int      Vcc, Vpp1, Vpp2;
-} modconf_t;
-
-/* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID  0x0100
-#define CONF_VCC_CHANGE_VALID  0x0200
-#define CONF_VPP1_CHANGE_VALID 0x0400
-#define CONF_VPP2_CHANGE_VALID 0x0800
-#define CONF_IO_CHANGE_WIDTH   0x1000
-
-/* For RequestConfiguration */
-typedef struct config_req_t {
-    u_int      Attributes;
-    u_int      Vpp; /* both Vpp1 and Vpp2 */
-    u_int      IntType;
-    u_int      ConfigBase;
-    u_char     Status, Pin, Copy, ExtStatus;
-    u_char     ConfigIndex;
-    u_int      Present;
-} config_req_t;
-
-/* Attributes for RequestConfiguration */
-#define CONF_ENABLE_IRQ                0x01
-#define CONF_ENABLE_DMA                0x02
-#define CONF_ENABLE_SPKR       0x04
-#define CONF_ENABLE_PULSE_IRQ  0x08
-#define CONF_VALID_CLIENT      0x100
-
-/* IntType field */
-#define INT_MEMORY             0x01
-#define INT_MEMORY_AND_IO      0x02
-#define INT_CARDBUS            0x04
-#define INT_ZOOMED_VIDEO       0x08
-
-/* Configuration registers present */
-#define PRESENT_OPTION         0x001
-#define PRESENT_STATUS         0x002
-#define PRESENT_PIN_REPLACE    0x004
-#define PRESENT_COPY           0x008
-#define PRESENT_EXT_STATUS     0x010
-#define PRESENT_IOBASE_0       0x020
-#define PRESENT_IOBASE_1       0x040
-#define PRESENT_IOBASE_2       0x080
-#define PRESENT_IOBASE_3       0x100
-#define PRESENT_IOSIZE         0x200
-
-/* For RequestWindow */
-typedef struct win_req_t {
-    u_int      Attributes;
-    u_long     Base;
-    u_int      Size;
-    u_int      AccessSpeed;
-} win_req_t;
-
-/* Attributes for RequestWindow */
-#define WIN_MEMORY_TYPE_CM     0x00 /* default */
-#define WIN_MEMORY_TYPE_AM     0x20 /* MAP_ATTRIB */
-#define WIN_DATA_WIDTH_8       0x00 /* default */
-#define WIN_DATA_WIDTH_16      0x02 /* MAP_16BIT */
-#define WIN_ENABLE             0x01 /* MAP_ACTIVE */
-#define WIN_USE_WAIT           0x40 /* MAP_USE_WAIT */
-
-#define WIN_FLAGS_MAP          0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
-                                       MAP_USE_WAIT */
-#define WIN_FLAGS_REQ          0x1c /* mapping to socket->win[i]:
-                                       0x04 -> 0
-                                       0x08 -> 1
-                                       0x0c -> 2
-                                       0x10 -> 3 */
-
-#endif /* _LINUX_CS_H */
index 70c58ed2278c43f80a355b7aac9c30f40bd2a315..8479b66c067bbab89374f55551e775ff61d47f29 100644 (file)
 
 #ifdef __KERNEL__
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <pcmcia/ss.h>
 #include <asm/atomic.h>
 
+
 /*
  * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
  * a.k.a. PCI drivers
@@ -36,8 +38,6 @@ struct pcmcia_device;
 struct config_t;
 struct net_device;
 
-typedef struct resource *window_handle_t;
-
 /* dynamic device IDs for PCMCIA device drivers. See
  * Documentation/pcmcia/driver.txt for details.
 */
@@ -47,6 +47,8 @@ struct pcmcia_dynids {
 };
 
 struct pcmcia_driver {
+       const char              *name;
+
        int (*probe)            (struct pcmcia_device *dev);
        void (*remove)          (struct pcmcia_device *dev);
 
@@ -90,15 +92,17 @@ struct pcmcia_device {
 
        struct list_head        socket_device_list;
 
-       /* deprecated, will be cleaned up soon */
-       config_req_t            conf;
-       window_handle_t         win;
-
        /* device setup */
        unsigned int            irq;
        struct resource         *resource[PCMCIA_NUM_RESOURCES];
+       resource_size_t         card_addr;      /* for the 1st IOMEM resource */
+       unsigned int            vpp;
 
-       unsigned int            io_lines; /* number of I/O lines */
+       unsigned int            config_flags;   /* CONF_ENABLE_ flags below */
+       unsigned int            config_base;
+       unsigned int            config_index;
+       unsigned int            config_regs;    /* PRESENT_ flags below */
+       unsigned int            io_lines;       /* number of I/O lines */
 
        /* Is the device suspended? */
        u16                     suspended:1;
@@ -174,9 +178,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse);
 /* loop CIS entries for valid configuration */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
                       int      (*conf_check)   (struct pcmcia_device *p_dev,
-                                                cistpl_cftable_entry_t *cf,
-                                                cistpl_cftable_entry_t *dflt,
-                                                unsigned int vcc,
                                                 void *priv_data),
                       void *priv_data);
 
@@ -206,16 +207,17 @@ pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
                                irq_handler_t handler);
 
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-                                config_req_t *req);
+int pcmcia_enable_device(struct pcmcia_device *p_dev);
 
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req,
-                         window_handle_t *wh);
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win);
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win,
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+                       unsigned int speed);
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
                        unsigned int offset);
 
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp);
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev);
+
 void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 /* IO ports */
@@ -224,15 +226,48 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev);
 #define IO_DATA_PATH_WIDTH_16  0x08
 #define IO_DATA_PATH_WIDTH_AUTO        0x10
 
-/* convert flag found in cfgtable to data path width parameter */
-static inline int pcmcia_io_cfg_data_width(unsigned int flags)
-{
-       if (!(flags & CISTPL_IO_8BIT))
-               return IO_DATA_PATH_WIDTH_16;
-       if (!(flags & CISTPL_IO_16BIT))
-               return IO_DATA_PATH_WIDTH_8;
-       return IO_DATA_PATH_WIDTH_AUTO;
-}
+/* IO memory */
+#define WIN_MEMORY_TYPE_CM     0x00 /* default */
+#define WIN_MEMORY_TYPE_AM     0x20 /* MAP_ATTRIB */
+#define WIN_DATA_WIDTH_8       0x00 /* default */
+#define WIN_DATA_WIDTH_16      0x02 /* MAP_16BIT */
+#define WIN_ENABLE             0x01 /* MAP_ACTIVE */
+#define WIN_USE_WAIT           0x40 /* MAP_USE_WAIT */
+
+#define WIN_FLAGS_MAP          0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
+                                       MAP_USE_WAIT */
+#define WIN_FLAGS_REQ          0x1c /* mapping to socket->win[i]:
+                                       0x04 -> 0
+                                       0x08 -> 1
+                                       0x0c -> 2
+                                       0x10 -> 3 */
+
+/* config_reg{ister}s present for this PCMCIA device */
+#define PRESENT_OPTION         0x001
+#define PRESENT_STATUS         0x002
+#define PRESENT_PIN_REPLACE    0x004
+#define PRESENT_COPY           0x008
+#define PRESENT_EXT_STATUS     0x010
+#define PRESENT_IOBASE_0       0x020
+#define PRESENT_IOBASE_1       0x040
+#define PRESENT_IOBASE_2       0x080
+#define PRESENT_IOBASE_3       0x100
+#define PRESENT_IOSIZE         0x200
+
+/* flags to be passed to pcmcia_enable_device() */
+#define CONF_ENABLE_IRQ         0x0001
+#define CONF_ENABLE_SPKR        0x0002
+#define CONF_ENABLE_PULSE_IRQ   0x0004
+#define CONF_ENABLE_ESR         0x0008
+#define CONF_ENABLE_IOCARD     0x0010 /* auto-enabled if IO resources or IRQ
+                                       * (CONF_ENABLE_IRQ) in use */
+
+/* flags used by pcmcia_loop_config() autoconfiguration */
+#define CONF_AUTO_CHECK_VCC    0x0100 /* check for matching Vcc? */
+#define CONF_AUTO_SET_VPP      0x0200 /* set Vpp? */
+#define CONF_AUTO_AUDIO                0x0400 /* enable audio line? */
+#define CONF_AUTO_SET_IO       0x0800 /* set ->resource[0,1] */
+#define CONF_AUTO_SET_IOMEM    0x1000 /* set ->resource[2] */
 
 #endif /* __KERNEL__ */
 
index 626b63c33d9e0e374387ca106063d19048899bb5..731cde010f424250cc8fe5f45aae772b0f2877f4 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>       /* task_struct, completion */
 #include <linux/mutex.h>
 
-#include <pcmcia/cs.h>
 #ifdef CONFIG_CARDBUS
 #include <linux/pci.h>
 #endif
index 0e4cfb694fe70630457af67e1b1bc568f56c9b09..6fa7cbab7d932c6649e9fbd4221615b6b4d0fd8d 100644 (file)
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)                         \
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
        ),
 
        TP_fast_assign(
-               __entry->vec = (int)(h - vec);
+               if (vec)
+                       __entry->vec = (int)(h - vec);
+               else
+                       __entry->vec = (int)(long)h;
        ),
 
        TP_printk("vec=%d [action=%s]", __entry->vec,
@@ -136,6 +141,23 @@ DEFINE_EVENT(softirq, softirq_exit,
        TP_ARGS(h, vec)
 );
 
+/**
+ * softirq_raise - called immediately when a softirq is raised
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter contains a pointer to the softirq vector number which is
+ * raised. @vec is NULL and it means @h includes vector number not
+ * softirq_action. When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise latency.
+ */
+DEFINE_EVENT(softirq, softirq_raise,
+
+       TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+       TP_ARGS(h, vec)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
index 188deca2f3c7721a1baac60cc07e8d7006442c71..8fe1e93f531dd81a8e549689a1b8e9b551231e9e 100644 (file)
@@ -6,10 +6,31 @@
 
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
+#include <linux/ftrace.h>
+
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(napi_poll,
 
-DECLARE_TRACE(napi_poll,
        TP_PROTO(struct napi_struct *napi),
-       TP_ARGS(napi));
+
+       TP_ARGS(napi),
+
+       TP_STRUCT__entry(
+               __field(        struct napi_struct *,   napi)
+               __string(       dev_name, napi->dev ? napi->dev->name : NO_DEV)
+       ),
+
+       TP_fast_assign(
+               __entry->napi = napi;
+               __assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
+       ),
+
+       TP_printk("napi poll on napi struct %p for device %s",
+               __entry->napi, __get_str(dev_name))
+);
+
+#undef NO_DEV
 
 #endif /* _TRACE_NAPI_H_ */
 
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
new file mode 100644 (file)
index 0000000..5f247f5
--- /dev/null
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net
+
+#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(net_dev_xmit,
+
+       TP_PROTO(struct sk_buff *skb,
+                int rc),
+
+       TP_ARGS(skb, rc),
+
+       TP_STRUCT__entry(
+               __field(        void *,         skbaddr         )
+               __field(        unsigned int,   len             )
+               __field(        int,            rc              )
+               __string(       name,           skb->dev->name  )
+       ),
+
+       TP_fast_assign(
+               __entry->skbaddr = skb;
+               __entry->len = skb->len;
+               __entry->rc = rc;
+               __assign_str(name, skb->dev->name);
+       ),
+
+       TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+               __get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
+);
+
+DECLARE_EVENT_CLASS(net_dev_template,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb),
+
+       TP_STRUCT__entry(
+               __field(        void *,         skbaddr         )
+               __field(        unsigned int,   len             )
+               __string(       name,           skb->dev->name  )
+       ),
+
+       TP_fast_assign(
+               __entry->skbaddr = skb;
+               __entry->len = skb->len;
+               __assign_str(name, skb->dev->name);
+       ),
+
+       TP_printk("dev=%s skbaddr=%p len=%u",
+               __get_str(name), __entry->skbaddr, __entry->len)
+)
+
+DEFINE_EVENT(net_dev_template, net_dev_queue,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_receive_skb,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_rx,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb)
+);
+#endif /* _TRACE_NET_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 35a2a6e7bf1e74992b8b83b242c4a507fed4246f..286784d69b8f480343244d8046327a5a7d9883d9 100644 (file)
 #ifndef _TRACE_POWER_ENUM_
 #define _TRACE_POWER_ENUM_
 enum {
-       POWER_NONE = 0,
-       POWER_CSTATE = 1,
-       POWER_PSTATE = 2,
+       POWER_NONE      = 0,
+       POWER_CSTATE    = 1,    /* C-State */
+       POWER_PSTATE    = 2,    /* Fequency change or DVFS */
+       POWER_SSTATE    = 3,    /* Suspend */
 };
 #endif
 
+/*
+ * The power events are used for cpuidle & suspend (power_start, power_end)
+ *  and for cpufreq (power_frequency)
+ */
 DECLARE_EVENT_CLASS(power,
 
        TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),
@@ -70,6 +75,85 @@ TRACE_EVENT(power_end,
 
 );
 
+/*
+ * The clock events are used for clock enable/disable and for
+ *  clock rate change
+ */
+DECLARE_EVENT_CLASS(clock,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id),
+
+       TP_STRUCT__entry(
+               __string(       name,           name            )
+               __field(        u64,            state           )
+               __field(        u64,            cpu_id          )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, name);
+               __entry->state = state;
+               __entry->cpu_id = cpu_id;
+       ),
+
+       TP_printk("%s state=%lu cpu_id=%lu", __get_str(name),
+               (unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_enable,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_disable,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_set_rate,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id)
+);
+
+/*
+ * The power domain events are used for power domains transitions
+ */
+DECLARE_EVENT_CLASS(power_domain,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id),
+
+       TP_STRUCT__entry(
+               __string(       name,           name            )
+               __field(        u64,            state           )
+               __field(        u64,            cpu_id          )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, name);
+               __entry->state = state;
+               __entry->cpu_id = cpu_id;
+),
+
+       TP_printk("%s state=%lu cpu_id=%lu", __get_str(name),
+               (unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
+);
+
+DEFINE_EVENT(power_domain, power_domain_target,
+
+       TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+       TP_ARGS(name, state, cpu_id)
+);
+
 #endif /* _TRACE_POWER_H */
 
 /* This part must be outside protection */
index 9208c92aeab5eee575b21f3000ea8034f6c00788..f6334782a593847907b82fcfc5756040b1bd6ff8 100644 (file)
@@ -362,6 +362,35 @@ TRACE_EVENT(sched_stat_runtime,
                        (unsigned long long)__entry->vruntime)
 );
 
+/*
+ * Tracepoint for showing priority inheritance modifying a tasks
+ * priority.
+ */
+TRACE_EVENT(sched_pi_setprio,
+
+       TP_PROTO(struct task_struct *tsk, int newprio),
+
+       TP_ARGS(tsk, newprio),
+
+       TP_STRUCT__entry(
+               __array( char,  comm,   TASK_COMM_LEN   )
+               __field( pid_t, pid                     )
+               __field( int,   oldprio                 )
+               __field( int,   newprio                 )
+       ),
+
+       TP_fast_assign(
+               memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+               __entry->pid            = tsk->pid;
+               __entry->oldprio        = tsk->prio;
+               __entry->newprio        = newprio;
+       ),
+
+       TP_printk("comm=%s pid=%d oldprio=%d newprio=%d",
+                       __entry->comm, __entry->pid,
+                       __entry->oldprio, __entry->newprio)
+);
+
 #endif /* _TRACE_SCHED_H */
 
 /* This part must be outside protection */
index 4b2be6dc76f091647eb30f30a40a49218def8682..75ce9d500d8e3c62dbfffbc0acafca13d11d90aa 100644 (file)
@@ -35,6 +35,23 @@ TRACE_EVENT(kfree_skb,
                __entry->skbaddr, __entry->protocol, __entry->location)
 );
 
+TRACE_EVENT(consume_skb,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb),
+
+       TP_STRUCT__entry(
+               __field(        void *, skbaddr )
+       ),
+
+       TP_fast_assign(
+               __entry->skbaddr = skb;
+       ),
+
+       TP_printk("skbaddr=%p", __entry->skbaddr)
+);
+
 TRACE_EVENT(skb_copy_datagram_iovec,
 
        TP_PROTO(const struct sk_buff *skb, int len),
index c624126a9c8a6fb889fe596ea261f649236d51a7..425bcfe56c620211678d94f6d3923a9451305db2 100644 (file)
@@ -81,14 +81,16 @@ TRACE_EVENT(timer_expire_entry,
        TP_STRUCT__entry(
                __field( void *,        timer   )
                __field( unsigned long, now     )
+               __field( void *,        function)
        ),
 
        TP_fast_assign(
                __entry->timer          = timer;
                __entry->now            = jiffies;
+               __entry->function       = timer->function;
        ),
 
-       TP_printk("timer=%p now=%lu", __entry->timer, __entry->now)
+       TP_printk("timer=%p function=%pf now=%lu", __entry->timer, __entry->function,__entry->now)
 );
 
 /**
@@ -200,14 +202,16 @@ TRACE_EVENT(hrtimer_expire_entry,
        TP_STRUCT__entry(
                __field( void *,        hrtimer )
                __field( s64,           now     )
+               __field( void *,        function)
        ),
 
        TP_fast_assign(
                __entry->hrtimer        = hrtimer;
                __entry->now            = now->tv64;
+               __entry->function       = hrtimer->function;
        ),
 
-       TP_printk("hrtimer=%p now=%llu", __entry->hrtimer,
+       TP_printk("hrtimer=%p function=%pf now=%llu", __entry->hrtimer, __entry->function,
                  (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now }))
  );
 
index ce9d671c636c85499d7077361710baab3d50b519..a785a3b0c8c7d89d9a46e1a1d90300cb91da5308 100644 (file)
 #define XEN_IOPORT_PROTOVER    (XEN_IOPORT_BASE + 2) /* 1 byte access (R) */
 #define XEN_IOPORT_PRODNUM     (XEN_IOPORT_BASE + 2) /* 2 byte access (W) */
 
-#define XEN_UNPLUG_ALL_IDE_DISKS 1
-#define XEN_UNPLUG_ALL_NICS 2
-#define XEN_UNPLUG_AUX_IDE_DISKS 4
-#define XEN_UNPLUG_ALL 7
-#define XEN_UNPLUG_IGNORE 8
+#define XEN_UNPLUG_ALL_IDE_DISKS       (1<<0)
+#define XEN_UNPLUG_ALL_NICS            (1<<1)
+#define XEN_UNPLUG_AUX_IDE_DISKS       (1<<2)
+#define XEN_UNPLUG_ALL                 (XEN_UNPLUG_ALL_IDE_DISKS|\
+                                        XEN_UNPLUG_ALL_NICS|\
+                                        XEN_UNPLUG_AUX_IDE_DISKS)
+
+#define XEN_UNPLUG_UNNECESSARY                 (1<<16)
+#define XEN_UNPLUG_NEVER                       (1<<17)
 
 static inline int xen_must_unplug_nics(void) {
 #if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
index 950ba26f723398ec227ed83f1c75347863dbe67f..bd125a795374c5d6cab24569c4d5df7b7474790c 100644 (file)
@@ -21,6 +21,13 @@ config CONSTRUCTORS
        depends on !UML
        default y
 
+config HAVE_IRQ_WORK
+       bool
+
+config IRQ_WORK
+       bool
+       depends on HAVE_IRQ_WORK
+
 menu "General setup"
 
 config EXPERIMENTAL
@@ -64,7 +71,7 @@ config BROKEN_ON_SMP
 
 config LOCK_KERNEL
        bool
-       depends on SMP || PREEMPT
+       depends on (SMP || PREEMPT) && BKL
        default y
 
 config INIT_ENV_ARG_LIMIT
@@ -332,6 +339,8 @@ config AUDIT_TREE
        depends on AUDITSYSCALL
        select FSNOTIFY
 
+source "kernel/irq/Kconfig"
+
 menu "RCU Subsystem"
 
 choice
@@ -340,6 +349,7 @@ choice
 
 config TREE_RCU
        bool "Tree-based hierarchical RCU"
+       depends on !PREEMPT && SMP
        help
          This option selects the RCU implementation that is
          designed for very large SMP system with hundreds or
@@ -347,7 +357,7 @@ config TREE_RCU
          smaller systems.
 
 config TREE_PREEMPT_RCU
-       bool "Preemptable tree-based hierarchical RCU"
+       bool "Preemptible tree-based hierarchical RCU"
        depends on PREEMPT
        help
          This option selects the RCU implementation that is
@@ -365,8 +375,22 @@ config TINY_RCU
          is not required.  This option greatly reduces the
          memory footprint of RCU.
 
+config TINY_PREEMPT_RCU
+       bool "Preemptible UP-only small-memory-footprint RCU"
+       depends on !SMP && PREEMPT
+       help
+         This option selects the RCU implementation that is designed
+         for real-time UP systems.  This option greatly reduces the
+         memory footprint of RCU.
+
 endchoice
 
+config PREEMPT_RCU
+       def_bool ( TREE_PREEMPT_RCU || TINY_PREEMPT_RCU )
+       help
+         This option enables preemptible-RCU code that is common between
+         the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations.
+
 config RCU_TRACE
        bool "Enable tracing for RCU"
        depends on TREE_RCU || TREE_PREEMPT_RCU
@@ -387,9 +411,12 @@ config RCU_FANOUT
        help
          This option controls the fanout of hierarchical implementations
          of RCU, allowing RCU to work efficiently on machines with
-         large numbers of CPUs.  This value must be at least the cube
-         root of NR_CPUS, which allows NR_CPUS up to 32,768 for 32-bit
-         systems and up to 262,144 for 64-bit systems.
+         large numbers of CPUs.  This value must be at least the fourth
+         root of NR_CPUS, which allows NR_CPUS to be insanely large.
+         The default value of RCU_FANOUT should be used for production
+         systems, but if you are stress-testing the RCU implementation
+         itself, small RCU_FANOUT values allow you to test large-system
+         code paths on small(er) systems.
 
          Select a specific number if testing RCU itself.
          Take the default if unsure.
@@ -990,6 +1017,7 @@ config PERF_EVENTS
        default y if (PROFILING || PERF_COUNTERS)
        depends on HAVE_PERF_EVENTS
        select ANON_INODES
+       select IRQ_WORK
        help
          Enable kernel support for various performance events provided
          by software and hardware.
index 94ab488039aab1dde97d442f785046475f09c978..e59af24a0b7c0dbb8417ff3b5c0818d544ac8060 100644 (file)
@@ -424,7 +424,6 @@ static void __init setup_command_line(char *command_line)
 static __initdata DECLARE_COMPLETION(kthreadd_done);
 
 static noinline void __init_refok rest_init(void)
-       __releases(kernel_lock)
 {
        int pid;
 
@@ -556,7 +555,6 @@ asmlinkage void __init start_kernel(void)
 
        local_irq_disable();
        early_boot_irqs_off();
-       early_init_irq_lock_class();
 
 /*
  * Interrupts are still disabled. Do necessary setups, then
@@ -819,7 +817,6 @@ static void run_init_process(const char *init_filename)
  * makes it inline to init() and it becomes part of init.text section
  */
 static noinline int init_post(void)
-       __releases(kernel_lock)
 {
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
index c60e519e2917671860efdd7c7f6cac53abd97e70..e1e7b9635f5da7c986dfd18426bce94c177d6630 100644 (file)
@@ -1219,6 +1219,7 @@ static const struct file_operations mqueue_file_operations = {
        .flush = mqueue_flush_file,
        .poll = mqueue_poll_file,
        .read = mqueue_read_file,
+       .llseek = default_llseek,
 };
 
 static const struct super_operations mqueue_super_ops = {
index 40a8f462a8224b298690cb07892f93afe8c15214..0e0d49bbb867f239be5690968227c53e7c0226c0 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -743,6 +743,8 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
            {
                struct semid_ds out;
 
+               memset(&out, 0, sizeof(out));
+
                ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm);
 
                out.sem_otime   = in->sem_otime;
index 52ed77eb9713a932804cc8bb2b430ce4cdff4750..7bc46a9fe1f8709cadae67f329f57b0943403832 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -298,6 +298,7 @@ static const struct file_operations shm_file_operations = {
 #ifndef CONFIG_MMU
        .get_unmapped_area      = shm_get_unmapped_area,
 #endif
+       .llseek         = noop_llseek,
 };
 
 static const struct file_operations shm_file_operations_huge = {
@@ -305,6 +306,7 @@ static const struct file_operations shm_file_operations_huge = {
        .fsync          = shm_fsync,
        .release        = shm_release,
        .get_unmapped_area      = shm_get_unmapped_area,
+       .llseek         = noop_llseek,
 };
 
 int is_file_shm_hugepages(struct file *file)
index 0b72d1a74be07c25b99a8da670ec4cfb0963cf77..0b5ff083fa22fa381a6fc1f092a824f255bda01a 100644 (file)
@@ -10,8 +10,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
            kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
            hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
            notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
-           async.o range.o
-obj-$(CONFIG_HAVE_EARLY_RES) += early_res.o
+           async.o range.o jump_label.o
 obj-y += groups.o
 
 ifdef CONFIG_FUNCTION_TRACER
@@ -23,6 +22,7 @@ CFLAGS_REMOVE_rtmutex-debug.o = -pg
 CFLAGS_REMOVE_cgroup-debug.o = -pg
 CFLAGS_REMOVE_sched_clock.o = -pg
 CFLAGS_REMOVE_perf_event.o = -pg
+CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
 obj-$(CONFIG_FREEZER) += freezer.o
@@ -86,6 +86,7 @@ obj-$(CONFIG_TREE_RCU) += rcutree.o
 obj-$(CONFIG_TREE_PREEMPT_RCU) += rcutree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o
 obj-$(CONFIG_TINY_RCU) += rcutiny.o
+obj-$(CONFIG_TINY_PREEMPT_RCU) += rcutiny.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
@@ -100,6 +101,7 @@ obj-$(CONFIG_TRACING) += trace/
 obj-$(CONFIG_X86_DS) += trace/
 obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_SMP) += sched_cpupri.o
+obj-$(CONFIG_IRQ_WORK) += irq_work.o
 obj-$(CONFIG_PERF_EVENTS) += perf_event.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
index 192f88c5b0f9df29b80d51d4c5ceba5388d099eb..7b69b8d0313d63a92bd4efaf4d07676456fe71fc 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/cgroupstats.h>
 #include <linux/hash.h>
 #include <linux/namei.h>
-#include <linux/smp_lock.h>
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
@@ -138,7 +137,7 @@ struct css_id {
         * is called after synchronize_rcu(). But for safe use, css_is_removed()
         * css_tryget() should be used for avoiding race.
         */
-       struct cgroup_subsys_state *css;
+       struct cgroup_subsys_state __rcu *css;
        /*
         * ID of this css.
         */
@@ -1222,7 +1221,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
        struct cgroup *cgrp = &root->top_cgroup;
        struct cgroup_sb_opts opts;
 
-       lock_kernel();
        mutex_lock(&cgrp->dentry->d_inode->i_mutex);
        mutex_lock(&cgroup_mutex);
 
@@ -1255,7 +1253,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
        kfree(opts.name);
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
-       unlock_kernel();
        return ret;
 }
 
@@ -1568,7 +1565,6 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
  out_err:
        kfree(opts.release_agent);
        kfree(opts.name);
-
        return ret;
 }
 
@@ -1791,19 +1787,20 @@ out:
 }
 
 /**
- * cgroup_attach_task_current_cg - attach task 'tsk' to current task's cgroup
+ * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
+ * @from: attach to all cgroups of a given task
  * @tsk: the task to be attached
  */
-int cgroup_attach_task_current_cg(struct task_struct *tsk)
+int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 {
        struct cgroupfs_root *root;
-       struct cgroup *cur_cg;
        int retval = 0;
 
        cgroup_lock();
        for_each_active_root(root) {
-               cur_cg = task_cgroup_from_root(current, root);
-               retval = cgroup_attach_task(cur_cg, tsk);
+               struct cgroup *from_cg = task_cgroup_from_root(from, root);
+
+               retval = cgroup_attach_task(from_cg, tsk);
                if (retval)
                        break;
        }
@@ -1811,7 +1808,7 @@ int cgroup_attach_task_current_cg(struct task_struct *tsk)
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(cgroup_attach_task_current_cg);
+EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
 
 /*
  * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex
index e167efce8423e2cdaf2709412c36cc3ae642c90f..c9e2ec0b34a8cc38cda604273618a22c8d2d928c 100644 (file)
@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
 
        return 0;
 }
+
+/*
+ * Allocate user-space memory for the duration of a single system call,
+ * in order to marshall parameters inside a compat thunk.
+ */
+void __user *compat_alloc_user_space(unsigned long len)
+{
+       void __user *ptr;
+
+       /* If len would occupy more than half of the entire compat space... */
+       if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
+               return NULL;
+
+       ptr = arch_compat_alloc_user_space(len);
+
+       if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
+               return NULL;
+
+       return ptr;
+}
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
index abaee684ecbf95fe1d47426d7b47b77e6ed91fab..b4066b44a99d09996555b8a233855cc3e637559a 100644 (file)
@@ -66,6 +66,7 @@ ikconfig_read_current(struct file *file, char __user *buf,
 static const struct file_operations ikconfig_file_ops = {
        .owner = THIS_MODULE,
        .read = ikconfig_read_current,
+       .llseek = default_llseek,
 };
 
 static int __init ikconfig_init(void)
index b23c0979bbe7212a748a9aac70697e92ee54f448..51b143e2a07a49603d9aa462728f6a45032c01d9 100644 (file)
@@ -1397,7 +1397,7 @@ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
        if (tsk->flags & PF_THREAD_BOUND)
                return -EINVAL;
 
-       ret = security_task_setscheduler(tsk, 0, NULL);
+       ret = security_task_setscheduler(tsk);
        if (ret)
                return ret;
        if (threadgroup) {
@@ -1405,7 +1405,7 @@ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
 
                rcu_read_lock();
                list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
-                       ret = security_task_setscheduler(c, 0, NULL);
+                       ret = security_task_setscheduler(c);
                        if (ret) {
                                rcu_read_unlock();
                                return ret;
index 3c2d4972d2352ad1bff0fb31a676f467420b6ddd..de407c78178d9014332255f2d8ae412f9fbd5e5a 100644 (file)
@@ -741,7 +741,7 @@ static struct console kgdbcons = {
 };
 
 #ifdef CONFIG_MAGIC_SYSRQ
-static void sysrq_handle_dbg(int key, struct tty_struct *tty)
+static void sysrq_handle_dbg(int key)
 {
        if (!dbg_io_ops) {
                printk(KERN_CRIT "ERROR: No KGDB I/O module available\n");
index 75bd9b3ebbb7cf501800115a531e86e7c30c5a28..20059ef4459a4ff293428337d9936ff438a8eb96 100644 (file)
@@ -274,7 +274,6 @@ static int kdb_bp(int argc, const char **argv)
        int i, bpno;
        kdb_bp_t *bp, *bp_check;
        int diag;
-       int free;
        char *symname = NULL;
        long offset = 0ul;
        int nextarg;
@@ -305,7 +304,6 @@ static int kdb_bp(int argc, const char **argv)
        /*
         * Find an empty bp structure to allocate
         */
-       free = KDB_MAXBPT;
        for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT; bpno++, bp++) {
                if (bp->bp_free)
                        break;
index 28b844118bbd9d27f1e6bede2fd2502c6fd4f1b8..caf057a3de0e8457cb35e92a4b371f4f4597df3a 100644 (file)
@@ -1929,7 +1929,7 @@ static int kdb_sr(int argc, const char **argv)
        if (argc != 1)
                return KDB_ARGCOUNT;
        kdb_trap_printk++;
-       __handle_sysrq(*argv[1], NULL, 0);
+       __handle_sysrq(*argv[1], false);
        kdb_trap_printk--;
 
        return 0;
diff --git a/kernel/early_res.c b/kernel/early_res.c
deleted file mode 100644 (file)
index 7bfae88..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * early_res, could be used to replace bootmem
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/early_res.h>
-#include <linux/slab.h>
-#include <linux/kmemleak.h>
-
-/*
- * Early reserved memory areas.
- */
-/*
- * need to make sure this one is bigger enough before
- * find_fw_memmap_area could be used
- */
-#define MAX_EARLY_RES_X 32
-
-struct early_res {
-       u64 start, end;
-       char name[15];
-       char overlap_ok;
-};
-static struct early_res early_res_x[MAX_EARLY_RES_X] __initdata;
-
-static int max_early_res __initdata = MAX_EARLY_RES_X;
-static struct early_res *early_res __initdata = &early_res_x[0];
-static int early_res_count __initdata;
-
-static int __init find_overlapped_early(u64 start, u64 end)
-{
-       int i;
-       struct early_res *r;
-
-       for (i = 0; i < max_early_res && early_res[i].end; i++) {
-               r = &early_res[i];
-               if (end > r->start && start < r->end)
-                       break;
-       }
-
-       return i;
-}
-
-/*
- * Drop the i-th range from the early reservation map,
- * by copying any higher ranges down one over it, and
- * clearing what had been the last slot.
- */
-static void __init drop_range(int i)
-{
-       int j;
-
-       for (j = i + 1; j < max_early_res && early_res[j].end; j++)
-               ;
-
-       memmove(&early_res[i], &early_res[i + 1],
-              (j - 1 - i) * sizeof(struct early_res));
-
-       early_res[j - 1].end = 0;
-       early_res_count--;
-}
-
-static void __init drop_range_partial(int i, u64 start, u64 end)
-{
-       u64 common_start, common_end;
-       u64 old_start, old_end;
-
-       old_start = early_res[i].start;
-       old_end = early_res[i].end;
-       common_start = max(old_start, start);
-       common_end = min(old_end, end);
-
-       /* no overlap ? */
-       if (common_start >= common_end)
-               return;
-
-       if (old_start < common_start) {
-               /* make head segment */
-               early_res[i].end = common_start;
-               if (old_end > common_end) {
-                       char name[15];
-
-                       /*
-                        * Save a local copy of the name, since the
-                        * early_res array could get resized inside
-                        * reserve_early_without_check() ->
-                        * __check_and_double_early_res(), which would
-                        * make the current name pointer invalid.
-                        */
-                       strncpy(name, early_res[i].name,
-                                        sizeof(early_res[i].name) - 1);
-                       /* add another for left over on tail */
-                       reserve_early_without_check(common_end, old_end, name);
-               }
-               return;
-       } else {
-               if (old_end > common_end) {
-                       /* reuse the entry for tail left */
-                       early_res[i].start = common_end;
-                       return;
-               }
-               /* all covered */
-               drop_range(i);
-       }
-}
-
-/*
- * Split any existing ranges that:
- *  1) are marked 'overlap_ok', and
- *  2) overlap with the stated range [start, end)
- * into whatever portion (if any) of the existing range is entirely
- * below or entirely above the stated range.  Drop the portion
- * of the existing range that overlaps with the stated range,
- * which will allow the caller of this routine to then add that
- * stated range without conflicting with any existing range.
- */
-static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
-{
-       int i;
-       struct early_res *r;
-       u64 lower_start, lower_end;
-       u64 upper_start, upper_end;
-       char name[15];
-
-       for (i = 0; i < max_early_res && early_res[i].end; i++) {
-               r = &early_res[i];
-
-               /* Continue past non-overlapping ranges */
-               if (end <= r->start || start >= r->end)
-                       continue;
-
-               /*
-                * Leave non-ok overlaps as is; let caller
-                * panic "Overlapping early reservations"
-                * when it hits this overlap.
-                */
-               if (!r->overlap_ok)
-                       return;
-
-               /*
-                * We have an ok overlap.  We will drop it from the early
-                * reservation map, and add back in any non-overlapping
-                * portions (lower or upper) as separate, overlap_ok,
-                * non-overlapping ranges.
-                */
-
-               /* 1. Note any non-overlapping (lower or upper) ranges. */
-               strncpy(name, r->name, sizeof(name) - 1);
-
-               lower_start = lower_end = 0;
-               upper_start = upper_end = 0;
-               if (r->start < start) {
-                       lower_start = r->start;
-                       lower_end = start;
-               }
-               if (r->end > end) {
-                       upper_start = end;
-                       upper_end = r->end;
-               }
-
-               /* 2. Drop the original ok overlapping range */
-               drop_range(i);
-
-               i--;            /* resume for-loop on copied down entry */
-
-               /* 3. Add back in any non-overlapping ranges. */
-               if (lower_end)
-                       reserve_early_overlap_ok(lower_start, lower_end, name);
-               if (upper_end)
-                       reserve_early_overlap_ok(upper_start, upper_end, name);
-       }
-}
-
-static void __init __reserve_early(u64 start, u64 end, char *name,
-                                               int overlap_ok)
-{
-       int i;
-       struct early_res *r;
-
-       i = find_overlapped_early(start, end);
-       if (i >= max_early_res)
-               panic("Too many early reservations");
-       r = &early_res[i];
-       if (r->end)
-               panic("Overlapping early reservations "
-                     "%llx-%llx %s to %llx-%llx %s\n",
-                     start, end - 1, name ? name : "", r->start,
-                     r->end - 1, r->name);
-       r->start = start;
-       r->end = end;
-       r->overlap_ok = overlap_ok;
-       if (name)
-               strncpy(r->name, name, sizeof(r->name) - 1);
-       early_res_count++;
-}
-
-/*
- * A few early reservtations come here.
- *
- * The 'overlap_ok' in the name of this routine does -not- mean it
- * is ok for these reservations to overlap an earlier reservation.
- * Rather it means that it is ok for subsequent reservations to
- * overlap this one.
- *
- * Use this entry point to reserve early ranges when you are doing
- * so out of "Paranoia", reserving perhaps more memory than you need,
- * just in case, and don't mind a subsequent overlapping reservation
- * that is known to be needed.
- *
- * The drop_overlaps_that_are_ok() call here isn't really needed.
- * It would be needed if we had two colliding 'overlap_ok'
- * reservations, so that the second such would not panic on the
- * overlap with the first.  We don't have any such as of this
- * writing, but might as well tolerate such if it happens in
- * the future.
- */
-void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
-{
-       drop_overlaps_that_are_ok(start, end);
-       __reserve_early(start, end, name, 1);
-}
-
-static void __init __check_and_double_early_res(u64 ex_start, u64 ex_end)
-{
-       u64 start, end, size, mem;
-       struct early_res *new;
-
-       /* do we have enough slots left ? */
-       if ((max_early_res - early_res_count) > max(max_early_res/8, 2))
-               return;
-
-       /* double it */
-       mem = -1ULL;
-       size = sizeof(struct early_res) * max_early_res * 2;
-       if (early_res == early_res_x)
-               start = 0;
-       else
-               start = early_res[0].end;
-       end = ex_start;
-       if (start + size < end)
-               mem = find_fw_memmap_area(start, end, size,
-                                        sizeof(struct early_res));
-       if (mem == -1ULL) {
-               start = ex_end;
-               end = get_max_mapped();
-               if (start + size < end)
-                       mem = find_fw_memmap_area(start, end, size,
-                                                sizeof(struct early_res));
-       }
-       if (mem == -1ULL)
-               panic("can not find more space for early_res array");
-
-       new = __va(mem);
-       /* save the first one for own */
-       new[0].start = mem;
-       new[0].end = mem + size;
-       new[0].overlap_ok = 0;
-       /* copy old to new */
-       if (early_res == early_res_x) {
-               memcpy(&new[1], &early_res[0],
-                        sizeof(struct early_res) * max_early_res);
-               memset(&new[max_early_res+1], 0,
-                        sizeof(struct early_res) * (max_early_res - 1));
-               early_res_count++;
-       } else {
-               memcpy(&new[1], &early_res[1],
-                        sizeof(struct early_res) * (max_early_res - 1));
-               memset(&new[max_early_res], 0,
-                        sizeof(struct early_res) * max_early_res);
-       }
-       memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
-       early_res = new;
-       max_early_res *= 2;
-       printk(KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n",
-               max_early_res, mem, mem + size - 1);
-}
-
-/*
- * Most early reservations come here.
- *
- * We first have drop_overlaps_that_are_ok() drop any pre-existing
- * 'overlap_ok' ranges, so that we can then reserve this memory
- * range without risk of panic'ing on an overlapping overlap_ok
- * early reservation.
- */
-void __init reserve_early(u64 start, u64 end, char *name)
-{
-       if (start >= end)
-               return;
-
-       __check_and_double_early_res(start, end);
-
-       drop_overlaps_that_are_ok(start, end);
-       __reserve_early(start, end, name, 0);
-}
-
-void __init reserve_early_without_check(u64 start, u64 end, char *name)
-{
-       struct early_res *r;
-
-       if (start >= end)
-               return;
-
-       __check_and_double_early_res(start, end);
-
-       r = &early_res[early_res_count];
-
-       r->start = start;
-       r->end = end;
-       r->overlap_ok = 0;
-       if (name)
-               strncpy(r->name, name, sizeof(r->name) - 1);
-       early_res_count++;
-}
-
-void __init free_early(u64 start, u64 end)
-{
-       struct early_res *r;
-       int i;
-
-       kmemleak_free_part(__va(start), end - start);
-
-       i = find_overlapped_early(start, end);
-       r = &early_res[i];
-       if (i >= max_early_res || r->end != end || r->start != start)
-               panic("free_early on not reserved area: %llx-%llx!",
-                        start, end - 1);
-
-       drop_range(i);
-}
-
-void __init free_early_partial(u64 start, u64 end)
-{
-       struct early_res *r;
-       int i;
-
-       kmemleak_free_part(__va(start), end - start);
-
-       if (start == end)
-               return;
-
-       if (WARN_ONCE(start > end, "  wrong range [%#llx, %#llx]\n", start, end))
-               return;
-
-try_next:
-       i = find_overlapped_early(start, end);
-       if (i >= max_early_res)
-               return;
-
-       r = &early_res[i];
-       /* hole ? */
-       if (r->end >= end && r->start <= start) {
-               drop_range_partial(i, start, end);
-               return;
-       }
-
-       drop_range_partial(i, start, end);
-       goto try_next;
-}
-
-#ifdef CONFIG_NO_BOOTMEM
-static void __init subtract_early_res(struct range *range, int az)
-{
-       int i, count;
-       u64 final_start, final_end;
-       int idx = 0;
-
-       count  = 0;
-       for (i = 0; i < max_early_res && early_res[i].end; i++)
-               count++;
-
-       /* need to skip first one ?*/
-       if (early_res != early_res_x)
-               idx = 1;
-
-#define DEBUG_PRINT_EARLY_RES 1
-
-#if DEBUG_PRINT_EARLY_RES
-       printk(KERN_INFO "Subtract (%d early reservations)\n", count);
-#endif
-       for (i = idx; i < count; i++) {
-               struct early_res *r = &early_res[i];
-#if DEBUG_PRINT_EARLY_RES
-               printk(KERN_INFO "  #%d [%010llx - %010llx] %15s\n", i,
-                       r->start, r->end, r->name);
-#endif
-               final_start = PFN_DOWN(r->start);
-               final_end = PFN_UP(r->end);
-               if (final_start >= final_end)
-                       continue;
-               subtract_range(range, az, final_start, final_end);
-       }
-
-}
-
-int __init get_free_all_memory_range(struct range **rangep, int nodeid)
-{
-       int i, count;
-       u64 start = 0, end;
-       u64 size;
-       u64 mem;
-       struct range *range;
-       int nr_range;
-
-       count  = 0;
-       for (i = 0; i < max_early_res && early_res[i].end; i++)
-               count++;
-
-       count *= 2;
-
-       size = sizeof(struct range) * count;
-       end = get_max_mapped();
-#ifdef MAX_DMA32_PFN
-       if (end > (MAX_DMA32_PFN << PAGE_SHIFT))
-               start = MAX_DMA32_PFN << PAGE_SHIFT;
-#endif
-       mem = find_fw_memmap_area(start, end, size, sizeof(struct range));
-       if (mem == -1ULL)
-               panic("can not find more space for range free");
-
-       range = __va(mem);
-       /* use early_node_map[] and early_res to get range array at first */
-       memset(range, 0, size);
-       nr_range = 0;
-
-       /* need to go over early_node_map to find out good range for node */
-       nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
-#ifdef CONFIG_X86_32
-       subtract_range(range, count, max_low_pfn, -1ULL);
-#endif
-       subtract_early_res(range, count);
-       nr_range = clean_sort_range(range, count);
-
-       /* need to clear it ? */
-       if (nodeid == MAX_NUMNODES) {
-               memset(&early_res[0], 0,
-                        sizeof(struct early_res) * max_early_res);
-               early_res = NULL;
-               max_early_res = 0;
-       }
-
-       *rangep = range;
-       return nr_range;
-}
-#else
-void __init early_res_to_bootmem(u64 start, u64 end)
-{
-       int i, count;
-       u64 final_start, final_end;
-       int idx = 0;
-
-       count  = 0;
-       for (i = 0; i < max_early_res && early_res[i].end; i++)
-               count++;
-
-       /* need to skip first one ?*/
-       if (early_res != early_res_x)
-               idx = 1;
-
-       printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n",
-                        count - idx, max_early_res, start, end);
-       for (i = idx; i < count; i++) {
-               struct early_res *r = &early_res[i];
-               printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
-                       r->start, r->end, r->name);
-               final_start = max(start, r->start);
-               final_end = min(end, r->end);
-               if (final_start >= final_end) {
-                       printk(KERN_CONT "\n");
-                       continue;
-               }
-               printk(KERN_CONT " ==> [%010llx - %010llx]\n",
-                       final_start, final_end);
-               reserve_bootmem_generic(final_start, final_end - final_start,
-                               BOOTMEM_DEFAULT);
-       }
-       /* clear them */
-       memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
-       early_res = NULL;
-       max_early_res = 0;
-       early_res_count = 0;
-}
-#endif
-
-/* Check for already reserved areas */
-static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
-{
-       int i;
-       u64 addr = *addrp;
-       int changed = 0;
-       struct early_res *r;
-again:
-       i = find_overlapped_early(addr, addr + size);
-       r = &early_res[i];
-       if (i < max_early_res && r->end) {
-               *addrp = addr = round_up(r->end, align);
-               changed = 1;
-               goto again;
-       }
-       return changed;
-}
-
-/* Check for already reserved areas */
-static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
-{
-       int i;
-       u64 addr = *addrp, last;
-       u64 size = *sizep;
-       int changed = 0;
-again:
-       last = addr + size;
-       for (i = 0; i < max_early_res && early_res[i].end; i++) {
-               struct early_res *r = &early_res[i];
-               if (last > r->start && addr < r->start) {
-                       size = r->start - addr;
-                       changed = 1;
-                       goto again;
-               }
-               if (last > r->end && addr < r->end) {
-                       addr = round_up(r->end, align);
-                       size = last - addr;
-                       changed = 1;
-                       goto again;
-               }
-               if (last <= r->end && addr >= r->start) {
-                       (*sizep)++;
-                       return 0;
-               }
-       }
-       if (changed) {
-               *addrp = addr;
-               *sizep = size;
-       }
-       return changed;
-}
-
-/*
- * Find a free area with specified alignment in a specific range.
- * only with the area.between start to end is active range from early_node_map
- * so they are good as RAM
- */
-u64 __init find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
-                        u64 size, u64 align)
-{
-       u64 addr, last;
-
-       addr = round_up(ei_start, align);
-       if (addr < start)
-               addr = round_up(start, align);
-       if (addr >= ei_last)
-               goto out;
-       while (bad_addr(&addr, size, align) && addr+size <= ei_last)
-               ;
-       last = addr + size;
-       if (last > ei_last)
-               goto out;
-       if (last > end)
-               goto out;
-
-       return addr;
-
-out:
-       return -1ULL;
-}
-
-u64 __init find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
-                        u64 *sizep, u64 align)
-{
-       u64 addr, last;
-
-       addr = round_up(ei_start, align);
-       if (addr < start)
-               addr = round_up(start, align);
-       if (addr >= ei_last)
-               goto out;
-       *sizep = ei_last - addr;
-       while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last)
-               ;
-       last = addr + *sizep;
-       if (last > ei_last)
-               goto out;
-
-       return addr;
-
-out:
-       return -1ULL;
-}
index 03120229db2802929065a210930e41c7fa701ba0..e2bdf37f9fdea71a15acb3523ec20b63a6aa42d3 100644 (file)
@@ -149,9 +149,7 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
 {
        struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
 
-#ifdef CONFIG_PERF_EVENTS
-       WARN_ON_ONCE(tsk->perf_event_ctxp);
-#endif
+       perf_event_delayed_put(tsk);
        trace_sched_process_free(tsk);
        put_task_struct(tsk);
 }
index b7e9d60a675d3a08a1096ce725380229217d9fa3..c445f8cc408d777dd7a94aec3fa78c07e1d98b98 100644 (file)
@@ -356,10 +356,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                if (IS_ERR(pol))
                        goto fail_nomem_policy;
                vma_set_policy(tmp, pol);
+               tmp->vm_mm = mm;
                if (anon_vma_fork(tmp, mpnt))
                        goto fail_nomem_anon_vma_fork;
                tmp->vm_flags &= ~VM_LOCKED;
-               tmp->vm_mm = mm;
                tmp->vm_next = tmp->vm_prev = NULL;
                file = tmp->vm_file;
                if (file) {
index 6a3a5fa1526d87d16b362e20d7d62e6809285c18..a118bf160e0b05a4b24404beda19d07adead5161 100644 (file)
@@ -91,6 +91,7 @@ struct futex_pi_state {
 
 /**
  * struct futex_q - The hashed futex queue entry, one per waiting task
+ * @list:              priority-sorted list of tasks waiting on this futex
  * @task:              the task waiting on the futex
  * @lock_ptr:          the hash bucket lock
  * @key:               the key the futex is hashed on
@@ -104,7 +105,7 @@ struct futex_pi_state {
  *
  * A futex_q has a woken state, just like tasks have TASK_RUNNING.
  * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
- * The order of wakup is always to make the first condition true, then
+ * The order of wakeup is always to make the first condition true, then
  * the second.
  *
  * PI futexes are typically woken before they are removed from the hash list via
@@ -295,7 +296,7 @@ void put_futex_key(int fshared, union futex_key *key)
  * Slow path to fixup the fault we just took in the atomic write
  * access to @uaddr.
  *
- * We have no generic implementation of a non destructive write to the
+ * We have no generic implementation of a non-destructive write to the
  * user address. We know that we faulted in the atomic pagefault
  * disabled section so we can as well avoid the #PF overhead by
  * calling get_user_pages() right away.
@@ -515,7 +516,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
                         */
                        pi_state = this->pi_state;
                        /*
-                        * Userspace might have messed up non PI and PI futexes
+                        * Userspace might have messed up non-PI and PI futexes
                         */
                        if (unlikely(!pi_state))
                                return -EINVAL;
@@ -736,8 +737,8 @@ static void wake_futex(struct futex_q *q)
 
        /*
         * We set q->lock_ptr = NULL _before_ we wake up the task. If
-        * a non futex wake up happens on another CPU then the task
-        * might exit and p would dereference a non existing task
+        * a non-futex wake up happens on another CPU then the task
+        * might exit and p would dereference a non-existing task
         * struct. Prevent this by holding a reference on p across the
         * wake up.
         */
@@ -1131,11 +1132,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
 
 /**
  * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
- * uaddr1:     source futex user address
- * uaddr2:     target futex user address
- * nr_wake:    number of waiters to wake (must be 1 for requeue_pi)
- * nr_requeue: number of waiters to requeue (0-INT_MAX)
- * requeue_pi: if we are attempting to requeue from a non-pi futex to a
+ * @uaddr1:    source futex user address
+ * @fshared:   0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
+ * @uaddr2:    target futex user address
+ * @nr_wake:   number of waiters to wake (must be 1 for requeue_pi)
+ * @nr_requeue:        number of waiters to requeue (0-INT_MAX)
+ * @cmpval:    @uaddr1 expected value (or %NULL)
+ * @requeue_pi:        if we are attempting to requeue from a non-pi futex to a
  *             pi futex (pi to pi requeue is not supported)
  *
  * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
@@ -1360,10 +1363,10 @@ out:
 
 /* The key must be already stored in q->key. */
 static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
+       __acquires(&hb->lock)
 {
        struct futex_hash_bucket *hb;
 
-       get_futex_key_refs(&q->key);
        hb = hash_futex(&q->key);
        q->lock_ptr = &hb->lock;
 
@@ -1373,9 +1376,9 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
 
 static inline void
 queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
+       __releases(&hb->lock)
 {
        spin_unlock(&hb->lock);
-       drop_futex_key_refs(&q->key);
 }
 
 /**
@@ -1391,6 +1394,7 @@ queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
  * an example).
  */
 static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
+       __releases(&hb->lock)
 {
        int prio;
 
@@ -1471,6 +1475,7 @@ retry:
  * and dropped here.
  */
 static void unqueue_me_pi(struct futex_q *q)
+       __releases(q->lock_ptr)
 {
        WARN_ON(plist_node_empty(&q->list));
        plist_del(&q->list, &q->list.plist);
@@ -1480,8 +1485,6 @@ static void unqueue_me_pi(struct futex_q *q)
        q->pi_state = NULL;
 
        spin_unlock(q->lock_ptr);
-
-       drop_futex_key_refs(&q->key);
 }
 
 /*
@@ -1812,7 +1815,10 @@ static int futex_wait(u32 __user *uaddr, int fshared,
        }
 
 retry:
-       /* Prepare to wait on uaddr. */
+       /*
+        * Prepare to wait on uaddr. On success, holds hb lock and increments
+        * q.key refs.
+        */
        ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
        if (ret)
                goto out;
@@ -1822,28 +1828,27 @@ retry:
 
        /* If we were woken (and unqueued), we succeeded, whatever. */
        ret = 0;
+       /* unqueue_me() drops q.key ref */
        if (!unqueue_me(&q))
-               goto out_put_key;
+               goto out;
        ret = -ETIMEDOUT;
        if (to && !to->task)
-               goto out_put_key;
+               goto out;
 
        /*
         * We expect signal_pending(current), but we might be the
         * victim of a spurious wakeup as well.
         */
-       if (!signal_pending(current)) {
-               put_futex_key(fshared, &q.key);
+       if (!signal_pending(current))
                goto retry;
-       }
 
        ret = -ERESTARTSYS;
        if (!abs_time)
-               goto out_put_key;
+               goto out;
 
        restart = &current_thread_info()->restart_block;
        restart->fn = futex_wait_restart;
-       restart->futex.uaddr = (u32 *)uaddr;
+       restart->futex.uaddr = uaddr;
        restart->futex.val = val;
        restart->futex.time = abs_time->tv64;
        restart->futex.bitset = bitset;
@@ -1856,8 +1861,6 @@ retry:
 
        ret = -ERESTART_RESTARTBLOCK;
 
-out_put_key:
-       put_futex_key(fshared, &q.key);
 out:
        if (to) {
                hrtimer_cancel(&to->timer);
@@ -1869,7 +1872,7 @@ out:
 
 static long futex_wait_restart(struct restart_block *restart)
 {
-       u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
+       u32 __user *uaddr = restart->futex.uaddr;
        int fshared = 0;
        ktime_t t, *tp = NULL;
 
@@ -2236,7 +2239,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
        q.rt_waiter = &rt_waiter;
        q.requeue_pi_key = &key2;
 
-       /* Prepare to wait on uaddr. */
+       /*
+        * Prepare to wait on uaddr. On success, increments q.key (key1) ref
+        * count.
+        */
        ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
        if (ret)
                goto out_key2;
@@ -2254,7 +2260,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
         * In order for us to be here, we know our q.key == key2, and since
         * we took the hb->lock above, we also know that futex_requeue() has
         * completed and we no longer have to concern ourselves with a wakeup
-        * race with the atomic proxy lock acquition by the requeue code.
+        * race with the atomic proxy lock acquisition by the requeue code. The
+        * futex_requeue dropped our key1 reference and incremented our key2
+        * reference count.
         */
 
        /* Check if the requeue code acquired the second futex for us. */
@@ -2458,7 +2466,7 @@ retry:
  */
 static inline int fetch_robust_entry(struct robust_list __user **entry,
                                     struct robust_list __user * __user *head,
-                                    int *pi)
+                                    unsigned int *pi)
 {
        unsigned long uentry;
 
@@ -2647,7 +2655,7 @@ static int __init futex_init(void)
         * of the complex code paths. Also we want to prevent
         * registration of robust lists in that case. NULL is
         * guaranteed to fault and we get -EFAULT on functional
-        * implementation, the non functional ones will return
+        * implementation, the non-functional ones will return
         * -ENOSYS.
         */
        curval = cmpxchg_futex_value_locked(NULL, 0, 0);
index d49afb2395e5cab17dd85417c95741c60c12a4cf..06da4dfc339b7362716858f92bec749962241808 100644 (file)
@@ -19,7 +19,7 @@
  */
 static inline int
 fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
-                  compat_uptr_t __user *head, int *pi)
+                  compat_uptr_t __user *head, unsigned int *pi)
 {
        if (get_user(*uentry, head))
                return -EFAULT;
index ef3c3f88a7a35e36d8f1fb551c56e534cea52687..9bd0934f6c33b31a3432b4d0e4adab9790ed0a6c 100644 (file)
  * @children: child nodes
  * @all: list head for list of all nodes
  * @parent: parent node
- * @info: associated profiling data structure if not a directory
- * @ghost: when an object file containing profiling data is unloaded we keep a
- *         copy of the profiling data here to allow collecting coverage data
- *         for cleanup code. Such a node is called a "ghost".
+ * @loaded_info: array of pointers to profiling data sets for loaded object
+ *   files.
+ * @num_loaded: number of profiling data sets for loaded object files.
+ * @unloaded_info: accumulated copy of profiling data sets for unloaded
+ *   object files. Used only when gcov_persist=1.
  * @dentry: main debugfs entry, either a directory or data file
  * @links: associated symbolic links
  * @name: data file basename
@@ -51,10 +52,11 @@ struct gcov_node {
        struct list_head children;
        struct list_head all;
        struct gcov_node *parent;
-       struct gcov_info *info;
-       struct gcov_info *ghost;
+       struct gcov_info **loaded_info;
+       struct gcov_info *unloaded_info;
        struct dentry *dentry;
        struct dentry **links;
+       int num_loaded;
        char name[0];
 };
 
@@ -136,16 +138,37 @@ static const struct seq_operations gcov_seq_ops = {
 };
 
 /*
- * Return the profiling data set for a given node. This can either be the
- * original profiling data structure or a duplicate (also called "ghost")
- * in case the associated object file has been unloaded.
+ * Return a profiling data set associated with the given node. This is
+ * either a data set for a loaded object file or a data set copy in case
+ * all associated object files have been unloaded.
  */
 static struct gcov_info *get_node_info(struct gcov_node *node)
 {
-       if (node->info)
-               return node->info;
+       if (node->num_loaded > 0)
+               return node->loaded_info[0];
 
-       return node->ghost;
+       return node->unloaded_info;
+}
+
+/*
+ * Return a newly allocated profiling data set which contains the sum of
+ * all profiling data associated with the given node.
+ */
+static struct gcov_info *get_accumulated_info(struct gcov_node *node)
+{
+       struct gcov_info *info;
+       int i = 0;
+
+       if (node->unloaded_info)
+               info = gcov_info_dup(node->unloaded_info);
+       else
+               info = gcov_info_dup(node->loaded_info[i++]);
+       if (!info)
+               return NULL;
+       for (; i < node->num_loaded; i++)
+               gcov_info_add(info, node->loaded_info[i]);
+
+       return info;
 }
 
 /*
@@ -163,9 +186,10 @@ static int gcov_seq_open(struct inode *inode, struct file *file)
        mutex_lock(&node_lock);
        /*
         * Read from a profiling data copy to minimize reference tracking
-        * complexity and concurrent access.
+        * complexity and concurrent access and to keep accumulating multiple
+        * profiling data sets associated with one node simple.
         */
-       info = gcov_info_dup(get_node_info(node));
+       info = get_accumulated_info(node);
        if (!info)
                goto out_unlock;
        iter = gcov_iter_new(info);
@@ -225,12 +249,25 @@ static struct gcov_node *get_node_by_name(const char *name)
        return NULL;
 }
 
+/*
+ * Reset all profiling data associated with the specified node.
+ */
+static void reset_node(struct gcov_node *node)
+{
+       int i;
+
+       if (node->unloaded_info)
+               gcov_info_reset(node->unloaded_info);
+       for (i = 0; i < node->num_loaded; i++)
+               gcov_info_reset(node->loaded_info[i]);
+}
+
 static void remove_node(struct gcov_node *node);
 
 /*
  * write() implementation for gcov data files. Reset profiling data for the
- * associated file. If the object file has been unloaded (i.e. this is
- * a "ghost" node), remove the debug fs node as well.
+ * corresponding file. If all associated object files have been unloaded,
+ * remove the debug fs node as well.
  */
 static ssize_t gcov_seq_write(struct file *file, const char __user *addr,
                              size_t len, loff_t *pos)
@@ -245,10 +282,10 @@ static ssize_t gcov_seq_write(struct file *file, const char __user *addr,
        node = get_node_by_name(info->filename);
        if (node) {
                /* Reset counts or remove node for unloaded modules. */
-               if (node->ghost)
+               if (node->num_loaded == 0)
                        remove_node(node);
                else
-                       gcov_info_reset(node->info);
+                       reset_node(node);
        }
        /* Reset counts for open file. */
        gcov_info_reset(info);
@@ -378,7 +415,10 @@ static void init_node(struct gcov_node *node, struct gcov_info *info,
        INIT_LIST_HEAD(&node->list);
        INIT_LIST_HEAD(&node->children);
        INIT_LIST_HEAD(&node->all);
-       node->info = info;
+       if (node->loaded_info) {
+               node->loaded_info[0] = info;
+               node->num_loaded = 1;
+       }
        node->parent = parent;
        if (name)
                strcpy(node->name, name);
@@ -394,9 +434,13 @@ static struct gcov_node *new_node(struct gcov_node *parent,
        struct gcov_node *node;
 
        node = kzalloc(sizeof(struct gcov_node) + strlen(name) + 1, GFP_KERNEL);
-       if (!node) {
-               pr_warning("out of memory\n");
-               return NULL;
+       if (!node)
+               goto err_nomem;
+       if (info) {
+               node->loaded_info = kcalloc(1, sizeof(struct gcov_info *),
+                                          GFP_KERNEL);
+               if (!node->loaded_info)
+                       goto err_nomem;
        }
        init_node(node, info, name, parent);
        /* Differentiate between gcov data file nodes and directory nodes. */
@@ -416,6 +460,11 @@ static struct gcov_node *new_node(struct gcov_node *parent,
        list_add(&node->all, &all_head);
 
        return node;
+
+err_nomem:
+       kfree(node);
+       pr_warning("out of memory\n");
+       return NULL;
 }
 
 /* Remove symbolic links associated with node. */
@@ -441,8 +490,9 @@ static void release_node(struct gcov_node *node)
        list_del(&node->all);
        debugfs_remove(node->dentry);
        remove_links(node);
-       if (node->ghost)
-               gcov_info_free(node->ghost);
+       kfree(node->loaded_info);
+       if (node->unloaded_info)
+               gcov_info_free(node->unloaded_info);
        kfree(node);
 }
 
@@ -477,7 +527,7 @@ static struct gcov_node *get_child_by_name(struct gcov_node *parent,
 
 /*
  * write() implementation for reset file. Reset all profiling data to zero
- * and remove ghost nodes.
+ * and remove nodes for which all associated object files are unloaded.
  */
 static ssize_t reset_write(struct file *file, const char __user *addr,
                           size_t len, loff_t *pos)
@@ -487,8 +537,8 @@ static ssize_t reset_write(struct file *file, const char __user *addr,
        mutex_lock(&node_lock);
 restart:
        list_for_each_entry(node, &all_head, all) {
-               if (node->info)
-                       gcov_info_reset(node->info);
+               if (node->num_loaded > 0)
+                       reset_node(node);
                else if (list_empty(&node->children)) {
                        remove_node(node);
                        /* Several nodes may have gone - restart loop. */
@@ -511,6 +561,7 @@ static ssize_t reset_read(struct file *file, char __user *addr, size_t len,
 static const struct file_operations gcov_reset_fops = {
        .write  = reset_write,
        .read   = reset_read,
+       .llseek = noop_llseek,
 };
 
 /*
@@ -564,37 +615,115 @@ err_remove:
 }
 
 /*
- * The profiling data set associated with this node is being unloaded. Store a
- * copy of the profiling data and turn this node into a "ghost".
+ * Associate a profiling data set with an existing node. Needs to be called
+ * with node_lock held.
  */
-static int ghost_node(struct gcov_node *node)
+static void add_info(struct gcov_node *node, struct gcov_info *info)
 {
-       node->ghost = gcov_info_dup(node->info);
-       if (!node->ghost) {
-               pr_warning("could not save data for '%s' (out of memory)\n",
-                          node->info->filename);
-               return -ENOMEM;
+       struct gcov_info **loaded_info;
+       int num = node->num_loaded;
+
+       /*
+        * Prepare new array. This is done first to simplify cleanup in
+        * case the new data set is incompatible, the node only contains
+        * unloaded data sets and there's not enough memory for the array.
+        */
+       loaded_info = kcalloc(num + 1, sizeof(struct gcov_info *), GFP_KERNEL);
+       if (!loaded_info) {
+               pr_warning("could not add '%s' (out of memory)\n",
+                          info->filename);
+               return;
+       }
+       memcpy(loaded_info, node->loaded_info,
+              num * sizeof(struct gcov_info *));
+       loaded_info[num] = info;
+       /* Check if the new data set is compatible. */
+       if (num == 0) {
+               /*
+                * A module was unloaded, modified and reloaded. The new
+                * data set replaces the copy of the last one.
+                */
+               if (!gcov_info_is_compatible(node->unloaded_info, info)) {
+                       pr_warning("discarding saved data for %s "
+                                  "(incompatible version)\n", info->filename);
+                       gcov_info_free(node->unloaded_info);
+                       node->unloaded_info = NULL;
+               }
+       } else {
+               /*
+                * Two different versions of the same object file are loaded.
+                * The initial one takes precedence.
+                */
+               if (!gcov_info_is_compatible(node->loaded_info[0], info)) {
+                       pr_warning("could not add '%s' (incompatible "
+                                  "version)\n", info->filename);
+                       kfree(loaded_info);
+                       return;
+               }
        }
-       node->info = NULL;
+       /* Overwrite previous array. */
+       kfree(node->loaded_info);
+       node->loaded_info = loaded_info;
+       node->num_loaded = num + 1;
+}
 
-       return 0;
+/*
+ * Return the index of a profiling data set associated with a node.
+ */
+static int get_info_index(struct gcov_node *node, struct gcov_info *info)
+{
+       int i;
+
+       for (i = 0; i < node->num_loaded; i++) {
+               if (node->loaded_info[i] == info)
+                       return i;
+       }
+       return -ENOENT;
 }
 
 /*
- * Profiling data for this node has been loaded again. Add profiling data
- * from previous instantiation and turn this node into a regular node.
+ * Save the data of a profiling data set which is being unloaded.
  */
-static void revive_node(struct gcov_node *node, struct gcov_info *info)
+static void save_info(struct gcov_node *node, struct gcov_info *info)
 {
-       if (gcov_info_is_compatible(node->ghost, info))
-               gcov_info_add(info, node->ghost);
+       if (node->unloaded_info)
+               gcov_info_add(node->unloaded_info, info);
        else {
-               pr_warning("discarding saved data for '%s' (version changed)\n",
+               node->unloaded_info = gcov_info_dup(info);
+               if (!node->unloaded_info) {
+                       pr_warning("could not save data for '%s' "
+                                  "(out of memory)\n", info->filename);
+               }
+       }
+}
+
+/*
+ * Disassociate a profiling data set from a node. Needs to be called with
+ * node_lock held.
+ */
+static void remove_info(struct gcov_node *node, struct gcov_info *info)
+{
+       int i;
+
+       i = get_info_index(node, info);
+       if (i < 0) {
+               pr_warning("could not remove '%s' (not found)\n",
                           info->filename);
+               return;
        }
-       gcov_info_free(node->ghost);
-       node->ghost = NULL;
-       node->info = info;
+       if (gcov_persist)
+               save_info(node, info);
+       /* Shrink array. */
+       node->loaded_info[i] = node->loaded_info[node->num_loaded - 1];
+       node->num_loaded--;
+       if (node->num_loaded > 0)
+               return;
+       /* Last loaded data set was removed. */
+       kfree(node->loaded_info);
+       node->loaded_info = NULL;
+       node->num_loaded = 0;
+       if (!node->unloaded_info)
+               remove_node(node);
 }
 
 /*
@@ -609,30 +738,18 @@ void gcov_event(enum gcov_action action, struct gcov_info *info)
        node = get_node_by_name(info->filename);
        switch (action) {
        case GCOV_ADD:
-               /* Add new node or revive ghost. */
-               if (!node) {
+               if (node)
+                       add_info(node, info);
+               else
                        add_node(info);
-                       break;
-               }
-               if (gcov_persist)
-                       revive_node(node, info);
-               else {
-                       pr_warning("could not add '%s' (already exists)\n",
-                                  info->filename);
-               }
                break;
        case GCOV_REMOVE:
-               /* Remove node or turn into ghost. */
-               if (!node) {
+               if (node)
+                       remove_info(node, info);
+               else {
                        pr_warning("could not remove '%s' (not found)\n",
                                   info->filename);
-                       break;
                }
-               if (gcov_persist) {
-                       if (!ghost_node(node))
-                               break;
-               }
-               remove_node(node);
                break;
        }
        mutex_unlock(&node_lock);
index 53b1916c94926c245aacd17ccb420fc00d06a19b..253dc0f35cf4c30786d1ff3565427d1374762a04 100644 (file)
@@ -143,10 +143,9 @@ int groups_search(const struct group_info *group_info, gid_t grp)
        right = group_info->ngroups;
        while (left < right) {
                unsigned int mid = (left+right)/2;
-               int cmp = grp - GROUP_AT(group_info, mid);
-               if (cmp > 0)
+               if (grp > GROUP_AT(group_info, mid))
                        left = mid + 1;
-               else if (cmp < 0)
+               else if (grp < GROUP_AT(group_info, mid))
                        right = mid;
                else
                        return 1;
index ce669174f355c7dd1e1893903bb4d18a25f17c34..72206cf5c6cf854898d889a6a645e44febdd526f 100644 (file)
@@ -931,6 +931,7 @@ static inline int
 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
        if (hrtimer_is_queued(timer)) {
+               unsigned long state;
                int reprogram;
 
                /*
@@ -944,8 +945,13 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
                debug_deactivate(timer);
                timer_stats_hrtimer_clear_start_info(timer);
                reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
-               __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
-                                reprogram);
+               /*
+                * We must preserve the CALLBACK state flag here,
+                * otherwise we could move the timer base in
+                * switch_hrtimer_base.
+                */
+               state = timer->state & HRTIMER_STATE_CALLBACK;
+               __remove_hrtimer(timer, base, state, reprogram);
                return 1;
        }
        return 0;
@@ -1091,11 +1097,10 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
  */
 ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
 {
-       struct hrtimer_clock_base *base;
        unsigned long flags;
        ktime_t rem;
 
-       base = lock_hrtimer_base(timer, &flags);
+       lock_hrtimer_base(timer, &flags);
        rem = hrtimer_expires_remaining(timer);
        unlock_hrtimer_base(timer, &flags);
 
@@ -1232,6 +1237,9 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
                BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
                enqueue_hrtimer(timer, base);
        }
+
+       WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));
+
        timer->state &= ~HRTIMER_STATE_CALLBACK;
 }
 
index 0c642d51aac2d8ab82c782a786eb13b90c0985c1..53ead174da2f0a7c7849df4ef81b60a96fe7c4f6 100644 (file)
@@ -98,7 +98,7 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
        printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
                        " disables this message.\n");
        sched_show_task(t);
-       __debug_show_held_locks(t);
+       debug_show_held_locks(t);
 
        touch_nmi_watchdog();
 
@@ -111,7 +111,7 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
  * periodically exit the critical section and enter a new one.
  *
  * For preemptible RCU it is sufficient to call rcu_read_unlock in order
- * exit the grace period. For classic RCU, a reschedule is required.
+ * to exit the grace period. For classic RCU, a reschedule is required.
  */
 static void rcu_lock_break(struct task_struct *g, struct task_struct *t)
 {
index d71a987fd2bf2ba5e698f9b69fccb59db4a1bb30..2c9120f0afca9872cc4edba57d4e5cfe9311788f 100644 (file)
@@ -113,12 +113,12 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
  */
 static int task_bp_pinned(struct perf_event *bp, enum bp_type_idx type)
 {
-       struct perf_event_context *ctx = bp->ctx;
+       struct task_struct *tsk = bp->hw.bp_target;
        struct perf_event *iter;
        int count = 0;
 
        list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
-               if (iter->ctx == ctx && find_slot_idx(iter) == type)
+               if (iter->hw.bp_target == tsk && find_slot_idx(iter) == type)
                        count += hw_breakpoint_weight(iter);
        }
 
@@ -134,7 +134,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
                    enum bp_type_idx type)
 {
        int cpu = bp->cpu;
-       struct task_struct *tsk = bp->ctx->task;
+       struct task_struct *tsk = bp->hw.bp_target;
 
        if (cpu >= 0) {
                slots->pinned = per_cpu(nr_cpu_bp_pinned[type], cpu);
@@ -213,7 +213,7 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type,
               int weight)
 {
        int cpu = bp->cpu;
-       struct task_struct *tsk = bp->ctx->task;
+       struct task_struct *tsk = bp->hw.bp_target;
 
        /* Pinned counter cpu profiling */
        if (!tsk) {
@@ -433,7 +433,7 @@ register_user_hw_breakpoint(struct perf_event_attr *attr,
                            perf_overflow_handler_t triggered,
                            struct task_struct *tsk)
 {
-       return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered);
+       return perf_event_create_kernel_counter(attr, -1, tsk, triggered);
 }
 EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
 
@@ -515,7 +515,7 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
        get_online_cpus();
        for_each_online_cpu(cpu) {
                pevent = per_cpu_ptr(cpu_events, cpu);
-               bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered);
+               bp = perf_event_create_kernel_counter(attr, cpu, NULL, triggered);
 
                *pevent = bp;
 
@@ -565,6 +565,61 @@ static struct notifier_block hw_breakpoint_exceptions_nb = {
        .priority = 0x7fffffff
 };
 
+static void bp_perf_event_destroy(struct perf_event *event)
+{
+       release_bp_slot(event);
+}
+
+static int hw_breakpoint_event_init(struct perf_event *bp)
+{
+       int err;
+
+       if (bp->attr.type != PERF_TYPE_BREAKPOINT)
+               return -ENOENT;
+
+       err = register_perf_hw_breakpoint(bp);
+       if (err)
+               return err;
+
+       bp->destroy = bp_perf_event_destroy;
+
+       return 0;
+}
+
+static int hw_breakpoint_add(struct perf_event *bp, int flags)
+{
+       if (!(flags & PERF_EF_START))
+               bp->hw.state = PERF_HES_STOPPED;
+
+       return arch_install_hw_breakpoint(bp);
+}
+
+static void hw_breakpoint_del(struct perf_event *bp, int flags)
+{
+       arch_uninstall_hw_breakpoint(bp);
+}
+
+static void hw_breakpoint_start(struct perf_event *bp, int flags)
+{
+       bp->hw.state = 0;
+}
+
+static void hw_breakpoint_stop(struct perf_event *bp, int flags)
+{
+       bp->hw.state = PERF_HES_STOPPED;
+}
+
+static struct pmu perf_breakpoint = {
+       .task_ctx_nr    = perf_sw_context, /* could eventually get its own */
+
+       .event_init     = hw_breakpoint_event_init,
+       .add            = hw_breakpoint_add,
+       .del            = hw_breakpoint_del,
+       .start          = hw_breakpoint_start,
+       .stop           = hw_breakpoint_stop,
+       .read           = hw_breakpoint_pmu_read,
+};
+
 static int __init init_hw_breakpoint(void)
 {
        unsigned int **task_bp_pinned;
@@ -586,6 +641,8 @@ static int __init init_hw_breakpoint(void)
 
        constraints_initialized = 1;
 
+       perf_pmu_register(&perf_breakpoint);
+
        return register_die_notifier(&hw_breakpoint_exceptions_nb);
 
  err_alloc:
@@ -601,8 +658,3 @@ static int __init init_hw_breakpoint(void)
 core_initcall(init_hw_breakpoint);
 
 
-struct pmu perf_ops_bp = {
-       .enable         = arch_install_hw_breakpoint,
-       .disable        = arch_uninstall_hw_breakpoint,
-       .read           = hw_breakpoint_pmu_read,
-};
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
new file mode 100644 (file)
index 0000000..31d766b
--- /dev/null
@@ -0,0 +1,53 @@
+config HAVE_GENERIC_HARDIRQS
+       def_bool n
+
+if HAVE_GENERIC_HARDIRQS
+menu "IRQ subsystem"
+#
+# Interrupt subsystem related configuration options
+#
+config GENERIC_HARDIRQS
+       def_bool y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
+
+# Select this to disable the deprecated stuff
+config GENERIC_HARDIRQS_NO_DEPRECATED
+       def_bool n
+
+# Options selectable by the architecture code
+config HAVE_SPARSE_IRQ
+       def_bool n
+
+config GENERIC_IRQ_PROBE
+       def_bool n
+
+config GENERIC_PENDING_IRQ
+       def_bool n
+
+config AUTO_IRQ_AFFINITY
+       def_bool n
+
+config IRQ_PER_CPU
+       def_bool n
+
+config HARDIRQS_SW_RESEND
+       def_bool n
+
+config SPARSE_IRQ
+       bool "Support sparse irq numbering"
+       depends on HAVE_SPARSE_IRQ
+       ---help---
+
+         Sparse irq numbering is useful for distro kernels that want
+         to define a high CONFIG_NR_CPUS value but still want to have
+         low kernel memory footprint on smaller machines.
+
+         ( Sparse irqs can also be beneficial on NUMA boxes, as they spread
+           out the interrupt descriptors in a more NUMA-friendly way. )
+
+         If you don't know what to do here, say N.
+
+endmenu
+endif
index 7d047808419da88e273fba8cd1efd88d9aaa5bcd..54329cd7b3ee3cb5ed2084e2072933b183e8a446 100644 (file)
@@ -1,7 +1,6 @@
 
-obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
+obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
-obj-$(CONFIG_NUMA_IRQ_DESC) += numa_migrate.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
index 2295a31ef110dab62a6e665358a9cb290fbe990e..505798f86c36d774afaa4938f2097ac32cd21e0a 100644 (file)
@@ -57,9 +57,10 @@ unsigned long probe_irq_on(void)
                         * Some chips need to know about probing in
                         * progress:
                         */
-                       if (desc->chip->set_type)
-                               desc->chip->set_type(i, IRQ_TYPE_PROBE);
-                       desc->chip->startup(i);
+                       if (desc->irq_data.chip->irq_set_type)
+                               desc->irq_data.chip->irq_set_type(&desc->irq_data,
+                                                        IRQ_TYPE_PROBE);
+                       desc->irq_data.chip->irq_startup(&desc->irq_data);
                }
                raw_spin_unlock_irq(&desc->lock);
        }
@@ -76,7 +77,7 @@ unsigned long probe_irq_on(void)
                raw_spin_lock_irq(&desc->lock);
                if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
                        desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-                       if (desc->chip->startup(i))
+                       if (desc->irq_data.chip->irq_startup(&desc->irq_data))
                                desc->status |= IRQ_PENDING;
                }
                raw_spin_unlock_irq(&desc->lock);
@@ -98,7 +99,7 @@ unsigned long probe_irq_on(void)
                        /* It triggered already - consider it spurious. */
                        if (!(status & IRQ_WAITING)) {
                                desc->status = status & ~IRQ_AUTODETECT;
-                               desc->chip->shutdown(i);
+                               desc->irq_data.chip->irq_shutdown(&desc->irq_data);
                        } else
                                if (i < 32)
                                        mask |= 1 << i;
@@ -137,7 +138,7 @@ unsigned int probe_irq_mask(unsigned long val)
                                mask |= 1 << i;
 
                        desc->status = status & ~IRQ_AUTODETECT;
-                       desc->chip->shutdown(i);
+                       desc->irq_data.chip->irq_shutdown(&desc->irq_data);
                }
                raw_spin_unlock_irq(&desc->lock);
        }
@@ -181,7 +182,7 @@ int probe_irq_off(unsigned long val)
                                nr_of_irqs++;
                        }
                        desc->status = status & ~IRQ_AUTODETECT;
-                       desc->chip->shutdown(i);
+                       desc->irq_data.chip->irq_shutdown(&desc->irq_data);
                }
                raw_spin_unlock_irq(&desc->lock);
        }
index b7091d5ca2f829ae61f0140ae6b1901213bfab62..baa5c4acad83cc4bd9efad28719d054afc960012 100644 (file)
 
 #include "internals.h"
 
-static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data)
-{
-       struct irq_desc *desc;
-       unsigned long flags;
-
-       desc = irq_to_desc(irq);
-       if (!desc) {
-               WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
-               return;
-       }
-
-       /* Ensure we don't have left over values from a previous use of this irq */
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->status = IRQ_DISABLED;
-       desc->chip = &no_irq_chip;
-       desc->handle_irq = handle_bad_irq;
-       desc->depth = 1;
-       desc->msi_desc = NULL;
-       desc->handler_data = NULL;
-       if (!keep_chip_data)
-               desc->chip_data = NULL;
-       desc->action = NULL;
-       desc->irq_count = 0;
-       desc->irqs_unhandled = 0;
-#ifdef CONFIG_SMP
-       cpumask_setall(desc->affinity);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_clear(desc->pending_mask);
-#endif
-#endif
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/**
- *     dynamic_irq_init - initialize a dynamically allocated irq
- *     @irq:   irq number to initialize
- */
-void dynamic_irq_init(unsigned int irq)
-{
-       dynamic_irq_init_x(irq, false);
-}
-
-/**
- *     dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq
- *     @irq:   irq number to initialize
- *
- *     does not set irq_to_desc(irq)->chip_data to NULL
- */
-void dynamic_irq_init_keep_chip_data(unsigned int irq)
-{
-       dynamic_irq_init_x(irq, true);
-}
-
-static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned long flags;
-
-       if (!desc) {
-               WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
-               return;
-       }
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       if (desc->action) {
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-               WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n",
-                       irq);
-               return;
-       }
-       desc->msi_desc = NULL;
-       desc->handler_data = NULL;
-       if (!keep_chip_data)
-               desc->chip_data = NULL;
-       desc->handle_irq = handle_bad_irq;
-       desc->chip = &no_irq_chip;
-       desc->name = NULL;
-       clear_kstat_irqs(desc);
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/**
- *     dynamic_irq_cleanup - cleanup a dynamically allocated irq
- *     @irq:   irq number to initialize
- */
-void dynamic_irq_cleanup(unsigned int irq)
-{
-       dynamic_irq_cleanup_x(irq, false);
-}
-
-/**
- *     dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq
- *     @irq:   irq number to initialize
- *
- *     does not set irq_to_desc(irq)->chip_data to NULL
- */
-void dynamic_irq_cleanup_keep_chip_data(unsigned int irq)
-{
-       dynamic_irq_cleanup_x(irq, true);
-}
-
-
 /**
  *     set_irq_chip - set the irq chip for an irq
  *     @irq:   irq number
@@ -140,7 +38,7 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
 
        raw_spin_lock_irqsave(&desc->lock, flags);
        irq_chip_set_defaults(chip);
-       desc->chip = chip;
+       desc->irq_data.chip = chip;
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 
        return 0;
@@ -193,7 +91,7 @@ int set_irq_data(unsigned int irq, void *data)
        }
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->handler_data = data;
+       desc->irq_data.handler_data = data;
        raw_spin_unlock_irqrestore(&desc->lock, flags);
        return 0;
 }
@@ -218,7 +116,7 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry)
        }
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->msi_desc = entry;
+       desc->irq_data.msi_desc = entry;
        if (entry)
                entry->irq = irq;
        raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -243,19 +141,27 @@ int set_irq_chip_data(unsigned int irq, void *data)
                return -EINVAL;
        }
 
-       if (!desc->chip) {
+       if (!desc->irq_data.chip) {
                printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
                return -EINVAL;
        }
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->chip_data = data;
+       desc->irq_data.chip_data = data;
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 
        return 0;
 }
 EXPORT_SYMBOL(set_irq_chip_data);
 
+struct irq_data *irq_get_irq_data(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       return desc ? &desc->irq_data : NULL;
+}
+EXPORT_SYMBOL_GPL(irq_get_irq_data);
+
 /**
  *     set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq
  *
@@ -287,93 +193,216 @@ EXPORT_SYMBOL_GPL(set_irq_nested_thread);
 /*
  * default enable function
  */
-static void default_enable(unsigned int irq)
+static void default_enable(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_desc *desc = irq_data_to_desc(data);
 
-       desc->chip->unmask(irq);
+       desc->irq_data.chip->irq_unmask(&desc->irq_data);
        desc->status &= ~IRQ_MASKED;
 }
 
 /*
  * default disable function
  */
-static void default_disable(unsigned int irq)
+static void default_disable(struct irq_data *data)
 {
 }
 
 /*
  * default startup function
  */
-static unsigned int default_startup(unsigned int irq)
+static unsigned int default_startup(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_desc *desc = irq_data_to_desc(data);
 
-       desc->chip->enable(irq);
+       desc->irq_data.chip->irq_enable(data);
        return 0;
 }
 
 /*
  * default shutdown function
  */
-static void default_shutdown(unsigned int irq)
+static void default_shutdown(struct irq_data *data)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_desc *desc = irq_data_to_desc(data);
 
-       desc->chip->mask(irq);
+       desc->irq_data.chip->irq_mask(&desc->irq_data);
        desc->status |= IRQ_MASKED;
 }
 
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+/* Temporary migration helpers */
+static void compat_irq_mask(struct irq_data *data)
+{
+       data->chip->mask(data->irq);
+}
+
+static void compat_irq_unmask(struct irq_data *data)
+{
+       data->chip->unmask(data->irq);
+}
+
+static void compat_irq_ack(struct irq_data *data)
+{
+       data->chip->ack(data->irq);
+}
+
+static void compat_irq_mask_ack(struct irq_data *data)
+{
+       data->chip->mask_ack(data->irq);
+}
+
+static void compat_irq_eoi(struct irq_data *data)
+{
+       data->chip->eoi(data->irq);
+}
+
+static void compat_irq_enable(struct irq_data *data)
+{
+       data->chip->enable(data->irq);
+}
+
+static void compat_irq_disable(struct irq_data *data)
+{
+       data->chip->disable(data->irq);
+}
+
+static void compat_irq_shutdown(struct irq_data *data)
+{
+       data->chip->shutdown(data->irq);
+}
+
+static unsigned int compat_irq_startup(struct irq_data *data)
+{
+       return data->chip->startup(data->irq);
+}
+
+static int compat_irq_set_affinity(struct irq_data *data,
+                                  const struct cpumask *dest, bool force)
+{
+       return data->chip->set_affinity(data->irq, dest);
+}
+
+static int compat_irq_set_type(struct irq_data *data, unsigned int type)
+{
+       return data->chip->set_type(data->irq, type);
+}
+
+static int compat_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       return data->chip->set_wake(data->irq, on);
+}
+
+static int compat_irq_retrigger(struct irq_data *data)
+{
+       return data->chip->retrigger(data->irq);
+}
+
+static void compat_bus_lock(struct irq_data *data)
+{
+       data->chip->bus_lock(data->irq);
+}
+
+static void compat_bus_sync_unlock(struct irq_data *data)
+{
+       data->chip->bus_sync_unlock(data->irq);
+}
+#endif
+
 /*
  * Fixup enable/disable function pointers
  */
 void irq_chip_set_defaults(struct irq_chip *chip)
 {
-       if (!chip->enable)
-               chip->enable = default_enable;
-       if (!chip->disable)
-               chip->disable = default_disable;
-       if (!chip->startup)
-               chip->startup = default_startup;
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
        /*
-        * We use chip->disable, when the user provided its own. When
-        * we have default_disable set for chip->disable, then we need
+        * Compat fixup functions need to be before we set the
+        * defaults for enable/disable/startup/shutdown
+        */
+       if (chip->enable)
+               chip->irq_enable = compat_irq_enable;
+       if (chip->disable)
+               chip->irq_disable = compat_irq_disable;
+       if (chip->shutdown)
+               chip->irq_shutdown = compat_irq_shutdown;
+       if (chip->startup)
+               chip->irq_startup = compat_irq_startup;
+#endif
+       /*
+        * The real defaults
+        */
+       if (!chip->irq_enable)
+               chip->irq_enable = default_enable;
+       if (!chip->irq_disable)
+               chip->irq_disable = default_disable;
+       if (!chip->irq_startup)
+               chip->irq_startup = default_startup;
+       /*
+        * We use chip->irq_disable, when the user provided its own. When
+        * we have default_disable set for chip->irq_disable, then we need
         * to use default_shutdown, otherwise the irq line is not
         * disabled on free_irq():
         */
-       if (!chip->shutdown)
-               chip->shutdown = chip->disable != default_disable ?
-                       chip->disable : default_shutdown;
-       if (!chip->name)
-               chip->name = chip->typename;
+       if (!chip->irq_shutdown)
+               chip->irq_shutdown = chip->irq_disable != default_disable ?
+                       chip->irq_disable : default_shutdown;
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
        if (!chip->end)
                chip->end = dummy_irq_chip.end;
+
+       /*
+        * Now fix up the remaining compat handlers
+        */
+       if (chip->bus_lock)
+               chip->irq_bus_lock = compat_bus_lock;
+       if (chip->bus_sync_unlock)
+               chip->irq_bus_sync_unlock = compat_bus_sync_unlock;
+       if (chip->mask)
+               chip->irq_mask = compat_irq_mask;
+       if (chip->unmask)
+               chip->irq_unmask = compat_irq_unmask;
+       if (chip->ack)
+               chip->irq_ack = compat_irq_ack;
+       if (chip->mask_ack)
+               chip->irq_mask_ack = compat_irq_mask_ack;
+       if (chip->eoi)
+               chip->irq_eoi = compat_irq_eoi;
+       if (chip->set_affinity)
+               chip->irq_set_affinity = compat_irq_set_affinity;
+       if (chip->set_type)
+               chip->irq_set_type = compat_irq_set_type;
+       if (chip->set_wake)
+               chip->irq_set_wake = compat_irq_set_wake;
+       if (chip->retrigger)
+               chip->irq_retrigger = compat_irq_retrigger;
+#endif
 }
 
-static inline void mask_ack_irq(struct irq_desc *desc, int irq)
+static inline void mask_ack_irq(struct irq_desc *desc)
 {
-       if (desc->chip->mask_ack)
-               desc->chip->mask_ack(irq);
+       if (desc->irq_data.chip->irq_mask_ack)
+               desc->irq_data.chip->irq_mask_ack(&desc->irq_data);
        else {
-               desc->chip->mask(irq);
-               if (desc->chip->ack)
-                       desc->chip->ack(irq);
+               desc->irq_data.chip->irq_mask(&desc->irq_data);
+               if (desc->irq_data.chip->irq_ack)
+                       desc->irq_data.chip->irq_ack(&desc->irq_data);
        }
        desc->status |= IRQ_MASKED;
 }
 
-static inline void mask_irq(struct irq_desc *desc, int irq)
+static inline void mask_irq(struct irq_desc *desc)
 {
-       if (desc->chip->mask) {
-               desc->chip->mask(irq);
+       if (desc->irq_data.chip->irq_mask) {
+               desc->irq_data.chip->irq_mask(&desc->irq_data);
                desc->status |= IRQ_MASKED;
        }
 }
 
-static inline void unmask_irq(struct irq_desc *desc, int irq)
+static inline void unmask_irq(struct irq_desc *desc)
 {
-       if (desc->chip->unmask) {
-               desc->chip->unmask(irq);
+       if (desc->irq_data.chip->irq_unmask) {
+               desc->irq_data.chip->irq_unmask(&desc->irq_data);
                desc->status &= ~IRQ_MASKED;
        }
 }
@@ -476,7 +505,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
        irqreturn_t action_ret;
 
        raw_spin_lock(&desc->lock);
-       mask_ack_irq(desc, irq);
+       mask_ack_irq(desc);
 
        if (unlikely(desc->status & IRQ_INPROGRESS))
                goto out_unlock;
@@ -502,7 +531,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
        desc->status &= ~IRQ_INPROGRESS;
 
        if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))
-               unmask_irq(desc, irq);
+               unmask_irq(desc);
 out_unlock:
        raw_spin_unlock(&desc->lock);
 }
@@ -539,7 +568,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
        action = desc->action;
        if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
                desc->status |= IRQ_PENDING;
-               mask_irq(desc, irq);
+               mask_irq(desc);
                goto out;
        }
 
@@ -554,7 +583,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
        raw_spin_lock(&desc->lock);
        desc->status &= ~IRQ_INPROGRESS;
 out:
-       desc->chip->eoi(irq);
+       desc->irq_data.chip->irq_eoi(&desc->irq_data);
 
        raw_spin_unlock(&desc->lock);
 }
@@ -590,14 +619,13 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
        if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
                    !desc->action)) {
                desc->status |= (IRQ_PENDING | IRQ_MASKED);
-               mask_ack_irq(desc, irq);
+               mask_ack_irq(desc);
                goto out_unlock;
        }
        kstat_incr_irqs_this_cpu(irq, desc);
 
        /* Start handling the irq */
-       if (desc->chip->ack)
-               desc->chip->ack(irq);
+       desc->irq_data.chip->irq_ack(&desc->irq_data);
 
        /* Mark the IRQ currently in progress.*/
        desc->status |= IRQ_INPROGRESS;
@@ -607,7 +635,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                irqreturn_t action_ret;
 
                if (unlikely(!action)) {
-                       mask_irq(desc, irq);
+                       mask_irq(desc);
                        goto out_unlock;
                }
 
@@ -619,7 +647,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                if (unlikely((desc->status &
                               (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
                              (IRQ_PENDING | IRQ_MASKED))) {
-                       unmask_irq(desc, irq);
+                       unmask_irq(desc);
                }
 
                desc->status &= ~IRQ_PENDING;
@@ -650,15 +678,15 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 
        kstat_incr_irqs_this_cpu(irq, desc);
 
-       if (desc->chip->ack)
-               desc->chip->ack(irq);
+       if (desc->irq_data.chip->irq_ack)
+               desc->irq_data.chip->irq_ack(&desc->irq_data);
 
        action_ret = handle_IRQ_event(irq, desc->action);
        if (!noirqdebug)
                note_interrupt(irq, desc, action_ret);
 
-       if (desc->chip->eoi)
-               desc->chip->eoi(irq);
+       if (desc->irq_data.chip->irq_eoi)
+               desc->irq_data.chip->irq_eoi(&desc->irq_data);
 }
 
 void
@@ -676,7 +704,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 
        if (!handle)
                handle = handle_bad_irq;
-       else if (desc->chip == &no_irq_chip) {
+       else if (desc->irq_data.chip == &no_irq_chip) {
                printk(KERN_WARNING "Trying to install %sinterrupt handler "
                       "for IRQ%d\n", is_chained ? "chained " : "", irq);
                /*
@@ -686,16 +714,16 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                 * prevent us to setup the interrupt at all. Switch it to
                 * dummy_irq_chip for easy transition.
                 */
-               desc->chip = &dummy_irq_chip;
+               desc->irq_data.chip = &dummy_irq_chip;
        }
 
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        raw_spin_lock_irqsave(&desc->lock, flags);
 
        /* Uninstall? */
        if (handle == handle_bad_irq) {
-               if (desc->chip != &no_irq_chip)
-                       mask_ack_irq(desc, irq);
+               if (desc->irq_data.chip != &no_irq_chip)
+                       mask_ack_irq(desc);
                desc->status |= IRQ_DISABLED;
                desc->depth = 1;
        }
@@ -706,10 +734,10 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                desc->status &= ~IRQ_DISABLED;
                desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
                desc->depth = 0;
-               desc->chip->startup(irq);
+               desc->irq_data.chip->irq_startup(&desc->irq_data);
        }
        raw_spin_unlock_irqrestore(&desc->lock, flags);
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL_GPL(__set_irq_handler);
 
@@ -729,32 +757,20 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
        __set_irq_handler(irq, handle, 0, name);
 }
 
-void set_irq_noprobe(unsigned int irq)
+void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        unsigned long flags;
 
-       if (!desc) {
-               printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
+       if (!desc)
                return;
-       }
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->status |= IRQ_NOPROBE;
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-void set_irq_probe(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned long flags;
 
-       if (!desc) {
-               printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
-               return;
-       }
+       /* Sanitize flags */
+       set &= IRQF_MODIFY_MASK;
+       clr &= IRQF_MODIFY_MASK;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc->status &= ~IRQ_NOPROBE;
+       desc->status &= ~clr;
+       desc->status |= set;
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
diff --git a/kernel/irq/dummychip.c b/kernel/irq/dummychip.c
new file mode 100644 (file)
index 0000000..20dc547
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ *
+ * This file contains the dummy interrupt chip implementation
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "internals.h"
+
+/*
+ * What should we do if we get a hw irq event on an illegal vector?
+ * Each architecture has to answer this themself.
+ */
+static void ack_bad(struct irq_data *data)
+{
+       struct irq_desc *desc = irq_data_to_desc(data);
+
+       print_irq_desc(data->irq, desc);
+       ack_bad_irq(data->irq);
+}
+
+/*
+ * NOP functions
+ */
+static void noop(struct irq_data *data) { }
+
+static unsigned int noop_ret(struct irq_data *data)
+{
+       return 0;
+}
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+static void compat_noop(unsigned int irq) { }
+#define END_INIT .end = compat_noop
+#else
+#define END_INIT
+#endif
+
+/*
+ * Generic no controller implementation
+ */
+struct irq_chip no_irq_chip = {
+       .name           = "none",
+       .irq_startup    = noop_ret,
+       .irq_shutdown   = noop,
+       .irq_enable     = noop,
+       .irq_disable    = noop,
+       .irq_ack        = ack_bad,
+       END_INIT
+};
+
+/*
+ * Generic dummy implementation which can be used for
+ * real dumb interrupt sources
+ */
+struct irq_chip dummy_irq_chip = {
+       .name           = "dummy",
+       .irq_startup    = noop_ret,
+       .irq_shutdown   = noop,
+       .irq_enable     = noop,
+       .irq_disable    = noop,
+       .irq_ack        = noop,
+       .irq_mask       = noop,
+       .irq_unmask     = noop,
+       END_INIT
+};
index 27e5c69112235c2f0cebe18981bb1f5504ed6807..e2347eb6330682501e99bb3214ccfa9015a8a521 100644 (file)
  */
 
 #include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/rculist.h>
-#include <linux/hash.h>
-#include <linux/radix-tree.h>
+
 #include <trace/events/irq.h>
 
 #include "internals.h"
 
-/*
- * lockdep: we want to handle all irq_desc locks as a single lock-class:
- */
-struct lock_class_key irq_desc_lock_class;
-
 /**
  * handle_bad_irq - handle spurious and unhandled irqs
  * @irq:       the interrupt number
@@ -43,304 +34,6 @@ void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
        ack_bad_irq(irq);
 }
 
-#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
-static void __init init_irq_default_affinity(void)
-{
-       alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
-       cpumask_setall(irq_default_affinity);
-}
-#else
-static void __init init_irq_default_affinity(void)
-{
-}
-#endif
-
-/*
- * Linux has a controller-independent interrupt architecture.
- * Every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the appropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * The code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic or
- * having to touch the generic code.
- *
- * Controller mappings for all interrupt sources:
- */
-int nr_irqs = NR_IRQS;
-EXPORT_SYMBOL_GPL(nr_irqs);
-
-#ifdef CONFIG_SPARSE_IRQ
-
-static struct irq_desc irq_desc_init = {
-       .irq        = -1,
-       .status     = IRQ_DISABLED,
-       .chip       = &no_irq_chip,
-       .handle_irq = handle_bad_irq,
-       .depth      = 1,
-       .lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
-};
-
-void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
-{
-       void *ptr;
-
-       ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
-                          GFP_ATOMIC, node);
-
-       /*
-        * don't overwite if can not get new one
-        * init_copy_kstat_irqs() could still use old one
-        */
-       if (ptr) {
-               printk(KERN_DEBUG "  alloc kstat_irqs on node %d\n", node);
-               desc->kstat_irqs = ptr;
-       }
-}
-
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
-{
-       memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
-
-       raw_spin_lock_init(&desc->lock);
-       desc->irq = irq;
-#ifdef CONFIG_SMP
-       desc->node = node;
-#endif
-       lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-       init_kstat_irqs(desc, node, nr_cpu_ids);
-       if (!desc->kstat_irqs) {
-               printk(KERN_ERR "can not alloc kstat_irqs\n");
-               BUG_ON(1);
-       }
-       if (!alloc_desc_masks(desc, node, false)) {
-               printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
-               BUG_ON(1);
-       }
-       init_desc_masks(desc);
-       arch_init_chip_data(desc, node);
-}
-
-/*
- * Protect the sparse_irqs:
- */
-DEFINE_RAW_SPINLOCK(sparse_irq_lock);
-
-static RADIX_TREE(irq_desc_tree, GFP_ATOMIC);
-
-static void set_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-       radix_tree_insert(&irq_desc_tree, irq, desc);
-}
-
-struct irq_desc *irq_to_desc(unsigned int irq)
-{
-       return radix_tree_lookup(&irq_desc_tree, irq);
-}
-
-void replace_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-       void **ptr;
-
-       ptr = radix_tree_lookup_slot(&irq_desc_tree, irq);
-       if (ptr)
-               radix_tree_replace_slot(ptr, desc);
-}
-
-static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
-       [0 ... NR_IRQS_LEGACY-1] = {
-               .irq        = -1,
-               .status     = IRQ_DISABLED,
-               .chip       = &no_irq_chip,
-               .handle_irq = handle_bad_irq,
-               .depth      = 1,
-               .lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
-       }
-};
-
-static unsigned int *kstat_irqs_legacy;
-
-int __init early_irq_init(void)
-{
-       struct irq_desc *desc;
-       int legacy_count;
-       int node;
-       int i;
-
-       init_irq_default_affinity();
-
-        /* initialize nr_irqs based on nr_cpu_ids */
-       arch_probe_nr_irqs();
-       printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs);
-
-       desc = irq_desc_legacy;
-       legacy_count = ARRAY_SIZE(irq_desc_legacy);
-       node = first_online_node;
-
-       /* allocate based on nr_cpu_ids */
-       kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids *
-                                         sizeof(int), GFP_NOWAIT, node);
-
-       for (i = 0; i < legacy_count; i++) {
-               desc[i].irq = i;
-#ifdef CONFIG_SMP
-               desc[i].node = node;
-#endif
-               desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
-               lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-               alloc_desc_masks(&desc[i], node, true);
-               init_desc_masks(&desc[i]);
-               set_irq_desc(i, &desc[i]);
-       }
-
-       return arch_early_irq_init();
-}
-
-struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
-{
-       struct irq_desc *desc;
-       unsigned long flags;
-
-       if (irq >= nr_irqs) {
-               WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
-                       irq, nr_irqs);
-               return NULL;
-       }
-
-       desc = irq_to_desc(irq);
-       if (desc)
-               return desc;
-
-       raw_spin_lock_irqsave(&sparse_irq_lock, flags);
-
-       /* We have to check it to avoid races with another CPU */
-       desc = irq_to_desc(irq);
-       if (desc)
-               goto out_unlock;
-
-       desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-
-       printk(KERN_DEBUG "  alloc irq_desc for %d on node %d\n", irq, node);
-       if (!desc) {
-               printk(KERN_ERR "can not alloc irq_desc\n");
-               BUG_ON(1);
-       }
-       init_one_irq_desc(irq, desc, node);
-
-       set_irq_desc(irq, desc);
-
-out_unlock:
-       raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-       return desc;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
-       [0 ... NR_IRQS-1] = {
-               .status = IRQ_DISABLED,
-               .chip = &no_irq_chip,
-               .handle_irq = handle_bad_irq,
-               .depth = 1,
-               .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
-       }
-};
-
-static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
-int __init early_irq_init(void)
-{
-       struct irq_desc *desc;
-       int count;
-       int i;
-
-       init_irq_default_affinity();
-
-       printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
-
-       desc = irq_desc;
-       count = ARRAY_SIZE(irq_desc);
-
-       for (i = 0; i < count; i++) {
-               desc[i].irq = i;
-               alloc_desc_masks(&desc[i], 0, true);
-               init_desc_masks(&desc[i]);
-               desc[i].kstat_irqs = kstat_irqs_all[i];
-       }
-       return arch_early_irq_init();
-}
-
-struct irq_desc *irq_to_desc(unsigned int irq)
-{
-       return (irq < NR_IRQS) ? irq_desc + irq : NULL;
-}
-
-struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
-{
-       return irq_to_desc(irq);
-}
-#endif /* !CONFIG_SPARSE_IRQ */
-
-void clear_kstat_irqs(struct irq_desc *desc)
-{
-       memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
-}
-
-/*
- * What should we do if we get a hw irq event on an illegal vector?
- * Each architecture has to answer this themself.
- */
-static void ack_bad(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       print_irq_desc(irq, desc);
-       ack_bad_irq(irq);
-}
-
-/*
- * NOP functions
- */
-static void noop(unsigned int irq)
-{
-}
-
-static unsigned int noop_ret(unsigned int irq)
-{
-       return 0;
-}
-
-/*
- * Generic no controller implementation
- */
-struct irq_chip no_irq_chip = {
-       .name           = "none",
-       .startup        = noop_ret,
-       .shutdown       = noop,
-       .enable         = noop,
-       .disable        = noop,
-       .ack            = ack_bad,
-       .end            = noop,
-};
-
-/*
- * Generic dummy implementation which can be used for
- * real dumb interrupt sources
- */
-struct irq_chip dummy_irq_chip = {
-       .name           = "dummy",
-       .startup        = noop_ret,
-       .shutdown       = noop,
-       .enable         = noop,
-       .disable        = noop,
-       .ack            = noop,
-       .mask           = noop,
-       .unmask         = noop,
-       .end            = noop,
-};
-
 /*
  * Special, empty irq handler:
  */
@@ -457,20 +150,20 @@ unsigned int __do_IRQ(unsigned int irq)
                /*
                 * No locking required for CPU-local interrupts:
                 */
-               if (desc->chip->ack)
-                       desc->chip->ack(irq);
+               if (desc->irq_data.chip->ack)
+                       desc->irq_data.chip->ack(irq);
                if (likely(!(desc->status & IRQ_DISABLED))) {
                        action_ret = handle_IRQ_event(irq, desc->action);
                        if (!noirqdebug)
                                note_interrupt(irq, desc, action_ret);
                }
-               desc->chip->end(irq);
+               desc->irq_data.chip->end(irq);
                return 1;
        }
 
        raw_spin_lock(&desc->lock);
-       if (desc->chip->ack)
-               desc->chip->ack(irq);
+       if (desc->irq_data.chip->ack)
+               desc->irq_data.chip->ack(irq);
        /*
         * REPLAY is when Linux resends an IRQ that was dropped earlier
         * WAITING is used by probe to mark irqs that are being tested
@@ -530,27 +223,9 @@ out:
         * The ->end() handler has to deal with interrupts which got
         * disabled while the handler was running.
         */
-       desc->chip->end(irq);
+       desc->irq_data.chip->end(irq);
        raw_spin_unlock(&desc->lock);
 
        return 1;
 }
 #endif
-
-void early_init_irq_lock_class(void)
-{
-       struct irq_desc *desc;
-       int i;
-
-       for_each_irq_desc(i, desc) {
-               lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-       }
-}
-
-unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       return desc ? desc->kstat_irqs[cpu] : 0;
-}
-EXPORT_SYMBOL(kstat_irqs_cpu);
-
index c63f3bc88f0b77727a45a2a8d44936d797aeaa01..4571ae7e085ac95ad6affb1f31d802f32064665e 100644 (file)
@@ -1,9 +1,12 @@
 /*
  * IRQ subsystem internal functions and variables:
  */
+#include <linux/irqdesc.h>
 
 extern int noirqdebug;
 
+#define irq_data_to_desc(data) container_of(data, struct irq_desc, irq_data)
+
 /* Set default functions for irq_chip structures: */
 extern void irq_chip_set_defaults(struct irq_chip *chip);
 
@@ -15,21 +18,19 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
 extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
 
-extern struct lock_class_key irq_desc_lock_class;
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
-extern void clear_kstat_irqs(struct irq_desc *desc);
-extern raw_spinlock_t sparse_irq_lock;
 
-#ifdef CONFIG_SPARSE_IRQ
-void replace_irq_desc(unsigned int irq, struct irq_desc *desc);
-#endif
+/* Resending of interrupts :*/
+void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
+extern void unregister_irq_proc(unsigned int irq, struct irq_desc *desc);
 extern void register_handler_proc(unsigned int irq, struct irqaction *action);
 extern void unregister_handler_proc(unsigned int irq, struct irqaction *action);
 #else
 static inline void register_irq_proc(unsigned int irq, struct irq_desc *desc) { }
+static inline void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) { }
 static inline void register_handler_proc(unsigned int irq,
                                         struct irqaction *action) { }
 static inline void unregister_handler_proc(unsigned int irq,
@@ -40,17 +41,27 @@ extern int irq_select_affinity_usr(unsigned int irq);
 
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+static inline void irq_end(unsigned int irq, struct irq_desc *desc)
+{
+       if (desc->irq_data.chip && desc->irq_data.chip->end)
+               desc->irq_data.chip->end(irq);
+}
+#else
+static inline void irq_end(unsigned int irq, struct irq_desc *desc) { }
+#endif
+
 /* Inline functions for support of irq chips on slow busses */
-static inline void chip_bus_lock(unsigned int irq, struct irq_desc *desc)
+static inline void chip_bus_lock(struct irq_desc *desc)
 {
-       if (unlikely(desc->chip->bus_lock))
-               desc->chip->bus_lock(irq);
+       if (unlikely(desc->irq_data.chip->irq_bus_lock))
+               desc->irq_data.chip->irq_bus_lock(&desc->irq_data);
 }
 
-static inline void chip_bus_sync_unlock(unsigned int irq, struct irq_desc *desc)
+static inline void chip_bus_sync_unlock(struct irq_desc *desc)
 {
-       if (unlikely(desc->chip->bus_sync_unlock))
-               desc->chip->bus_sync_unlock(irq);
+       if (unlikely(desc->irq_data.chip->irq_bus_sync_unlock))
+               desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);
 }
 
 /*
@@ -67,8 +78,8 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
                irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled);
        printk("->handle_irq():  %p, ", desc->handle_irq);
        print_symbol("%s\n", (unsigned long)desc->handle_irq);
-       printk("->chip(): %p, ", desc->chip);
-       print_symbol("%s\n", (unsigned long)desc->chip);
+       printk("->irq_data.chip(): %p, ", desc->irq_data.chip);
+       print_symbol("%s\n", (unsigned long)desc->irq_data.chip);
        printk("->action(): %p\n", desc->action);
        if (desc->action) {
                printk("->action->handler(): %p, ", desc->action->handler);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
new file mode 100644 (file)
index 0000000..9d917ff
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ *
+ * This file contains the interrupt descriptor management code
+ *
+ * Detailed information is available in Documentation/DocBook/genericirq
+ *
+ */
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/radix-tree.h>
+#include <linux/bitmap.h>
+
+#include "internals.h"
+
+/*
+ * lockdep: we want to handle all irq_desc locks as a single lock-class:
+ */
+static struct lock_class_key irq_desc_lock_class;
+
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
+static void __init init_irq_default_affinity(void)
+{
+       alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
+       cpumask_setall(irq_default_affinity);
+}
+#else
+static void __init init_irq_default_affinity(void)
+{
+}
+#endif
+
+#ifdef CONFIG_SMP
+static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node)
+{
+       if (!zalloc_cpumask_var_node(&desc->irq_data.affinity, gfp, node))
+               return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+       if (!zalloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
+               free_cpumask_var(desc->irq_data.affinity);
+               return -ENOMEM;
+       }
+#endif
+       return 0;
+}
+
+static void desc_smp_init(struct irq_desc *desc, int node)
+{
+       desc->irq_data.node = node;
+       cpumask_copy(desc->irq_data.affinity, irq_default_affinity);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+       cpumask_clear(desc->pending_mask);
+#endif
+}
+
+static inline int desc_node(struct irq_desc *desc)
+{
+       return desc->irq_data.node;
+}
+
+#else
+static inline int
+alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; }
+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)
+{
+       desc->irq_data.irq = irq;
+       desc->irq_data.chip = &no_irq_chip;
+       desc->irq_data.chip_data = NULL;
+       desc->irq_data.handler_data = NULL;
+       desc->irq_data.msi_desc = NULL;
+       desc->status = IRQ_DEFAULT_INIT_FLAGS;
+       desc->handle_irq = handle_bad_irq;
+       desc->depth = 1;
+       desc->irq_count = 0;
+       desc->irqs_unhandled = 0;
+       desc->name = NULL;
+       memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
+       desc_smp_init(desc, node);
+}
+
+int nr_irqs = NR_IRQS;
+EXPORT_SYMBOL_GPL(nr_irqs);
+
+static DEFINE_MUTEX(sparse_irq_lock);
+static DECLARE_BITMAP(allocated_irqs, NR_IRQS);
+
+#ifdef CONFIG_SPARSE_IRQ
+
+static RADIX_TREE(irq_desc_tree, GFP_KERNEL);
+
+static void irq_insert_desc(unsigned int irq, struct irq_desc *desc)
+{
+       radix_tree_insert(&irq_desc_tree, irq, desc);
+}
+
+struct irq_desc *irq_to_desc(unsigned int irq)
+{
+       return radix_tree_lookup(&irq_desc_tree, irq);
+}
+
+static void delete_irq_desc(unsigned int irq)
+{
+       radix_tree_delete(&irq_desc_tree, irq);
+}
+
+#ifdef CONFIG_SMP
+static void free_masks(struct irq_desc *desc)
+{
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+       free_cpumask_var(desc->pending_mask);
+#endif
+       free_cpumask_var(desc->irq_data.affinity);
+}
+#else
+static inline void free_masks(struct irq_desc *desc) { }
+#endif
+
+static struct irq_desc *alloc_desc(int irq, int node)
+{
+       struct irq_desc *desc;
+       gfp_t gfp = GFP_KERNEL;
+
+       desc = kzalloc_node(sizeof(*desc), gfp, node);
+       if (!desc)
+               return NULL;
+       /* allocate based on nr_cpu_ids */
+       desc->kstat_irqs = kzalloc_node(nr_cpu_ids * sizeof(*desc->kstat_irqs),
+                                        gfp, node);
+       if (!desc->kstat_irqs)
+               goto err_desc;
+
+       if (alloc_masks(desc, gfp, node))
+               goto err_kstat;
+
+       raw_spin_lock_init(&desc->lock);
+       lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+
+       desc_set_defaults(irq, desc, node);
+
+       return desc;
+
+err_kstat:
+       kfree(desc->kstat_irqs);
+err_desc:
+       kfree(desc);
+       return NULL;
+}
+
+static void free_desc(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       unregister_irq_proc(irq, desc);
+
+       mutex_lock(&sparse_irq_lock);
+       delete_irq_desc(irq);
+       mutex_unlock(&sparse_irq_lock);
+
+       free_masks(desc);
+       kfree(desc->kstat_irqs);
+       kfree(desc);
+}
+
+static int alloc_descs(unsigned int start, unsigned int cnt, int node)
+{
+       struct irq_desc *desc;
+       int i;
+
+       for (i = 0; i < cnt; i++) {
+               desc = alloc_desc(start + i, node);
+               if (!desc)
+                       goto err;
+               mutex_lock(&sparse_irq_lock);
+               irq_insert_desc(start + i, desc);
+               mutex_unlock(&sparse_irq_lock);
+       }
+       return start;
+
+err:
+       for (i--; i >= 0; i--)
+               free_desc(start + i);
+
+       mutex_lock(&sparse_irq_lock);
+       bitmap_clear(allocated_irqs, start, cnt);
+       mutex_unlock(&sparse_irq_lock);
+       return -ENOMEM;
+}
+
+struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
+{
+       int res = irq_alloc_descs(irq, irq, 1, node);
+
+       if (res == -EEXIST || res == irq)
+               return irq_to_desc(irq);
+       return NULL;
+}
+
+int __init early_irq_init(void)
+{
+       int i, initcnt, node = first_online_node;
+       struct irq_desc *desc;
+
+       init_irq_default_affinity();
+
+       /* Let arch update nr_irqs and return the nr of preallocated irqs */
+       initcnt = arch_probe_nr_irqs();
+       printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt);
+
+       for (i = 0; i < initcnt; i++) {
+               desc = alloc_desc(i, node);
+               set_bit(i, allocated_irqs);
+               irq_insert_desc(i, desc);
+       }
+       return arch_early_irq_init();
+}
+
+#else /* !CONFIG_SPARSE_IRQ */
+
+struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
+       [0 ... NR_IRQS-1] = {
+               .status         = IRQ_DEFAULT_INIT_FLAGS,
+               .handle_irq     = handle_bad_irq,
+               .depth          = 1,
+               .lock           = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
+       }
+};
+
+static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
+int __init early_irq_init(void)
+{
+       int count, i, node = first_online_node;
+       struct irq_desc *desc;
+
+       init_irq_default_affinity();
+
+       printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
+
+       desc = irq_desc;
+       count = ARRAY_SIZE(irq_desc);
+
+       for (i = 0; i < count; i++) {
+               desc[i].irq_data.irq = i;
+               desc[i].irq_data.chip = &no_irq_chip;
+               desc[i].kstat_irqs = kstat_irqs_all[i];
+               alloc_masks(desc + i, GFP_KERNEL, node);
+               desc_smp_init(desc + i, node);
+               lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+       }
+       return arch_early_irq_init();
+}
+
+struct irq_desc *irq_to_desc(unsigned int irq)
+{
+       return (irq < NR_IRQS) ? irq_desc + irq : NULL;
+}
+
+struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
+{
+       return irq_to_desc(irq);
+}
+
+static void free_desc(unsigned int irq)
+{
+       dynamic_irq_cleanup(irq);
+}
+
+static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
+{
+       return start;
+}
+#endif /* !CONFIG_SPARSE_IRQ */
+
+/* Dynamic interrupt handling */
+
+/**
+ * irq_free_descs - free irq descriptors
+ * @from:      Start of descriptor range
+ * @cnt:       Number of consecutive irqs to free
+ */
+void irq_free_descs(unsigned int from, unsigned int cnt)
+{
+       int i;
+
+       if (from >= nr_irqs || (from + cnt) > nr_irqs)
+               return;
+
+       for (i = 0; i < cnt; i++)
+               free_desc(from + i);
+
+       mutex_lock(&sparse_irq_lock);
+       bitmap_clear(allocated_irqs, from, cnt);
+       mutex_unlock(&sparse_irq_lock);
+}
+
+/**
+ * irq_alloc_descs - allocate and initialize a range of irq descriptors
+ * @irq:       Allocate for specific irq number if irq >= 0
+ * @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
+ *
+ * Returns the first irq number or error code
+ */
+int __ref
+irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
+{
+       int start, ret;
+
+       if (!cnt)
+               return -EINVAL;
+
+       mutex_lock(&sparse_irq_lock);
+
+       start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
+       ret = -EEXIST;
+       if (irq >=0 && start != irq)
+               goto err;
+
+       ret = -ENOMEM;
+       if (start >= nr_irqs)
+               goto err;
+
+       bitmap_set(allocated_irqs, start, cnt);
+       mutex_unlock(&sparse_irq_lock);
+       return alloc_descs(start, cnt, node);
+
+err:
+       mutex_unlock(&sparse_irq_lock);
+       return ret;
+}
+
+/**
+ * irq_reserve_irqs - mark irqs allocated
+ * @from:      mark from irq number
+ * @cnt:       number of irqs to mark
+ *
+ * Returns 0 on success or an appropriate error code
+ */
+int irq_reserve_irqs(unsigned int from, unsigned int cnt)
+{
+       unsigned int start;
+       int ret = 0;
+
+       if (!cnt || (from + cnt) > nr_irqs)
+               return -EINVAL;
+
+       mutex_lock(&sparse_irq_lock);
+       start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
+       if (start == from)
+               bitmap_set(allocated_irqs, start, cnt);
+       else
+               ret = -EEXIST;
+       mutex_unlock(&sparse_irq_lock);
+       return ret;
+}
+
+/**
+ * irq_get_next_irq - get next allocated irq number
+ * @offset:    where to start the search
+ *
+ * Returns next irq number after offset or nr_irqs if none is found.
+ */
+unsigned int irq_get_next_irq(unsigned int offset)
+{
+       return find_next_bit(allocated_irqs, nr_irqs, offset);
+}
+
+/**
+ * dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ * @irq:       irq number to initialize
+ */
+void dynamic_irq_cleanup(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&desc->lock, flags);
+       desc_set_defaults(irq, desc, desc_node(desc));
+       raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+       return desc ? desc->kstat_irqs[cpu] : 0;
+}
index c3003e9d91a37da04c8c7ffc9aa5f986fc90fb04..644e8d5fa367e74c3cc06a2114f2e283c701b0e6 100644 (file)
@@ -73,8 +73,8 @@ int irq_can_set_affinity(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
 
-       if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
-           !desc->chip->set_affinity)
+       if (CHECK_IRQ_PER_CPU(desc->status) || !desc->irq_data.chip ||
+           !desc->irq_data.chip->irq_set_affinity)
                return 0;
 
        return 1;
@@ -109,17 +109,18 @@ void irq_set_thread_affinity(struct irq_desc *desc)
 int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
        struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_chip *chip = desc->irq_data.chip;
        unsigned long flags;
 
-       if (!desc->chip->set_affinity)
+       if (!chip->irq_set_affinity)
                return -EINVAL;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (desc->status & IRQ_MOVE_PCNTXT) {
-               if (!desc->chip->set_affinity(irq, cpumask)) {
-                       cpumask_copy(desc->affinity, cpumask);
+               if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
+                       cpumask_copy(desc->irq_data.affinity, cpumask);
                        irq_set_thread_affinity(desc);
                }
        }
@@ -128,8 +129,8 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
                cpumask_copy(desc->pending_mask, cpumask);
        }
 #else
-       if (!desc->chip->set_affinity(irq, cpumask)) {
-               cpumask_copy(desc->affinity, cpumask);
+       if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
+               cpumask_copy(desc->irq_data.affinity, cpumask);
                irq_set_thread_affinity(desc);
        }
 #endif
@@ -168,16 +169,16 @@ static int setup_affinity(unsigned int irq, struct irq_desc *desc)
         * one of the targets is online.
         */
        if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
-               if (cpumask_any_and(desc->affinity, cpu_online_mask)
+               if (cpumask_any_and(desc->irq_data.affinity, cpu_online_mask)
                    < nr_cpu_ids)
                        goto set_affinity;
                else
                        desc->status &= ~IRQ_AFFINITY_SET;
        }
 
-       cpumask_and(desc->affinity, cpu_online_mask, irq_default_affinity);
+       cpumask_and(desc->irq_data.affinity, cpu_online_mask, irq_default_affinity);
 set_affinity:
-       desc->chip->set_affinity(irq, desc->affinity);
+       desc->irq_data.chip->irq_set_affinity(&desc->irq_data, desc->irq_data.affinity, false);
 
        return 0;
 }
@@ -223,7 +224,7 @@ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
 
        if (!desc->depth++) {
                desc->status |= IRQ_DISABLED;
-               desc->chip->disable(irq);
+               desc->irq_data.chip->irq_disable(&desc->irq_data);
        }
 }
 
@@ -246,11 +247,11 @@ void disable_irq_nosync(unsigned int irq)
        if (!desc)
                return;
 
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        raw_spin_lock_irqsave(&desc->lock, flags);
        __disable_irq(desc, irq, false);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(disable_irq_nosync);
 
@@ -313,7 +314,7 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
  *     IRQ line is re-enabled.
  *
  *     This function may be called from IRQ context only when
- *     desc->chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
+ *     desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
  */
 void enable_irq(unsigned int irq)
 {
@@ -323,11 +324,11 @@ void enable_irq(unsigned int irq)
        if (!desc)
                return;
 
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        raw_spin_lock_irqsave(&desc->lock, flags);
        __enable_irq(desc, irq, false);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(enable_irq);
 
@@ -336,8 +337,8 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on)
        struct irq_desc *desc = irq_to_desc(irq);
        int ret = -ENXIO;
 
-       if (desc->chip->set_wake)
-               ret = desc->chip->set_wake(irq, on);
+       if (desc->irq_data.chip->irq_set_wake)
+               ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on);
 
        return ret;
 }
@@ -429,12 +430,12 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
 }
 
 int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
-               unsigned long flags)
+                     unsigned long flags)
 {
        int ret;
-       struct irq_chip *chip = desc->chip;
+       struct irq_chip *chip = desc->irq_data.chip;
 
-       if (!chip || !chip->set_type) {
+       if (!chip || !chip->irq_set_type) {
                /*
                 * IRQF_TRIGGER_* but the PIC does not support multiple
                 * flow-types?
@@ -445,11 +446,11 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
        }
 
        /* caller masked out all except trigger mode flags */
-       ret = chip->set_type(irq, flags);
+       ret = chip->irq_set_type(&desc->irq_data, flags);
 
        if (ret)
-               pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
-                               (int)flags, irq, chip->set_type);
+               pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",
+                      flags, irq, chip->irq_set_type);
        else {
                if (flags & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
                        flags |= IRQ_LEVEL;
@@ -457,8 +458,8 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
                desc->status |= flags;
 
-               if (chip != desc->chip)
-                       irq_chip_set_defaults(desc->chip);
+               if (chip != desc->irq_data.chip)
+                       irq_chip_set_defaults(desc->irq_data.chip);
        }
 
        return ret;
@@ -507,7 +508,7 @@ static int irq_wait_for_interrupt(struct irqaction *action)
 static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
 {
 again:
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        raw_spin_lock_irq(&desc->lock);
 
        /*
@@ -521,17 +522,17 @@ again:
         */
        if (unlikely(desc->status & IRQ_INPROGRESS)) {
                raw_spin_unlock_irq(&desc->lock);
-               chip_bus_sync_unlock(irq, desc);
+               chip_bus_sync_unlock(desc);
                cpu_relax();
                goto again;
        }
 
        if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
                desc->status &= ~IRQ_MASKED;
-               desc->chip->unmask(irq);
+               desc->irq_data.chip->irq_unmask(&desc->irq_data);
        }
        raw_spin_unlock_irq(&desc->lock);
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 }
 
 #ifdef CONFIG_SMP
@@ -556,7 +557,7 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
        }
 
        raw_spin_lock_irq(&desc->lock);
-       cpumask_copy(mask, desc->affinity);
+       cpumask_copy(mask, desc->irq_data.affinity);
        raw_spin_unlock_irq(&desc->lock);
 
        set_cpus_allowed_ptr(current, mask);
@@ -657,7 +658,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
        if (!desc)
                return -EINVAL;
 
-       if (desc->chip == &no_irq_chip)
+       if (desc->irq_data.chip == &no_irq_chip)
                return -ENOSYS;
        /*
         * Some drivers like serial.c use request_irq() heavily,
@@ -752,7 +753,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
        }
 
        if (!shared) {
-               irq_chip_set_defaults(desc->chip);
+               irq_chip_set_defaults(desc->irq_data.chip);
 
                init_waitqueue_head(&desc->wait_for_threads);
 
@@ -779,7 +780,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                if (!(desc->status & IRQ_NOAUTOEN)) {
                        desc->depth = 0;
                        desc->status &= ~IRQ_DISABLED;
-                       desc->chip->startup(irq);
+                       desc->irq_data.chip->irq_startup(&desc->irq_data);
                } else
                        /* Undo nested disables: */
                        desc->depth = 1;
@@ -912,17 +913,17 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 
        /* Currently used only by UML, might disappear one day: */
 #ifdef CONFIG_IRQ_RELEASE_METHOD
-       if (desc->chip->release)
-               desc->chip->release(irq, dev_id);
+       if (desc->irq_data.chip->release)
+               desc->irq_data.chip->release(irq, dev_id);
 #endif
 
        /* If this was the last handler, shut down the IRQ line: */
        if (!desc->action) {
                desc->status |= IRQ_DISABLED;
-               if (desc->chip->shutdown)
-                       desc->chip->shutdown(irq);
+               if (desc->irq_data.chip->irq_shutdown)
+                       desc->irq_data.chip->irq_shutdown(&desc->irq_data);
                else
-                       desc->chip->disable(irq);
+                       desc->irq_data.chip->irq_disable(&desc->irq_data);
        }
 
 #ifdef CONFIG_SMP
@@ -997,9 +998,9 @@ void free_irq(unsigned int irq, void *dev_id)
        if (!desc)
                return;
 
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        kfree(__free_irq(irq, dev_id));
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(free_irq);
 
@@ -1086,9 +1087,9 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
        action->name = devname;
        action->dev_id = dev_id;
 
-       chip_bus_lock(irq, desc);
+       chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
-       chip_bus_sync_unlock(irq, desc);
+       chip_bus_sync_unlock(desc);
 
        if (retval)
                kfree(action);
index 241962280836ff73e8143dc8ebc63a83f53d9115..1d25419404803e60229dc15b1cc13980fe35db78 100644 (file)
@@ -7,6 +7,7 @@
 void move_masked_irq(int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_chip *chip = desc->irq_data.chip;
 
        if (likely(!(desc->status & IRQ_MOVE_PENDING)))
                return;
@@ -24,7 +25,7 @@ void move_masked_irq(int irq)
        if (unlikely(cpumask_empty(desc->pending_mask)))
                return;
 
-       if (!desc->chip->set_affinity)
+       if (!chip->irq_set_affinity)
                return;
 
        assert_raw_spin_locked(&desc->lock);
@@ -43,8 +44,9 @@ void move_masked_irq(int irq)
         */
        if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
                   < nr_cpu_ids))
-               if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
-                       cpumask_copy(desc->affinity, desc->pending_mask);
+               if (!chip->irq_set_affinity(&desc->irq_data,
+                                           desc->pending_mask, false)) {
+                       cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
                        irq_set_thread_affinity(desc);
                }
 
@@ -61,8 +63,8 @@ void move_native_irq(int irq)
        if (unlikely(desc->status & IRQ_DISABLED))
                return;
 
-       desc->chip->mask(irq);
+       desc->irq_data.chip->irq_mask(&desc->irq_data);
        move_masked_irq(irq);
-       desc->chip->unmask(irq);
+       desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c
deleted file mode 100644 (file)
index 65d3845..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * NUMA irq-desc migration code
- *
- * Migrate IRQ data structures (irq_desc, chip_data, etc.) over to
- * the new "home node" of the IRQ.
- */
-
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include "internals.h"
-
-static void init_copy_kstat_irqs(struct irq_desc *old_desc,
-                                struct irq_desc *desc,
-                                int node, int nr)
-{
-       init_kstat_irqs(desc, node, nr);
-
-       if (desc->kstat_irqs != old_desc->kstat_irqs)
-               memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
-                        nr * sizeof(*desc->kstat_irqs));
-}
-
-static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
-{
-       if (old_desc->kstat_irqs == desc->kstat_irqs)
-               return;
-
-       kfree(old_desc->kstat_irqs);
-       old_desc->kstat_irqs = NULL;
-}
-
-static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
-                struct irq_desc *desc, int node)
-{
-       memcpy(desc, old_desc, sizeof(struct irq_desc));
-       if (!alloc_desc_masks(desc, node, false)) {
-               printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
-                               "for migration.\n", irq);
-               return false;
-       }
-       raw_spin_lock_init(&desc->lock);
-       desc->node = node;
-       lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-       init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
-       init_copy_desc_masks(old_desc, desc);
-       arch_init_copy_chip_data(old_desc, desc, node);
-       return true;
-}
-
-static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
-{
-       free_kstat_irqs(old_desc, desc);
-       free_desc_masks(old_desc, desc);
-       arch_free_chip_data(old_desc, desc);
-}
-
-static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
-                                               int node)
-{
-       struct irq_desc *desc;
-       unsigned int irq;
-       unsigned long flags;
-
-       irq = old_desc->irq;
-
-       raw_spin_lock_irqsave(&sparse_irq_lock, flags);
-
-       /* We have to check it to avoid races with another CPU */
-       desc = irq_to_desc(irq);
-
-       if (desc && old_desc != desc)
-               goto out_unlock;
-
-       desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-       if (!desc) {
-               printk(KERN_ERR "irq %d: can not get new irq_desc "
-                               "for migration.\n", irq);
-               /* still use old one */
-               desc = old_desc;
-               goto out_unlock;
-       }
-       if (!init_copy_one_irq_desc(irq, old_desc, desc, node)) {
-               /* still use old one */
-               kfree(desc);
-               desc = old_desc;
-               goto out_unlock;
-       }
-
-       replace_irq_desc(irq, desc);
-       raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-       /* free the old one */
-       free_one_irq_desc(old_desc, desc);
-       kfree(old_desc);
-
-       return desc;
-
-out_unlock:
-       raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-       return desc;
-}
-
-struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
-{
-       /* those static or target node is -1, do not move them */
-       if (desc->irq < NR_IRQS_LEGACY || node == -1)
-               return desc;
-
-       if (desc->node != node)
-               desc = __real_move_irq_desc(desc, node);
-
-       return desc;
-}
-
index 09a2ee540bd246e127f07c653f262b22009488ae..01b1d3a88983f92c189e0c9b27f23ffe0e73f88f 100644 (file)
@@ -21,7 +21,7 @@ static struct proc_dir_entry *root_irq_dir;
 static int irq_affinity_proc_show(struct seq_file *m, void *v)
 {
        struct irq_desc *desc = irq_to_desc((long)m->private);
-       const struct cpumask *mask = desc->affinity;
+       const struct cpumask *mask = desc->irq_data.affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (desc->status & IRQ_MOVE_PENDING)
@@ -65,7 +65,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
        cpumask_var_t new_value;
        int err;
 
-       if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity ||
+       if (!irq_to_desc(irq)->irq_data.chip->irq_set_affinity || no_irq_affinity ||
            irq_balancing_disabled(irq))
                return -EIO;
 
@@ -185,7 +185,7 @@ static int irq_node_proc_show(struct seq_file *m, void *v)
 {
        struct irq_desc *desc = irq_to_desc((long) m->private);
 
-       seq_printf(m, "%d\n", desc->node);
+       seq_printf(m, "%d\n", desc->irq_data.node);
        return 0;
 }
 
@@ -269,7 +269,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 {
        char name [MAX_NAMELEN];
 
-       if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir)
+       if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
                return;
 
        memset(name, 0, MAX_NAMELEN);
@@ -297,6 +297,24 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
                         &irq_spurious_proc_fops, (void *)(long)irq);
 }
 
+void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
+{
+       char name [MAX_NAMELEN];
+
+       if (!root_irq_dir || !desc->dir)
+               return;
+#ifdef CONFIG_SMP
+       remove_proc_entry("smp_affinity", desc->dir);
+       remove_proc_entry("affinity_hint", desc->dir);
+       remove_proc_entry("node", desc->dir);
+#endif
+       remove_proc_entry("spurious", desc->dir);
+
+       memset(name, 0, MAX_NAMELEN);
+       sprintf(name, "%u", irq);
+       remove_proc_entry(name, root_irq_dir);
+}
+
 #undef MAX_NAMELEN
 
 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
index 090c3763f3a294143b47d8a89cefff884fc1b826..891115a929aa1dfe223b01c5f50efbc0ec35a2f7 100644 (file)
@@ -60,7 +60,7 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
        /*
         * Make sure the interrupt is enabled, before resending it:
         */
-       desc->chip->enable(irq);
+       desc->irq_data.chip->irq_enable(&desc->irq_data);
 
        /*
         * We do not resend level type interrupts. Level type
@@ -70,7 +70,8 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
        if ((status & (IRQ_LEVEL | IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
                desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;
 
-               if (!desc->chip->retrigger || !desc->chip->retrigger(irq)) {
+               if (!desc->irq_data.chip->irq_retrigger ||
+                   !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
 #ifdef CONFIG_HARDIRQS_SW_RESEND
                        /* Set it pending and activate the softirq: */
                        set_bit(irq, irqs_resend);
index 89fb90ae534f551defdda8e43d7f1d274cb12b9e..3089d3b9d5f3912643d49bf46960fe7938a46e6a 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/moduleparam.h>
 #include <linux/timer.h>
 
+#include "internals.h"
+
 static int irqfixup __read_mostly;
 
 #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
@@ -78,8 +80,8 @@ static int try_one_irq(int irq, struct irq_desc *desc)
         * If we did actual work for the real IRQ line we must let the
         * IRQ controller clean up too
         */
-       if (work && desc->chip && desc->chip->end)
-               desc->chip->end(irq);
+       if (work)
+               irq_end(irq, desc);
        raw_spin_unlock(&desc->lock);
 
        return ok;
@@ -254,7 +256,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
                desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
                desc->depth++;
-               desc->chip->disable(irq);
+               desc->irq_data.chip->irq_disable(&desc->irq_data);
 
                mod_timer(&poll_spurious_irq_timer,
                          jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
new file mode 100644 (file)
index 0000000..f16763f
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ * Provides a framework for enqueueing and running callbacks from hardirq
+ * context. The enqueueing is NMI-safe.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq_work.h>
+#include <linux/hardirq.h>
+
+/*
+ * An entry can be in one of four states:
+ *
+ * free             NULL, 0 -> {claimed}       : free to be used
+ * claimed   NULL, 3 -> {pending}       : claimed to be enqueued
+ * pending   next, 3 -> {busy}          : queued, pending callback
+ * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
+ *
+ * We use the lower two bits of the next pointer to keep PENDING and BUSY
+ * flags.
+ */
+
+#define IRQ_WORK_PENDING       1UL
+#define IRQ_WORK_BUSY          2UL
+#define IRQ_WORK_FLAGS         3UL
+
+static inline bool irq_work_is_set(struct irq_work *entry, int flags)
+{
+       return (unsigned long)entry->next & flags;
+}
+
+static inline struct irq_work *irq_work_next(struct irq_work *entry)
+{
+       unsigned long next = (unsigned long)entry->next;
+       next &= ~IRQ_WORK_FLAGS;
+       return (struct irq_work *)next;
+}
+
+static inline struct irq_work *next_flags(struct irq_work *entry, int flags)
+{
+       unsigned long next = (unsigned long)entry;
+       next |= flags;
+       return (struct irq_work *)next;
+}
+
+static DEFINE_PER_CPU(struct irq_work *, irq_work_list);
+
+/*
+ * Claim the entry so that no one else will poke at it.
+ */
+static bool irq_work_claim(struct irq_work *entry)
+{
+       struct irq_work *next, *nflags;
+
+       do {
+               next = entry->next;
+               if ((unsigned long)next & IRQ_WORK_PENDING)
+                       return false;
+               nflags = next_flags(next, IRQ_WORK_FLAGS);
+       } while (cmpxchg(&entry->next, next, nflags) != next);
+
+       return true;
+}
+
+
+void __weak arch_irq_work_raise(void)
+{
+       /*
+        * Lame architectures will get the timer tick callback
+        */
+}
+
+/*
+ * Queue the entry and raise the IPI if needed.
+ */
+static void __irq_work_queue(struct irq_work *entry)
+{
+       struct irq_work **head, *next;
+
+       head = &get_cpu_var(irq_work_list);
+
+       do {
+               next = *head;
+               /* Can assign non-atomic because we keep the flags set. */
+               entry->next = next_flags(next, IRQ_WORK_FLAGS);
+       } while (cmpxchg(head, next, entry) != next);
+
+       /* The list was empty, raise self-interrupt to start processing. */
+       if (!irq_work_next(entry))
+               arch_irq_work_raise();
+
+       put_cpu_var(irq_work_list);
+}
+
+/*
+ * Enqueue the irq_work @entry, returns true on success, failure when the
+ * @entry was already enqueued by someone else.
+ *
+ * Can be re-enqueued while the callback is still in progress.
+ */
+bool irq_work_queue(struct irq_work *entry)
+{
+       if (!irq_work_claim(entry)) {
+               /*
+                * Already enqueued, can't do!
+                */
+               return false;
+       }
+
+       __irq_work_queue(entry);
+       return true;
+}
+EXPORT_SYMBOL_GPL(irq_work_queue);
+
+/*
+ * Run the irq_work entries on this cpu. Requires to be ran from hardirq
+ * context with local IRQs disabled.
+ */
+void irq_work_run(void)
+{
+       struct irq_work *list, **head;
+
+       head = &__get_cpu_var(irq_work_list);
+       if (*head == NULL)
+               return;
+
+       BUG_ON(!in_irq());
+       BUG_ON(!irqs_disabled());
+
+       list = xchg(head, NULL);
+       while (list != NULL) {
+               struct irq_work *entry = list;
+
+               list = irq_work_next(list);
+
+               /*
+                * Clear the PENDING bit, after this point the @entry
+                * can be re-used.
+                */
+               entry->next = next_flags(NULL, IRQ_WORK_BUSY);
+               entry->func(entry);
+               /*
+                * Clear the BUSY bit and return to the free state if
+                * no-one else claimed it meanwhile.
+                */
+               cmpxchg(&entry->next, next_flags(NULL, IRQ_WORK_BUSY), NULL);
+       }
+}
+EXPORT_SYMBOL_GPL(irq_work_run);
+
+/*
+ * Synchronize against the irq_work @entry, ensures the entry is not
+ * currently in use.
+ */
+void irq_work_sync(struct irq_work *entry)
+{
+       WARN_ON_ONCE(irqs_disabled());
+
+       while (irq_work_is_set(entry, IRQ_WORK_BUSY))
+               cpu_relax();
+}
+EXPORT_SYMBOL_GPL(irq_work_sync);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..7be868b
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * jump label support
+ *
+ * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ *
+ */
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/err.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+#define JUMP_LABEL_HASH_BITS 6
+#define JUMP_LABEL_TABLE_SIZE (1 << JUMP_LABEL_HASH_BITS)
+static struct hlist_head jump_label_table[JUMP_LABEL_TABLE_SIZE];
+
+/* mutex to protect coming/going of the the jump_label table */
+static DEFINE_MUTEX(jump_label_mutex);
+
+struct jump_label_entry {
+       struct hlist_node hlist;
+       struct jump_entry *table;
+       int nr_entries;
+       /* hang modules off here */
+       struct hlist_head modules;
+       unsigned long key;
+};
+
+struct jump_label_module_entry {
+       struct hlist_node hlist;
+       struct jump_entry *table;
+       int nr_entries;
+       struct module *mod;
+};
+
+static int jump_label_cmp(const void *a, const void *b)
+{
+       const struct jump_entry *jea = a;
+       const struct jump_entry *jeb = b;
+
+       if (jea->key < jeb->key)
+               return -1;
+
+       if (jea->key > jeb->key)
+               return 1;
+
+       return 0;
+}
+
+static void
+sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop)
+{
+       unsigned long size;
+
+       size = (((unsigned long)stop - (unsigned long)start)
+                                       / sizeof(struct jump_entry));
+       sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
+}
+
+static struct jump_label_entry *get_jump_label_entry(jump_label_t key)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct jump_label_entry *e;
+       u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0);
+
+       head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
+       hlist_for_each_entry(e, node, head, hlist) {
+               if (key == e->key)
+                       return e;
+       }
+       return NULL;
+}
+
+static struct jump_label_entry *
+add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table)
+{
+       struct hlist_head *head;
+       struct jump_label_entry *e;
+       u32 hash;
+
+       e = get_jump_label_entry(key);
+       if (e)
+               return ERR_PTR(-EEXIST);
+
+       e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL);
+       if (!e)
+               return ERR_PTR(-ENOMEM);
+
+       hash = jhash((void *)&key, sizeof(jump_label_t), 0);
+       head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
+       e->key = key;
+       e->table = table;
+       e->nr_entries = nr_entries;
+       INIT_HLIST_HEAD(&(e->modules));
+       hlist_add_head(&e->hlist, head);
+       return e;
+}
+
+static int
+build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop)
+{
+       struct jump_entry *iter, *iter_begin;
+       struct jump_label_entry *entry;
+       int count;
+
+       sort_jump_label_entries(start, stop);
+       iter = start;
+       while (iter < stop) {
+               entry = get_jump_label_entry(iter->key);
+               if (!entry) {
+                       iter_begin = iter;
+                       count = 0;
+                       while ((iter < stop) &&
+                               (iter->key == iter_begin->key)) {
+                               iter++;
+                               count++;
+                       }
+                       entry = add_jump_label_entry(iter_begin->key,
+                                                       count, iter_begin);
+                       if (IS_ERR(entry))
+                               return PTR_ERR(entry);
+                } else {
+                       WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+/***
+ * jump_label_update - update jump label text
+ * @key -  key value associated with a a jump label
+ * @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE
+ *
+ * Will enable/disable the jump for jump label @key, depending on the
+ * value of @type.
+ *
+ */
+
+void jump_label_update(unsigned long key, enum jump_label_type type)
+{
+       struct jump_entry *iter;
+       struct jump_label_entry *entry;
+       struct hlist_node *module_node;
+       struct jump_label_module_entry *e_module;
+       int count;
+
+       mutex_lock(&jump_label_mutex);
+       entry = get_jump_label_entry((jump_label_t)key);
+       if (entry) {
+               count = entry->nr_entries;
+               iter = entry->table;
+               while (count--) {
+                       if (kernel_text_address(iter->code))
+                               arch_jump_label_transform(iter, type);
+                       iter++;
+               }
+               /* eanble/disable jump labels in modules */
+               hlist_for_each_entry(e_module, module_node, &(entry->modules),
+                                                       hlist) {
+                       count = e_module->nr_entries;
+                       iter = e_module->table;
+                       while (count--) {
+                               if (kernel_text_address(iter->code))
+                                       arch_jump_label_transform(iter, type);
+                               iter++;
+                       }
+               }
+       }
+       mutex_unlock(&jump_label_mutex);
+}
+
+static int addr_conflict(struct jump_entry *entry, void *start, void *end)
+{
+       if (entry->code <= (unsigned long)end &&
+               entry->code + JUMP_LABEL_NOP_SIZE > (unsigned long)start)
+               return 1;
+
+       return 0;
+}
+
+#ifdef CONFIG_MODULES
+
+static int module_conflict(void *start, void *end)
+{
+       struct hlist_head *head;
+       struct hlist_node *node, *node_next, *module_node, *module_node_next;
+       struct jump_label_entry *e;
+       struct jump_label_module_entry *e_module;
+       struct jump_entry *iter;
+       int i, count;
+       int conflict = 0;
+
+       for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
+               head = &jump_label_table[i];
+               hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
+                       hlist_for_each_entry_safe(e_module, module_node,
+                                                       module_node_next,
+                                                       &(e->modules), hlist) {
+                               count = e_module->nr_entries;
+                               iter = e_module->table;
+                               while (count--) {
+                                       if (addr_conflict(iter, start, end)) {
+                                               conflict = 1;
+                                               goto out;
+                                       }
+                                       iter++;
+                               }
+                       }
+               }
+       }
+out:
+       return conflict;
+}
+
+#endif
+
+/***
+ * jump_label_text_reserved - check if addr range is reserved
+ * @start: start text addr
+ * @end: end text addr
+ *
+ * checks if the text addr located between @start and @end
+ * overlaps with any of the jump label patch addresses. Code
+ * that wants to modify kernel text should first verify that
+ * it does not overlap with any of the jump label addresses.
+ *
+ * returns 1 if there is an overlap, 0 otherwise
+ */
+int jump_label_text_reserved(void *start, void *end)
+{
+       struct jump_entry *iter;
+       struct jump_entry *iter_start = __start___jump_table;
+       struct jump_entry *iter_stop = __start___jump_table;
+       int conflict = 0;
+
+       mutex_lock(&jump_label_mutex);
+       iter = iter_start;
+       while (iter < iter_stop) {
+               if (addr_conflict(iter, start, end)) {
+                       conflict = 1;
+                       goto out;
+               }
+               iter++;
+       }
+
+       /* now check modules */
+#ifdef CONFIG_MODULES
+       conflict = module_conflict(start, end);
+#endif
+out:
+       mutex_unlock(&jump_label_mutex);
+       return conflict;
+}
+
+static __init int init_jump_label(void)
+{
+       int ret;
+       struct jump_entry *iter_start = __start___jump_table;
+       struct jump_entry *iter_stop = __stop___jump_table;
+       struct jump_entry *iter;
+
+       mutex_lock(&jump_label_mutex);
+       ret = build_jump_label_hashtable(__start___jump_table,
+                                        __stop___jump_table);
+       iter = iter_start;
+       while (iter < iter_stop) {
+               arch_jump_label_text_poke_early(iter->code);
+               iter++;
+       }
+       mutex_unlock(&jump_label_mutex);
+       return ret;
+}
+early_initcall(init_jump_label);
+
+#ifdef CONFIG_MODULES
+
+static struct jump_label_module_entry *
+add_jump_label_module_entry(struct jump_label_entry *entry,
+                           struct jump_entry *iter_begin,
+                           int count, struct module *mod)
+{
+       struct jump_label_module_entry *e;
+
+       e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL);
+       if (!e)
+               return ERR_PTR(-ENOMEM);
+       e->mod = mod;
+       e->nr_entries = count;
+       e->table = iter_begin;
+       hlist_add_head(&e->hlist, &entry->modules);
+       return e;
+}
+
+static int add_jump_label_module(struct module *mod)
+{
+       struct jump_entry *iter, *iter_begin;
+       struct jump_label_entry *entry;
+       struct jump_label_module_entry *module_entry;
+       int count;
+
+       /* if the module doesn't have jump label entries, just return */
+       if (!mod->num_jump_entries)
+               return 0;
+
+       sort_jump_label_entries(mod->jump_entries,
+                               mod->jump_entries + mod->num_jump_entries);
+       iter = mod->jump_entries;
+       while (iter < mod->jump_entries + mod->num_jump_entries) {
+               entry = get_jump_label_entry(iter->key);
+               iter_begin = iter;
+               count = 0;
+               while ((iter < mod->jump_entries + mod->num_jump_entries) &&
+                       (iter->key == iter_begin->key)) {
+                               iter++;
+                               count++;
+               }
+               if (!entry) {
+                       entry = add_jump_label_entry(iter_begin->key, 0, NULL);
+                       if (IS_ERR(entry))
+                               return PTR_ERR(entry);
+               }
+               module_entry = add_jump_label_module_entry(entry, iter_begin,
+                                                          count, mod);
+               if (IS_ERR(module_entry))
+                       return PTR_ERR(module_entry);
+       }
+       return 0;
+}
+
+static void remove_jump_label_module(struct module *mod)
+{
+       struct hlist_head *head;
+       struct hlist_node *node, *node_next, *module_node, *module_node_next;
+       struct jump_label_entry *e;
+       struct jump_label_module_entry *e_module;
+       int i;
+
+       /* if the module doesn't have jump label entries, just return */
+       if (!mod->num_jump_entries)
+               return;
+
+       for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
+               head = &jump_label_table[i];
+               hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
+                       hlist_for_each_entry_safe(e_module, module_node,
+                                                 module_node_next,
+                                                 &(e->modules), hlist) {
+                               if (e_module->mod == mod) {
+                                       hlist_del(&e_module->hlist);
+                                       kfree(e_module);
+                               }
+                       }
+                       if (hlist_empty(&e->modules) && (e->nr_entries == 0)) {
+                               hlist_del(&e->hlist);
+                               kfree(e);
+                       }
+               }
+       }
+}
+
+static int
+jump_label_module_notify(struct notifier_block *self, unsigned long val,
+                        void *data)
+{
+       struct module *mod = data;
+       int ret = 0;
+
+       switch (val) {
+       case MODULE_STATE_COMING:
+               mutex_lock(&jump_label_mutex);
+               ret = add_jump_label_module(mod);
+               if (ret)
+                       remove_jump_label_module(mod);
+               mutex_unlock(&jump_label_mutex);
+               break;
+       case MODULE_STATE_GOING:
+               mutex_lock(&jump_label_mutex);
+               remove_jump_label_module(mod);
+               mutex_unlock(&jump_label_mutex);
+               break;
+       }
+       return ret;
+}
+
+/***
+ * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
+ * @mod: module to patch
+ *
+ * Allow for run-time selection of the optimal nops. Before the module
+ * loads patch these with arch_get_jump_label_nop(), which is specified by
+ * the arch specific jump label code.
+ */
+void jump_label_apply_nops(struct module *mod)
+{
+       struct jump_entry *iter;
+
+       /* if the module doesn't have jump label entries, just return */
+       if (!mod->num_jump_entries)
+               return;
+
+       iter = mod->jump_entries;
+       while (iter < mod->jump_entries + mod->num_jump_entries) {
+               arch_jump_label_text_poke_early(iter->code);
+               iter++;
+       }
+}
+
+struct notifier_block jump_label_module_nb = {
+       .notifier_call = jump_label_module_notify,
+       .priority = 0,
+};
+
+static __init int init_jump_label_module(void)
+{
+       return register_module_notifier(&jump_label_module_nb);
+}
+early_initcall(init_jump_label_module);
+
+#endif /* CONFIG_MODULES */
+
+#endif
index 6b5580c57644dc1804b02fd85648e7100d5d75dd..01a0700e873f53ca60084da3c0c1142bebf49b16 100644 (file)
@@ -365,8 +365,6 @@ static unsigned int setup_sgl(struct __kfifo *fifo, struct scatterlist *sgl,
        n = setup_sgl_buf(sgl, fifo->data + off, nents, l);
        n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l);
 
-       if (n)
-               sg_mark_end(sgl + n - 1);
        return n;
 }
 
index 282035f3ae964e1e288f352c370be8edd11d3078..56a891914273319e0e0a69ca911d7824db1341f8 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/memory.h>
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
+#include <linux/jump_label.h>
 
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
@@ -399,7 +400,7 @@ static inline int kprobe_optready(struct kprobe *p)
  * Return an optimized kprobe whose optimizing code replaces
  * instructions including addr (exclude breakpoint).
  */
-struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr)
+static struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr)
 {
        int i;
        struct kprobe *p = NULL;
@@ -831,6 +832,7 @@ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
 
 void __kprobes kretprobe_hash_lock(struct task_struct *tsk,
                         struct hlist_head **head, unsigned long *flags)
+__acquires(hlist_lock)
 {
        unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
        spinlock_t *hlist_lock;
@@ -842,6 +844,7 @@ void __kprobes kretprobe_hash_lock(struct task_struct *tsk,
 
 static void __kprobes kretprobe_table_lock(unsigned long hash,
        unsigned long *flags)
+__acquires(hlist_lock)
 {
        spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
        spin_lock_irqsave(hlist_lock, *flags);
@@ -849,6 +852,7 @@ static void __kprobes kretprobe_table_lock(unsigned long hash,
 
 void __kprobes kretprobe_hash_unlock(struct task_struct *tsk,
        unsigned long *flags)
+__releases(hlist_lock)
 {
        unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
        spinlock_t *hlist_lock;
@@ -857,7 +861,9 @@ void __kprobes kretprobe_hash_unlock(struct task_struct *tsk,
        spin_unlock_irqrestore(hlist_lock, *flags);
 }
 
-void __kprobes kretprobe_table_unlock(unsigned long hash, unsigned long *flags)
+static void __kprobes kretprobe_table_unlock(unsigned long hash,
+       unsigned long *flags)
+__releases(hlist_lock)
 {
        spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
        spin_unlock_irqrestore(hlist_lock, *flags);
@@ -1141,7 +1147,8 @@ int __kprobes register_kprobe(struct kprobe *p)
        preempt_disable();
        if (!kernel_text_address((unsigned long) p->addr) ||
            in_kprobes_functions((unsigned long) p->addr) ||
-           ftrace_text_reserved(p->addr, p->addr)) {
+           ftrace_text_reserved(p->addr, p->addr) ||
+           jump_label_text_reserved(p->addr, p->addr)) {
                preempt_enable();
                return -EINVAL;
        }
@@ -1339,18 +1346,19 @@ int __kprobes register_jprobes(struct jprobe **jps, int num)
        if (num <= 0)
                return -EINVAL;
        for (i = 0; i < num; i++) {
-               unsigned long addr;
+               unsigned long addr, offset;
                jp = jps[i];
                addr = arch_deref_entry_point(jp->entry);
 
-               if (!kernel_text_address(addr))
-                       ret = -EINVAL;
-               else {
-                       /* Todo: Verify probepoint is a function entry point */
+               /* Verify probepoint is a function entry point */
+               if (kallsyms_lookup_size_offset(addr, NULL, &offset) &&
+                   offset == 0) {
                        jp->kp.pre_handler = setjmp_pre_handler;
                        jp->kp.break_handler = longjmp_break_handler;
                        ret = register_kprobe(&jp->kp);
-               }
+               } else
+                       ret = -EINVAL;
+
                if (ret < 0) {
                        if (i > 0)
                                unregister_jprobes(jps, i);
@@ -1992,6 +2000,7 @@ static ssize_t write_enabled_file_bool(struct file *file,
 static const struct file_operations fops_kp = {
        .read =         read_enabled_file_bool,
        .write =        write_enabled_file_bool,
+       .llseek =       default_llseek,
 };
 
 static int __kprobes debugfs_kprobe_init(void)
index f2852a5102327f74c39531a517e488c0d1e673e5..42ba65dff7d99e4eeadfe6175d70c2f9665ad431 100644 (file)
@@ -639,6 +639,16 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
        }
 #endif
 
+       if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
+               debug_locks_off();
+               printk(KERN_ERR
+                       "BUG: looking up invalid subclass: %u\n", subclass);
+               printk(KERN_ERR
+                       "turning off the locking correctness validator.\n");
+               dump_stack();
+               return NULL;
+       }
+
        /*
         * Static locks do not have their class-keys yet - for them the key
         * is the lock object itself:
@@ -774,7 +784,9 @@ out_unlock_set:
        raw_local_irq_restore(flags);
 
        if (!subclass || force)
-               lock->class_cache = class;
+               lock->class_cache[0] = class;
+       else if (subclass < NR_LOCKDEP_CACHING_CLASSES)
+               lock->class_cache[subclass] = class;
 
        if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass))
                return NULL;
@@ -2679,7 +2691,11 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
 void lockdep_init_map(struct lockdep_map *lock, const char *name,
                      struct lock_class_key *key, int subclass)
 {
-       lock->class_cache = NULL;
+       int i;
+
+       for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
+               lock->class_cache[i] = NULL;
+
 #ifdef CONFIG_LOCK_STAT
        lock->cpu = raw_smp_processor_id();
 #endif
@@ -2739,21 +2755,13 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return 0;
 
-       if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
-               debug_locks_off();
-               printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n");
-               printk("turning off the locking correctness validator.\n");
-               dump_stack();
-               return 0;
-       }
-
        if (lock->key == &__lockdep_no_validate__)
                check = 1;
 
-       if (!subclass)
-               class = lock->class_cache;
+       if (subclass < NR_LOCKDEP_CACHING_CLASSES)
+               class = lock->class_cache[subclass];
        /*
-        * Not cached yet or subclass?
+        * Not cached?
         */
        if (unlikely(!class)) {
                class = register_lock_class(lock, subclass, 0);
@@ -2918,7 +2926,7 @@ static int match_held_lock(struct held_lock *hlock, struct lockdep_map *lock)
                return 1;
 
        if (hlock->references) {
-               struct lock_class *class = lock->class_cache;
+               struct lock_class *class = lock->class_cache[0];
 
                if (!class)
                        class = look_up_lock_class(lock, 0);
@@ -3559,7 +3567,12 @@ void lockdep_reset_lock(struct lockdep_map *lock)
                if (list_empty(head))
                        continue;
                list_for_each_entry_safe(class, next, head, hash_entry) {
-                       if (unlikely(class == lock->class_cache)) {
+                       int match = 0;
+
+                       for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
+                               match |= class == lock->class_cache[j];
+
+                       if (unlikely(match)) {
                                if (debug_locks_off_graph_unlock())
                                        WARN_ON(1);
                                goto out_restore;
@@ -3775,7 +3788,7 @@ EXPORT_SYMBOL_GPL(debug_show_all_locks);
  * Careful: only use this function if you are sure that
  * the task cannot run in parallel!
  */
-void __debug_show_held_locks(struct task_struct *task)
+void debug_show_held_locks(struct task_struct *task)
 {
        if (unlikely(!debug_locks)) {
                printk("INFO: lockdep is turned off.\n");
@@ -3783,12 +3796,6 @@ void __debug_show_held_locks(struct task_struct *task)
        }
        lockdep_print_held_locks(task);
 }
-EXPORT_SYMBOL_GPL(__debug_show_held_locks);
-
-void debug_show_held_locks(struct task_struct *task)
-{
-               __debug_show_held_locks(task);
-}
 EXPORT_SYMBOL_GPL(debug_show_held_locks);
 
 void lockdep_sys_exit(void)
index d0b5f8db11b4a4183c229e2a44f433a99f58090a..2df46301a7a407dcde3435542e38f6944358d7c1 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/async.h>
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
+#include <linux/jump_label.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -1537,6 +1538,7 @@ static int __unlink_module(void *_mod)
 {
        struct module *mod = _mod;
        list_del(&mod->list);
+       module_bug_cleanup(mod);
        return 0;
 }
 
@@ -2308,6 +2310,11 @@ static void find_module_sections(struct module *mod, struct load_info *info)
                                        sizeof(*mod->tracepoints),
                                        &mod->num_tracepoints);
 #endif
+#ifdef HAVE_JUMP_LABEL
+       mod->jump_entries = section_objs(info, "__jump_table",
+                                       sizeof(*mod->jump_entries),
+                                       &mod->num_jump_entries);
+#endif
 #ifdef CONFIG_EVENT_TRACING
        mod->trace_events = section_objs(info, "_ftrace_events",
                                         sizeof(*mod->trace_events),
@@ -2625,6 +2632,7 @@ static struct module *load_module(void __user *umod,
        if (err < 0)
                goto ddebug;
 
+       module_bug_finalize(info.hdr, info.sechdrs, mod);
        list_add_rcu(&mod->list, &modules);
        mutex_unlock(&module_mutex);
 
@@ -2650,6 +2658,8 @@ static struct module *load_module(void __user *umod,
        mutex_lock(&module_mutex);
        /* Unlink carefully: kallsyms could be walking list. */
        list_del_rcu(&mod->list);
+       module_bug_cleanup(mod);
+
  ddebug:
        if (!mod->taints)
                dynamic_debug_remove(info.debug);
index 4c0b7b3e6d2e9a483c6cb4cc384e979911ed03bb..200407c1502f509ee3f9d8a665bc4d3b78a27f74 100644 (file)
 # include <asm/mutex.h>
 #endif
 
-/***
- * mutex_init - initialize the mutex
- * @lock: the mutex to be initialized
- * @key: the lock_class_key for the class; used by mutex lock debugging
- *
- * Initialize the mutex to unlocked state.
- *
- * It is not allowed to initialize an already locked mutex.
- */
 void
 __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
 {
@@ -68,7 +59,7 @@ EXPORT_SYMBOL(__mutex_init);
 static __used noinline void __sched
 __mutex_lock_slowpath(atomic_t *lock_count);
 
-/***
+/**
  * mutex_lock - acquire the mutex
  * @lock: the mutex to be acquired
  *
@@ -105,7 +96,7 @@ EXPORT_SYMBOL(mutex_lock);
 
 static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
 
-/***
+/**
  * mutex_unlock - release the mutex
  * @lock: the mutex to be released
  *
@@ -364,8 +355,8 @@ __mutex_lock_killable_slowpath(atomic_t *lock_count);
 static noinline int __sched
 __mutex_lock_interruptible_slowpath(atomic_t *lock_count);
 
-/***
- * mutex_lock_interruptible - acquire the mutex, interruptable
+/**
+ * mutex_lock_interruptible - acquire the mutex, interruptible
  * @lock: the mutex to be acquired
  *
  * Lock the mutex like mutex_lock(), and return 0 if the mutex has
@@ -456,15 +447,15 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
        return prev == 1;
 }
 
-/***
- * mutex_trylock - try acquire the mutex, without waiting
+/**
+ * mutex_trylock - try to acquire the mutex, without waiting
  * @lock: the mutex to be acquired
  *
  * Try to acquire the mutex atomically. Returns 1 if the mutex
  * has been acquired successfully, and 0 on contention.
  *
  * NOTE: this function follows the spin_trylock() convention, so
- * it is negated to the down_trylock() return values! Be careful
+ * it is negated from the down_trylock() return values! Be careful
  * about this when converting semaphore users to mutexes.
  *
  * This function must not be used in interrupt context. The
index 403d1804b198140e4f1355c70c0b25e6efa9e5d8..f309e8014c7853105d1a38bc662f10164dc4d3d1 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/perf_event.h>
 #include <linux/ftrace_event.h>
-#include <linux/hw_breakpoint.h>
 
 #include <asm/irq_regs.h>
 
-/*
- * Each CPU has a list of per CPU events:
- */
-static DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context);
-
-int perf_max_events __read_mostly = 1;
-static int perf_reserved_percpu __read_mostly;
-static int perf_overcommit __read_mostly = 1;
-
-static atomic_t nr_events __read_mostly;
+atomic_t perf_task_events __read_mostly;
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
 static atomic_t nr_task_events __read_mostly;
 
+static LIST_HEAD(pmus);
+static DEFINE_MUTEX(pmus_lock);
+static struct srcu_struct pmus_srcu;
+
 /*
  * perf event paranoia level:
  *  -1 - not paranoid at all
@@ -67,36 +61,43 @@ int sysctl_perf_event_sample_rate __read_mostly = 100000;
 
 static atomic64_t perf_event_id;
 
-/*
- * Lock for (sysadmin-configurable) event reservations:
- */
-static DEFINE_SPINLOCK(perf_resource_lock);
+void __weak perf_event_print_debug(void)       { }
 
-/*
- * Architecture provided APIs - weak aliases:
- */
-extern __weak const struct pmu *hw_perf_event_init(struct perf_event *event)
+extern __weak const char *perf_pmu_name(void)
 {
-       return NULL;
+       return "pmu";
 }
 
-void __weak hw_perf_disable(void)              { barrier(); }
-void __weak hw_perf_enable(void)               { barrier(); }
-
-void __weak perf_event_print_debug(void)       { }
-
-static DEFINE_PER_CPU(int, perf_disable_count);
+void perf_pmu_disable(struct pmu *pmu)
+{
+       int *count = this_cpu_ptr(pmu->pmu_disable_count);
+       if (!(*count)++)
+               pmu->pmu_disable(pmu);
+}
 
-void perf_disable(void)
+void perf_pmu_enable(struct pmu *pmu)
 {
-       if (!__get_cpu_var(perf_disable_count)++)
-               hw_perf_disable();
+       int *count = this_cpu_ptr(pmu->pmu_disable_count);
+       if (!--(*count))
+               pmu->pmu_enable(pmu);
 }
 
-void perf_enable(void)
+static DEFINE_PER_CPU(struct list_head, rotation_list);
+
+/*
+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
+ * because they're strictly cpu affine and rotate_start is called with IRQs
+ * disabled, while rotate_context is called from IRQ context.
+ */
+static void perf_pmu_rotate_start(struct pmu *pmu)
 {
-       if (!--__get_cpu_var(perf_disable_count))
-               hw_perf_enable();
+       struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+       struct list_head *head = &__get_cpu_var(rotation_list);
+
+       WARN_ON(!irqs_disabled());
+
+       if (list_empty(&cpuctx->rotation_list))
+               list_add(&cpuctx->rotation_list, head);
 }
 
 static void get_ctx(struct perf_event_context *ctx)
@@ -151,13 +152,13 @@ static u64 primary_event_id(struct perf_event *event)
  * the context could get moved to another task.
  */
 static struct perf_event_context *
-perf_lock_task_context(struct task_struct *task, unsigned long *flags)
+perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
 {
        struct perf_event_context *ctx;
 
        rcu_read_lock();
- retry:
-       ctx = rcu_dereference(task->perf_event_ctxp);
+retry:
+       ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
        if (ctx) {
                /*
                 * If this context is a clone of another, it might
@@ -170,7 +171,7 @@ perf_lock_task_context(struct task_struct *task, unsigned long *flags)
                 * can't get swapped on us any more.
                 */
                raw_spin_lock_irqsave(&ctx->lock, *flags);
-               if (ctx != rcu_dereference(task->perf_event_ctxp)) {
+               if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
                        raw_spin_unlock_irqrestore(&ctx->lock, *flags);
                        goto retry;
                }
@@ -189,12 +190,13 @@ perf_lock_task_context(struct task_struct *task, unsigned long *flags)
  * can't get swapped to another task.  This also increments its
  * reference count so that the context can't get freed.
  */
-static struct perf_event_context *perf_pin_task_context(struct task_struct *task)
+static struct perf_event_context *
+perf_pin_task_context(struct task_struct *task, int ctxn)
 {
        struct perf_event_context *ctx;
        unsigned long flags;
 
-       ctx = perf_lock_task_context(task, &flags);
+       ctx = perf_lock_task_context(task, ctxn, &flags);
        if (ctx) {
                ++ctx->pin_count;
                raw_spin_unlock_irqrestore(&ctx->lock, flags);
@@ -302,6 +304,8 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
        }
 
        list_add_rcu(&event->event_entry, &ctx->event_list);
+       if (!ctx->nr_events)
+               perf_pmu_rotate_start(ctx->pmu);
        ctx->nr_events++;
        if (event->attr.inherit_stat)
                ctx->nr_stat++;
@@ -311,7 +315,12 @@ static void perf_group_attach(struct perf_event *event)
 {
        struct perf_event *group_leader = event->group_leader;
 
-       WARN_ON_ONCE(event->attach_state & PERF_ATTACH_GROUP);
+       /*
+        * We can have double attach due to group movement in perf_event_open.
+        */
+       if (event->attach_state & PERF_ATTACH_GROUP)
+               return;
+
        event->attach_state |= PERF_ATTACH_GROUP;
 
        if (group_leader == event)
@@ -402,21 +411,40 @@ static void perf_group_detach(struct perf_event *event)
        }
 }
 
-static void
-event_sched_out(struct perf_event *event,
+static inline int
+event_filter_match(struct perf_event *event)
+{
+       return event->cpu == -1 || event->cpu == smp_processor_id();
+}
+
+static int
+__event_sched_out(struct perf_event *event,
                  struct perf_cpu_context *cpuctx,
                  struct perf_event_context *ctx)
 {
+       u64 delta;
+       /*
+        * An event which could not be activated because of
+        * filter mismatch still needs to have its timings
+        * maintained, otherwise bogus information is return
+        * via read() for time_enabled, time_running:
+        */
+       if (event->state == PERF_EVENT_STATE_INACTIVE
+           && !event_filter_match(event)) {
+               delta = ctx->time - event->tstamp_stopped;
+               event->tstamp_running += delta;
+               event->tstamp_stopped = ctx->time;
+       }
+
        if (event->state != PERF_EVENT_STATE_ACTIVE)
-               return;
+               return 0;
 
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
                event->state = PERF_EVENT_STATE_OFF;
        }
-       event->tstamp_stopped = ctx->time;
-       event->pmu->disable(event);
+       event->pmu->del(event, 0);
        event->oncpu = -1;
 
        if (!is_software_event(event))
@@ -424,6 +452,19 @@ event_sched_out(struct perf_event *event,
        ctx->nr_active--;
        if (event->attr.exclusive || !cpuctx->active_oncpu)
                cpuctx->exclusive = 0;
+       return 1;
+}
+
+static void
+event_sched_out(struct perf_event *event,
+                 struct perf_cpu_context *cpuctx,
+                 struct perf_event_context *ctx)
+{
+       int ret;
+
+       ret = __event_sched_out(event, cpuctx, ctx);
+       if (ret)
+               event->tstamp_stopped = ctx->time;
 }
 
 static void
@@ -432,9 +473,7 @@ group_sched_out(struct perf_event *group_event,
                struct perf_event_context *ctx)
 {
        struct perf_event *event;
-
-       if (group_event->state != PERF_EVENT_STATE_ACTIVE)
-               return;
+       int state = group_event->state;
 
        event_sched_out(group_event, cpuctx, ctx);
 
@@ -444,10 +483,16 @@ group_sched_out(struct perf_event *group_event,
        list_for_each_entry(event, &group_event->sibling_list, group_entry)
                event_sched_out(event, cpuctx, ctx);
 
-       if (group_event->attr.exclusive)
+       if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive)
                cpuctx->exclusive = 0;
 }
 
+static inline struct perf_cpu_context *
+__get_cpu_context(struct perf_event_context *ctx)
+{
+       return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
+}
+
 /*
  * Cross CPU call to remove a performance event
  *
@@ -456,9 +501,9 @@ group_sched_out(struct perf_event *group_event,
  */
 static void __perf_event_remove_from_context(void *info)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_event *event = info;
        struct perf_event_context *ctx = event->ctx;
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
        /*
         * If this is a task context, we need to check whether it is
@@ -469,27 +514,11 @@ static void __perf_event_remove_from_context(void *info)
                return;
 
        raw_spin_lock(&ctx->lock);
-       /*
-        * Protect the list operation against NMI by disabling the
-        * events on a global level.
-        */
-       perf_disable();
 
        event_sched_out(event, cpuctx, ctx);
 
        list_del_event(event, ctx);
 
-       if (!ctx->task) {
-               /*
-                * Allow more per task events with respect to the
-                * reservation:
-                */
-               cpuctx->max_pertask =
-                       min(perf_max_events - ctx->nr_events,
-                           perf_max_events - perf_reserved_percpu);
-       }
-
-       perf_enable();
        raw_spin_unlock(&ctx->lock);
 }
 
@@ -554,8 +583,8 @@ retry:
 static void __perf_event_disable(void *info)
 {
        struct perf_event *event = info;
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_event_context *ctx = event->ctx;
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
        /*
         * If this is a per-task event, need to check whether this
@@ -610,7 +639,7 @@ void perf_event_disable(struct perf_event *event)
                return;
        }
 
- retry:
+retry:
        task_oncpu_function_call(task, __perf_event_disable, event);
 
        raw_spin_lock_irq(&ctx->lock);
@@ -635,7 +664,7 @@ void perf_event_disable(struct perf_event *event)
 }
 
 static int
-event_sched_in(struct perf_event *event,
+__event_sched_in(struct perf_event *event,
                 struct perf_cpu_context *cpuctx,
                 struct perf_event_context *ctx)
 {
@@ -649,14 +678,12 @@ event_sched_in(struct perf_event *event,
         */
        smp_wmb();
 
-       if (event->pmu->enable(event)) {
+       if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
                return -EAGAIN;
        }
 
-       event->tstamp_running += ctx->time - event->tstamp_stopped;
-
        if (!is_software_event(event))
                cpuctx->active_oncpu++;
        ctx->nr_active++;
@@ -667,28 +694,56 @@ event_sched_in(struct perf_event *event,
        return 0;
 }
 
+static inline int
+event_sched_in(struct perf_event *event,
+                struct perf_cpu_context *cpuctx,
+                struct perf_event_context *ctx)
+{
+       int ret = __event_sched_in(event, cpuctx, ctx);
+       if (ret)
+               return ret;
+       event->tstamp_running += ctx->time - event->tstamp_stopped;
+       return 0;
+}
+
+static void
+group_commit_event_sched_in(struct perf_event *group_event,
+              struct perf_cpu_context *cpuctx,
+              struct perf_event_context *ctx)
+{
+       struct perf_event *event;
+       u64 now = ctx->time;
+
+       group_event->tstamp_running += now - group_event->tstamp_stopped;
+       /*
+        * Schedule in siblings as one group (if any):
+        */
+       list_for_each_entry(event, &group_event->sibling_list, group_entry) {
+               event->tstamp_running += now - event->tstamp_stopped;
+       }
+}
+
 static int
 group_sched_in(struct perf_event *group_event,
               struct perf_cpu_context *cpuctx,
               struct perf_event_context *ctx)
 {
        struct perf_event *event, *partial_group = NULL;
-       const struct pmu *pmu = group_event->pmu;
-       bool txn = false;
+       struct pmu *pmu = group_event->pmu;
 
        if (group_event->state == PERF_EVENT_STATE_OFF)
                return 0;
 
-       /* Check if group transaction availabe */
-       if (pmu->start_txn)
-               txn = true;
-
-       if (txn)
-               pmu->start_txn(pmu);
+       pmu->start_txn(pmu);
 
-       if (event_sched_in(group_event, cpuctx, ctx)) {
-               if (txn)
-                       pmu->cancel_txn(pmu);
+       /*
+        * use __event_sched_in() to delay updating tstamp_running
+        * until the transaction is committed. In case of failure
+        * we will keep an unmodified tstamp_running which is a
+        * requirement to get correct timing information
+        */
+       if (__event_sched_in(group_event, cpuctx, ctx)) {
+               pmu->cancel_txn(pmu);
                return -EAGAIN;
        }
 
@@ -696,29 +751,33 @@ group_sched_in(struct perf_event *group_event,
         * Schedule in siblings as one group (if any):
         */
        list_for_each_entry(event, &group_event->sibling_list, group_entry) {
-               if (event_sched_in(event, cpuctx, ctx)) {
+               if (__event_sched_in(event, cpuctx, ctx)) {
                        partial_group = event;
                        goto group_error;
                }
        }
 
-       if (!txn || !pmu->commit_txn(pmu))
+       if (!pmu->commit_txn(pmu)) {
+               /* commit tstamp_running */
+               group_commit_event_sched_in(group_event, cpuctx, ctx);
                return 0;
-
+       }
 group_error:
        /*
         * Groups can be scheduled in as one unit only, so undo any
         * partial group before returning:
+        *
+        * use __event_sched_out() to avoid updating tstamp_stopped
+        * because the event never actually ran
         */
        list_for_each_entry(event, &group_event->sibling_list, group_entry) {
                if (event == partial_group)
                        break;
-               event_sched_out(event, cpuctx, ctx);
+               __event_sched_out(event, cpuctx, ctx);
        }
-       event_sched_out(group_event, cpuctx, ctx);
+       __event_sched_out(group_event, cpuctx, ctx);
 
-       if (txn)
-               pmu->cancel_txn(pmu);
+       pmu->cancel_txn(pmu);
 
        return -EAGAIN;
 }
@@ -771,10 +830,10 @@ static void add_event_to_ctx(struct perf_event *event,
  */
 static void __perf_install_in_context(void *info)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_event *event = info;
        struct perf_event_context *ctx = event->ctx;
        struct perf_event *leader = event->group_leader;
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        int err;
 
        /*
@@ -794,12 +853,6 @@ static void __perf_install_in_context(void *info)
        ctx->is_active = 1;
        update_context_time(ctx);
 
-       /*
-        * Protect the list operation against NMI by disabling the
-        * events on a global level. NOP for non NMI based events.
-        */
-       perf_disable();
-
        add_event_to_ctx(event, ctx);
 
        if (event->cpu != -1 && event->cpu != smp_processor_id())
@@ -837,12 +890,7 @@ static void __perf_install_in_context(void *info)
                }
        }
 
-       if (!err && !ctx->task && cpuctx->max_pertask)
-               cpuctx->max_pertask--;
-
- unlock:
-       perf_enable();
-
+unlock:
        raw_spin_unlock(&ctx->lock);
 }
 
@@ -865,6 +913,8 @@ perf_install_in_context(struct perf_event_context *ctx,
 {
        struct task_struct *task = ctx->task;
 
+       event->ctx = ctx;
+
        if (!task) {
                /*
                 * Per cpu events are installed via an smp call and
@@ -913,10 +963,12 @@ static void __perf_event_mark_enabled(struct perf_event *event,
 
        event->state = PERF_EVENT_STATE_INACTIVE;
        event->tstamp_enabled = ctx->time - event->total_time_enabled;
-       list_for_each_entry(sub, &event->sibling_list, group_entry)
-               if (sub->state >= PERF_EVENT_STATE_INACTIVE)
+       list_for_each_entry(sub, &event->sibling_list, group_entry) {
+               if (sub->state >= PERF_EVENT_STATE_INACTIVE) {
                        sub->tstamp_enabled =
                                ctx->time - sub->total_time_enabled;
+               }
+       }
 }
 
 /*
@@ -925,9 +977,9 @@ static void __perf_event_mark_enabled(struct perf_event *event,
 static void __perf_event_enable(void *info)
 {
        struct perf_event *event = info;
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_event_context *ctx = event->ctx;
        struct perf_event *leader = event->group_leader;
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        int err;
 
        /*
@@ -961,12 +1013,10 @@ static void __perf_event_enable(void *info)
        if (!group_can_go_on(event, cpuctx, 1)) {
                err = -EEXIST;
        } else {
-               perf_disable();
                if (event == leader)
                        err = group_sched_in(event, cpuctx, ctx);
                else
                        err = event_sched_in(event, cpuctx, ctx);
-               perf_enable();
        }
 
        if (err) {
@@ -982,7 +1032,7 @@ static void __perf_event_enable(void *info)
                }
        }
 
- unlock:
+unlock:
        raw_spin_unlock(&ctx->lock);
 }
 
@@ -1023,7 +1073,7 @@ void perf_event_enable(struct perf_event *event)
        if (event->state == PERF_EVENT_STATE_ERROR)
                event->state = PERF_EVENT_STATE_OFF;
 
- retry:
+retry:
        raw_spin_unlock_irq(&ctx->lock);
        task_oncpu_function_call(task, __perf_event_enable, event);
 
@@ -1043,7 +1093,7 @@ void perf_event_enable(struct perf_event *event)
        if (event->state == PERF_EVENT_STATE_OFF)
                __perf_event_mark_enabled(event, ctx);
 
- out:
+out:
        raw_spin_unlock_irq(&ctx->lock);
 }
 
@@ -1074,26 +1124,26 @@ static void ctx_sched_out(struct perf_event_context *ctx,
        struct perf_event *event;
 
        raw_spin_lock(&ctx->lock);
+       perf_pmu_disable(ctx->pmu);
        ctx->is_active = 0;
        if (likely(!ctx->nr_events))
                goto out;
        update_context_time(ctx);
 
-       perf_disable();
        if (!ctx->nr_active)
-               goto out_enable;
+               goto out;
 
-       if (event_type & EVENT_PINNED)
+       if (event_type & EVENT_PINNED) {
                list_for_each_entry(event, &ctx->pinned_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
+       }
 
-       if (event_type & EVENT_FLEXIBLE)
+       if (event_type & EVENT_FLEXIBLE) {
                list_for_each_entry(event, &ctx->flexible_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
-
- out_enable:
-       perf_enable();
- out:
+       }
+out:
+       perf_pmu_enable(ctx->pmu);
        raw_spin_unlock(&ctx->lock);
 }
 
@@ -1191,34 +1241,25 @@ static void perf_event_sync_stat(struct perf_event_context *ctx,
        }
 }
 
-/*
- * Called from scheduler to remove the events of the current task,
- * with interrupts disabled.
- *
- * We stop each event and update the event value in event->count.
- *
- * This does not protect us against NMI, but disable()
- * sets the disabled bit in the control field of event _before_
- * accessing the event control register. If a NMI hits, then it will
- * not restart the event.
- */
-void perf_event_task_sched_out(struct task_struct *task,
-                                struct task_struct *next)
+void perf_event_context_sched_out(struct task_struct *task, int ctxn,
+                                 struct task_struct *next)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       struct perf_event_context *ctx = task->perf_event_ctxp;
+       struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
        struct perf_event_context *next_ctx;
        struct perf_event_context *parent;
+       struct perf_cpu_context *cpuctx;
        int do_switch = 1;
 
-       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+       if (likely(!ctx))
+               return;
 
-       if (likely(!ctx || !cpuctx->task_ctx))
+       cpuctx = __get_cpu_context(ctx);
+       if (!cpuctx->task_ctx)
                return;
 
        rcu_read_lock();
        parent = rcu_dereference(ctx->parent_ctx);
-       next_ctx = next->perf_event_ctxp;
+       next_ctx = next->perf_event_ctxp[ctxn];
        if (parent && next_ctx &&
            rcu_dereference(next_ctx->parent_ctx) == parent) {
                /*
@@ -1237,8 +1278,8 @@ void perf_event_task_sched_out(struct task_struct *task,
                         * XXX do we need a memory barrier of sorts
                         * wrt to rcu_dereference() of perf_event_ctxp
                         */
-                       task->perf_event_ctxp = next_ctx;
-                       next->perf_event_ctxp = ctx;
+                       task->perf_event_ctxp[ctxn] = next_ctx;
+                       next->perf_event_ctxp[ctxn] = ctx;
                        ctx->task = next;
                        next_ctx->task = task;
                        do_switch = 0;
@@ -1256,10 +1297,35 @@ void perf_event_task_sched_out(struct task_struct *task,
        }
 }
 
+#define for_each_task_context_nr(ctxn)                                 \
+       for ((ctxn) = 0; (ctxn) < perf_nr_task_contexts; (ctxn)++)
+
+/*
+ * Called from scheduler to remove the events of the current task,
+ * with interrupts disabled.
+ *
+ * We stop each event and update the event value in event->count.
+ *
+ * This does not protect us against NMI, but disable()
+ * sets the disabled bit in the control field of event _before_
+ * accessing the event control register. If a NMI hits, then it will
+ * not restart the event.
+ */
+void __perf_event_task_sched_out(struct task_struct *task,
+                                struct task_struct *next)
+{
+       int ctxn;
+
+       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+
+       for_each_task_context_nr(ctxn)
+               perf_event_context_sched_out(task, ctxn, next);
+}
+
 static void task_ctx_sched_out(struct perf_event_context *ctx,
                               enum event_type_t event_type)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
        if (!cpuctx->task_ctx)
                return;
@@ -1271,14 +1337,6 @@ static void task_ctx_sched_out(struct perf_event_context *ctx,
        cpuctx->task_ctx = NULL;
 }
 
-/*
- * Called with IRQs disabled
- */
-static void __perf_event_task_sched_out(struct perf_event_context *ctx)
-{
-       task_ctx_sched_out(ctx, EVENT_ALL);
-}
-
 /*
  * Called with IRQs disabled
  */
@@ -1332,9 +1390,10 @@ ctx_flexible_sched_in(struct perf_event_context *ctx,
                if (event->cpu != -1 && event->cpu != smp_processor_id())
                        continue;
 
-               if (group_can_go_on(event, cpuctx, can_add_hw))
+               if (group_can_go_on(event, cpuctx, can_add_hw)) {
                        if (group_sched_in(event, cpuctx, ctx))
                                can_add_hw = 0;
+               }
        }
 }
 
@@ -1350,8 +1409,6 @@ ctx_sched_in(struct perf_event_context *ctx,
 
        ctx->timestamp = perf_clock();
 
-       perf_disable();
-
        /*
         * First go through the list and put on any pinned groups
         * in order to give them the best chance of going on.
@@ -1363,8 +1420,7 @@ ctx_sched_in(struct perf_event_context *ctx,
        if (event_type & EVENT_FLEXIBLE)
                ctx_flexible_sched_in(ctx, cpuctx);
 
-       perf_enable();
- out:
+out:
        raw_spin_unlock(&ctx->lock);
 }
 
@@ -1376,43 +1432,28 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
        ctx_sched_in(ctx, cpuctx, event_type);
 }
 
-static void task_ctx_sched_in(struct task_struct *task,
+static void task_ctx_sched_in(struct perf_event_context *ctx,
                              enum event_type_t event_type)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       struct perf_event_context *ctx = task->perf_event_ctxp;
+       struct perf_cpu_context *cpuctx;
 
-       if (likely(!ctx))
-               return;
+               cpuctx = __get_cpu_context(ctx);
        if (cpuctx->task_ctx == ctx)
                return;
+
        ctx_sched_in(ctx, cpuctx, event_type);
        cpuctx->task_ctx = ctx;
 }
-/*
- * Called from scheduler to add the events of the current task
- * with interrupts disabled.
- *
- * We restore the event value and then enable it.
- *
- * This does not protect us against NMI, but enable()
- * sets the enabled bit in the control field of event _before_
- * 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)
-{
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       struct perf_event_context *ctx = task->perf_event_ctxp;
 
-       if (likely(!ctx))
-               return;
+void perf_event_context_sched_in(struct perf_event_context *ctx)
+{
+       struct perf_cpu_context *cpuctx;
 
+       cpuctx = __get_cpu_context(ctx);
        if (cpuctx->task_ctx == ctx)
                return;
 
-       perf_disable();
-
+       perf_pmu_disable(ctx->pmu);
        /*
         * We want to keep the following priority order:
         * cpu pinned (that don't need to move), task pinned,
@@ -1426,7 +1467,37 @@ void perf_event_task_sched_in(struct task_struct *task)
 
        cpuctx->task_ctx = ctx;
 
-       perf_enable();
+       /*
+        * Since these rotations are per-cpu, we need to ensure the
+        * cpu-context we got scheduled on is actually rotating.
+        */
+       perf_pmu_rotate_start(ctx->pmu);
+       perf_pmu_enable(ctx->pmu);
+}
+
+/*
+ * Called from scheduler to add the events of the current task
+ * with interrupts disabled.
+ *
+ * We restore the event value and then enable it.
+ *
+ * This does not protect us against NMI, but enable()
+ * sets the enabled bit in the control field of event _before_
+ * 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)
+{
+       struct perf_event_context *ctx;
+       int ctxn;
+
+       for_each_task_context_nr(ctxn) {
+               ctx = task->perf_event_ctxp[ctxn];
+               if (likely(!ctx))
+                       continue;
+
+               perf_event_context_sched_in(ctx);
+       }
 }
 
 #define MAX_INTERRUPTS (~0ULL)
@@ -1506,22 +1577,6 @@ do {                                     \
        return div64_u64(dividend, divisor);
 }
 
-static void perf_event_stop(struct perf_event *event)
-{
-       if (!event->pmu->stop)
-               return event->pmu->disable(event);
-
-       return event->pmu->stop(event);
-}
-
-static int perf_event_start(struct perf_event *event)
-{
-       if (!event->pmu->start)
-               return event->pmu->enable(event);
-
-       return event->pmu->start(event);
-}
-
 static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
 {
        struct hw_perf_event *hwc = &event->hw;
@@ -1541,15 +1596,13 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
        hwc->sample_period = sample_period;
 
        if (local64_read(&hwc->period_left) > 8*sample_period) {
-               perf_disable();
-               perf_event_stop(event);
+               event->pmu->stop(event, PERF_EF_UPDATE);
                local64_set(&hwc->period_left, 0);
-               perf_event_start(event);
-               perf_enable();
+               event->pmu->start(event, PERF_EF_RELOAD);
        }
 }
 
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
+static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 {
        struct perf_event *event;
        struct hw_perf_event *hwc;
@@ -1574,23 +1627,19 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
                 */
                if (interrupts == MAX_INTERRUPTS) {
                        perf_log_throttle(event, 1);
-                       perf_disable();
-                       event->pmu->unthrottle(event);
-                       perf_enable();
+                       event->pmu->start(event, 0);
                }
 
                if (!event->attr.freq || !event->attr.sample_freq)
                        continue;
 
-               perf_disable();
                event->pmu->read(event);
                now = local64_read(&event->count);
                delta = now - hwc->freq_count_stamp;
                hwc->freq_count_stamp = now;
 
                if (delta > 0)
-                       perf_adjust_period(event, TICK_NSEC, delta);
-               perf_enable();
+                       perf_adjust_period(event, period, delta);
        }
        raw_spin_unlock(&ctx->lock);
 }
@@ -1608,32 +1657,38 @@ static void rotate_ctx(struct perf_event_context *ctx)
        raw_spin_unlock(&ctx->lock);
 }
 
-void perf_event_task_tick(struct task_struct *curr)
+/*
+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
+ * because they're strictly cpu affine and rotate_start is called with IRQs
+ * disabled, while rotate_context is called from IRQ context.
+ */
+static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 {
-       struct perf_cpu_context *cpuctx;
-       struct perf_event_context *ctx;
-       int rotate = 0;
-
-       if (!atomic_read(&nr_events))
-               return;
+       u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
+       struct perf_event_context *ctx = NULL;
+       int rotate = 0, remove = 1;
 
-       cpuctx = &__get_cpu_var(perf_cpu_context);
-       if (cpuctx->ctx.nr_events &&
-           cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
-               rotate = 1;
+       if (cpuctx->ctx.nr_events) {
+               remove = 0;
+               if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
+                       rotate = 1;
+       }
 
-       ctx = curr->perf_event_ctxp;
-       if (ctx && ctx->nr_events && ctx->nr_events != ctx->nr_active)
-               rotate = 1;
+       ctx = cpuctx->task_ctx;
+       if (ctx && ctx->nr_events) {
+               remove = 0;
+               if (ctx->nr_events != ctx->nr_active)
+                       rotate = 1;
+       }
 
-       perf_ctx_adjust_freq(&cpuctx->ctx);
+       perf_pmu_disable(cpuctx->ctx.pmu);
+       perf_ctx_adjust_freq(&cpuctx->ctx, interval);
        if (ctx)
-               perf_ctx_adjust_freq(ctx);
+               perf_ctx_adjust_freq(ctx, interval);
 
        if (!rotate)
-               return;
+               goto done;
 
-       perf_disable();
        cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
        if (ctx)
                task_ctx_sched_out(ctx, EVENT_FLEXIBLE);
@@ -1644,8 +1699,27 @@ void perf_event_task_tick(struct task_struct *curr)
 
        cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE);
        if (ctx)
-               task_ctx_sched_in(curr, EVENT_FLEXIBLE);
-       perf_enable();
+               task_ctx_sched_in(ctx, EVENT_FLEXIBLE);
+
+done:
+       if (remove)
+               list_del_init(&cpuctx->rotation_list);
+
+       perf_pmu_enable(cpuctx->ctx.pmu);
+}
+
+void perf_event_task_tick(void)
+{
+       struct list_head *head = &__get_cpu_var(rotation_list);
+       struct perf_cpu_context *cpuctx, *tmp;
+
+       WARN_ON(!irqs_disabled());
+
+       list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+               if (cpuctx->jiffies_interval == 1 ||
+                               !(jiffies % cpuctx->jiffies_interval))
+                       perf_rotate_context(cpuctx);
+       }
 }
 
 static int event_enable_on_exec(struct perf_event *event,
@@ -1667,20 +1741,18 @@ static int event_enable_on_exec(struct perf_event *event,
  * Enable all of a task's events that have been marked enable-on-exec.
  * This expects task == current.
  */
-static void perf_event_enable_on_exec(struct task_struct *task)
+static void perf_event_enable_on_exec(struct perf_event_context *ctx)
 {
-       struct perf_event_context *ctx;
        struct perf_event *event;
        unsigned long flags;
        int enabled = 0;
        int ret;
 
        local_irq_save(flags);
-       ctx = task->perf_event_ctxp;
        if (!ctx || !ctx->nr_events)
                goto out;
 
-       __perf_event_task_sched_out(ctx);
+       task_ctx_sched_out(ctx, EVENT_ALL);
 
        raw_spin_lock(&ctx->lock);
 
@@ -1704,8 +1776,8 @@ static void perf_event_enable_on_exec(struct task_struct *task)
 
        raw_spin_unlock(&ctx->lock);
 
-       perf_event_task_sched_in(task);
- out:
+       perf_event_context_sched_in(ctx);
+out:
        local_irq_restore(flags);
 }
 
@@ -1714,9 +1786,9 @@ static void perf_event_enable_on_exec(struct task_struct *task)
  */
 static void __perf_event_read(void *info)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_event *event = info;
        struct perf_event_context *ctx = event->ctx;
+       struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
        /*
         * If this is a task context, we need to check whether it is
@@ -1755,7 +1827,13 @@ static u64 perf_event_read(struct perf_event *event)
                unsigned long flags;
 
                raw_spin_lock_irqsave(&ctx->lock, flags);
-               update_context_time(ctx);
+               /*
+                * may read while context is not active
+                * (e.g., thread is blocked), in that case
+                * we cannot update context time
+                */
+               if (ctx->is_active)
+                       update_context_time(ctx);
                update_event_times(event);
                raw_spin_unlock_irqrestore(&ctx->lock, flags);
        }
@@ -1764,57 +1842,258 @@ static u64 perf_event_read(struct perf_event *event)
 }
 
 /*
- * Initialize the perf_event context in a task_struct:
+ * Callchain support
  */
-static void
-__perf_event_init_context(struct perf_event_context *ctx,
-                           struct task_struct *task)
+
+struct callchain_cpus_entries {
+       struct rcu_head                 rcu_head;
+       struct perf_callchain_entry     *cpu_entries[0];
+};
+
+static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]);
+static atomic_t nr_callchain_events;
+static DEFINE_MUTEX(callchain_mutex);
+struct callchain_cpus_entries *callchain_cpus_entries;
+
+
+__weak void perf_callchain_kernel(struct perf_callchain_entry *entry,
+                                 struct pt_regs *regs)
 {
-       raw_spin_lock_init(&ctx->lock);
-       mutex_init(&ctx->mutex);
-       INIT_LIST_HEAD(&ctx->pinned_groups);
-       INIT_LIST_HEAD(&ctx->flexible_groups);
-       INIT_LIST_HEAD(&ctx->event_list);
-       atomic_set(&ctx->refcount, 1);
-       ctx->task = task;
 }
 
-static struct perf_event_context *find_get_context(pid_t pid, int cpu)
+__weak void perf_callchain_user(struct perf_callchain_entry *entry,
+                               struct pt_regs *regs)
 {
-       struct perf_event_context *ctx;
-       struct perf_cpu_context *cpuctx;
-       struct task_struct *task;
-       unsigned long flags;
-       int err;
+}
 
-       if (pid == -1 && cpu != -1) {
-               /* Must be root to operate on a CPU event: */
-               if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
-                       return ERR_PTR(-EACCES);
+static void release_callchain_buffers_rcu(struct rcu_head *head)
+{
+       struct callchain_cpus_entries *entries;
+       int cpu;
 
-               if (cpu < 0 || cpu >= nr_cpumask_bits)
-                       return ERR_PTR(-EINVAL);
+       entries = container_of(head, struct callchain_cpus_entries, rcu_head);
 
-               /*
-                * We could be clever and allow to attach a event to an
-                * offline CPU and activate it when the CPU comes up, but
-                * that's for later.
-                */
-               if (!cpu_online(cpu))
-                       return ERR_PTR(-ENODEV);
+       for_each_possible_cpu(cpu)
+               kfree(entries->cpu_entries[cpu]);
 
-               cpuctx = &per_cpu(perf_cpu_context, cpu);
-               ctx = &cpuctx->ctx;
-               get_ctx(ctx);
+       kfree(entries);
+}
 
-               return ctx;
+static void release_callchain_buffers(void)
+{
+       struct callchain_cpus_entries *entries;
+
+       entries = callchain_cpus_entries;
+       rcu_assign_pointer(callchain_cpus_entries, NULL);
+       call_rcu(&entries->rcu_head, release_callchain_buffers_rcu);
+}
+
+static int alloc_callchain_buffers(void)
+{
+       int cpu;
+       int size;
+       struct callchain_cpus_entries *entries;
+
+       /*
+        * We can't use the percpu allocation API for data that can be
+        * accessed from NMI. Use a temporary manual per cpu allocation
+        * until that gets sorted out.
+        */
+       size = sizeof(*entries) + sizeof(struct perf_callchain_entry *) *
+               num_possible_cpus();
+
+       entries = kzalloc(size, GFP_KERNEL);
+       if (!entries)
+               return -ENOMEM;
+
+       size = sizeof(struct perf_callchain_entry) * PERF_NR_CONTEXTS;
+
+       for_each_possible_cpu(cpu) {
+               entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL,
+                                                        cpu_to_node(cpu));
+               if (!entries->cpu_entries[cpu])
+                       goto fail;
+       }
+
+       rcu_assign_pointer(callchain_cpus_entries, entries);
+
+       return 0;
+
+fail:
+       for_each_possible_cpu(cpu)
+               kfree(entries->cpu_entries[cpu]);
+       kfree(entries);
+
+       return -ENOMEM;
+}
+
+static int get_callchain_buffers(void)
+{
+       int err = 0;
+       int count;
+
+       mutex_lock(&callchain_mutex);
+
+       count = atomic_inc_return(&nr_callchain_events);
+       if (WARN_ON_ONCE(count < 1)) {
+               err = -EINVAL;
+               goto exit;
+       }
+
+       if (count > 1) {
+               /* If the allocation failed, give up */
+               if (!callchain_cpus_entries)
+                       err = -ENOMEM;
+               goto exit;
+       }
+
+       err = alloc_callchain_buffers();
+       if (err)
+               release_callchain_buffers();
+exit:
+       mutex_unlock(&callchain_mutex);
+
+       return err;
+}
+
+static void put_callchain_buffers(void)
+{
+       if (atomic_dec_and_mutex_lock(&nr_callchain_events, &callchain_mutex)) {
+               release_callchain_buffers();
+               mutex_unlock(&callchain_mutex);
+       }
+}
+
+static int get_recursion_context(int *recursion)
+{
+       int rctx;
+
+       if (in_nmi())
+               rctx = 3;
+       else if (in_irq())
+               rctx = 2;
+       else if (in_softirq())
+               rctx = 1;
+       else
+               rctx = 0;
+
+       if (recursion[rctx])
+               return -1;
+
+       recursion[rctx]++;
+       barrier();
+
+       return rctx;
+}
+
+static inline void put_recursion_context(int *recursion, int rctx)
+{
+       barrier();
+       recursion[rctx]--;
+}
+
+static struct perf_callchain_entry *get_callchain_entry(int *rctx)
+{
+       int cpu;
+       struct callchain_cpus_entries *entries;
+
+       *rctx = get_recursion_context(__get_cpu_var(callchain_recursion));
+       if (*rctx == -1)
+               return NULL;
+
+       entries = rcu_dereference(callchain_cpus_entries);
+       if (!entries)
+               return NULL;
+
+       cpu = smp_processor_id();
+
+       return &entries->cpu_entries[cpu][*rctx];
+}
+
+static void
+put_callchain_entry(int rctx)
+{
+       put_recursion_context(__get_cpu_var(callchain_recursion), rctx);
+}
+
+static struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+{
+       int rctx;
+       struct perf_callchain_entry *entry;
+
+
+       entry = get_callchain_entry(&rctx);
+       if (rctx == -1)
+               return NULL;
+
+       if (!entry)
+               goto exit_put;
+
+       entry->nr = 0;
+
+       if (!user_mode(regs)) {
+               perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
+               perf_callchain_kernel(entry, regs);
+               if (current->mm)
+                       regs = task_pt_regs(current);
+               else
+                       regs = NULL;
+       }
+
+       if (regs) {
+               perf_callchain_store(entry, PERF_CONTEXT_USER);
+               perf_callchain_user(entry, regs);
+       }
+
+exit_put:
+       put_callchain_entry(rctx);
+
+       return entry;
+}
+
+/*
+ * Initialize the perf_event context in a task_struct:
+ */
+static void __perf_event_init_context(struct perf_event_context *ctx)
+{
+       raw_spin_lock_init(&ctx->lock);
+       mutex_init(&ctx->mutex);
+       INIT_LIST_HEAD(&ctx->pinned_groups);
+       INIT_LIST_HEAD(&ctx->flexible_groups);
+       INIT_LIST_HEAD(&ctx->event_list);
+       atomic_set(&ctx->refcount, 1);
+}
+
+static struct perf_event_context *
+alloc_perf_context(struct pmu *pmu, struct task_struct *task)
+{
+       struct perf_event_context *ctx;
+
+       ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL);
+       if (!ctx)
+               return NULL;
+
+       __perf_event_init_context(ctx);
+       if (task) {
+               ctx->task = task;
+               get_task_struct(task);
        }
+       ctx->pmu = pmu;
+
+       return ctx;
+}
+
+static struct task_struct *
+find_lively_task_by_vpid(pid_t vpid)
+{
+       struct task_struct *task;
+       int err;
 
        rcu_read_lock();
-       if (!pid)
+       if (!vpid)
                task = current;
        else
-               task = find_task_by_vpid(pid);
+               task = find_task_by_vpid(vpid);
        if (task)
                get_task_struct(task);
        rcu_read_unlock();
@@ -1834,36 +2113,78 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu)
        if (!ptrace_may_access(task, PTRACE_MODE_READ))
                goto errout;
 
- retry:
-       ctx = perf_lock_task_context(task, &flags);
+       return task;
+errout:
+       put_task_struct(task);
+       return ERR_PTR(err);
+
+}
+
+static struct perf_event_context *
+find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
+{
+       struct perf_event_context *ctx;
+       struct perf_cpu_context *cpuctx;
+       unsigned long flags;
+       int ctxn, err;
+
+       if (!task && cpu != -1) {
+               /* Must be root to operate on a CPU event: */
+               if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+                       return ERR_PTR(-EACCES);
+
+               if (cpu < 0 || cpu >= nr_cpumask_bits)
+                       return ERR_PTR(-EINVAL);
+
+               /*
+                * We could be clever and allow to attach a event to an
+                * offline CPU and activate it when the CPU comes up, but
+                * that's for later.
+                */
+               if (!cpu_online(cpu))
+                       return ERR_PTR(-ENODEV);
+
+               cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+               ctx = &cpuctx->ctx;
+               get_ctx(ctx);
+
+               return ctx;
+       }
+
+       err = -EINVAL;
+       ctxn = pmu->task_ctx_nr;
+       if (ctxn < 0)
+               goto errout;
+
+retry:
+       ctx = perf_lock_task_context(task, ctxn, &flags);
        if (ctx) {
                unclone_ctx(ctx);
                raw_spin_unlock_irqrestore(&ctx->lock, flags);
        }
 
        if (!ctx) {
-               ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL);
+               ctx = alloc_perf_context(pmu, task);
                err = -ENOMEM;
                if (!ctx)
                        goto errout;
-               __perf_event_init_context(ctx, task);
+
                get_ctx(ctx);
-               if (cmpxchg(&task->perf_event_ctxp, NULL, ctx)) {
+
+               if (cmpxchg(&task->perf_event_ctxp[ctxn], NULL, ctx)) {
                        /*
                         * We raced with some other task; use
                         * the context they set.
                         */
+                       put_task_struct(task);
                        kfree(ctx);
                        goto retry;
                }
-               get_task_struct(task);
        }
 
-       put_task_struct(task);
        return ctx;
 
- errout:
-       put_task_struct(task);
+errout:
        return ERR_PTR(err);
 }
 
@@ -1880,21 +2201,23 @@ static void free_event_rcu(struct rcu_head *head)
        kfree(event);
 }
 
-static void perf_pending_sync(struct perf_event *event);
 static void perf_buffer_put(struct perf_buffer *buffer);
 
 static void free_event(struct perf_event *event)
 {
-       perf_pending_sync(event);
+       irq_work_sync(&event->pending);
 
        if (!event->parent) {
-               atomic_dec(&nr_events);
+               if (event->attach_state & PERF_ATTACH_TASK)
+                       jump_label_dec(&perf_task_events);
                if (event->attr.mmap || event->attr.mmap_data)
                        atomic_dec(&nr_mmap_events);
                if (event->attr.comm)
                        atomic_dec(&nr_comm_events);
                if (event->attr.task)
                        atomic_dec(&nr_task_events);
+               if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+                       put_callchain_buffers();
        }
 
        if (event->buffer) {
@@ -1905,7 +2228,9 @@ static void free_event(struct perf_event *event)
        if (event->destroy)
                event->destroy(event);
 
-       put_ctx(event->ctx);
+       if (event->ctx)
+               put_ctx(event->ctx);
+
        call_rcu(&event->rcu_head, free_event_rcu);
 }
 
@@ -2184,15 +2509,13 @@ static void perf_event_for_each(struct perf_event *event,
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
        struct perf_event_context *ctx = event->ctx;
-       unsigned long size;
        int ret = 0;
        u64 value;
 
        if (!event->attr.sample_period)
                return -EINVAL;
 
-       size = copy_from_user(&value, arg, sizeof(value));
-       if (size != sizeof(value))
+       if (copy_from_user(&value, arg, sizeof(value)))
                return -EFAULT;
 
        if (!value)
@@ -2326,6 +2649,9 @@ int perf_event_task_disable(void)
 
 static int perf_event_index(struct perf_event *event)
 {
+       if (event->hw.state & PERF_HES_STOPPED)
+               return 0;
+
        if (event->state != PERF_EVENT_STATE_ACTIVE)
                return 0;
 
@@ -2829,16 +3155,7 @@ void perf_event_wakeup(struct perf_event *event)
        }
 }
 
-/*
- * Pending wakeups
- *
- * Handle the case where we need to wakeup up from NMI (or rq->lock) context.
- *
- * The NMI bit means we cannot possibly take locks. Therefore, maintain a
- * single linked list and use cmpxchg() to add entries lockless.
- */
-
-static void perf_pending_event(struct perf_pending_entry *entry)
+static void perf_pending_event(struct irq_work *entry)
 {
        struct perf_event *event = container_of(entry,
                        struct perf_event, pending);
@@ -2854,99 +3171,6 @@ static void perf_pending_event(struct perf_pending_entry *entry)
        }
 }
 
-#define PENDING_TAIL ((struct perf_pending_entry *)-1UL)
-
-static DEFINE_PER_CPU(struct perf_pending_entry *, perf_pending_head) = {
-       PENDING_TAIL,
-};
-
-static void perf_pending_queue(struct perf_pending_entry *entry,
-                              void (*func)(struct perf_pending_entry *))
-{
-       struct perf_pending_entry **head;
-
-       if (cmpxchg(&entry->next, NULL, PENDING_TAIL) != NULL)
-               return;
-
-       entry->func = func;
-
-       head = &get_cpu_var(perf_pending_head);
-
-       do {
-               entry->next = *head;
-       } while (cmpxchg(head, entry->next, entry) != entry->next);
-
-       set_perf_event_pending();
-
-       put_cpu_var(perf_pending_head);
-}
-
-static int __perf_pending_run(void)
-{
-       struct perf_pending_entry *list;
-       int nr = 0;
-
-       list = xchg(&__get_cpu_var(perf_pending_head), PENDING_TAIL);
-       while (list != PENDING_TAIL) {
-               void (*func)(struct perf_pending_entry *);
-               struct perf_pending_entry *entry = list;
-
-               list = list->next;
-
-               func = entry->func;
-               entry->next = NULL;
-               /*
-                * Ensure we observe the unqueue before we issue the wakeup,
-                * so that we won't be waiting forever.
-                * -- see perf_not_pending().
-                */
-               smp_wmb();
-
-               func(entry);
-               nr++;
-       }
-
-       return nr;
-}
-
-static inline int perf_not_pending(struct perf_event *event)
-{
-       /*
-        * If we flush on whatever cpu we run, there is a chance we don't
-        * need to wait.
-        */
-       get_cpu();
-       __perf_pending_run();
-       put_cpu();
-
-       /*
-        * Ensure we see the proper queue state before going to sleep
-        * so that we do not miss the wakeup. -- see perf_pending_handle()
-        */
-       smp_rmb();
-       return event->pending.next == NULL;
-}
-
-static void perf_pending_sync(struct perf_event *event)
-{
-       wait_event(event->waitq, perf_not_pending(event));
-}
-
-void perf_event_do_pending(void)
-{
-       __perf_pending_run();
-}
-
-/*
- * Callchain support -- arch specific
- */
-
-__weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-       return NULL;
-}
-
-
 /*
  * We assume there is only KVM supporting the callbacks.
  * Later on, we might change it to a list if there is
@@ -2996,8 +3220,7 @@ static void perf_output_wakeup(struct perf_output_handle *handle)
 
        if (handle->nmi) {
                handle->event->pending_wakeup = 1;
-               perf_pending_queue(&handle->event->pending,
-                                  perf_pending_event);
+               irq_work_queue(&handle->event->pending);
        } else
                perf_event_wakeup(handle->event);
 }
@@ -3053,7 +3276,7 @@ again:
        if (handle->wakeup != local_read(&buffer->wakeup))
                perf_output_wakeup(handle);
 
- out:
+out:
        preempt_enable();
 }
 
@@ -3441,14 +3664,20 @@ static void perf_event_output(struct perf_event *event, int nmi,
        struct perf_output_handle handle;
        struct perf_event_header header;
 
+       /* protect the callchain buffers */
+       rcu_read_lock();
+
        perf_prepare_sample(&header, data, event, regs);
 
        if (perf_output_begin(&handle, event, header.size, nmi, 1))
-               return;
+               goto exit;
 
        perf_output_sample(&handle, &header, data, event);
 
        perf_output_end(&handle);
+
+exit:
+       rcu_read_unlock();
 }
 
 /*
@@ -3562,16 +3791,27 @@ static void perf_event_task_ctx(struct perf_event_context *ctx,
 static void perf_event_task_event(struct perf_task_event *task_event)
 {
        struct perf_cpu_context *cpuctx;
-       struct perf_event_context *ctx = task_event->task_ctx;
+       struct perf_event_context *ctx;
+       struct pmu *pmu;
+       int ctxn;
 
        rcu_read_lock();
-       cpuctx = &get_cpu_var(perf_cpu_context);
-       perf_event_task_ctx(&cpuctx->ctx, task_event);
-       if (!ctx)
-               ctx = rcu_dereference(current->perf_event_ctxp);
-       if (ctx)
-               perf_event_task_ctx(ctx, task_event);
-       put_cpu_var(perf_cpu_context);
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               perf_event_task_ctx(&cpuctx->ctx, task_event);
+
+               ctx = task_event->task_ctx;
+               if (!ctx) {
+                       ctxn = pmu->task_ctx_nr;
+                       if (ctxn < 0)
+                               goto next;
+                       ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+               }
+               if (ctx)
+                       perf_event_task_ctx(ctx, task_event);
+next:
+               put_cpu_ptr(pmu->pmu_cpu_context);
+       }
        rcu_read_unlock();
 }
 
@@ -3676,8 +3916,10 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
 {
        struct perf_cpu_context *cpuctx;
        struct perf_event_context *ctx;
-       unsigned int size;
        char comm[TASK_COMM_LEN];
+       unsigned int size;
+       struct pmu *pmu;
+       int ctxn;
 
        memset(comm, 0, sizeof(comm));
        strlcpy(comm, comm_event->task->comm, sizeof(comm));
@@ -3689,21 +3931,36 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
 
        rcu_read_lock();
-       cpuctx = &get_cpu_var(perf_cpu_context);
-       perf_event_comm_ctx(&cpuctx->ctx, comm_event);
-       ctx = rcu_dereference(current->perf_event_ctxp);
-       if (ctx)
-               perf_event_comm_ctx(ctx, comm_event);
-       put_cpu_var(perf_cpu_context);
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               perf_event_comm_ctx(&cpuctx->ctx, comm_event);
+
+               ctxn = pmu->task_ctx_nr;
+               if (ctxn < 0)
+                       goto next;
+
+               ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+               if (ctx)
+                       perf_event_comm_ctx(ctx, comm_event);
+next:
+               put_cpu_ptr(pmu->pmu_cpu_context);
+       }
        rcu_read_unlock();
 }
 
 void perf_event_comm(struct task_struct *task)
 {
        struct perf_comm_event comm_event;
+       struct perf_event_context *ctx;
+       int ctxn;
+
+       for_each_task_context_nr(ctxn) {
+               ctx = task->perf_event_ctxp[ctxn];
+               if (!ctx)
+                       continue;
 
-       if (task->perf_event_ctxp)
-               perf_event_enable_on_exec(task);
+               perf_event_enable_on_exec(ctx);
+       }
 
        if (!atomic_read(&nr_comm_events))
                return;
@@ -3805,6 +4062,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
        char tmp[16];
        char *buf = NULL;
        const char *name;
+       struct pmu *pmu;
+       int ctxn;
 
        memset(tmp, 0, sizeof(tmp));
 
@@ -3857,12 +4116,23 @@ got_name:
        mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
 
        rcu_read_lock();
-       cpuctx = &get_cpu_var(perf_cpu_context);
-       perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, vma->vm_flags & VM_EXEC);
-       ctx = rcu_dereference(current->perf_event_ctxp);
-       if (ctx)
-               perf_event_mmap_ctx(ctx, mmap_event, vma->vm_flags & VM_EXEC);
-       put_cpu_var(perf_cpu_context);
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
+                                       vma->vm_flags & VM_EXEC);
+
+               ctxn = pmu->task_ctx_nr;
+               if (ctxn < 0)
+                       goto next;
+
+               ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+               if (ctx) {
+                       perf_event_mmap_ctx(ctx, mmap_event,
+                                       vma->vm_flags & VM_EXEC);
+               }
+next:
+               put_cpu_ptr(pmu->pmu_cpu_context);
+       }
        rcu_read_unlock();
 
        kfree(buf);
@@ -3944,8 +4214,6 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
        struct hw_perf_event *hwc = &event->hw;
        int ret = 0;
 
-       throttle = (throttle && event->pmu->unthrottle != NULL);
-
        if (!throttle) {
                hwc->interrupts++;
        } else {
@@ -3988,8 +4256,7 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
                event->pending_kill = POLL_HUP;
                if (nmi) {
                        event->pending_disable = 1;
-                       perf_pending_queue(&event->pending,
-                                          perf_pending_event);
+                       irq_work_queue(&event->pending);
                } else
                        perf_event_disable(event);
        }
@@ -4013,6 +4280,17 @@ int perf_event_overflow(struct perf_event *event, int nmi,
  * Generic software event infrastructure
  */
 
+struct swevent_htable {
+       struct swevent_hlist            *swevent_hlist;
+       struct mutex                    hlist_mutex;
+       int                             hlist_refcount;
+
+       /* Recursion avoidance in each contexts */
+       int                             recursion[PERF_NR_CONTEXTS];
+};
+
+static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
+
 /*
  * We directly increment event->count and keep a second value in
  * event->hw.period_left to count intervals. This period event
@@ -4070,7 +4348,7 @@ static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
        }
 }
 
-static void perf_swevent_add(struct perf_event *event, u64 nr,
+static void perf_swevent_event(struct perf_event *event, u64 nr,
                               int nmi, struct perf_sample_data *data,
                               struct pt_regs *regs)
 {
@@ -4096,6 +4374,9 @@ static void perf_swevent_add(struct perf_event *event, u64 nr,
 static int perf_exclude_event(struct perf_event *event,
                              struct pt_regs *regs)
 {
+       if (event->hw.state & PERF_HES_STOPPED)
+               return 0;
+
        if (regs) {
                if (event->attr.exclude_user && user_mode(regs))
                        return 1;
@@ -4142,11 +4423,11 @@ __find_swevent_head(struct swevent_hlist *hlist, u64 type, u32 event_id)
 
 /* For the read side: events when they trigger */
 static inline struct hlist_head *
-find_swevent_head_rcu(struct perf_cpu_context *ctx, u64 type, u32 event_id)
+find_swevent_head_rcu(struct swevent_htable *swhash, u64 type, u32 event_id)
 {
        struct swevent_hlist *hlist;
 
-       hlist = rcu_dereference(ctx->swevent_hlist);
+       hlist = rcu_dereference(swhash->swevent_hlist);
        if (!hlist)
                return NULL;
 
@@ -4155,7 +4436,7 @@ find_swevent_head_rcu(struct perf_cpu_context *ctx, u64 type, u32 event_id)
 
 /* For the event head insertion and removal in the hlist */
 static inline struct hlist_head *
-find_swevent_head(struct perf_cpu_context *ctx, struct perf_event *event)
+find_swevent_head(struct swevent_htable *swhash, struct perf_event *event)
 {
        struct swevent_hlist *hlist;
        u32 event_id = event->attr.config;
@@ -4166,7 +4447,7 @@ find_swevent_head(struct perf_cpu_context *ctx, struct perf_event *event)
         * and release. Which makes the protected version suitable here.
         * The context lock guarantees that.
         */
-       hlist = rcu_dereference_protected(ctx->swevent_hlist,
+       hlist = rcu_dereference_protected(swhash->swevent_hlist,
                                          lockdep_is_held(&event->ctx->lock));
        if (!hlist)
                return NULL;
@@ -4179,23 +4460,19 @@ static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
                                    struct perf_sample_data *data,
                                    struct pt_regs *regs)
 {
-       struct perf_cpu_context *cpuctx;
+       struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
        struct perf_event *event;
        struct hlist_node *node;
        struct hlist_head *head;
 
-       cpuctx = &__get_cpu_var(perf_cpu_context);
-
        rcu_read_lock();
-
-       head = find_swevent_head_rcu(cpuctx, type, event_id);
-
+       head = find_swevent_head_rcu(swhash, type, event_id);
        if (!head)
                goto end;
 
        hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
                if (perf_swevent_match(event, type, event_id, data, regs))
-                       perf_swevent_add(event, nr, nmi, data, regs);
+                       perf_swevent_event(event, nr, nmi, data, regs);
        }
 end:
        rcu_read_unlock();
@@ -4203,33 +4480,17 @@ end:
 
 int perf_swevent_get_recursion_context(void)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       int rctx;
-
-       if (in_nmi())
-               rctx = 3;
-       else if (in_irq())
-               rctx = 2;
-       else if (in_softirq())
-               rctx = 1;
-       else
-               rctx = 0;
-
-       if (cpuctx->recursion[rctx])
-               return -1;
-
-       cpuctx->recursion[rctx]++;
-       barrier();
+       struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
 
-       return rctx;
+       return get_recursion_context(swhash->recursion);
 }
 EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context);
 
 void inline perf_swevent_put_recursion_context(int rctx)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       barrier();
-       cpuctx->recursion[rctx]--;
+       struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
+
+       put_recursion_context(swhash->recursion, rctx);
 }
 
 void __perf_sw_event(u32 event_id, u64 nr, int nmi,
@@ -4255,20 +4516,20 @@ static void perf_swevent_read(struct perf_event *event)
 {
 }
 
-static int perf_swevent_enable(struct perf_event *event)
+static int perf_swevent_add(struct perf_event *event, int flags)
 {
+       struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
        struct hw_perf_event *hwc = &event->hw;
-       struct perf_cpu_context *cpuctx;
        struct hlist_head *head;
 
-       cpuctx = &__get_cpu_var(perf_cpu_context);
-
        if (hwc->sample_period) {
                hwc->last_period = hwc->sample_period;
                perf_swevent_set_period(event);
        }
 
-       head = find_swevent_head(cpuctx, event);
+       hwc->state = !(flags & PERF_EF_START);
+
+       head = find_swevent_head(swhash, event);
        if (WARN_ON_ONCE(!head))
                return -EINVAL;
 
@@ -4277,202 +4538,27 @@ static int perf_swevent_enable(struct perf_event *event)
        return 0;
 }
 
-static void perf_swevent_disable(struct perf_event *event)
+static void perf_swevent_del(struct perf_event *event, int flags)
 {
        hlist_del_rcu(&event->hlist_entry);
 }
 
-static void perf_swevent_void(struct perf_event *event)
-{
-}
-
-static int perf_swevent_int(struct perf_event *event)
-{
-       return 0;
-}
-
-static const struct pmu perf_ops_generic = {
-       .enable         = perf_swevent_enable,
-       .disable        = perf_swevent_disable,
-       .start          = perf_swevent_int,
-       .stop           = perf_swevent_void,
-       .read           = perf_swevent_read,
-       .unthrottle     = perf_swevent_void, /* hwc->interrupts already reset */
-};
-
-/*
- * hrtimer based swevent callback
- */
-
-static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
-{
-       enum hrtimer_restart ret = HRTIMER_RESTART;
-       struct perf_sample_data data;
-       struct pt_regs *regs;
-       struct perf_event *event;
-       u64 period;
-
-       event = container_of(hrtimer, struct perf_event, hw.hrtimer);
-       event->pmu->read(event);
-
-       perf_sample_data_init(&data, 0);
-       data.period = event->hw.last_period;
-       regs = get_irq_regs();
-
-       if (regs && !perf_exclude_event(event, regs)) {
-               if (!(event->attr.exclude_idle && current->pid == 0))
-                       if (perf_event_overflow(event, 0, &data, regs))
-                               ret = HRTIMER_NORESTART;
-       }
-
-       period = max_t(u64, 10000, event->hw.sample_period);
-       hrtimer_forward_now(hrtimer, ns_to_ktime(period));
-
-       return ret;
-}
-
-static void perf_swevent_start_hrtimer(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hwc->hrtimer.function = perf_swevent_hrtimer;
-       if (hwc->sample_period) {
-               u64 period;
-
-               if (hwc->remaining) {
-                       if (hwc->remaining < 0)
-                               period = 10000;
-                       else
-                               period = hwc->remaining;
-                       hwc->remaining = 0;
-               } else {
-                       period = max_t(u64, 10000, hwc->sample_period);
-               }
-               __hrtimer_start_range_ns(&hwc->hrtimer,
-                               ns_to_ktime(period), 0,
-                               HRTIMER_MODE_REL, 0);
-       }
-}
-
-static void perf_swevent_cancel_hrtimer(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (hwc->sample_period) {
-               ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
-               hwc->remaining = ktime_to_ns(remaining);
-
-               hrtimer_cancel(&hwc->hrtimer);
-       }
-}
-
-/*
- * Software event: cpu wall time clock
- */
-
-static void cpu_clock_perf_event_update(struct perf_event *event)
-{
-       int cpu = raw_smp_processor_id();
-       s64 prev;
-       u64 now;
-
-       now = cpu_clock(cpu);
-       prev = local64_xchg(&event->hw.prev_count, now);
-       local64_add(now - prev, &event->count);
-}
-
-static int cpu_clock_perf_event_enable(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       int cpu = raw_smp_processor_id();
-
-       local64_set(&hwc->prev_count, cpu_clock(cpu));
-       perf_swevent_start_hrtimer(event);
-
-       return 0;
-}
-
-static void cpu_clock_perf_event_disable(struct perf_event *event)
-{
-       perf_swevent_cancel_hrtimer(event);
-       cpu_clock_perf_event_update(event);
-}
-
-static void cpu_clock_perf_event_read(struct perf_event *event)
-{
-       cpu_clock_perf_event_update(event);
-}
-
-static const struct pmu perf_ops_cpu_clock = {
-       .enable         = cpu_clock_perf_event_enable,
-       .disable        = cpu_clock_perf_event_disable,
-       .read           = cpu_clock_perf_event_read,
-};
-
-/*
- * Software event: task time clock
- */
-
-static void task_clock_perf_event_update(struct perf_event *event, u64 now)
-{
-       u64 prev;
-       s64 delta;
-
-       prev = local64_xchg(&event->hw.prev_count, now);
-       delta = now - prev;
-       local64_add(delta, &event->count);
-}
-
-static int task_clock_perf_event_enable(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 now;
-
-       now = event->ctx->time;
-
-       local64_set(&hwc->prev_count, now);
-
-       perf_swevent_start_hrtimer(event);
-
-       return 0;
-}
-
-static void task_clock_perf_event_disable(struct perf_event *event)
+static void perf_swevent_start(struct perf_event *event, int flags)
 {
-       perf_swevent_cancel_hrtimer(event);
-       task_clock_perf_event_update(event, event->ctx->time);
-
+       event->hw.state = 0;
 }
 
-static void task_clock_perf_event_read(struct perf_event *event)
+static void perf_swevent_stop(struct perf_event *event, int flags)
 {
-       u64 time;
-
-       if (!in_nmi()) {
-               update_context_time(event->ctx);
-               time = event->ctx->time;
-       } else {
-               u64 now = perf_clock();
-               u64 delta = now - event->ctx->timestamp;
-               time = event->ctx->time + delta;
-       }
-
-       task_clock_perf_event_update(event, time);
+       event->hw.state = PERF_HES_STOPPED;
 }
 
-static const struct pmu perf_ops_task_clock = {
-       .enable         = task_clock_perf_event_enable,
-       .disable        = task_clock_perf_event_disable,
-       .read           = task_clock_perf_event_read,
-};
-
 /* Deref the hlist from the update side */
 static inline struct swevent_hlist *
-swevent_hlist_deref(struct perf_cpu_context *cpuctx)
+swevent_hlist_deref(struct swevent_htable *swhash)
 {
-       return rcu_dereference_protected(cpuctx->swevent_hlist,
-                                        lockdep_is_held(&cpuctx->hlist_mutex));
+       return rcu_dereference_protected(swhash->swevent_hlist,
+                                        lockdep_is_held(&swhash->hlist_mutex));
 }
 
 static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
@@ -4483,27 +4569,27 @@ static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
        kfree(hlist);
 }
 
-static void swevent_hlist_release(struct perf_cpu_context *cpuctx)
+static void swevent_hlist_release(struct swevent_htable *swhash)
 {
-       struct swevent_hlist *hlist = swevent_hlist_deref(cpuctx);
+       struct swevent_hlist *hlist = swevent_hlist_deref(swhash);
 
        if (!hlist)
                return;
 
-       rcu_assign_pointer(cpuctx->swevent_hlist, NULL);
+       rcu_assign_pointer(swhash->swevent_hlist, NULL);
        call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu);
 }
 
 static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
 {
-       struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
+       struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-       mutex_lock(&cpuctx->hlist_mutex);
+       mutex_lock(&swhash->hlist_mutex);
 
-       if (!--cpuctx->hlist_refcount)
-               swevent_hlist_release(cpuctx);
+       if (!--swhash->hlist_refcount)
+               swevent_hlist_release(swhash);
 
-       mutex_unlock(&cpuctx->hlist_mutex);
+       mutex_unlock(&swhash->hlist_mutex);
 }
 
 static void swevent_hlist_put(struct perf_event *event)
@@ -4521,12 +4607,12 @@ static void swevent_hlist_put(struct perf_event *event)
 
 static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
 {
-       struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
+       struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
        int err = 0;
 
-       mutex_lock(&cpuctx->hlist_mutex);
+       mutex_lock(&swhash->hlist_mutex);
 
-       if (!swevent_hlist_deref(cpuctx) && cpu_online(cpu)) {
+       if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
                struct swevent_hlist *hlist;
 
                hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
@@ -4534,11 +4620,11 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
                        err = -ENOMEM;
                        goto exit;
                }
-               rcu_assign_pointer(cpuctx->swevent_hlist, hlist);
+               rcu_assign_pointer(swhash->swevent_hlist, hlist);
        }
-       cpuctx->hlist_refcount++;
- exit:
-       mutex_unlock(&cpuctx->hlist_mutex);
+       swhash->hlist_refcount++;
+exit:
+       mutex_unlock(&swhash->hlist_mutex);
 
        return err;
 }
@@ -4562,7 +4648,7 @@ static int swevent_hlist_get(struct perf_event *event)
        put_online_cpus();
 
        return 0;
- fail:
+fail:
        for_each_possible_cpu(cpu) {
                if (cpu == failed_cpu)
                        break;
@@ -4573,17 +4659,64 @@ static int swevent_hlist_get(struct perf_event *event)
        return err;
 }
 
-#ifdef CONFIG_EVENT_TRACING
+atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+
+static void sw_perf_event_destroy(struct perf_event *event)
+{
+       u64 event_id = event->attr.config;
+
+       WARN_ON(event->parent);
+
+       jump_label_dec(&perf_swevent_enabled[event_id]);
+       swevent_hlist_put(event);
+}
 
-static const struct pmu perf_ops_tracepoint = {
-       .enable         = perf_trace_enable,
-       .disable        = perf_trace_disable,
-       .start          = perf_swevent_int,
-       .stop           = perf_swevent_void,
+static int perf_swevent_init(struct perf_event *event)
+{
+       int event_id = event->attr.config;
+
+       if (event->attr.type != PERF_TYPE_SOFTWARE)
+               return -ENOENT;
+
+       switch (event_id) {
+       case PERF_COUNT_SW_CPU_CLOCK:
+       case PERF_COUNT_SW_TASK_CLOCK:
+               return -ENOENT;
+
+       default:
+               break;
+       }
+
+       if (event_id > PERF_COUNT_SW_MAX)
+               return -ENOENT;
+
+       if (!event->parent) {
+               int err;
+
+               err = swevent_hlist_get(event);
+               if (err)
+                       return err;
+
+               jump_label_inc(&perf_swevent_enabled[event_id]);
+               event->destroy = sw_perf_event_destroy;
+       }
+
+       return 0;
+}
+
+static struct pmu perf_swevent = {
+       .task_ctx_nr    = perf_sw_context,
+
+       .event_init     = perf_swevent_init,
+       .add            = perf_swevent_add,
+       .del            = perf_swevent_del,
+       .start          = perf_swevent_start,
+       .stop           = perf_swevent_stop,
        .read           = perf_swevent_read,
-       .unthrottle     = perf_swevent_void,
 };
 
+#ifdef CONFIG_EVENT_TRACING
+
 static int perf_tp_filter_match(struct perf_event *event,
                                struct perf_sample_data *data)
 {
@@ -4627,7 +4760,7 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,
 
        hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
                if (perf_tp_event_match(event, &data, regs))
-                       perf_swevent_add(event, count, 1, &data, regs);
+                       perf_swevent_event(event, count, 1, &data, regs);
        }
 
        perf_swevent_put_recursion_context(rctx);
@@ -4639,10 +4772,13 @@ static void tp_perf_event_destroy(struct perf_event *event)
        perf_trace_destroy(event);
 }
 
-static const struct pmu *tp_perf_event_init(struct perf_event *event)
+static int perf_tp_event_init(struct perf_event *event)
 {
        int err;
 
+       if (event->attr.type != PERF_TYPE_TRACEPOINT)
+               return -ENOENT;
+
        /*
         * Raw tracepoint data is a severe data leak, only allow root to
         * have these.
@@ -4650,15 +4786,31 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event)
        if ((event->attr.sample_type & PERF_SAMPLE_RAW) &&
                        perf_paranoid_tracepoint_raw() &&
                        !capable(CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
+               return -EPERM;
 
        err = perf_trace_init(event);
        if (err)
-               return NULL;
+               return err;
 
        event->destroy = tp_perf_event_destroy;
 
-       return &perf_ops_tracepoint;
+       return 0;
+}
+
+static struct pmu perf_tracepoint = {
+       .task_ctx_nr    = perf_sw_context,
+
+       .event_init     = perf_tp_event_init,
+       .add            = perf_trace_add,
+       .del            = perf_trace_del,
+       .start          = perf_swevent_start,
+       .stop           = perf_swevent_stop,
+       .read           = perf_swevent_read,
+};
+
+static inline void perf_tp_register(void)
+{
+       perf_pmu_register(&perf_tracepoint);
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4686,9 +4838,8 @@ static void perf_event_free_filter(struct perf_event *event)
 
 #else
 
-static const struct pmu *tp_perf_event_init(struct perf_event *event)
+static inline void perf_tp_register(void)
 {
-       return NULL;
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4703,24 +4854,6 @@ static void perf_event_free_filter(struct perf_event *event)
 #endif /* CONFIG_EVENT_TRACING */
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-static void bp_perf_event_destroy(struct perf_event *event)
-{
-       release_bp_slot(event);
-}
-
-static const struct pmu *bp_perf_event_init(struct perf_event *bp)
-{
-       int err;
-
-       err = register_perf_hw_breakpoint(bp);
-       if (err)
-               return ERR_PTR(err);
-
-       bp->destroy = bp_perf_event_destroy;
-
-       return &perf_ops_bp;
-}
-
 void perf_bp_event(struct perf_event *bp, void *data)
 {
        struct perf_sample_data sample;
@@ -4728,81 +4861,383 @@ void perf_bp_event(struct perf_event *bp, void *data)
 
        perf_sample_data_init(&sample, bp->attr.bp_addr);
 
-       if (!perf_exclude_event(bp, regs))
-               perf_swevent_add(bp, 1, 1, &sample, regs);
-}
-#else
-static const struct pmu *bp_perf_event_init(struct perf_event *bp)
-{
-       return NULL;
-}
-
-void perf_bp_event(struct perf_event *bp, void *regs)
-{
+       if (!bp->hw.state && !perf_exclude_event(bp, regs))
+               perf_swevent_event(bp, 1, 1, &sample, regs);
 }
 #endif
 
-atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+/*
+ * hrtimer based swevent callback
+ */
 
-static void sw_perf_event_destroy(struct perf_event *event)
+static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
 {
-       u64 event_id = event->attr.config;
-
-       WARN_ON(event->parent);
+       enum hrtimer_restart ret = HRTIMER_RESTART;
+       struct perf_sample_data data;
+       struct pt_regs *regs;
+       struct perf_event *event;
+       u64 period;
 
-       atomic_dec(&perf_swevent_enabled[event_id]);
-       swevent_hlist_put(event);
+       event = container_of(hrtimer, struct perf_event, hw.hrtimer);
+       event->pmu->read(event);
+
+       perf_sample_data_init(&data, 0);
+       data.period = event->hw.last_period;
+       regs = get_irq_regs();
+
+       if (regs && !perf_exclude_event(event, regs)) {
+               if (!(event->attr.exclude_idle && current->pid == 0))
+                       if (perf_event_overflow(event, 0, &data, regs))
+                               ret = HRTIMER_NORESTART;
+       }
+
+       period = max_t(u64, 10000, event->hw.sample_period);
+       hrtimer_forward_now(hrtimer, ns_to_ktime(period));
+
+       return ret;
 }
 
-static const struct pmu *sw_perf_event_init(struct perf_event *event)
+static void perf_swevent_start_hrtimer(struct perf_event *event)
 {
-       const struct pmu *pmu = NULL;
-       u64 event_id = event->attr.config;
+       struct hw_perf_event *hwc = &event->hw;
+
+       hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hwc->hrtimer.function = perf_swevent_hrtimer;
+       if (hwc->sample_period) {
+               s64 period = local64_read(&hwc->period_left);
+
+               if (period) {
+                       if (period < 0)
+                               period = 10000;
 
+                       local64_set(&hwc->period_left, 0);
+               } else {
+                       period = max_t(u64, 10000, hwc->sample_period);
+               }
+               __hrtimer_start_range_ns(&hwc->hrtimer,
+                               ns_to_ktime(period), 0,
+                               HRTIMER_MODE_REL_PINNED, 0);
+       }
+}
+
+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->sample_period) {
+               ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
+               local64_set(&hwc->period_left, ktime_to_ns(remaining));
+
+               hrtimer_cancel(&hwc->hrtimer);
+       }
+}
+
+/*
+ * Software event: cpu wall time clock
+ */
+
+static void cpu_clock_event_update(struct perf_event *event)
+{
+       s64 prev;
+       u64 now;
+
+       now = local_clock();
+       prev = local64_xchg(&event->hw.prev_count, now);
+       local64_add(now - prev, &event->count);
+}
+
+static void cpu_clock_event_start(struct perf_event *event, int flags)
+{
+       local64_set(&event->hw.prev_count, local_clock());
+       perf_swevent_start_hrtimer(event);
+}
+
+static void cpu_clock_event_stop(struct perf_event *event, int flags)
+{
+       perf_swevent_cancel_hrtimer(event);
+       cpu_clock_event_update(event);
+}
+
+static int cpu_clock_event_add(struct perf_event *event, int flags)
+{
+       if (flags & PERF_EF_START)
+               cpu_clock_event_start(event, flags);
+
+       return 0;
+}
+
+static void cpu_clock_event_del(struct perf_event *event, int flags)
+{
+       cpu_clock_event_stop(event, flags);
+}
+
+static void cpu_clock_event_read(struct perf_event *event)
+{
+       cpu_clock_event_update(event);
+}
+
+static int cpu_clock_event_init(struct perf_event *event)
+{
+       if (event->attr.type != PERF_TYPE_SOFTWARE)
+               return -ENOENT;
+
+       if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
+               return -ENOENT;
+
+       return 0;
+}
+
+static struct pmu perf_cpu_clock = {
+       .task_ctx_nr    = perf_sw_context,
+
+       .event_init     = cpu_clock_event_init,
+       .add            = cpu_clock_event_add,
+       .del            = cpu_clock_event_del,
+       .start          = cpu_clock_event_start,
+       .stop           = cpu_clock_event_stop,
+       .read           = cpu_clock_event_read,
+};
+
+/*
+ * Software event: task time clock
+ */
+
+static void task_clock_event_update(struct perf_event *event, u64 now)
+{
+       u64 prev;
+       s64 delta;
+
+       prev = local64_xchg(&event->hw.prev_count, now);
+       delta = now - prev;
+       local64_add(delta, &event->count);
+}
+
+static void task_clock_event_start(struct perf_event *event, int flags)
+{
+       local64_set(&event->hw.prev_count, event->ctx->time);
+       perf_swevent_start_hrtimer(event);
+}
+
+static void task_clock_event_stop(struct perf_event *event, int flags)
+{
+       perf_swevent_cancel_hrtimer(event);
+       task_clock_event_update(event, event->ctx->time);
+}
+
+static int task_clock_event_add(struct perf_event *event, int flags)
+{
+       if (flags & PERF_EF_START)
+               task_clock_event_start(event, flags);
+
+       return 0;
+}
+
+static void task_clock_event_del(struct perf_event *event, int flags)
+{
+       task_clock_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void task_clock_event_read(struct perf_event *event)
+{
+       u64 time;
+
+       if (!in_nmi()) {
+               update_context_time(event->ctx);
+               time = event->ctx->time;
+       } else {
+               u64 now = perf_clock();
+               u64 delta = now - event->ctx->timestamp;
+               time = event->ctx->time + delta;
+       }
+
+       task_clock_event_update(event, time);
+}
+
+static int task_clock_event_init(struct perf_event *event)
+{
+       if (event->attr.type != PERF_TYPE_SOFTWARE)
+               return -ENOENT;
+
+       if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
+               return -ENOENT;
+
+       return 0;
+}
+
+static struct pmu perf_task_clock = {
+       .task_ctx_nr    = perf_sw_context,
+
+       .event_init     = task_clock_event_init,
+       .add            = task_clock_event_add,
+       .del            = task_clock_event_del,
+       .start          = task_clock_event_start,
+       .stop           = task_clock_event_stop,
+       .read           = task_clock_event_read,
+};
+
+static void perf_pmu_nop_void(struct pmu *pmu)
+{
+}
+
+static int perf_pmu_nop_int(struct pmu *pmu)
+{
+       return 0;
+}
+
+static void perf_pmu_start_txn(struct pmu *pmu)
+{
+       perf_pmu_disable(pmu);
+}
+
+static int perf_pmu_commit_txn(struct pmu *pmu)
+{
+       perf_pmu_enable(pmu);
+       return 0;
+}
+
+static void perf_pmu_cancel_txn(struct pmu *pmu)
+{
+       perf_pmu_enable(pmu);
+}
+
+/*
+ * Ensures all contexts with the same task_ctx_nr have the same
+ * pmu_cpu_context too.
+ */
+static void *find_pmu_context(int ctxn)
+{
+       struct pmu *pmu;
+
+       if (ctxn < 0)
+               return NULL;
+
+       list_for_each_entry(pmu, &pmus, entry) {
+               if (pmu->task_ctx_nr == ctxn)
+                       return pmu->pmu_cpu_context;
+       }
+
+       return NULL;
+}
+
+static void free_pmu_context(void * __percpu cpu_context)
+{
+       struct pmu *pmu;
+
+       mutex_lock(&pmus_lock);
        /*
-        * Software events (currently) can't in general distinguish
-        * between user, kernel and hypervisor events.
-        * However, context switches and cpu migrations are considered
-        * to be kernel events, and page faults are never hypervisor
-        * events.
+        * Like a real lame refcount.
         */
-       switch (event_id) {
-       case PERF_COUNT_SW_CPU_CLOCK:
-               pmu = &perf_ops_cpu_clock;
+       list_for_each_entry(pmu, &pmus, entry) {
+               if (pmu->pmu_cpu_context == cpu_context)
+                       goto out;
+       }
 
-               break;
-       case PERF_COUNT_SW_TASK_CLOCK:
-               /*
-                * If the user instantiates this as a per-cpu event,
-                * use the cpu_clock event instead.
-                */
-               if (event->ctx->task)
-                       pmu = &perf_ops_task_clock;
-               else
-                       pmu = &perf_ops_cpu_clock;
+       free_percpu(cpu_context);
+out:
+       mutex_unlock(&pmus_lock);
+}
 
-               break;
-       case PERF_COUNT_SW_PAGE_FAULTS:
-       case PERF_COUNT_SW_PAGE_FAULTS_MIN:
-       case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
-       case PERF_COUNT_SW_CONTEXT_SWITCHES:
-       case PERF_COUNT_SW_CPU_MIGRATIONS:
-       case PERF_COUNT_SW_ALIGNMENT_FAULTS:
-       case PERF_COUNT_SW_EMULATION_FAULTS:
-               if (!event->parent) {
-                       int err;
-
-                       err = swevent_hlist_get(event);
-                       if (err)
-                               return ERR_PTR(err);
+int perf_pmu_register(struct pmu *pmu)
+{
+       int cpu, ret;
+
+       mutex_lock(&pmus_lock);
+       ret = -ENOMEM;
+       pmu->pmu_disable_count = alloc_percpu(int);
+       if (!pmu->pmu_disable_count)
+               goto unlock;
 
-                       atomic_inc(&perf_swevent_enabled[event_id]);
-                       event->destroy = sw_perf_event_destroy;
+       pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
+       if (pmu->pmu_cpu_context)
+               goto got_cpu_context;
+
+       pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
+       if (!pmu->pmu_cpu_context)
+               goto free_pdc;
+
+       for_each_possible_cpu(cpu) {
+               struct perf_cpu_context *cpuctx;
+
+               cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+               __perf_event_init_context(&cpuctx->ctx);
+               cpuctx->ctx.type = cpu_context;
+               cpuctx->ctx.pmu = pmu;
+               cpuctx->jiffies_interval = 1;
+               INIT_LIST_HEAD(&cpuctx->rotation_list);
+       }
+
+got_cpu_context:
+       if (!pmu->start_txn) {
+               if (pmu->pmu_enable) {
+                       /*
+                        * If we have pmu_enable/pmu_disable calls, install
+                        * transaction stubs that use that to try and batch
+                        * hardware accesses.
+                        */
+                       pmu->start_txn  = perf_pmu_start_txn;
+                       pmu->commit_txn = perf_pmu_commit_txn;
+                       pmu->cancel_txn = perf_pmu_cancel_txn;
+               } else {
+                       pmu->start_txn  = perf_pmu_nop_void;
+                       pmu->commit_txn = perf_pmu_nop_int;
+                       pmu->cancel_txn = perf_pmu_nop_void;
                }
-               pmu = &perf_ops_generic;
-               break;
        }
 
+       if (!pmu->pmu_enable) {
+               pmu->pmu_enable  = perf_pmu_nop_void;
+               pmu->pmu_disable = perf_pmu_nop_void;
+       }
+
+       list_add_rcu(&pmu->entry, &pmus);
+       ret = 0;
+unlock:
+       mutex_unlock(&pmus_lock);
+
+       return ret;
+
+free_pdc:
+       free_percpu(pmu->pmu_disable_count);
+       goto unlock;
+}
+
+void perf_pmu_unregister(struct pmu *pmu)
+{
+       mutex_lock(&pmus_lock);
+       list_del_rcu(&pmu->entry);
+       mutex_unlock(&pmus_lock);
+
+       /*
+        * We dereference the pmu list under both SRCU and regular RCU, so
+        * synchronize against both of those.
+        */
+       synchronize_srcu(&pmus_srcu);
+       synchronize_rcu();
+
+       free_percpu(pmu->pmu_disable_count);
+       free_pmu_context(pmu->pmu_cpu_context);
+}
+
+struct pmu *perf_init_event(struct perf_event *event)
+{
+       struct pmu *pmu = NULL;
+       int idx;
+
+       idx = srcu_read_lock(&pmus_srcu);
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               int ret = pmu->event_init(event);
+               if (!ret)
+                       goto unlock;
+
+               if (ret != -ENOENT) {
+                       pmu = ERR_PTR(ret);
+                       goto unlock;
+               }
+       }
+       pmu = ERR_PTR(-ENOENT);
+unlock:
+       srcu_read_unlock(&pmus_srcu, idx);
+
        return pmu;
 }
 
@@ -4810,20 +5245,18 @@ static const struct pmu *sw_perf_event_init(struct perf_event *event)
  * Allocate and initialize a event structure
  */
 static struct perf_event *
-perf_event_alloc(struct perf_event_attr *attr,
-                  int cpu,
-                  struct perf_event_context *ctx,
-                  struct perf_event *group_leader,
-                  struct perf_event *parent_event,
-                  perf_overflow_handler_t overflow_handler,
-                  gfp_t gfpflags)
-{
-       const struct pmu *pmu;
+perf_event_alloc(struct perf_event_attr *attr, int cpu,
+                struct task_struct *task,
+                struct perf_event *group_leader,
+                struct perf_event *parent_event,
+                perf_overflow_handler_t overflow_handler)
+{
+       struct pmu *pmu;
        struct perf_event *event;
        struct hw_perf_event *hwc;
        long err;
 
-       event = kzalloc(sizeof(*event), gfpflags);
+       event = kzalloc(sizeof(*event), GFP_KERNEL);
        if (!event)
                return ERR_PTR(-ENOMEM);
 
@@ -4841,6 +5274,7 @@ perf_event_alloc(struct perf_event_attr *attr,
        INIT_LIST_HEAD(&event->event_entry);
        INIT_LIST_HEAD(&event->sibling_list);
        init_waitqueue_head(&event->waitq);
+       init_irq_work(&event->pending, perf_pending_event);
 
        mutex_init(&event->mmap_mutex);
 
@@ -4848,7 +5282,6 @@ perf_event_alloc(struct perf_event_attr *attr,
        event->attr             = *attr;
        event->group_leader     = group_leader;
        event->pmu              = NULL;
-       event->ctx              = ctx;
        event->oncpu            = -1;
 
        event->parent           = parent_event;
@@ -4858,6 +5291,17 @@ perf_event_alloc(struct perf_event_attr *attr,
 
        event->state            = PERF_EVENT_STATE_INACTIVE;
 
+       if (task) {
+               event->attach_state = PERF_ATTACH_TASK;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+               /*
+                * hw_breakpoint is a bit difficult here..
+                */
+               if (attr->type == PERF_TYPE_BREAKPOINT)
+                       event->hw.bp_target = task;
+#endif
+       }
+
        if (!overflow_handler && parent_event)
                overflow_handler = parent_event->overflow_handler;
        
@@ -4882,29 +5326,8 @@ perf_event_alloc(struct perf_event_attr *attr,
        if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
                goto done;
 
-       switch (attr->type) {
-       case PERF_TYPE_RAW:
-       case PERF_TYPE_HARDWARE:
-       case PERF_TYPE_HW_CACHE:
-               pmu = hw_perf_event_init(event);
-               break;
-
-       case PERF_TYPE_SOFTWARE:
-               pmu = sw_perf_event_init(event);
-               break;
-
-       case PERF_TYPE_TRACEPOINT:
-               pmu = tp_perf_event_init(event);
-               break;
-
-       case PERF_TYPE_BREAKPOINT:
-               pmu = bp_perf_event_init(event);
-               break;
-
+       pmu = perf_init_event(event);
 
-       default:
-               break;
-       }
 done:
        err = 0;
        if (!pmu)
@@ -4922,13 +5345,21 @@ done:
        event->pmu = pmu;
 
        if (!event->parent) {
-               atomic_inc(&nr_events);
+               if (event->attach_state & PERF_ATTACH_TASK)
+                       jump_label_inc(&perf_task_events);
                if (event->attr.mmap || event->attr.mmap_data)
                        atomic_inc(&nr_mmap_events);
                if (event->attr.comm)
                        atomic_inc(&nr_comm_events);
                if (event->attr.task)
                        atomic_inc(&nr_task_events);
+               if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
+                       err = get_callchain_buffers();
+                       if (err) {
+                               free_event(event);
+                               return ERR_PTR(err);
+                       }
+               }
        }
 
        return event;
@@ -5076,12 +5507,16 @@ SYSCALL_DEFINE5(perf_event_open,
                struct perf_event_attr __user *, attr_uptr,
                pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
 {
-       struct perf_event *event, *group_leader = NULL, *output_event = NULL;
+       struct perf_event *group_leader = NULL, *output_event = NULL;
+       struct perf_event *event, *sibling;
        struct perf_event_attr attr;
        struct perf_event_context *ctx;
        struct file *event_file = NULL;
        struct file *group_file = NULL;
+       struct task_struct *task = NULL;
+       struct pmu *pmu;
        int event_fd;
+       int move_group = 0;
        int fput_needed = 0;
        int err;
 
@@ -5107,20 +5542,11 @@ SYSCALL_DEFINE5(perf_event_open,
        if (event_fd < 0)
                return event_fd;
 
-       /*
-        * Get the target context (task or percpu):
-        */
-       ctx = find_get_context(pid, cpu);
-       if (IS_ERR(ctx)) {
-               err = PTR_ERR(ctx);
-               goto err_fd;
-       }
-
        if (group_fd != -1) {
                group_leader = perf_fget_light(group_fd, &fput_needed);
                if (IS_ERR(group_leader)) {
                        err = PTR_ERR(group_leader);
-                       goto err_put_context;
+                       goto err_fd;
                }
                group_file = group_leader->filp;
                if (flags & PERF_FLAG_FD_OUTPUT)
@@ -5129,6 +5555,58 @@ SYSCALL_DEFINE5(perf_event_open,
                        group_leader = NULL;
        }
 
+       if (pid != -1) {
+               task = find_lively_task_by_vpid(pid);
+               if (IS_ERR(task)) {
+                       err = PTR_ERR(task);
+                       goto err_group_fd;
+               }
+       }
+
+       event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, NULL);
+       if (IS_ERR(event)) {
+               err = PTR_ERR(event);
+               goto err_task;
+       }
+
+       /*
+        * Special case software events and allow them to be part of
+        * any hardware group.
+        */
+       pmu = event->pmu;
+
+       if (group_leader &&
+           (is_software_event(event) != is_software_event(group_leader))) {
+               if (is_software_event(event)) {
+                       /*
+                        * If event and group_leader are not both a software
+                        * event, and event is, then group leader is not.
+                        *
+                        * Allow the addition of software events to !software
+                        * groups, this is safe because software events never
+                        * fail to schedule.
+                        */
+                       pmu = group_leader->pmu;
+               } else if (is_software_event(group_leader) &&
+                          (group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
+                       /*
+                        * In case the group is a pure software group, and we
+                        * try to add a hardware event, move the whole group to
+                        * the hardware context.
+                        */
+                       move_group = 1;
+               }
+       }
+
+       /*
+        * Get the target context (task or percpu):
+        */
+       ctx = find_get_context(pmu, task, cpu);
+       if (IS_ERR(ctx)) {
+               err = PTR_ERR(ctx);
+               goto err_alloc;
+       }
+
        /*
         * Look up the group leader (we will attach this event to it):
         */
@@ -5140,42 +5618,66 @@ SYSCALL_DEFINE5(perf_event_open,
                 * becoming part of another group-sibling):
                 */
                if (group_leader->group_leader != group_leader)
-                       goto err_put_context;
+                       goto err_context;
                /*
                 * Do not allow to attach to a group in a different
                 * task or CPU context:
                 */
-               if (group_leader->ctx != ctx)
-                       goto err_put_context;
+               if (move_group) {
+                       if (group_leader->ctx->type != ctx->type)
+                               goto err_context;
+               } else {
+                       if (group_leader->ctx != ctx)
+                               goto err_context;
+               }
+
                /*
                 * Only a group leader can be exclusive or pinned
                 */
                if (attr.exclusive || attr.pinned)
-                       goto err_put_context;
-       }
-
-       event = perf_event_alloc(&attr, cpu, ctx, group_leader,
-                                    NULL, NULL, GFP_KERNEL);
-       if (IS_ERR(event)) {
-               err = PTR_ERR(event);
-               goto err_put_context;
+                       goto err_context;
        }
 
        if (output_event) {
                err = perf_event_set_output(event, output_event);
                if (err)
-                       goto err_free_put_context;
+                       goto err_context;
        }
 
        event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
        if (IS_ERR(event_file)) {
                err = PTR_ERR(event_file);
-               goto err_free_put_context;
+               goto err_context;
+       }
+
+       if (move_group) {
+               struct perf_event_context *gctx = group_leader->ctx;
+
+               mutex_lock(&gctx->mutex);
+               perf_event_remove_from_context(group_leader);
+               list_for_each_entry(sibling, &group_leader->sibling_list,
+                                   group_entry) {
+                       perf_event_remove_from_context(sibling);
+                       put_ctx(gctx);
+               }
+               mutex_unlock(&gctx->mutex);
+               put_ctx(gctx);
        }
 
        event->filp = event_file;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
+
+       if (move_group) {
+               perf_install_in_context(ctx, group_leader, cpu);
+               get_ctx(ctx);
+               list_for_each_entry(sibling, &group_leader->sibling_list,
+                                   group_entry) {
+                       perf_install_in_context(ctx, sibling, cpu);
+                       get_ctx(ctx);
+               }
+       }
+
        perf_install_in_context(ctx, event, cpu);
        ++ctx->generation;
        mutex_unlock(&ctx->mutex);
@@ -5196,11 +5698,15 @@ SYSCALL_DEFINE5(perf_event_open,
        fd_install(event_fd, event_file);
        return event_fd;
 
-err_free_put_context:
+err_context:
+       put_ctx(ctx);
+err_alloc:
        free_event(event);
-err_put_context:
+err_task:
+       if (task)
+               put_task_struct(task);
+err_group_fd:
        fput_light(group_file, fput_needed);
-       put_ctx(ctx);
 err_fd:
        put_unused_fd(event_fd);
        return err;
@@ -5211,154 +5717,54 @@ err_fd:
  *
  * @attr: attributes of the counter to create
  * @cpu: cpu in which the counter is bound
- * @pid: task to profile
+ * @task: task to profile (NULL for percpu)
  */
 struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
-                                pid_t pid,
+                                struct task_struct *task,
                                 perf_overflow_handler_t overflow_handler)
 {
-       struct perf_event *event;
        struct perf_event_context *ctx;
-       int err;
-
-       /*
-        * Get the target context (task or percpu):
-        */
-
-       ctx = find_get_context(pid, cpu);
-       if (IS_ERR(ctx)) {
-               err = PTR_ERR(ctx);
-               goto err_exit;
-       }
-
-       event = perf_event_alloc(attr, cpu, ctx, NULL,
-                                NULL, overflow_handler, GFP_KERNEL);
-       if (IS_ERR(event)) {
-               err = PTR_ERR(event);
-               goto err_put_context;
-       }
-
-       event->filp = NULL;
-       WARN_ON_ONCE(ctx->parent_ctx);
-       mutex_lock(&ctx->mutex);
-       perf_install_in_context(ctx, event, cpu);
-       ++ctx->generation;
-       mutex_unlock(&ctx->mutex);
-
-       event->owner = current;
-       get_task_struct(current);
-       mutex_lock(&current->perf_event_mutex);
-       list_add_tail(&event->owner_entry, &current->perf_event_list);
-       mutex_unlock(&current->perf_event_mutex);
-
-       return event;
-
- err_put_context:
-       put_ctx(ctx);
- err_exit:
-       return ERR_PTR(err);
-}
-EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
-
-/*
- * inherit a event from parent task to child task:
- */
-static struct perf_event *
-inherit_event(struct perf_event *parent_event,
-             struct task_struct *parent,
-             struct perf_event_context *parent_ctx,
-             struct task_struct *child,
-             struct perf_event *group_leader,
-             struct perf_event_context *child_ctx)
-{
-       struct perf_event *child_event;
-
-       /*
-        * Instead of creating recursive hierarchies of events,
-        * we link inherited events back to the original parent,
-        * which has a filp for sure, which we use as the reference
-        * count:
-        */
-       if (parent_event->parent)
-               parent_event = parent_event->parent;
-
-       child_event = perf_event_alloc(&parent_event->attr,
-                                          parent_event->cpu, child_ctx,
-                                          group_leader, parent_event,
-                                          NULL, GFP_KERNEL);
-       if (IS_ERR(child_event))
-               return child_event;
-       get_ctx(child_ctx);
-
-       /*
-        * Make the child state follow the state of the parent event,
-        * not its attr.disabled bit.  We hold the parent's mutex,
-        * so we won't race with perf_event_{en, dis}able_family.
-        */
-       if (parent_event->state >= PERF_EVENT_STATE_INACTIVE)
-               child_event->state = PERF_EVENT_STATE_INACTIVE;
-       else
-               child_event->state = PERF_EVENT_STATE_OFF;
-
-       if (parent_event->attr.freq) {
-               u64 sample_period = parent_event->hw.sample_period;
-               struct hw_perf_event *hwc = &child_event->hw;
-
-               hwc->sample_period = sample_period;
-               hwc->last_period   = sample_period;
-
-               local64_set(&hwc->period_left, sample_period);
-       }
-
-       child_event->overflow_handler = parent_event->overflow_handler;
-
-       /*
-        * Link it up in the child's context:
-        */
-       add_event_to_ctx(child_event, child_ctx);
-
-       /*
-        * Get a reference to the parent filp - we will fput it
-        * when the child event exits. This is safe to do because
-        * we are in the parent and we know that the filp still
-        * exists and has a nonzero count:
-        */
-       atomic_long_inc(&parent_event->filp->f_count);
-
-       /*
-        * Link this into the parent event's child list
-        */
-       WARN_ON_ONCE(parent_event->ctx->parent_ctx);
-       mutex_lock(&parent_event->child_mutex);
-       list_add_tail(&child_event->child_list, &parent_event->child_list);
-       mutex_unlock(&parent_event->child_mutex);
+       struct perf_event *event;
+       int err;
 
-       return child_event;
-}
+       /*
+        * Get the target context (task or percpu):
+        */
 
-static int inherit_group(struct perf_event *parent_event,
-             struct task_struct *parent,
-             struct perf_event_context *parent_ctx,
-             struct task_struct *child,
-             struct perf_event_context *child_ctx)
-{
-       struct perf_event *leader;
-       struct perf_event *sub;
-       struct perf_event *child_ctr;
+       event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler);
+       if (IS_ERR(event)) {
+               err = PTR_ERR(event);
+               goto err;
+       }
 
-       leader = inherit_event(parent_event, parent, parent_ctx,
-                                child, NULL, child_ctx);
-       if (IS_ERR(leader))
-               return PTR_ERR(leader);
-       list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
-               child_ctr = inherit_event(sub, parent, parent_ctx,
-                                           child, leader, child_ctx);
-               if (IS_ERR(child_ctr))
-                       return PTR_ERR(child_ctr);
+       ctx = find_get_context(event->pmu, task, cpu);
+       if (IS_ERR(ctx)) {
+               err = PTR_ERR(ctx);
+               goto err_free;
        }
-       return 0;
+
+       event->filp = NULL;
+       WARN_ON_ONCE(ctx->parent_ctx);
+       mutex_lock(&ctx->mutex);
+       perf_install_in_context(ctx, event, cpu);
+       ++ctx->generation;
+       mutex_unlock(&ctx->mutex);
+
+       event->owner = current;
+       get_task_struct(current);
+       mutex_lock(&current->perf_event_mutex);
+       list_add_tail(&event->owner_entry, &current->perf_event_list);
+       mutex_unlock(&current->perf_event_mutex);
+
+       return event;
+
+err_free:
+       free_event(event);
+err:
+       return ERR_PTR(err);
 }
+EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
 
 static void sync_child_event(struct perf_event *child_event,
                               struct task_struct *child)
@@ -5416,16 +5822,13 @@ __perf_event_exit_task(struct perf_event *child_event,
        }
 }
 
-/*
- * When a child task exits, feed back event values to parent events.
- */
-void perf_event_exit_task(struct task_struct *child)
+static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
 {
        struct perf_event *child_event, *tmp;
        struct perf_event_context *child_ctx;
        unsigned long flags;
 
-       if (likely(!child->perf_event_ctxp)) {
+       if (likely(!child->perf_event_ctxp[ctxn])) {
                perf_event_task(child, NULL, 0);
                return;
        }
@@ -5437,8 +5840,8 @@ void perf_event_exit_task(struct task_struct *child)
         * scheduled, so we are now safe from rescheduling changing
         * our context.
         */
-       child_ctx = child->perf_event_ctxp;
-       __perf_event_task_sched_out(child_ctx);
+       child_ctx = child->perf_event_ctxp[ctxn];
+       task_ctx_sched_out(child_ctx, EVENT_ALL);
 
        /*
         * Take the context lock here so that if find_get_context is
@@ -5446,7 +5849,7 @@ void perf_event_exit_task(struct task_struct *child)
         * incremented the context's refcount before we do put_ctx below.
         */
        raw_spin_lock(&child_ctx->lock);
-       child->perf_event_ctxp = NULL;
+       child->perf_event_ctxp[ctxn] = NULL;
        /*
         * If this context is a clone; unclone it so it can't get
         * swapped to another process while we're removing all
@@ -5499,6 +5902,17 @@ again:
        put_ctx(child_ctx);
 }
 
+/*
+ * When a child task exits, feed back event values to parent events.
+ */
+void perf_event_exit_task(struct task_struct *child)
+{
+       int ctxn;
+
+       for_each_task_context_nr(ctxn)
+               perf_event_exit_task_context(child, ctxn);
+}
+
 static void perf_free_event(struct perf_event *event,
                            struct perf_event_context *ctx)
 {
@@ -5520,48 +5934,166 @@ static void perf_free_event(struct perf_event *event,
 
 /*
  * free an unexposed, unused context as created by inheritance by
- * init_task below, used by fork() in case of fail.
+ * perf_event_init_task below, used by fork() in case of fail.
  */
 void perf_event_free_task(struct task_struct *task)
 {
-       struct perf_event_context *ctx = task->perf_event_ctxp;
+       struct perf_event_context *ctx;
        struct perf_event *event, *tmp;
+       int ctxn;
 
-       if (!ctx)
-               return;
+       for_each_task_context_nr(ctxn) {
+               ctx = task->perf_event_ctxp[ctxn];
+               if (!ctx)
+                       continue;
 
-       mutex_lock(&ctx->mutex);
+               mutex_lock(&ctx->mutex);
 again:
-       list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
-               perf_free_event(event, ctx);
+               list_for_each_entry_safe(event, tmp, &ctx->pinned_groups,
+                               group_entry)
+                       perf_free_event(event, ctx);
 
-       list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
-                                group_entry)
-               perf_free_event(event, ctx);
+               list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
+                               group_entry)
+                       perf_free_event(event, ctx);
 
-       if (!list_empty(&ctx->pinned_groups) ||
-           !list_empty(&ctx->flexible_groups))
-               goto again;
+               if (!list_empty(&ctx->pinned_groups) ||
+                               !list_empty(&ctx->flexible_groups))
+                       goto again;
 
-       mutex_unlock(&ctx->mutex);
+               mutex_unlock(&ctx->mutex);
 
-       put_ctx(ctx);
+               put_ctx(ctx);
+       }
+}
+
+void perf_event_delayed_put(struct task_struct *task)
+{
+       int ctxn;
+
+       for_each_task_context_nr(ctxn)
+               WARN_ON_ONCE(task->perf_event_ctxp[ctxn]);
+}
+
+/*
+ * inherit a event from parent task to child task:
+ */
+static struct perf_event *
+inherit_event(struct perf_event *parent_event,
+             struct task_struct *parent,
+             struct perf_event_context *parent_ctx,
+             struct task_struct *child,
+             struct perf_event *group_leader,
+             struct perf_event_context *child_ctx)
+{
+       struct perf_event *child_event;
+       unsigned long flags;
+
+       /*
+        * Instead of creating recursive hierarchies of events,
+        * we link inherited events back to the original parent,
+        * which has a filp for sure, which we use as the reference
+        * count:
+        */
+       if (parent_event->parent)
+               parent_event = parent_event->parent;
+
+       child_event = perf_event_alloc(&parent_event->attr,
+                                          parent_event->cpu,
+                                          child,
+                                          group_leader, parent_event,
+                                          NULL);
+       if (IS_ERR(child_event))
+               return child_event;
+       get_ctx(child_ctx);
+
+       /*
+        * Make the child state follow the state of the parent event,
+        * not its attr.disabled bit.  We hold the parent's mutex,
+        * so we won't race with perf_event_{en, dis}able_family.
+        */
+       if (parent_event->state >= PERF_EVENT_STATE_INACTIVE)
+               child_event->state = PERF_EVENT_STATE_INACTIVE;
+       else
+               child_event->state = PERF_EVENT_STATE_OFF;
+
+       if (parent_event->attr.freq) {
+               u64 sample_period = parent_event->hw.sample_period;
+               struct hw_perf_event *hwc = &child_event->hw;
+
+               hwc->sample_period = sample_period;
+               hwc->last_period   = sample_period;
+
+               local64_set(&hwc->period_left, sample_period);
+       }
+
+       child_event->ctx = child_ctx;
+       child_event->overflow_handler = parent_event->overflow_handler;
+
+       /*
+        * Link it up in the child's context:
+        */
+       raw_spin_lock_irqsave(&child_ctx->lock, flags);
+       add_event_to_ctx(child_event, child_ctx);
+       raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
+
+       /*
+        * Get a reference to the parent filp - we will fput it
+        * when the child event exits. This is safe to do because
+        * we are in the parent and we know that the filp still
+        * exists and has a nonzero count:
+        */
+       atomic_long_inc(&parent_event->filp->f_count);
+
+       /*
+        * Link this into the parent event's child list
+        */
+       WARN_ON_ONCE(parent_event->ctx->parent_ctx);
+       mutex_lock(&parent_event->child_mutex);
+       list_add_tail(&child_event->child_list, &parent_event->child_list);
+       mutex_unlock(&parent_event->child_mutex);
+
+       return child_event;
+}
+
+static int inherit_group(struct perf_event *parent_event,
+             struct task_struct *parent,
+             struct perf_event_context *parent_ctx,
+             struct task_struct *child,
+             struct perf_event_context *child_ctx)
+{
+       struct perf_event *leader;
+       struct perf_event *sub;
+       struct perf_event *child_ctr;
+
+       leader = inherit_event(parent_event, parent, parent_ctx,
+                                child, NULL, child_ctx);
+       if (IS_ERR(leader))
+               return PTR_ERR(leader);
+       list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
+               child_ctr = inherit_event(sub, parent, parent_ctx,
+                                           child, leader, child_ctx);
+               if (IS_ERR(child_ctr))
+                       return PTR_ERR(child_ctr);
+       }
+       return 0;
 }
 
 static int
 inherit_task_group(struct perf_event *event, struct task_struct *parent,
                   struct perf_event_context *parent_ctx,
-                  struct task_struct *child,
+                  struct task_struct *child, int ctxn,
                   int *inherited_all)
 {
        int ret;
-       struct perf_event_context *child_ctx = child->perf_event_ctxp;
+       struct perf_event_context *child_ctx;
 
        if (!event->attr.inherit) {
                *inherited_all = 0;
                return 0;
        }
 
+               child_ctx = child->perf_event_ctxp[ctxn];
        if (!child_ctx) {
                /*
                 * This is executed from the parent task context, so
@@ -5570,14 +6102,11 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
                 * child.
                 */
 
-               child_ctx = kzalloc(sizeof(struct perf_event_context),
-                                   GFP_KERNEL);
+               child_ctx = alloc_perf_context(event->pmu, child);
                if (!child_ctx)
                        return -ENOMEM;
 
-               __perf_event_init_context(child_ctx, child);
-               child->perf_event_ctxp = child_ctx;
-               get_task_struct(child);
+               child->perf_event_ctxp[ctxn] = child_ctx;
        }
 
        ret = inherit_group(event, parent, parent_ctx,
@@ -5589,11 +6118,10 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
        return ret;
 }
 
-
 /*
  * Initialize the perf_event context in task_struct
  */
-int perf_event_init_task(struct task_struct *child)
+int perf_event_init_context(struct task_struct *child, int ctxn)
 {
        struct perf_event_context *child_ctx, *parent_ctx;
        struct perf_event_context *cloned_ctx;
@@ -5602,19 +6130,19 @@ int perf_event_init_task(struct task_struct *child)
        int inherited_all = 1;
        int ret = 0;
 
-       child->perf_event_ctxp = NULL;
+       child->perf_event_ctxp[ctxn] = NULL;
 
        mutex_init(&child->perf_event_mutex);
        INIT_LIST_HEAD(&child->perf_event_list);
 
-       if (likely(!parent->perf_event_ctxp))
+       if (likely(!parent->perf_event_ctxp[ctxn]))
                return 0;
 
        /*
         * If the parent's context is a clone, pin it so it won't get
         * swapped under us.
         */
-       parent_ctx = perf_pin_task_context(parent);
+       parent_ctx = perf_pin_task_context(parent, ctxn);
 
        /*
         * No need to check if parent_ctx != NULL here; since we saw
@@ -5634,20 +6162,20 @@ int perf_event_init_task(struct task_struct *child)
         * the list, not manipulating it:
         */
        list_for_each_entry(event, &parent_ctx->pinned_groups, group_entry) {
-               ret = inherit_task_group(event, parent, parent_ctx, child,
-                                        &inherited_all);
+               ret = inherit_task_group(event, parent, parent_ctx,
+                                        child, ctxn, &inherited_all);
                if (ret)
                        break;
        }
 
        list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) {
-               ret = inherit_task_group(event, parent, parent_ctx, child,
-                                        &inherited_all);
+               ret = inherit_task_group(event, parent, parent_ctx,
+                                        child, ctxn, &inherited_all);
                if (ret)
                        break;
        }
 
-       child_ctx = child->perf_event_ctxp;
+       child_ctx = child->perf_event_ctxp[ctxn];
 
        if (child_ctx && inherited_all) {
                /*
@@ -5676,63 +6204,98 @@ int perf_event_init_task(struct task_struct *child)
        return ret;
 }
 
+/*
+ * Initialize the perf_event context in task_struct
+ */
+int perf_event_init_task(struct task_struct *child)
+{
+       int ctxn, ret;
+
+       for_each_task_context_nr(ctxn) {
+               ret = perf_event_init_context(child, ctxn);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void __init perf_event_init_all_cpus(void)
 {
+       struct swevent_htable *swhash;
        int cpu;
-       struct perf_cpu_context *cpuctx;
 
        for_each_possible_cpu(cpu) {
-               cpuctx = &per_cpu(perf_cpu_context, cpu);
-               mutex_init(&cpuctx->hlist_mutex);
-               __perf_event_init_context(&cpuctx->ctx, NULL);
+               swhash = &per_cpu(swevent_htable, cpu);
+               mutex_init(&swhash->hlist_mutex);
+               INIT_LIST_HEAD(&per_cpu(rotation_list, cpu));
        }
 }
 
 static void __cpuinit perf_event_init_cpu(int cpu)
 {
-       struct perf_cpu_context *cpuctx;
-
-       cpuctx = &per_cpu(perf_cpu_context, cpu);
+       struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-       spin_lock(&perf_resource_lock);
-       cpuctx->max_pertask = perf_max_events - perf_reserved_percpu;
-       spin_unlock(&perf_resource_lock);
-
-       mutex_lock(&cpuctx->hlist_mutex);
-       if (cpuctx->hlist_refcount > 0) {
+       mutex_lock(&swhash->hlist_mutex);
+       if (swhash->hlist_refcount > 0) {
                struct swevent_hlist *hlist;
 
-               hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
-               WARN_ON_ONCE(!hlist);
-               rcu_assign_pointer(cpuctx->swevent_hlist, hlist);
+               hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu));
+               WARN_ON(!hlist);
+               rcu_assign_pointer(swhash->swevent_hlist, hlist);
        }
-       mutex_unlock(&cpuctx->hlist_mutex);
+       mutex_unlock(&swhash->hlist_mutex);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void __perf_event_exit_cpu(void *info)
+static void perf_pmu_rotate_stop(struct pmu *pmu)
 {
-       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-       struct perf_event_context *ctx = &cpuctx->ctx;
+       struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+       WARN_ON(!irqs_disabled());
+
+       list_del_init(&cpuctx->rotation_list);
+}
+
+static void __perf_event_exit_context(void *__info)
+{
+       struct perf_event_context *ctx = __info;
        struct perf_event *event, *tmp;
 
+       perf_pmu_rotate_stop(ctx->pmu);
+
        list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
                __perf_event_remove_from_context(event);
        list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
                __perf_event_remove_from_context(event);
 }
+
+static void perf_event_exit_cpu_context(int cpu)
+{
+       struct perf_event_context *ctx;
+       struct pmu *pmu;
+       int idx;
+
+       idx = srcu_read_lock(&pmus_srcu);
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
+
+               mutex_lock(&ctx->mutex);
+               smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
+               mutex_unlock(&ctx->mutex);
+       }
+       srcu_read_unlock(&pmus_srcu, idx);
+}
+
 static void perf_event_exit_cpu(int cpu)
 {
-       struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-       struct perf_event_context *ctx = &cpuctx->ctx;
+       struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-       mutex_lock(&cpuctx->hlist_mutex);
-       swevent_hlist_release(cpuctx);
-       mutex_unlock(&cpuctx->hlist_mutex);
+       mutex_lock(&swhash->hlist_mutex);
+       swevent_hlist_release(swhash);
+       mutex_unlock(&swhash->hlist_mutex);
 
-       mutex_lock(&ctx->mutex);
-       smp_call_function_single(cpu, __perf_event_exit_cpu, NULL, 1);
-       mutex_unlock(&ctx->mutex);
+       perf_event_exit_cpu_context(cpu);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
@@ -5743,15 +6306,15 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (long)hcpu;
 
-       switch (action) {
+       switch (action & ~CPU_TASKS_FROZEN) {
 
        case CPU_UP_PREPARE:
-       case CPU_UP_PREPARE_FROZEN:
+       case CPU_DOWN_FAILED:
                perf_event_init_cpu(cpu);
                break;
 
+       case CPU_UP_CANCELED:
        case CPU_DOWN_PREPARE:
-       case CPU_DOWN_PREPARE_FROZEN:
                perf_event_exit_cpu(cpu);
                break;
 
@@ -5762,118 +6325,13 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
        return NOTIFY_OK;
 }
 
-/*
- * This has to have a higher priority than migration_notifier in sched.c.
- */
-static struct notifier_block __cpuinitdata perf_cpu_nb = {
-       .notifier_call          = perf_cpu_notify,
-       .priority               = 20,
-};
-
 void __init perf_event_init(void)
 {
        perf_event_init_all_cpus();
-       perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE,
-                       (void *)(long)smp_processor_id());
-       perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
-                       (void *)(long)smp_processor_id());
-       register_cpu_notifier(&perf_cpu_nb);
-}
-
-static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
-                                       struct sysdev_class_attribute *attr,
-                                       char *buf)
-{
-       return sprintf(buf, "%d\n", perf_reserved_percpu);
-}
-
-static ssize_t
-perf_set_reserve_percpu(struct sysdev_class *class,
-                       struct sysdev_class_attribute *attr,
-                       const char *buf,
-                       size_t count)
-{
-       struct perf_cpu_context *cpuctx;
-       unsigned long val;
-       int err, cpu, mpt;
-
-       err = strict_strtoul(buf, 10, &val);
-       if (err)
-               return err;
-       if (val > perf_max_events)
-               return -EINVAL;
-
-       spin_lock(&perf_resource_lock);
-       perf_reserved_percpu = val;
-       for_each_online_cpu(cpu) {
-               cpuctx = &per_cpu(perf_cpu_context, cpu);
-               raw_spin_lock_irq(&cpuctx->ctx.lock);
-               mpt = min(perf_max_events - cpuctx->ctx.nr_events,
-                         perf_max_events - perf_reserved_percpu);
-               cpuctx->max_pertask = mpt;
-               raw_spin_unlock_irq(&cpuctx->ctx.lock);
-       }
-       spin_unlock(&perf_resource_lock);
-
-       return count;
-}
-
-static ssize_t perf_show_overcommit(struct sysdev_class *class,
-                                   struct sysdev_class_attribute *attr,
-                                   char *buf)
-{
-       return sprintf(buf, "%d\n", perf_overcommit);
-}
-
-static ssize_t
-perf_set_overcommit(struct sysdev_class *class,
-                   struct sysdev_class_attribute *attr,
-                   const char *buf, size_t count)
-{
-       unsigned long val;
-       int err;
-
-       err = strict_strtoul(buf, 10, &val);
-       if (err)
-               return err;
-       if (val > 1)
-               return -EINVAL;
-
-       spin_lock(&perf_resource_lock);
-       perf_overcommit = val;
-       spin_unlock(&perf_resource_lock);
-
-       return count;
-}
-
-static SYSDEV_CLASS_ATTR(
-                               reserve_percpu,
-                               0644,
-                               perf_show_reserve_percpu,
-                               perf_set_reserve_percpu
-                       );
-
-static SYSDEV_CLASS_ATTR(
-                               overcommit,
-                               0644,
-                               perf_show_overcommit,
-                               perf_set_overcommit
-                       );
-
-static struct attribute *perfclass_attrs[] = {
-       &attr_reserve_percpu.attr,
-       &attr_overcommit.attr,
-       NULL
-};
-
-static struct attribute_group perfclass_attr_group = {
-       .attrs                  = perfclass_attrs,
-       .name                   = "perf_events",
-};
-
-static int __init perf_event_sysfs_init(void)
-{
-       return sysfs_create_group(&cpu_sysdev_class.kset.kobj,
-                                 &perfclass_attr_group);
+       init_srcu_struct(&pmus_srcu);
+       perf_pmu_register(&perf_swevent);
+       perf_pmu_register(&perf_cpu_clock);
+       perf_pmu_register(&perf_task_clock);
+       perf_tp_register();
+       perf_cpu_notifier(perf_cpu_notify);
 }
-device_initcall(perf_event_sysfs_init);
index d55c6fb8d087a24a2d462886dfe1fc53bf9deced..39b65b69584f5b0f373e360d6ecc3118751840a9 100644 (file)
@@ -401,7 +401,7 @@ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
        struct task_struct *result = NULL;
        if (pid) {
                struct hlist_node *first;
-               first = rcu_dereference_check(pid->tasks[type].first,
+               first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]),
                                              rcu_read_lock_held() ||
                                              lockdep_tasklist_lock_is_held());
                if (first)
@@ -416,6 +416,7 @@ EXPORT_SYMBOL(pid_task);
  */
 struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
 {
+       rcu_lockdep_assert(rcu_read_lock_held());
        return pid_task(find_pid_ns(nr, ns), PIDTYPE_PID);
 }
 
index 996a4dec5f968406aae7ef9b79240768da1ffddb..a96b850ba08a6a47dc9c9bd624849c4fbfe99349 100644 (file)
@@ -110,6 +110,7 @@ static const struct file_operations pm_qos_power_fops = {
        .write = pm_qos_power_write,
        .open = pm_qos_power_open,
        .release = pm_qos_power_release,
+       .llseek = noop_llseek,
 };
 
 /* unlocked internal variant */
@@ -212,15 +213,17 @@ EXPORT_SYMBOL_GPL(pm_qos_request_active);
 
 /**
  * pm_qos_add_request - inserts new qos request into the list
- * @pm_qos_class: identifies which list of qos request to us
+ * @dep: pointer to a preallocated handle
+ * @pm_qos_class: identifies which list of qos request to use
  * @value: defines the qos request
  *
  * This function inserts a new entry in the pm_qos_class list of requested qos
  * performance characteristics.  It recomputes the aggregate QoS expectations
- * for the pm_qos_class of parameters, and returns the pm_qos_request list
- * element as a handle for use in updating and removal.  Call needs to save
- * this handle for later use.
+ * for the pm_qos_class of parameters and initializes the pm_qos_request_list
+ * handle.  Caller needs to save this handle for later use in updates and
+ * removal.
  */
+
 void pm_qos_add_request(struct pm_qos_request_list *dep,
                        int pm_qos_class, s32 value)
 {
@@ -348,7 +351,7 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
 
        pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
        if (pm_qos_class >= 0) {
-               struct pm_qos_request_list *req = kzalloc(GFP_KERNEL, sizeof(*req));
+               struct pm_qos_request_list *req = kzalloc(sizeof(*req), GFP_KERNEL);
                if (!req)
                        return -ENOMEM;
 
@@ -387,10 +390,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
        } else if (count == 11) { /* len('0x12345678/0') */
                if (copy_from_user(ascii_value, buf, 11))
                        return -EFAULT;
+               if (strlen(ascii_value) != 10)
+                       return -EINVAL;
                x = sscanf(ascii_value, "%x", &value);
                if (x != 1)
                        return -EINVAL;
-               pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
+               pr_debug("%s, %d, 0x%x\n", ascii_value, x, value);
        } else
                return -EINVAL;
 
index ca6066a6952e792421c8aff49b57afec5ae2415b..29bff6117abca747d31131424f58927e1a30558d 100644 (file)
@@ -86,6 +86,7 @@ config PM_SLEEP_SMP
        depends on SMP
        depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE
        depends on PM_SLEEP
+       select HOTPLUG
        select HOTPLUG_CPU
        default y
 
@@ -137,6 +138,8 @@ config SUSPEND_FREEZER
 config HIBERNATION
        bool "Hibernation (aka 'suspend to disk')"
        depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
+       select LZO_COMPRESS
+       select LZO_DECOMPRESS
        select SUSPEND_NVS if HAS_IOMEM
        ---help---
          Enable the suspend to disk (STD) functionality, which is usually
@@ -242,3 +245,17 @@ config PM_OPS
        bool
        depends on PM_SLEEP || PM_RUNTIME
        default y
+
+config PM_OPP
+       bool "Operating Performance Point (OPP) Layer library"
+       depends on PM
+       ---help---
+         SOCs have a standard set of tuples consisting of frequency and
+         voltage pairs that the device will support per voltage domain. This
+         is called Operating Performance Point or OPP. The actual definitions
+         of OPP varies over silicon within the same family of devices.
+
+         OPP layer organizes the data internally using device pointers
+         representing individual voltage domains and provides SOC
+         implementations a ready to use framework to manage OPPs.
+         For more information, read <file:Documentation/power/opp.txt>
index c77963938bca440a90423952d6d85cf4d66abd83..657272e91d0a0af648a892fd64ca2111a100dfb4 100644 (file)
@@ -29,6 +29,7 @@
 #include "power.h"
 
 
+static int nocompress = 0;
 static int noresume = 0;
 static char resume_file[256] = CONFIG_PM_STD_PARTITION;
 dev_t swsusp_resume_device;
@@ -338,7 +339,6 @@ int hibernation_snapshot(int platform_mode)
                goto Close;
 
        suspend_console();
-       hibernation_freeze_swap();
        saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
        error = dpm_suspend_start(PMSG_FREEZE);
        if (error)
@@ -639,6 +639,8 @@ int hibernate(void)
 
                if (hibernation_mode == HIBERNATION_PLATFORM)
                        flags |= SF_PLATFORM_MODE;
+               if (nocompress)
+                       flags |= SF_NOCOMPRESS_MODE;
                pr_debug("PM: writing image.\n");
                error = swsusp_write(flags);
                swsusp_free();
@@ -706,7 +708,7 @@ static int software_resume(void)
                goto Unlock;
        }
 
-       pr_debug("PM: Checking image partition %s\n", resume_file);
+       pr_debug("PM: Checking hibernation image partition %s\n", resume_file);
 
        /* Check if the device is there */
        swsusp_resume_device = name_to_dev_t(resume_file);
@@ -731,10 +733,10 @@ static int software_resume(void)
        }
 
  Check_image:
-       pr_debug("PM: Resume from partition %d:%d\n",
+       pr_debug("PM: Hibernation image partition %d:%d present\n",
                MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
 
-       pr_debug("PM: Checking hibernation image.\n");
+       pr_debug("PM: Looking for hibernation image.\n");
        error = swsusp_check();
        if (error)
                goto Unlock;
@@ -766,14 +768,14 @@ static int software_resume(void)
                goto Done;
        }
 
-       pr_debug("PM: Reading hibernation image.\n");
+       pr_debug("PM: Loading hibernation image.\n");
 
        error = swsusp_read(&flags);
        swsusp_close(FMODE_READ);
        if (!error)
                hibernation_restore(flags & SF_PLATFORM_MODE);
 
-       printk(KERN_ERR "PM: Restore failed, recovering.\n");
+       printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
        swsusp_free();
        thaw_processes();
  Done:
@@ -786,7 +788,7 @@ static int software_resume(void)
        /* For success case, the suspend path will release the lock */
  Unlock:
        mutex_unlock(&pm_mutex);
-       pr_debug("PM: Resume from disk failed.\n");
+       pr_debug("PM: Hibernation image not present or could not be loaded.\n");
        return error;
 close_finish:
        swsusp_close(FMODE_READ);
@@ -1005,6 +1007,15 @@ static int __init resume_offset_setup(char *str)
        return 1;
 }
 
+static int __init hibernate_setup(char *str)
+{
+       if (!strncmp(str, "noresume", 8))
+               noresume = 1;
+       else if (!strncmp(str, "nocompress", 10))
+               nocompress = 1;
+       return 1;
+}
+
 static int __init noresume_setup(char *str)
 {
        noresume = 1;
@@ -1014,3 +1025,4 @@ static int __init noresume_setup(char *str)
 __setup("noresume", noresume_setup);
 __setup("resume_offset=", resume_offset_setup);
 __setup("resume=", resume_setup);
+__setup("hibernate=", hibernate_setup);
index 62b0bc6e4983cfdec1a2b4feb0f34d2235781ad6..7b5db6a8561e9a945b75f08d82acfb401bc8cd4e 100644 (file)
@@ -237,18 +237,18 @@ static ssize_t wakeup_count_show(struct kobject *kobj,
                                struct kobj_attribute *attr,
                                char *buf)
 {
-       unsigned long val;
+       unsigned int val;
 
-       return pm_get_wakeup_count(&val) ? sprintf(buf, "%lu\n", val) : -EINTR;
+       return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
 }
 
 static ssize_t wakeup_count_store(struct kobject *kobj,
                                struct kobj_attribute *attr,
                                const char *buf, size_t n)
 {
-       unsigned long val;
+       unsigned int val;
 
-       if (sscanf(buf, "%lu", &val) == 1) {
+       if (sscanf(buf, "%u", &val) == 1) {
                if (pm_save_wakeup_count(val))
                        return n;
        }
@@ -281,12 +281,30 @@ pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
 }
 
 power_attr(pm_trace);
+
+static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr,
+                                      char *buf)
+{
+       return show_trace_dev_match(buf, PAGE_SIZE);
+}
+
+static ssize_t
+pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
+                        const char *buf, size_t n)
+{
+       return -EINVAL;
+}
+
+power_attr(pm_trace_dev_match);
+
 #endif /* CONFIG_PM_TRACE */
 
 static struct attribute * g[] = {
        &state_attr.attr,
 #ifdef CONFIG_PM_TRACE
        &pm_trace_attr.attr,
+       &pm_trace_dev_match_attr.attr,
 #endif
 #ifdef CONFIG_PM_SLEEP
        &pm_async_attr.attr,
@@ -308,7 +326,7 @@ EXPORT_SYMBOL_GPL(pm_wq);
 
 static int __init pm_start_workqueue(void)
 {
-       pm_wq = create_freezeable_workqueue("pm");
+       pm_wq = alloc_workqueue("pm", WQ_FREEZEABLE, 0);
 
        return pm_wq ? 0 : -ENOMEM;
 }
@@ -321,6 +339,7 @@ static int __init pm_init(void)
        int error = pm_start_workqueue();
        if (error)
                return error;
+       hibernate_image_size_init();
        power_kobj = kobject_create_and_add("power", NULL);
        if (!power_kobj)
                return -ENOMEM;
index 006270fe382d7f756e02082e4f5309258b1ca5e3..03634be55f62aabb407b8797d6a5a74ca6feef96 100644 (file)
@@ -14,6 +14,9 @@ struct swsusp_info {
 } __attribute__((aligned(PAGE_SIZE)));
 
 #ifdef CONFIG_HIBERNATION
+/* kernel/power/snapshot.c */
+extern void __init hibernate_image_size_init(void);
+
 #ifdef CONFIG_ARCH_HIBERNATION_HEADER
 /* Maximum size of architecture specific data in a hibernation header */
 #define MAX_ARCH_HEADER_SIZE   (sizeof(struct new_utsname) + 4)
@@ -49,7 +52,11 @@ static inline char *check_image_kernel(struct swsusp_info *info)
 extern int hibernation_snapshot(int platform_mode);
 extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
-#endif
+
+#else /* !CONFIG_HIBERNATION */
+
+static inline void hibernate_image_size_init(void) {}
+#endif /* !CONFIG_HIBERNATION */
 
 extern int pfn_is_nosave(unsigned long);
 
@@ -134,6 +141,7 @@ extern int swsusp_swap_in_use(void);
  * the image header.
  */
 #define SF_PLATFORM_MODE       1
+#define SF_NOCOMPRESS_MODE     2
 
 /* kernel/power/hibernate.c */
 extern int swsusp_check(void);
index e8b337006276e71e782876db74cb94a4bbcb41a8..d52359374e8501e8c1f4e8a88427468249509fb3 100644 (file)
@@ -24,7 +24,7 @@ static void do_poweroff(struct work_struct *dummy)
 
 static DECLARE_WORK(poweroff_work, do_poweroff);
 
-static void handle_poweroff(int key, struct tty_struct *tty)
+static void handle_poweroff(int key)
 {
        /* run sysrq poweroff on boot cpu */
        schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
index 028a99598f4986b6dfcfaf946af51952f071c346..e50b4c1b2a0f7f8943acb041b5d8ab202c40d5cd 100644 (file)
@@ -40,6 +40,7 @@ static int try_to_freeze_tasks(bool sig_only)
        struct timeval start, end;
        u64 elapsed_csecs64;
        unsigned int elapsed_csecs;
+       bool wakeup = false;
 
        do_gettimeofday(&start);
 
@@ -78,6 +79,11 @@ static int try_to_freeze_tasks(bool sig_only)
                if (!todo || time_after(jiffies, end_time))
                        break;
 
+               if (!pm_check_wakeup_events()) {
+                       wakeup = true;
+                       break;
+               }
+
                /*
                 * We need to retry, but first give the freezing tasks some
                 * time to enter the regrigerator.
@@ -97,8 +103,9 @@ static int try_to_freeze_tasks(bool sig_only)
                 * but it cleans up leftover PF_FREEZE requests.
                 */
                printk("\n");
-               printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
+               printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
                       "(%d tasks refusing to freeze, wq_busy=%d):\n",
+                      wakeup ? "aborted" : "failed",
                       elapsed_csecs / 100, elapsed_csecs % 100,
                       todo - wq_busy, wq_busy);
 
@@ -107,7 +114,7 @@ static int try_to_freeze_tasks(bool sig_only)
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
                        task_lock(p);
-                       if (freezing(p) && !freezer_should_skip(p))
+                       if (!wakeup && freezing(p) && !freezer_should_skip(p))
                                sched_show_task(p);
                        cancel_freezing(p);
                        task_unlock(p);
index 5e7edfb05e66cff0d2c99d5fc8fddfde03e372c3..ac7eb109f19635d11930a9cef03ed4cd352cc235 100644 (file)
@@ -46,7 +46,12 @@ static void swsusp_unset_page_forbidden(struct page *);
  * size will not exceed N bytes, but if that is impossible, it will
  * try to create the smallest image possible.
  */
-unsigned long image_size = 500 * 1024 * 1024;
+unsigned long image_size;
+
+void __init hibernate_image_size_init(void)
+{
+       image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
+}
 
 /* List of PBEs needed for restoring the pages that were allocated before
  * the suspend and included in the suspend image, but have also been
@@ -1086,7 +1091,6 @@ void swsusp_free(void)
        buffer = NULL;
        alloc_normal = 0;
        alloc_highmem = 0;
-       hibernation_thaw_swap();
 }
 
 /* Helper functions used for the shrinking of memory. */
@@ -1122,9 +1126,19 @@ static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask)
        return nr_alloc;
 }
 
-static unsigned long preallocate_image_memory(unsigned long nr_pages)
+static unsigned long preallocate_image_memory(unsigned long nr_pages,
+                                             unsigned long avail_normal)
 {
-       return preallocate_image_pages(nr_pages, GFP_IMAGE);
+       unsigned long alloc;
+
+       if (avail_normal <= alloc_normal)
+               return 0;
+
+       alloc = avail_normal - alloc_normal;
+       if (nr_pages < alloc)
+               alloc = nr_pages;
+
+       return preallocate_image_pages(alloc, GFP_IMAGE);
 }
 
 #ifdef CONFIG_HIGHMEM
@@ -1170,15 +1184,22 @@ static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
  */
 static void free_unnecessary_pages(void)
 {
-       unsigned long save_highmem, to_free_normal, to_free_highmem;
+       unsigned long save, to_free_normal, to_free_highmem;
 
-       to_free_normal = alloc_normal - count_data_pages();
-       save_highmem = count_highmem_pages();
-       if (alloc_highmem > save_highmem) {
-               to_free_highmem = alloc_highmem - save_highmem;
+       save = count_data_pages();
+       if (alloc_normal >= save) {
+               to_free_normal = alloc_normal - save;
+               save = 0;
+       } else {
+               to_free_normal = 0;
+               save -= alloc_normal;
+       }
+       save += count_highmem_pages();
+       if (alloc_highmem >= save) {
+               to_free_highmem = alloc_highmem - save;
        } else {
                to_free_highmem = 0;
-               to_free_normal -= save_highmem - alloc_highmem;
+               to_free_normal -= save - alloc_highmem;
        }
 
        memory_bm_position_reset(&copy_bm);
@@ -1259,7 +1280,7 @@ int hibernate_preallocate_memory(void)
 {
        struct zone *zone;
        unsigned long saveable, size, max_size, count, highmem, pages = 0;
-       unsigned long alloc, save_highmem, pages_highmem;
+       unsigned long alloc, save_highmem, pages_highmem, avail_normal;
        struct timeval start, stop;
        int error;
 
@@ -1296,26 +1317,38 @@ int hibernate_preallocate_memory(void)
                else
                        count += zone_page_state(zone, NR_FREE_PAGES);
        }
+       avail_normal = count;
        count += highmem;
        count -= totalreserve_pages;
 
        /* Compute the maximum number of saveable pages to leave in memory. */
        max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES;
+       /* Compute the desired number of image pages specified by image_size. */
        size = DIV_ROUND_UP(image_size, PAGE_SIZE);
        if (size > max_size)
                size = max_size;
        /*
-        * If the maximum is not less than the current number of saveable pages
-        * in memory, allocate page frames for the image and we're done.
+        * If the desired number of image pages is at least as large as the
+        * current number of saveable pages in memory, allocate page frames for
+        * the image and we're done.
         */
        if (size >= saveable) {
                pages = preallocate_image_highmem(save_highmem);
-               pages += preallocate_image_memory(saveable - pages);
+               pages += preallocate_image_memory(saveable - pages, avail_normal);
                goto out;
        }
 
        /* Estimate the minimum size of the image. */
        pages = minimum_image_size(saveable);
+       /*
+        * To avoid excessive pressure on the normal zone, leave room in it to
+        * accommodate an image of the minimum size (unless it's already too
+        * small, in which case don't preallocate pages from it at all).
+        */
+       if (avail_normal > pages)
+               avail_normal -= pages;
+       else
+               avail_normal = 0;
        if (size < pages)
                size = min_t(unsigned long, pages, max_size);
 
@@ -1336,16 +1369,34 @@ int hibernate_preallocate_memory(void)
         */
        pages_highmem = preallocate_image_highmem(highmem / 2);
        alloc = (count - max_size) - pages_highmem;
-       pages = preallocate_image_memory(alloc);
-       if (pages < alloc)
-               goto err_out;
-       size = max_size - size;
-       alloc = size;
-       size = preallocate_highmem_fraction(size, highmem, count);
-       pages_highmem += size;
-       alloc -= size;
-       pages += preallocate_image_memory(alloc);
-       pages += pages_highmem;
+       pages = preallocate_image_memory(alloc, avail_normal);
+       if (pages < alloc) {
+               /* We have exhausted non-highmem pages, try highmem. */
+               alloc -= pages;
+               pages += pages_highmem;
+               pages_highmem = preallocate_image_highmem(alloc);
+               if (pages_highmem < alloc)
+                       goto err_out;
+               pages += pages_highmem;
+               /*
+                * size is the desired number of saveable pages to leave in
+                * memory, so try to preallocate (all memory - size) pages.
+                */
+               alloc = (count - pages) - size;
+               pages += preallocate_image_highmem(alloc);
+       } else {
+               /*
+                * There are approximately max_size saveable pages at this point
+                * and we want to reduce this number down to size.
+                */
+               alloc = max_size - size;
+               size = preallocate_highmem_fraction(alloc, highmem, count);
+               pages_highmem += size;
+               alloc -= size;
+               size = preallocate_image_memory(alloc, avail_normal);
+               pages_highmem += preallocate_image_highmem(alloc - size);
+               pages += pages_highmem + size;
+       }
 
        /*
         * We only need as many page frames for the image as there are saveable
index 5d0059eed3e4e3ce0bc38ad072bd7b1430d9f712..916eaa79039968ff8412128858e9b8aeda951ac6 100644 (file)
 #include <linux/swapops.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/lzo.h>
+#include <linux/vmalloc.h>
 
 #include "power.h"
 
-#define SWSUSP_SIG     "S1SUSPEND"
+#define HIBERNATE_SIG  "LINHIB0001"
 
 /*
  *     The swap map is a data structure used for keeping track of each page
@@ -136,10 +138,10 @@ sector_t alloc_swapdev_block(int swap)
 {
        unsigned long offset;
 
-       offset = swp_offset(get_swap_for_hibernation(swap));
+       offset = swp_offset(get_swap_page_of_type(swap));
        if (offset) {
                if (swsusp_extents_insert(offset))
-                       swap_free_for_hibernation(swp_entry(swap, offset));
+                       swap_free(swp_entry(swap, offset));
                else
                        return swapdev_block(swap, offset);
        }
@@ -163,7 +165,7 @@ void free_all_swap_pages(int swap)
                ext = container_of(node, struct swsusp_extent, node);
                rb_erase(node, &swsusp_extents);
                for (offset = ext->start; offset <= ext->end; offset++)
-                       swap_free_for_hibernation(swp_entry(swap, offset));
+                       swap_free(swp_entry(swap, offset));
 
                kfree(ext);
        }
@@ -193,7 +195,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
        if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
            !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
                memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
-               memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
+               memcpy(swsusp_header->sig, HIBERNATE_SIG, 10);
                swsusp_header->image = handle->first_sector;
                swsusp_header->flags = flags;
                error = hib_bio_write_page(swsusp_resume_block,
@@ -357,6 +359,18 @@ static int swap_writer_finish(struct swap_map_handle *handle,
        return error;
 }
 
+/* We need to remember how much compressed data we need to read. */
+#define LZO_HEADER     sizeof(size_t)
+
+/* Number of pages/bytes we'll compress at one time. */
+#define LZO_UNC_PAGES  32
+#define LZO_UNC_SIZE   (LZO_UNC_PAGES * PAGE_SIZE)
+
+/* Number of pages/bytes we need for compressed data (worst case). */
+#define LZO_CMP_PAGES  DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
+                                    LZO_HEADER, PAGE_SIZE)
+#define LZO_CMP_SIZE   (LZO_CMP_PAGES * PAGE_SIZE)
+
 /**
  *     save_image - save the suspend image data
  */
@@ -404,6 +418,137 @@ static int save_image(struct swap_map_handle *handle,
        return ret;
 }
 
+
+/**
+ * save_image_lzo - Save the suspend image data compressed with LZO.
+ * @handle: Swap mam handle to use for saving the image.
+ * @snapshot: Image to read data from.
+ * @nr_to_write: Number of pages to save.
+ */
+static int save_image_lzo(struct swap_map_handle *handle,
+                          struct snapshot_handle *snapshot,
+                          unsigned int nr_to_write)
+{
+       unsigned int m;
+       int ret = 0;
+       int nr_pages;
+       int err2;
+       struct bio *bio;
+       struct timeval start;
+       struct timeval stop;
+       size_t off, unc_len, cmp_len;
+       unsigned char *unc, *cmp, *wrk, *page;
+
+       page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+       if (!page) {
+               printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+               return -ENOMEM;
+       }
+
+       wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
+       if (!wrk) {
+               printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
+               free_page((unsigned long)page);
+               return -ENOMEM;
+       }
+
+       unc = vmalloc(LZO_UNC_SIZE);
+       if (!unc) {
+               printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+               vfree(wrk);
+               free_page((unsigned long)page);
+               return -ENOMEM;
+       }
+
+       cmp = vmalloc(LZO_CMP_SIZE);
+       if (!cmp) {
+               printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+               vfree(unc);
+               vfree(wrk);
+               free_page((unsigned long)page);
+               return -ENOMEM;
+       }
+
+       printk(KERN_INFO
+               "PM: Compressing and saving image data (%u pages) ...     ",
+               nr_to_write);
+       m = nr_to_write / 100;
+       if (!m)
+               m = 1;
+       nr_pages = 0;
+       bio = NULL;
+       do_gettimeofday(&start);
+       for (;;) {
+               for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
+                       ret = snapshot_read_next(snapshot);
+                       if (ret < 0)
+                               goto out_finish;
+
+                       if (!ret)
+                               break;
+
+                       memcpy(unc + off, data_of(*snapshot), PAGE_SIZE);
+
+                       if (!(nr_pages % m))
+                               printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
+                       nr_pages++;
+               }
+
+               if (!off)
+                       break;
+
+               unc_len = off;
+               ret = lzo1x_1_compress(unc, unc_len,
+                                      cmp + LZO_HEADER, &cmp_len, wrk);
+               if (ret < 0) {
+                       printk(KERN_ERR "PM: LZO compression failed\n");
+                       break;
+               }
+
+               if (unlikely(!cmp_len ||
+                            cmp_len > lzo1x_worst_compress(unc_len))) {
+                       printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+                       ret = -1;
+                       break;
+               }
+
+               *(size_t *)cmp = cmp_len;
+
+               /*
+                * Given we are writing one page at a time to disk, we copy
+                * that much from the buffer, although the last bit will likely
+                * be smaller than full page. This is OK - we saved the length
+                * of the compressed data, so any garbage at the end will be
+                * discarded when we read it.
+                */
+               for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+                       memcpy(page, cmp + off, PAGE_SIZE);
+
+                       ret = swap_write_page(handle, page, &bio);
+                       if (ret)
+                               goto out_finish;
+               }
+       }
+
+out_finish:
+       err2 = hib_wait_on_bio_chain(&bio);
+       do_gettimeofday(&stop);
+       if (!ret)
+               ret = err2;
+       if (!ret)
+               printk(KERN_CONT "\b\b\b\bdone\n");
+       else
+               printk(KERN_CONT "\n");
+       swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+
+       vfree(cmp);
+       vfree(unc);
+       vfree(wrk);
+       free_page((unsigned long)page);
+
+       return ret;
+}
+
 /**
  *     enough_swap - Make sure we have enough swap to save the image.
  *
@@ -411,12 +556,16 @@ static int save_image(struct swap_map_handle *handle,
  *     space avaiable from the resume partition.
  */
 
-static int enough_swap(unsigned int nr_pages)
+static int enough_swap(unsigned int nr_pages, unsigned int flags)
 {
        unsigned int free_swap = count_swap_pages(root_swap, 1);
+       unsigned int required;
 
        pr_debug("PM: Free swap pages: %u\n", free_swap);
-       return free_swap > nr_pages + PAGES_FOR_IO;
+
+       required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ?
+               nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
+       return free_swap > required;
 }
 
 /**
@@ -443,7 +592,7 @@ int swsusp_write(unsigned int flags)
                printk(KERN_ERR "PM: Cannot get swap writer\n");
                return error;
        }
-       if (!enough_swap(pages)) {
+       if (!enough_swap(pages, flags)) {
                printk(KERN_ERR "PM: Not enough free swap\n");
                error = -ENOSPC;
                goto out_finish;
@@ -458,8 +607,11 @@ int swsusp_write(unsigned int flags)
        }
        header = (struct swsusp_info *)data_of(snapshot);
        error = swap_write_page(&handle, header, NULL);
-       if (!error)
-               error = save_image(&handle, &snapshot, pages - 1);
+       if (!error) {
+               error = (flags & SF_NOCOMPRESS_MODE) ?
+                       save_image(&handle, &snapshot, pages - 1) :
+                       save_image_lzo(&handle, &snapshot, pages - 1);
+       }
 out_finish:
        error = swap_writer_finish(&handle, flags, error);
        return error;
@@ -589,6 +741,127 @@ static int load_image(struct swap_map_handle *handle,
        return error;
 }
 
+/**
+ * load_image_lzo - Load compressed image data and decompress them with LZO.
+ * @handle: Swap map handle to use for loading data.
+ * @snapshot: Image to copy uncompressed data into.
+ * @nr_to_read: Number of pages to load.
+ */
+static int load_image_lzo(struct swap_map_handle *handle,
+                          struct snapshot_handle *snapshot,
+                          unsigned int nr_to_read)
+{
+       unsigned int m;
+       int error = 0;
+       struct timeval start;
+       struct timeval stop;
+       unsigned nr_pages;
+       size_t off, unc_len, cmp_len;
+       unsigned char *unc, *cmp, *page;
+
+       page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+       if (!page) {
+               printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+               return -ENOMEM;
+       }
+
+       unc = vmalloc(LZO_UNC_SIZE);
+       if (!unc) {
+               printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+               free_page((unsigned long)page);
+               return -ENOMEM;
+       }
+
+       cmp = vmalloc(LZO_CMP_SIZE);
+       if (!cmp) {
+               printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+               vfree(unc);
+               free_page((unsigned long)page);
+               return -ENOMEM;
+       }
+
+       printk(KERN_INFO
+               "PM: Loading and decompressing image data (%u pages) ...     ",
+               nr_to_read);
+       m = nr_to_read / 100;
+       if (!m)
+               m = 1;
+       nr_pages = 0;
+       do_gettimeofday(&start);
+
+       error = snapshot_write_next(snapshot);
+       if (error <= 0)
+               goto out_finish;
+
+       for (;;) {
+               error = swap_read_page(handle, page, NULL); /* sync */
+               if (error)
+                       break;
+
+               cmp_len = *(size_t *)page;
+               if (unlikely(!cmp_len ||
+                            cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
+                       printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+                       error = -1;
+                       break;
+               }
+
+               memcpy(cmp, page, PAGE_SIZE);
+               for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+                       error = swap_read_page(handle, page, NULL); /* sync */
+                       if (error)
+                               goto out_finish;
+
+                       memcpy(cmp + off, page, PAGE_SIZE);
+               }
+
+               unc_len = LZO_UNC_SIZE;
+               error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
+                                             unc, &unc_len);
+               if (error < 0) {
+                       printk(KERN_ERR "PM: LZO decompression failed\n");
+                       break;
+               }
+
+               if (unlikely(!unc_len ||
+                            unc_len > LZO_UNC_SIZE ||
+                            unc_len & (PAGE_SIZE - 1))) {
+                       printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
+                       error = -1;
+                       break;
+               }
+
+               for (off = 0; off < unc_len; off += PAGE_SIZE) {
+                       memcpy(data_of(*snapshot), unc + off, PAGE_SIZE);
+
+                       if (!(nr_pages % m))
+                               printk("\b\b\b\b%3d%%", nr_pages / m);
+                       nr_pages++;
+
+                       error = snapshot_write_next(snapshot);
+                       if (error <= 0)
+                               goto out_finish;
+               }
+       }
+
+out_finish:
+       do_gettimeofday(&stop);
+       if (!error) {
+               printk("\b\b\b\bdone\n");
+               snapshot_write_finalize(snapshot);
+               if (!snapshot_image_loaded(snapshot))
+                       error = -ENODATA;
+       } else
+               printk("\n");
+       swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+
+       vfree(cmp);
+       vfree(unc);
+       free_page((unsigned long)page);
+
+       return error;
+}
+
 /**
  *     swsusp_read - read the hibernation image.
  *     @flags_p: flags passed by the "frozen" kernel in the image header should
@@ -612,8 +885,11 @@ int swsusp_read(unsigned int *flags_p)
                goto end;
        if (!error)
                error = swap_read_page(&handle, header, NULL);
-       if (!error)
-               error = load_image(&handle, &snapshot, header->pages - 1);
+       if (!error) {
+               error = (*flags_p & SF_NOCOMPRESS_MODE) ?
+                       load_image(&handle, &snapshot, header->pages - 1) :
+                       load_image_lzo(&handle, &snapshot, header->pages - 1);
+       }
        swap_reader_finish(&handle);
 end:
        if (!error)
@@ -640,7 +916,7 @@ int swsusp_check(void)
                if (error)
                        goto put;
 
-               if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
+               if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) {
                        memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
                        /* Reset swap signature now */
                        error = hib_bio_write_page(swsusp_resume_block,
@@ -653,13 +929,13 @@ put:
                if (error)
                        blkdev_put(hib_resume_bdev, FMODE_READ);
                else
-                       pr_debug("PM: Signature found, resuming\n");
+                       pr_debug("PM: Image signature found, resuming\n");
        } else {
                error = PTR_ERR(hib_resume_bdev);
        }
 
        if (error)
-               pr_debug("PM: Error %d checking image file\n", error);
+               pr_debug("PM: Image not found (code %d)\n", error);
 
        return error;
 }
index 8fe465ac008aebdcdbb0e9db9fcd644d5b12c231..2531017795f63e7d9c60d1db976e2b227c98ffda 100644 (file)
@@ -85,7 +85,7 @@ EXPORT_SYMBOL(oops_in_progress);
  * provides serialisation for access to the entire console
  * driver system.
  */
-static DECLARE_MUTEX(console_sem);
+static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
@@ -556,7 +556,7 @@ static void zap_locks(void)
        /* If a crash is occurring, make sure we can't deadlock */
        spin_lock_init(&logbuf_lock);
        /* And make sure that we print immediately */
-       init_MUTEX(&console_sem);
+       sema_init(&console_sem, 1);
 }
 
 #if defined(CONFIG_PRINTK_TIME)
index b22a899934cc4fe1669f4599f50ce8f54ca46632..66f841b7fbd38fd0fcca92d62c4f70860b24bbb2 100644 (file)
@@ -555,6 +555,7 @@ static ssize_t write_profile(struct file *file, const char __user *buf,
 static const struct file_operations proc_profile_operations = {
        .read           = read_profile,
        .write          = write_profile,
+       .llseek         = default_llseek,
 };
 
 #ifdef CONFIG_SMP
index 4d169835fb362dcd6eb52a916a0d8e85e48c8fb8..a23a57a976d1a46f69cb2c32ecc38dd78e5e8b08 100644 (file)
@@ -73,12 +73,14 @@ int debug_lockdep_rcu_enabled(void)
 EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
 
 /**
- * rcu_read_lock_bh_held - might we be in RCU-bh read-side critical section?
+ * rcu_read_lock_bh_held() - might we be in RCU-bh read-side critical section?
  *
  * Check for bottom half being disabled, which covers both the
  * CONFIG_PROVE_RCU and not cases.  Note that if someone uses
  * rcu_read_lock_bh(), but then later enables BH, lockdep (if enabled)
- * will show the situation.
+ * will show the situation.  This is useful for debug checks in functions
+ * that require that they be called within an RCU read-side critical
+ * section.
  *
  * Check debug_lockdep_rcu_enabled() to prevent false positives during boot.
  */
@@ -86,7 +88,7 @@ int rcu_read_lock_bh_held(void)
 {
        if (!debug_lockdep_rcu_enabled())
                return 1;
-       return in_softirq();
+       return in_softirq() || irqs_disabled();
 }
 EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
 
index 196ec02f8be0c1ad884b7d69599005a6fc3a4429..d806735342acb10bc3e3ae787e62ade34f1d5955 100644 (file)
@@ -59,6 +59,14 @@ int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+/* Forward declarations for rcutiny_plugin.h. */
+static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp);
+static void __call_rcu(struct rcu_head *head,
+                      void (*func)(struct rcu_head *rcu),
+                      struct rcu_ctrlblk *rcp);
+
+#include "rcutiny_plugin.h"
+
 #ifdef CONFIG_NO_HZ
 
 static long rcu_dynticks_nesting = 1;
@@ -140,6 +148,7 @@ void rcu_check_callbacks(int cpu, int user)
                rcu_sched_qs(cpu);
        else if (!in_softirq())
                rcu_bh_qs(cpu);
+       rcu_preempt_check_callbacks();
 }
 
 /*
@@ -162,6 +171,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
        *rcp->donetail = NULL;
        if (rcp->curtail == rcp->donetail)
                rcp->curtail = &rcp->rcucblist;
+       rcu_preempt_remove_callbacks(rcp);
        rcp->donetail = &rcp->rcucblist;
        local_irq_restore(flags);
 
@@ -182,6 +192,7 @@ static void rcu_process_callbacks(struct softirq_action *unused)
 {
        __rcu_process_callbacks(&rcu_sched_ctrlblk);
        __rcu_process_callbacks(&rcu_bh_ctrlblk);
+       rcu_preempt_process_callbacks();
 }
 
 /*
@@ -223,15 +234,15 @@ static void __call_rcu(struct rcu_head *head,
 }
 
 /*
- * Post an RCU callback to be invoked after the end of an RCU grace
+ * Post an RCU callback to be invoked after the end of an RCU-sched grace
  * period.  But since we have but one CPU, that would be after any
  * quiescent state.
  */
-void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
        __call_rcu(head, func, &rcu_sched_ctrlblk);
 }
-EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_sched);
 
 /*
  * Post an RCU bottom-half callback to be invoked after any subsequent
@@ -243,20 +254,6 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 }
 EXPORT_SYMBOL_GPL(call_rcu_bh);
 
-void rcu_barrier(void)
-{
-       struct rcu_synchronize rcu;
-
-       init_rcu_head_on_stack(&rcu.head);
-       init_completion(&rcu.completion);
-       /* Will wake me after RCU finished. */
-       call_rcu(&rcu.head, wakeme_after_rcu);
-       /* Wait for it. */
-       wait_for_completion(&rcu.completion);
-       destroy_rcu_head_on_stack(&rcu.head);
-}
-EXPORT_SYMBOL_GPL(rcu_barrier);
-
 void rcu_barrier_bh(void)
 {
        struct rcu_synchronize rcu;
@@ -289,5 +286,3 @@ void __init rcu_init(void)
 {
        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 }
-
-#include "rcutiny_plugin.h"
index d223a92bc7427ffd098f8c49d524974eb12902fe..6ceca4f745ffa1f4535c69467ea59704e2ddbe97 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Read-Copy Update mechanism for mutual exclusion (tree-based version)
+ * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition
  * Internal non-public definitions that provide either classic
- * or preemptable semantics.
+ * or preemptible semantics.
  *
  * 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * Copyright IBM Corporation, 2009
+ * Copyright (c) 2010 Linaro
  *
  * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
  */
 
+#ifdef CONFIG_TINY_PREEMPT_RCU
+
+#include <linux/delay.h>
+
+/* Global control variables for preemptible RCU. */
+struct rcu_preempt_ctrlblk {
+       struct rcu_ctrlblk rcb; /* curtail: ->next ptr of last CB for GP. */
+       struct rcu_head **nexttail;
+                               /* Tasks blocked in a preemptible RCU */
+                               /*  read-side critical section while an */
+                               /*  preemptible-RCU grace period is in */
+                               /*  progress must wait for a later grace */
+                               /*  period.  This pointer points to the */
+                               /*  ->next pointer of the last task that */
+                               /*  must wait for a later grace period, or */
+                               /*  to &->rcb.rcucblist if there is no */
+                               /*  such task. */
+       struct list_head blkd_tasks;
+                               /* Tasks blocked in RCU read-side critical */
+                               /*  section.  Tasks are placed at the head */
+                               /*  of this list and age towards the tail. */
+       struct list_head *gp_tasks;
+                               /* Pointer to the first task blocking the */
+                               /*  current grace period, or NULL if there */
+                               /*  is not such task. */
+       struct list_head *exp_tasks;
+                               /* Pointer to first task blocking the */
+                               /*  current expedited grace period, or NULL */
+                               /*  if there is no such task.  If there */
+                               /*  is no current expedited grace period, */
+                               /*  then there cannot be any such task. */
+       u8 gpnum;               /* Current grace period. */
+       u8 gpcpu;               /* Last grace period blocked by the CPU. */
+       u8 completed;           /* Last grace period completed. */
+                               /*  If all three are equal, RCU is idle. */
+};
+
+static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
+       .rcb.donetail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+       .rcb.curtail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+       .nexttail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+       .blkd_tasks = LIST_HEAD_INIT(rcu_preempt_ctrlblk.blkd_tasks),
+};
+
+static int rcu_preempted_readers_exp(void);
+static void rcu_report_exp_done(void);
+
+/*
+ * Return true if the CPU has not yet responded to the current grace period.
+ */
+static int rcu_cpu_blocking_cur_gp(void)
+{
+       return rcu_preempt_ctrlblk.gpcpu != rcu_preempt_ctrlblk.gpnum;
+}
+
+/*
+ * Check for a running RCU reader.  Because there is only one CPU,
+ * there can be but one running RCU reader at a time.  ;-)
+ */
+static int rcu_preempt_running_reader(void)
+{
+       return current->rcu_read_lock_nesting;
+}
+
+/*
+ * Check for preempted RCU readers blocking any grace period.
+ * If the caller needs a reliable answer, it must disable hard irqs.
+ */
+static int rcu_preempt_blocked_readers_any(void)
+{
+       return !list_empty(&rcu_preempt_ctrlblk.blkd_tasks);
+}
+
+/*
+ * Check for preempted RCU readers blocking the current grace period.
+ * If the caller needs a reliable answer, it must disable hard irqs.
+ */
+static int rcu_preempt_blocked_readers_cgp(void)
+{
+       return rcu_preempt_ctrlblk.gp_tasks != NULL;
+}
+
+/*
+ * Return true if another preemptible-RCU grace period is needed.
+ */
+static int rcu_preempt_needs_another_gp(void)
+{
+       return *rcu_preempt_ctrlblk.rcb.curtail != NULL;
+}
+
+/*
+ * Return true if a preemptible-RCU grace period is in progress.
+ * The caller must disable hardirqs.
+ */
+static int rcu_preempt_gp_in_progress(void)
+{
+       return rcu_preempt_ctrlblk.completed != rcu_preempt_ctrlblk.gpnum;
+}
+
+/*
+ * Record a preemptible-RCU quiescent state for the specified CPU.  Note
+ * that this just means that the task currently running on the CPU is
+ * in a quiescent state.  There might be any number of tasks blocked
+ * while in an RCU read-side critical section.
+ *
+ * Unlike the other rcu_*_qs() functions, callers to this function
+ * must disable irqs in order to protect the assignment to
+ * ->rcu_read_unlock_special.
+ *
+ * Because this is a single-CPU implementation, the only way a grace
+ * period can end is if the CPU is in a quiescent state.  The reason is
+ * that a blocked preemptible-RCU reader can exit its critical section
+ * only if the CPU is running it at the time.  Therefore, when the
+ * last task blocking the current grace period exits its RCU read-side
+ * critical section, neither the CPU nor blocked tasks will be stopping
+ * the current grace period.  (In contrast, SMP implementations
+ * might have CPUs running in RCU read-side critical sections that
+ * block later grace periods -- but this is not possible given only
+ * one CPU.)
+ */
+static void rcu_preempt_cpu_qs(void)
+{
+       /* Record both CPU and task as having responded to current GP. */
+       rcu_preempt_ctrlblk.gpcpu = rcu_preempt_ctrlblk.gpnum;
+       current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
+
+       /*
+        * If there is no GP, or if blocked readers are still blocking GP,
+        * then there is nothing more to do.
+        */
+       if (!rcu_preempt_gp_in_progress() || rcu_preempt_blocked_readers_cgp())
+               return;
+
+       /* Advance callbacks. */
+       rcu_preempt_ctrlblk.completed = rcu_preempt_ctrlblk.gpnum;
+       rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.rcb.curtail;
+       rcu_preempt_ctrlblk.rcb.curtail = rcu_preempt_ctrlblk.nexttail;
+
+       /* If there are no blocked readers, next GP is done instantly. */
+       if (!rcu_preempt_blocked_readers_any())
+               rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.nexttail;
+
+       /* If there are done callbacks, make RCU_SOFTIRQ process them. */
+       if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
+               raise_softirq(RCU_SOFTIRQ);
+}
+
+/*
+ * Start a new RCU grace period if warranted.  Hard irqs must be disabled.
+ */
+static void rcu_preempt_start_gp(void)
+{
+       if (!rcu_preempt_gp_in_progress() && rcu_preempt_needs_another_gp()) {
+
+               /* Official start of GP. */
+               rcu_preempt_ctrlblk.gpnum++;
+
+               /* Any blocked RCU readers block new GP. */
+               if (rcu_preempt_blocked_readers_any())
+                       rcu_preempt_ctrlblk.gp_tasks =
+                               rcu_preempt_ctrlblk.blkd_tasks.next;
+
+               /* If there is no running reader, CPU is done with GP. */
+               if (!rcu_preempt_running_reader())
+                       rcu_preempt_cpu_qs();
+       }
+}
+
+/*
+ * We have entered the scheduler, and the current task might soon be
+ * context-switched away from.  If this task is in an RCU read-side
+ * critical section, we will no longer be able to rely on the CPU to
+ * record that fact, so we enqueue the task on the blkd_tasks list.
+ * If the task started after the current grace period began, as recorded
+ * by ->gpcpu, we enqueue at the beginning of the list.  Otherwise
+ * before the element referenced by ->gp_tasks (or at the tail if
+ * ->gp_tasks is NULL) and point ->gp_tasks at the newly added element.
+ * The task will dequeue itself when it exits the outermost enclosing
+ * RCU read-side critical section.  Therefore, the current grace period
+ * cannot be permitted to complete until the ->gp_tasks pointer becomes
+ * NULL.
+ *
+ * Caller must disable preemption.
+ */
+void rcu_preempt_note_context_switch(void)
+{
+       struct task_struct *t = current;
+       unsigned long flags;
+
+       local_irq_save(flags); /* must exclude scheduler_tick(). */
+       if (rcu_preempt_running_reader() &&
+           (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
+
+               /* Possibly blocking in an RCU read-side critical section. */
+               t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
+
+               /*
+                * If this CPU has already checked in, then this task
+                * will hold up the next grace period rather than the
+                * current grace period.  Queue the task accordingly.
+                * If the task is queued for the current grace period
+                * (i.e., this CPU has not yet passed through a quiescent
+                * state for the current grace period), then as long
+                * as that task remains queued, the current grace period
+                * cannot end.
+                */
+               list_add(&t->rcu_node_entry, &rcu_preempt_ctrlblk.blkd_tasks);
+               if (rcu_cpu_blocking_cur_gp())
+                       rcu_preempt_ctrlblk.gp_tasks = &t->rcu_node_entry;
+       }
+
+       /*
+        * Either we were not in an RCU read-side critical section to
+        * begin with, or we have now recorded that critical section
+        * globally.  Either way, we can now note a quiescent state
+        * for this CPU.  Again, if we were in an RCU read-side critical
+        * section, and if that critical section was blocking the current
+        * grace period, then the fact that the task has been enqueued
+        * means that current grace period continues to be blocked.
+        */
+       rcu_preempt_cpu_qs();
+       local_irq_restore(flags);
+}
+
+/*
+ * Tiny-preemptible RCU implementation for rcu_read_lock().
+ * Just increment ->rcu_read_lock_nesting, shared state will be updated
+ * if we block.
+ */
+void __rcu_read_lock(void)
+{
+       current->rcu_read_lock_nesting++;
+       barrier();  /* needed if we ever invoke rcu_read_lock in rcutiny.c */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_lock);
+
+/*
+ * Handle special cases during rcu_read_unlock(), such as needing to
+ * notify RCU core processing or task having blocked during the RCU
+ * read-side critical section.
+ */
+static void rcu_read_unlock_special(struct task_struct *t)
+{
+       int empty;
+       int empty_exp;
+       unsigned long flags;
+       struct list_head *np;
+       int special;
+
+       /*
+        * NMI handlers cannot block and cannot safely manipulate state.
+        * They therefore cannot possibly be special, so just leave.
+        */
+       if (in_nmi())
+               return;
+
+       local_irq_save(flags);
+
+       /*
+        * If RCU core is waiting for this CPU to exit critical section,
+        * let it know that we have done so.
+        */
+       special = t->rcu_read_unlock_special;
+       if (special & RCU_READ_UNLOCK_NEED_QS)
+               rcu_preempt_cpu_qs();
+
+       /* Hardware IRQ handlers cannot block. */
+       if (in_irq()) {
+               local_irq_restore(flags);
+               return;
+       }
+
+       /* Clean up if blocked during RCU read-side critical section. */
+       if (special & RCU_READ_UNLOCK_BLOCKED) {
+               t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_BLOCKED;
+
+               /*
+                * Remove this task from the ->blkd_tasks list and adjust
+                * any pointers that might have been referencing it.
+                */
+               empty = !rcu_preempt_blocked_readers_cgp();
+               empty_exp = rcu_preempt_ctrlblk.exp_tasks == NULL;
+               np = t->rcu_node_entry.next;
+               if (np == &rcu_preempt_ctrlblk.blkd_tasks)
+                       np = NULL;
+               list_del(&t->rcu_node_entry);
+               if (&t->rcu_node_entry == rcu_preempt_ctrlblk.gp_tasks)
+                       rcu_preempt_ctrlblk.gp_tasks = np;
+               if (&t->rcu_node_entry == rcu_preempt_ctrlblk.exp_tasks)
+                       rcu_preempt_ctrlblk.exp_tasks = np;
+               INIT_LIST_HEAD(&t->rcu_node_entry);
+
+               /*
+                * If this was the last task on the current list, and if
+                * we aren't waiting on the CPU, report the quiescent state
+                * and start a new grace period if needed.
+                */
+               if (!empty && !rcu_preempt_blocked_readers_cgp()) {
+                       rcu_preempt_cpu_qs();
+                       rcu_preempt_start_gp();
+               }
+
+               /*
+                * If this was the last task on the expedited lists,
+                * then we need wake up the waiting task.
+                */
+               if (!empty_exp && rcu_preempt_ctrlblk.exp_tasks == NULL)
+                       rcu_report_exp_done();
+       }
+       local_irq_restore(flags);
+}
+
+/*
+ * Tiny-preemptible RCU implementation for rcu_read_unlock().
+ * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
+ * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
+ * invoke rcu_read_unlock_special() to clean up after a context switch
+ * in an RCU read-side critical section and other special cases.
+ */
+void __rcu_read_unlock(void)
+{
+       struct task_struct *t = current;
+
+       barrier();  /* needed if we ever invoke rcu_read_unlock in rcutiny.c */
+       --t->rcu_read_lock_nesting;
+       barrier();  /* decrement before load of ->rcu_read_unlock_special */
+       if (t->rcu_read_lock_nesting == 0 &&
+           unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
+               rcu_read_unlock_special(t);
+#ifdef CONFIG_PROVE_LOCKING
+       WARN_ON_ONCE(t->rcu_read_lock_nesting < 0);
+#endif /* #ifdef CONFIG_PROVE_LOCKING */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_unlock);
+
+/*
+ * Check for a quiescent state from the current CPU.  When a task blocks,
+ * the task is recorded in the rcu_preempt_ctrlblk structure, which is
+ * checked elsewhere.  This is called from the scheduling-clock interrupt.
+ *
+ * Caller must disable hard irqs.
+ */
+static void rcu_preempt_check_callbacks(void)
+{
+       struct task_struct *t = current;
+
+       if (rcu_preempt_gp_in_progress() &&
+           (!rcu_preempt_running_reader() ||
+            !rcu_cpu_blocking_cur_gp()))
+               rcu_preempt_cpu_qs();
+       if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
+           rcu_preempt_ctrlblk.rcb.donetail)
+               raise_softirq(RCU_SOFTIRQ);
+       if (rcu_preempt_gp_in_progress() &&
+           rcu_cpu_blocking_cur_gp() &&
+           rcu_preempt_running_reader())
+               t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
+}
+
+/*
+ * TINY_PREEMPT_RCU has an extra callback-list tail pointer to
+ * update, so this is invoked from __rcu_process_callbacks() to
+ * handle that case.  Of course, it is invoked for all flavors of
+ * RCU, but RCU callbacks can appear only on one of the lists, and
+ * neither ->nexttail nor ->donetail can possibly be NULL, so there
+ * is no need for an explicit check.
+ */
+static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
+{
+       if (rcu_preempt_ctrlblk.nexttail == rcp->donetail)
+               rcu_preempt_ctrlblk.nexttail = &rcp->rcucblist;
+}
+
+/*
+ * Process callbacks for preemptible RCU.
+ */
+static void rcu_preempt_process_callbacks(void)
+{
+       __rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
+}
+
+/*
+ * Queue a preemptible -RCU callback for invocation after a grace period.
+ */
+void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+{
+       unsigned long flags;
+
+       debug_rcu_head_queue(head);
+       head->func = func;
+       head->next = NULL;
+
+       local_irq_save(flags);
+       *rcu_preempt_ctrlblk.nexttail = head;
+       rcu_preempt_ctrlblk.nexttail = &head->next;
+       rcu_preempt_start_gp();  /* checks to see if GP needed. */
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(call_rcu);
+
+void rcu_barrier(void)
+{
+       struct rcu_synchronize rcu;
+
+       init_rcu_head_on_stack(&rcu.head);
+       init_completion(&rcu.completion);
+       /* Will wake me after RCU finished. */
+       call_rcu(&rcu.head, wakeme_after_rcu);
+       /* Wait for it. */
+       wait_for_completion(&rcu.completion);
+       destroy_rcu_head_on_stack(&rcu.head);
+}
+EXPORT_SYMBOL_GPL(rcu_barrier);
+
+/*
+ * synchronize_rcu - wait until a grace period has elapsed.
+ *
+ * Control will return to the caller some time after a full grace
+ * period has elapsed, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
+ */
+void synchronize_rcu(void)
+{
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       if (!rcu_scheduler_active)
+               return;
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+       WARN_ON_ONCE(rcu_preempt_running_reader());
+       if (!rcu_preempt_blocked_readers_any())
+               return;
+
+       /* Once we get past the fastpath checks, same code as rcu_barrier(). */
+       rcu_barrier();
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu);
+
+static DECLARE_WAIT_QUEUE_HEAD(sync_rcu_preempt_exp_wq);
+static unsigned long sync_rcu_preempt_exp_count;
+static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex);
+
+/*
+ * Return non-zero if there are any tasks in RCU read-side critical
+ * sections blocking the current preemptible-RCU expedited grace period.
+ * If there is no preemptible-RCU expedited grace period currently in
+ * progress, returns zero unconditionally.
+ */
+static int rcu_preempted_readers_exp(void)
+{
+       return rcu_preempt_ctrlblk.exp_tasks != NULL;
+}
+
+/*
+ * Report the exit from RCU read-side critical section for the last task
+ * that queued itself during or before the current expedited preemptible-RCU
+ * grace period.
+ */
+static void rcu_report_exp_done(void)
+{
+       wake_up(&sync_rcu_preempt_exp_wq);
+}
+
+/*
+ * Wait for an rcu-preempt grace period, but expedite it.  The basic idea
+ * is to rely in the fact that there is but one CPU, and that it is
+ * illegal for a task to invoke synchronize_rcu_expedited() while in a
+ * preemptible-RCU read-side critical section.  Therefore, any such
+ * critical sections must correspond to blocked tasks, which must therefore
+ * be on the ->blkd_tasks list.  So just record the current head of the
+ * list in the ->exp_tasks pointer, and wait for all tasks including and
+ * after the task pointed to by ->exp_tasks to drain.
+ */
+void synchronize_rcu_expedited(void)
+{
+       unsigned long flags;
+       struct rcu_preempt_ctrlblk *rpcp = &rcu_preempt_ctrlblk;
+       unsigned long snap;
+
+       barrier(); /* ensure prior action seen before grace period. */
+
+       WARN_ON_ONCE(rcu_preempt_running_reader());
+
+       /*
+        * Acquire lock so that there is only one preemptible RCU grace
+        * period in flight.  Of course, if someone does the expedited
+        * grace period for us while we are acquiring the lock, just leave.
+        */
+       snap = sync_rcu_preempt_exp_count + 1;
+       mutex_lock(&sync_rcu_preempt_exp_mutex);
+       if (ULONG_CMP_LT(snap, sync_rcu_preempt_exp_count))
+               goto unlock_mb_ret; /* Others did our work for us. */
+
+       local_irq_save(flags);
+
+       /*
+        * All RCU readers have to already be on blkd_tasks because
+        * we cannot legally be executing in an RCU read-side critical
+        * section.
+        */
+
+       /* Snapshot current head of ->blkd_tasks list. */
+       rpcp->exp_tasks = rpcp->blkd_tasks.next;
+       if (rpcp->exp_tasks == &rpcp->blkd_tasks)
+               rpcp->exp_tasks = NULL;
+       local_irq_restore(flags);
+
+       /* Wait for tail of ->blkd_tasks list to drain. */
+       if (rcu_preempted_readers_exp())
+               wait_event(sync_rcu_preempt_exp_wq,
+                          !rcu_preempted_readers_exp());
+
+       /* Clean up and exit. */
+       barrier(); /* ensure expedited GP seen before counter increment. */
+       sync_rcu_preempt_exp_count++;
+unlock_mb_ret:
+       mutex_unlock(&sync_rcu_preempt_exp_mutex);
+       barrier(); /* ensure subsequent action seen after grace period. */
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
+
+/*
+ * Does preemptible RCU need the CPU to stay out of dynticks mode?
+ */
+int rcu_preempt_needs_cpu(void)
+{
+       if (!rcu_preempt_running_reader())
+               rcu_preempt_cpu_qs();
+       return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
+}
+
+/*
+ * Check for a task exiting while in a preemptible -RCU read-side
+ * critical section, clean up if so.  No need to issue warnings,
+ * as debug_check_no_locks_held() already does this if lockdep
+ * is enabled.
+ */
+void exit_rcu(void)
+{
+       struct task_struct *t = current;
+
+       if (t->rcu_read_lock_nesting == 0)
+               return;
+       t->rcu_read_lock_nesting = 1;
+       rcu_read_unlock();
+}
+
+#else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to check.
+ */
+static void rcu_preempt_check_callbacks(void)
+{
+}
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to remove.
+ */
+static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
+{
+}
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to process.
+ */
+static void rcu_preempt_process_callbacks(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
 #include <linux/kernel_stat.h>
index 2e2726d790b98eff18d88d71dbeba8caf8ec7f7a..9d8e8fb2515f4e4801c214841a7f8c95b8b45ffe 100644 (file)
@@ -120,7 +120,7 @@ struct rcu_torture {
 };
 
 static LIST_HEAD(rcu_torture_freelist);
-static struct rcu_torture *rcu_torture_current;
+static struct rcu_torture __rcu *rcu_torture_current;
 static long rcu_torture_current_version;
 static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
 static DEFINE_SPINLOCK(rcu_torture_lock);
@@ -153,8 +153,10 @@ int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
 #define FULLSTOP_SHUTDOWN 1    /* System shutdown with rcutorture running. */
 #define FULLSTOP_RMMOD    2    /* Normal rmmod of rcutorture. */
 static int fullstop = FULLSTOP_RMMOD;
-DEFINE_MUTEX(fullstop_mutex);  /* Protect fullstop transitions and spawning */
-                               /*  of kthreads. */
+/*
+ * Protect fullstop transitions and spawning of kthreads.
+ */
+static DEFINE_MUTEX(fullstop_mutex);
 
 /*
  * Detect and respond to a system shutdown.
@@ -303,6 +305,10 @@ static void rcu_read_delay(struct rcu_random_state *rrsp)
                mdelay(longdelay_ms);
        if (!(rcu_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
                udelay(shortdelay_us);
+#ifdef CONFIG_PREEMPT
+       if (!preempt_count() && !(rcu_random(rrsp) % (nrealreaders * 20000)))
+               preempt_schedule();  /* No QS if preempt_disable() in effect */
+#endif
 }
 
 static void rcu_torture_read_unlock(int idx) __releases(RCU)
@@ -536,6 +542,8 @@ static void srcu_read_delay(struct rcu_random_state *rrsp)
        delay = rcu_random(rrsp) % (nrealreaders * 2 * longdelay * uspertick);
        if (!delay)
                schedule_timeout_interruptible(longdelay);
+       else
+               rcu_read_delay(rrsp);
 }
 
 static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
@@ -731,7 +739,8 @@ rcu_torture_writer(void *arg)
                        continue;
                rp->rtort_pipe_count = 0;
                udelay(rcu_random(&rand) & 0x3ff);
-               old_rp = rcu_torture_current;
+               old_rp = rcu_dereference_check(rcu_torture_current,
+                                              current == writer_task);
                rp->rtort_mbtest = 1;
                rcu_assign_pointer(rcu_torture_current, rp);
                smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
index d5bc43976c5ad202fa41be0456797d40bdde0c0d..ccdc04c479815addc8dbacea69643174a4636670 100644 (file)
@@ -143,6 +143,11 @@ module_param(blimit, int, 0);
 module_param(qhimark, int, 0);
 module_param(qlowmark, int, 0);
 
+#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
+int rcu_cpu_stall_suppress __read_mostly = RCU_CPU_STALL_SUPPRESS_INIT;
+module_param(rcu_cpu_stall_suppress, int, 0644);
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+
 static void force_quiescent_state(struct rcu_state *rsp, int relaxed);
 static int rcu_pending(int cpu);
 
@@ -450,7 +455,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
 
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
-int rcu_cpu_stall_panicking __read_mostly;
+int rcu_cpu_stall_suppress __read_mostly;
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
@@ -482,8 +487,11 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        rcu_print_task_stall(rnp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
-       /* OK, time to rat on our buddy... */
-
+       /*
+        * OK, time to rat on our buddy...
+        * See Documentation/RCU/stallwarn.txt for info on how to debug
+        * RCU CPU stall warnings.
+        */
        printk(KERN_ERR "INFO: %s detected stalls on CPUs/tasks: {",
               rsp->name);
        rcu_for_each_leaf_node(rsp, rnp) {
@@ -512,6 +520,11 @@ static void print_cpu_stall(struct rcu_state *rsp)
        unsigned long flags;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
+       /*
+        * OK, time to rat on ourselves...
+        * See Documentation/RCU/stallwarn.txt for info on how to debug
+        * RCU CPU stall warnings.
+        */
        printk(KERN_ERR "INFO: %s detected stall on CPU %d (t=%lu jiffies)\n",
               rsp->name, smp_processor_id(), jiffies - rsp->gp_start);
        trigger_all_cpu_backtrace();
@@ -530,11 +543,11 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
        long delta;
        struct rcu_node *rnp;
 
-       if (rcu_cpu_stall_panicking)
+       if (rcu_cpu_stall_suppress)
                return;
-       delta = jiffies - rsp->jiffies_stall;
+       delta = jiffies - ACCESS_ONCE(rsp->jiffies_stall);
        rnp = rdp->mynode;
-       if ((rnp->qsmask & rdp->grpmask) && delta >= 0) {
+       if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && delta >= 0) {
 
                /* We haven't checked in, so go dump stack. */
                print_cpu_stall(rsp);
@@ -548,10 +561,26 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 
 static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
 {
-       rcu_cpu_stall_panicking = 1;
+       rcu_cpu_stall_suppress = 1;
        return NOTIFY_DONE;
 }
 
+/**
+ * rcu_cpu_stall_reset - prevent further stall warnings in current grace period
+ *
+ * Set the stall-warning timeout way off into the future, thus preventing
+ * any RCU CPU stall-warning messages from appearing in the current set of
+ * RCU grace periods.
+ *
+ * The caller must disable hard irqs.
+ */
+void rcu_cpu_stall_reset(void)
+{
+       rcu_sched_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+       rcu_bh_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+       rcu_preempt_stall_reset();
+}
+
 static struct notifier_block rcu_panic_block = {
        .notifier_call = rcu_panic,
 };
@@ -571,6 +600,10 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 {
 }
 
+void rcu_cpu_stall_reset(void)
+{
+}
+
 static void __init check_cpu_stall_init(void)
 {
 }
@@ -712,7 +745,7 @@ static void
 rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
        __releases(rcu_get_root(rsp)->lock)
 {
-       struct rcu_data *rdp = rsp->rda[smp_processor_id()];
+       struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) {
@@ -960,7 +993,7 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
 static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
 {
        int i;
-       struct rcu_data *rdp = rsp->rda[smp_processor_id()];
+       struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
 
        if (rdp->nxtlist == NULL)
                return;  /* irqs disabled, so comparison is stable. */
@@ -971,6 +1004,7 @@ static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
        for (i = 0; i < RCU_NEXT_SIZE; i++)
                rdp->nxttail[i] = &rdp->nxtlist;
        rsp->orphan_qlen += rdp->qlen;
+       rdp->n_cbs_orphaned += rdp->qlen;
        rdp->qlen = 0;
        raw_spin_unlock(&rsp->onofflock);  /* irqs remain disabled. */
 }
@@ -984,7 +1018,7 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
        struct rcu_data *rdp;
 
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
-       rdp = rsp->rda[smp_processor_id()];
+       rdp = this_cpu_ptr(rsp->rda);
        if (rsp->orphan_cbs_list == NULL) {
                raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
                return;
@@ -992,6 +1026,7 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
        *rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_list;
        rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_tail;
        rdp->qlen += rsp->orphan_qlen;
+       rdp->n_cbs_adopted += rsp->orphan_qlen;
        rsp->orphan_cbs_list = NULL;
        rsp->orphan_cbs_tail = &rsp->orphan_cbs_list;
        rsp->orphan_qlen = 0;
@@ -1007,7 +1042,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
        unsigned long flags;
        unsigned long mask;
        int need_report = 0;
-       struct rcu_data *rdp = rsp->rda[cpu];
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp;
 
        /* Exclude any attempts to start a new grace period. */
@@ -1123,6 +1158,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 
        /* Update count, and requeue any remaining callbacks. */
        rdp->qlen -= count;
+       rdp->n_cbs_invoked += count;
        if (list != NULL) {
                *tail = rdp->nxtlist;
                rdp->nxtlist = list;
@@ -1226,7 +1262,8 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
                cpu = rnp->grplo;
                bit = 1;
                for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
-                       if ((rnp->qsmask & bit) != 0 && f(rsp->rda[cpu]))
+                       if ((rnp->qsmask & bit) != 0 &&
+                           f(per_cpu_ptr(rsp->rda, cpu)))
                                mask |= bit;
                }
                if (mask != 0) {
@@ -1402,7 +1439,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
         * a quiescent state betweentimes.
         */
        local_irq_save(flags);
-       rdp = rsp->rda[smp_processor_id()];
+       rdp = this_cpu_ptr(rsp->rda);
        rcu_process_gp_end(rsp, rdp);
        check_for_new_grace_period(rsp, rdp);
 
@@ -1701,7 +1738,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
 {
        unsigned long flags;
        int i;
-       struct rcu_data *rdp = rsp->rda[cpu];
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Set up local state, ensuring consistent view of global state. */
@@ -1729,7 +1766,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
 {
        unsigned long flags;
        unsigned long mask;
-       struct rcu_data *rdp = rsp->rda[cpu];
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Set up local state, ensuring consistent view of global state. */
@@ -1865,7 +1902,8 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
 /*
  * Helper function for rcu_init() that initializes one rcu_state structure.
  */
-static void __init rcu_init_one(struct rcu_state *rsp)
+static void __init rcu_init_one(struct rcu_state *rsp,
+               struct rcu_data __percpu *rda)
 {
        static char *buf[] = { "rcu_node_level_0",
                               "rcu_node_level_1",
@@ -1918,37 +1956,23 @@ static void __init rcu_init_one(struct rcu_state *rsp)
                }
        }
 
+       rsp->rda = rda;
        rnp = rsp->level[NUM_RCU_LVLS - 1];
        for_each_possible_cpu(i) {
                while (i > rnp->grphi)
                        rnp++;
-               rsp->rda[i]->mynode = rnp;
+               per_cpu_ptr(rsp->rda, i)->mynode = rnp;
                rcu_boot_init_percpu_data(i, rsp);
        }
 }
 
-/*
- * Helper macro for __rcu_init() and __rcu_init_preempt().  To be used
- * nowhere else!  Assigns leaf node pointers into each CPU's rcu_data
- * structure.
- */
-#define RCU_INIT_FLAVOR(rsp, rcu_data) \
-do { \
-       int i; \
-       \
-       for_each_possible_cpu(i) { \
-               (rsp)->rda[i] = &per_cpu(rcu_data, i); \
-       } \
-       rcu_init_one(rsp); \
-} while (0)
-
 void __init rcu_init(void)
 {
        int cpu;
 
        rcu_bootup_announce();
-       RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data);
-       RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data);
+       rcu_init_one(&rcu_sched_state, &rcu_sched_data);
+       rcu_init_one(&rcu_bh_state, &rcu_bh_data);
        __rcu_init_preempt();
        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
index 14c040b18ed04a23f34448d9278d9ad55e5ab0c1..91d4170c5c13afd2e8997bd59b28e7cc2a4385e8 100644 (file)
@@ -202,6 +202,9 @@ struct rcu_data {
        long            qlen;           /* # of queued callbacks */
        long            qlen_last_fqs_check;
                                        /* qlen at last check for QS forcing */
+       unsigned long   n_cbs_invoked;  /* count of RCU cbs invoked. */
+       unsigned long   n_cbs_orphaned; /* RCU cbs sent to orphanage. */
+       unsigned long   n_cbs_adopted;  /* RCU cbs adopted from orphanage. */
        unsigned long   n_force_qs_snap;
                                        /* did other CPU force QS recently? */
        long            blimit;         /* Upper limit on a processed batch */
@@ -254,19 +257,23 @@ struct rcu_data {
 #define RCU_STALL_DELAY_DELTA         0
 #endif
 
-#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ + RCU_STALL_DELAY_DELTA)
+#define RCU_SECONDS_TILL_STALL_CHECK   (CONFIG_RCU_CPU_STALL_TIMEOUT * HZ + \
+                                       RCU_STALL_DELAY_DELTA)
                                                /* for rsp->jiffies_stall */
-#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ + RCU_STALL_DELAY_DELTA)
+#define RCU_SECONDS_TILL_STALL_RECHECK (3 * RCU_SECONDS_TILL_STALL_CHECK + 30)
                                                /* for rsp->jiffies_stall */
 #define RCU_STALL_RAT_DELAY            2       /* Allow other CPUs time */
                                                /*  to take at least one */
                                                /*  scheduling clock irq */
                                                /*  before ratting on them. */
 
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+#ifdef CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE
+#define RCU_CPU_STALL_SUPPRESS_INIT 0
+#else
+#define RCU_CPU_STALL_SUPPRESS_INIT 1
+#endif
 
-#define ULONG_CMP_GE(a, b)     (ULONG_MAX / 2 >= (a) - (b))
-#define ULONG_CMP_LT(a, b)     (ULONG_MAX / 2 < (a) - (b))
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
  * RCU global state, including node hierarchy.  This hierarchy is
@@ -283,7 +290,7 @@ struct rcu_state {
        struct rcu_node *level[NUM_RCU_LVLS];   /* Hierarchy levels. */
        u32 levelcnt[MAX_RCU_LVLS + 1];         /* # nodes in each level. */
        u8 levelspread[NUM_RCU_LVLS];           /* kids/node in each level. */
-       struct rcu_data *rda[NR_CPUS];          /* array of rdp pointers. */
+       struct rcu_data __percpu *rda;          /* pointer of percu rcu_data. */
 
        /* The following fields are guarded by the root rcu_node's lock. */
 
@@ -365,6 +372,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static void rcu_print_task_stall(struct rcu_node *rnp);
+static void rcu_preempt_stall_reset(void);
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
index 0e4f420245d97369b7fdf6bb99815789ffe13233..71a4147473f95f51d2b2e88db4c14372dafe375f 100644 (file)
@@ -57,7 +57,7 @@ static void __init rcu_bootup_announce_oddness(void)
        printk(KERN_INFO
               "\tRCU-based detection of stalled CPUs is disabled.\n");
 #endif
-#ifndef CONFIG_RCU_CPU_STALL_VERBOSE
+#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
        printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n");
 #endif
 #if NUM_RCU_LVL_4 != 0
@@ -154,7 +154,7 @@ static void rcu_preempt_note_context_switch(int cpu)
            (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
 
                /* Possibly blocking in an RCU read-side critical section. */
-               rdp = rcu_preempt_state.rda[cpu];
+               rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
                rnp = rdp->mynode;
                raw_spin_lock_irqsave(&rnp->lock, flags);
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
@@ -201,7 +201,7 @@ static void rcu_preempt_note_context_switch(int cpu)
  */
 void __rcu_read_lock(void)
 {
-       ACCESS_ONCE(current->rcu_read_lock_nesting)++;
+       current->rcu_read_lock_nesting++;
        barrier();  /* needed if we ever invoke rcu_read_lock in rcutree.c */
 }
 EXPORT_SYMBOL_GPL(__rcu_read_lock);
@@ -344,7 +344,9 @@ void __rcu_read_unlock(void)
        struct task_struct *t = current;
 
        barrier();  /* needed if we ever invoke rcu_read_unlock in rcutree.c */
-       if (--ACCESS_ONCE(t->rcu_read_lock_nesting) == 0 &&
+       --t->rcu_read_lock_nesting;
+       barrier();  /* decrement before load of ->rcu_read_unlock_special */
+       if (t->rcu_read_lock_nesting == 0 &&
            unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
                rcu_read_unlock_special(t);
 #ifdef CONFIG_PROVE_LOCKING
@@ -417,6 +419,16 @@ static void rcu_print_task_stall(struct rcu_node *rnp)
        }
 }
 
+/*
+ * Suppress preemptible RCU's CPU stall warnings by pushing the
+ * time of the next stall-warning message comfortably far into the
+ * future.
+ */
+static void rcu_preempt_stall_reset(void)
+{
+       rcu_preempt_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+}
+
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
@@ -546,9 +558,11 @@ EXPORT_SYMBOL_GPL(call_rcu);
  *
  * Control will return to the caller some time after a full grace
  * period has elapsed, in other words after all currently executing RCU
- * read-side critical sections have completed.  RCU read-side critical
- * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
- * and may be nested.
+ * read-side critical sections have completed.  Note, however, that
+ * upon return from synchronize_rcu(), the caller might well be executing
+ * concurrently with new RCU read-side critical sections that began while
+ * synchronize_rcu() was waiting.  RCU read-side critical sections are
+ * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested.
  */
 void synchronize_rcu(void)
 {
@@ -771,7 +785,7 @@ static void rcu_preempt_send_cbs_to_orphanage(void)
  */
 static void __init __rcu_init_preempt(void)
 {
-       RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
+       rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
 }
 
 /*
@@ -865,6 +879,14 @@ static void rcu_print_task_stall(struct rcu_node *rnp)
 {
 }
 
+/*
+ * Because preemptible RCU does not exist, there is no need to suppress
+ * its CPU stall warnings.
+ */
+static void rcu_preempt_stall_reset(void)
+{
+}
+
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
@@ -918,15 +940,6 @@ static void rcu_preempt_process_callbacks(void)
 {
 }
 
-/*
- * In classic RCU, call_rcu() is just call_rcu_sched().
- */
-void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
-{
-       call_rcu_sched(head, func);
-}
-EXPORT_SYMBOL_GPL(call_rcu);
-
 /*
  * Wait for an rcu-preempt grace period, but make it happen quickly.
  * But because preemptable RCU does not exist, map to rcu-sched.
index 36c95b45738ed7f74fb78b901ddcff7fc1488498..d15430b9d122f4d619e76fb6b5069aa1f494a575 100644 (file)
@@ -64,7 +64,9 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, " ql=%ld b=%ld\n", rdp->qlen, rdp->blimit);
+       seq_printf(m, " ql=%ld b=%ld", rdp->qlen, rdp->blimit);
+       seq_printf(m, " ci=%lu co=%lu ca=%lu\n",
+                  rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
 #define PRINT_RCU_DATA(name, func, m) \
@@ -119,7 +121,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, ",%ld,%ld\n", rdp->qlen, rdp->blimit);
+       seq_printf(m, ",%ld,%ld", rdp->qlen, rdp->blimit);
+       seq_printf(m, ",%lu,%lu,%lu\n",
+                  rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
 static int show_rcudata_csv(struct seq_file *m, void *unused)
@@ -128,7 +132,7 @@ static int show_rcudata_csv(struct seq_file *m, void *unused)
 #ifdef CONFIG_NO_HZ
        seq_puts(m, "\"dt\",\"dt nesting\",\"dn\",\"df\",");
 #endif /* #ifdef CONFIG_NO_HZ */
-       seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\"\n");
+       seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n");
 #ifdef CONFIG_TREE_PREEMPT_RCU
        seq_puts(m, "\"rcu_preempt:\"\n");
        PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m);
@@ -262,7 +266,7 @@ static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_data *rdp;
 
        for_each_possible_cpu(cpu) {
-               rdp = rsp->rda[cpu];
+               rdp = per_cpu_ptr(rsp->rda, cpu);
                if (rdp->beenonline)
                        print_one_rcu_pending(m, rdp);
        }
index a56f629b057a75be4ff0428d265b8c833886dd85..66cb89bc5ef1203f08b5d17d140b0786a8f80bbd 100644 (file)
@@ -76,7 +76,9 @@ static int handle_op(struct test_thread_data *td, int lockwakeup)
                }
 
                if (!lockwakeup && td->bkl == 4) {
+#ifdef CONFIG_LOCK_KERNEL
                        unlock_kernel();
+#endif
                        td->bkl = 0;
                }
                return 0;
@@ -133,14 +135,18 @@ static int handle_op(struct test_thread_data *td, int lockwakeup)
                if (td->bkl)
                        return 0;
                td->bkl = 1;
+#ifdef CONFIG_LOCK_KERNEL
                lock_kernel();
+#endif
                td->bkl = 4;
                return 0;
 
        case RTTEST_UNLOCKBKL:
                if (td->bkl != 4)
                        break;
+#ifdef CONFIG_LOCK_KERNEL
                unlock_kernel();
+#endif
                td->bkl = 0;
                return 0;
 
index 41541d79e3c85ac7d367f3ddffc4e51a0f63e755..d42992bccdfae88569559f3e88f81bbcea8e9494 100644 (file)
@@ -426,9 +426,7 @@ struct root_domain {
         */
        cpumask_var_t rto_mask;
        atomic_t rto_count;
-#ifdef CONFIG_SMP
        struct cpupri cpupri;
-#endif
 };
 
 /*
@@ -437,7 +435,7 @@ struct root_domain {
  */
 static struct root_domain def_root_domain;
 
-#endif
+#endif /* CONFIG_SMP */
 
 /*
  * This is the main, per-CPU runqueue data structure.
@@ -488,11 +486,12 @@ struct rq {
         */
        unsigned long nr_uninterruptible;
 
-       struct task_struct *curr, *idle;
+       struct task_struct *curr, *idle, *stop;
        unsigned long next_balance;
        struct mm_struct *prev_mm;
 
        u64 clock;
+       u64 clock_task;
 
        atomic_t nr_iowait;
 
@@ -520,6 +519,10 @@ struct rq {
        u64 avg_idle;
 #endif
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+       u64 prev_irq_time;
+#endif
+
        /* calc_load related fields */
        unsigned long calc_load_update;
        long calc_load_active;
@@ -643,10 +646,22 @@ static inline struct task_group *task_group(struct task_struct *p)
 
 #endif /* CONFIG_CGROUP_SCHED */
 
+static u64 irq_time_cpu(int cpu);
+static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+
 inline void update_rq_clock(struct rq *rq)
 {
-       if (!rq->skip_clock_update)
-               rq->clock = sched_clock_cpu(cpu_of(rq));
+       if (!rq->skip_clock_update) {
+               int cpu = cpu_of(rq);
+               u64 irq_time;
+
+               rq->clock = sched_clock_cpu(cpu);
+               irq_time = irq_time_cpu(cpu);
+               if (rq->clock - irq_time > rq->clock_task)
+                       rq->clock_task = rq->clock - irq_time;
+
+               sched_irq_time_avg_update(rq, irq_time);
+       }
 }
 
 /*
@@ -723,7 +738,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf,
                size_t cnt, loff_t *ppos)
 {
        char buf[64];
-       char *cmp = buf;
+       char *cmp;
        int neg = 0;
        int i;
 
@@ -734,6 +749,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf,
                return -EFAULT;
 
        buf[cnt] = 0;
+       cmp = strstrip(buf);
 
        if (strncmp(buf, "NO_", 3) == 0) {
                neg = 1;
@@ -741,9 +757,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf,
        }
 
        for (i = 0; sched_feat_names[i]; i++) {
-               int len = strlen(sched_feat_names[i]);
-
-               if (strncmp(cmp, sched_feat_names[i], len) == 0) {
+               if (strcmp(cmp, sched_feat_names[i]) == 0) {
                        if (neg)
                                sysctl_sched_features &= ~(1UL << i);
                        else
@@ -1294,6 +1308,10 @@ static void resched_task(struct task_struct *p)
 static void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
 {
 }
+
+static void sched_avg_update(struct rq *rq)
+{
+}
 #endif /* CONFIG_SMP */
 
 #if BITS_PER_LONG == 32
@@ -1836,7 +1854,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
 
 static const struct sched_class rt_sched_class;
 
-#define sched_class_highest (&rt_sched_class)
+#define sched_class_highest (&stop_sched_class)
 #define for_each_class(class) \
    for (class = sched_class_highest; class; class = class->next)
 
@@ -1854,12 +1872,6 @@ static void dec_nr_running(struct rq *rq)
 
 static void set_load_weight(struct task_struct *p)
 {
-       if (task_has_rt_policy(p)) {
-               p->se.load.weight = 0;
-               p->se.load.inv_weight = WMULT_CONST;
-               return;
-       }
-
        /*
         * SCHED_IDLE tasks get minimal weight:
         */
@@ -1913,13 +1925,132 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
        dec_nr_running(rq);
 }
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+
+/*
+ * There are no locks covering percpu hardirq/softirq time.
+ * They are only modified in account_system_vtime, on corresponding CPU
+ * with interrupts disabled. So, writes are safe.
+ * They are read and saved off onto struct rq in update_rq_clock().
+ * This may result in other CPU reading this CPU's irq time and can
+ * race with irq/account_system_vtime on this CPU. We would either get old
+ * or new value (or semi updated value on 32 bit) with a side effect of
+ * accounting a slice of irq time to wrong task when irq is in progress
+ * while we read rq->clock. That is a worthy compromise in place of having
+ * locks on each irq in account_system_time.
+ */
+static DEFINE_PER_CPU(u64, cpu_hardirq_time);
+static DEFINE_PER_CPU(u64, cpu_softirq_time);
+
+static DEFINE_PER_CPU(u64, irq_start_time);
+static int sched_clock_irqtime;
+
+void enable_sched_clock_irqtime(void)
+{
+       sched_clock_irqtime = 1;
+}
+
+void disable_sched_clock_irqtime(void)
+{
+       sched_clock_irqtime = 0;
+}
+
+static u64 irq_time_cpu(int cpu)
+{
+       if (!sched_clock_irqtime)
+               return 0;
+
+       return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
+}
+
+void account_system_vtime(struct task_struct *curr)
+{
+       unsigned long flags;
+       int cpu;
+       u64 now, delta;
+
+       if (!sched_clock_irqtime)
+               return;
+
+       local_irq_save(flags);
+
+       cpu = smp_processor_id();
+       now = sched_clock_cpu(cpu);
+       delta = now - per_cpu(irq_start_time, cpu);
+       per_cpu(irq_start_time, cpu) = now;
+       /*
+        * We do not account for softirq time from ksoftirqd here.
+        * We want to continue accounting softirq time to ksoftirqd thread
+        * in that case, so as not to confuse scheduler with a special task
+        * that do not consume any time, but still wants to run.
+        */
+       if (hardirq_count())
+               per_cpu(cpu_hardirq_time, cpu) += delta;
+       else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
+               per_cpu(cpu_softirq_time, cpu) += delta;
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(account_system_vtime);
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+{
+       if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
+               u64 delta_irq = curr_irq_time - rq->prev_irq_time;
+               rq->prev_irq_time = curr_irq_time;
+               sched_rt_avg_update(rq, delta_irq);
+       }
+}
+
+#else
+
+static u64 irq_time_cpu(int cpu)
+{
+       return 0;
+}
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
+
+#endif
+
 #include "sched_idletask.c"
 #include "sched_fair.c"
 #include "sched_rt.c"
+#include "sched_stoptask.c"
 #ifdef CONFIG_SCHED_DEBUG
 # include "sched_debug.c"
 #endif
 
+void sched_set_stop_task(int cpu, struct task_struct *stop)
+{
+       struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+       struct task_struct *old_stop = cpu_rq(cpu)->stop;
+
+       if (stop) {
+               /*
+                * Make it appear like a SCHED_FIFO task, its something
+                * userspace knows about and won't get confused about.
+                *
+                * Also, it will make PI more or less work without too
+                * much confusion -- but then, stop work should not
+                * rely on PI working anyway.
+                */
+               sched_setscheduler_nocheck(stop, SCHED_FIFO, &param);
+
+               stop->sched_class = &stop_sched_class;
+       }
+
+       cpu_rq(cpu)->stop = stop;
+
+       if (old_stop) {
+               /*
+                * Reset it back to a normal scheduling class so that
+                * it can die in pieces.
+                */
+               old_stop->sched_class = &rt_sched_class;
+       }
+}
+
 /*
  * __normal_prio - return the priority that is based on the static prio
  */
@@ -1999,6 +2130,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
        if (p->sched_class != &fair_sched_class)
                return 0;
 
+       if (unlikely(p->policy == SCHED_IDLE))
+               return 0;
+
        /*
         * Buddy candidates are cache hot:
         */
@@ -2848,14 +2982,14 @@ context_switch(struct rq *rq, struct task_struct *prev,
         */
        arch_start_context_switch(prev);
 
-       if (likely(!mm)) {
+       if (!mm) {
                next->active_mm = oldmm;
                atomic_inc(&oldmm->mm_count);
                enter_lazy_tlb(oldmm, next);
        } else
                switch_mm(oldmm, mm, next);
 
-       if (likely(!prev->mm)) {
+       if (!prev->mm) {
                prev->active_mm = NULL;
                rq->prev_mm = oldmm;
        }
@@ -3182,6 +3316,8 @@ static void update_cpu_load(struct rq *this_rq)
 
                this_rq->cpu_load[i] = (old_load * (scale - 1) + new_load) >> i;
        }
+
+       sched_avg_update(this_rq);
 }
 
 static void update_cpu_load_active(struct rq *this_rq)
@@ -3242,7 +3378,7 @@ static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq)
 
        if (task_current(rq, p)) {
                update_rq_clock(rq);
-               ns = rq->clock - p->se.exec_start;
+               ns = rq->clock_task - p->se.exec_start;
                if ((s64)ns < 0)
                        ns = 0;
        }
@@ -3391,7 +3527,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
        tmp = cputime_to_cputime64(cputime);
        if (hardirq_count() - hardirq_offset)
                cpustat->irq = cputime64_add(cpustat->irq, tmp);
-       else if (softirq_count())
+       else if (in_serving_softirq())
                cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
        else
                cpustat->system = cputime64_add(cpustat->system, tmp);
@@ -3507,9 +3643,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
        rtime = nsecs_to_cputime(p->se.sum_exec_runtime);
 
        if (total) {
-               u64 temp;
+               u64 temp = rtime;
 
-               temp = (u64)(rtime * utime);
+               temp *= utime;
                do_div(temp, total);
                utime = (cputime_t)temp;
        } else
@@ -3540,9 +3676,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
        rtime = nsecs_to_cputime(cputime.sum_exec_runtime);
 
        if (total) {
-               u64 temp;
+               u64 temp = rtime;
 
-               temp = (u64)(rtime * cputime.utime);
+               temp *= cputime.utime;
                do_div(temp, total);
                utime = (cputime_t)temp;
        } else
@@ -3578,7 +3714,7 @@ void scheduler_tick(void)
        curr->sched_class->task_tick(rq, curr, 0);
        raw_spin_unlock(&rq->lock);
 
-       perf_event_task_tick(curr);
+       perf_event_task_tick();
 
 #ifdef CONFIG_SMP
        rq->idle_at_tick = idle_cpu(cpu);
@@ -3717,17 +3853,13 @@ pick_next_task(struct rq *rq)
                        return p;
        }
 
-       class = sched_class_highest;
-       for ( ; ; ) {
+       for_each_class(class) {
                p = class->pick_next_task(rq);
                if (p)
                        return p;
-               /*
-                * Will never be NULL as the idle class always
-                * returns a non-NULL p:
-                */
-               class = class->next;
        }
+
+       BUG(); /* the idle class will always have a runnable task */
 }
 
 /*
@@ -3865,8 +3997,16 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
                /*
                 * Owner changed, break to re-assess state.
                 */
-               if (lock->owner != owner)
+               if (lock->owner != owner) {
+                       /*
+                        * If the lock has switched to a different owner,
+                        * we likely have heavy contention. Return 0 to quit
+                        * optimistic spinning and not contend further:
+                        */
+                       if (lock->owner)
+                               return 0;
                        break;
+               }
 
                /*
                 * Is that owner really running on that cpu?
@@ -4344,6 +4484,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
 
        rq = task_rq_lock(p, &flags);
 
+       trace_sched_pi_setprio(p, prio);
        oldprio = p->prio;
        prev_class = p->sched_class;
        on_rq = p->se.on_rq;
@@ -4631,7 +4772,7 @@ recheck:
        }
 
        if (user) {
-               retval = security_task_setscheduler(p, policy, param);
+               retval = security_task_setscheduler(p);
                if (retval)
                        return retval;
        }
@@ -4647,6 +4788,15 @@ recheck:
         */
        rq = __task_rq_lock(p);
 
+       /*
+        * Changing the policy of the stop threads its a very bad idea
+        */
+       if (p == rq->stop) {
+               __task_rq_unlock(rq);
+               raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+               return -EINVAL;
+       }
+
 #ifdef CONFIG_RT_GROUP_SCHED
        if (user) {
                /*
@@ -4873,13 +5023,13 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
        if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
                goto out_unlock;
 
-       retval = security_task_setscheduler(p, 0, NULL);
+       retval = security_task_setscheduler(p);
        if (retval)
                goto out_unlock;
 
        cpuset_cpus_allowed(p, cpus_allowed);
        cpumask_and(new_mask, in_mask, cpus_allowed);
- again:
+again:
        retval = set_cpus_allowed_ptr(p, new_mask);
 
        if (!retval) {
@@ -5323,7 +5473,19 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
        idle->se.exec_start = sched_clock();
 
        cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu));
+       /*
+        * We're having a chicken and egg problem, even though we are
+        * holding rq->lock, the cpu isn't yet set to this cpu so the
+        * lockdep check in task_group() will fail.
+        *
+        * Similar case to sched_fork(). / Alternatively we could
+        * use task_rq_lock() here and obtain the other rq->lock.
+        *
+        * Silence PROVE_RCU
+        */
+       rcu_read_lock();
        __set_task_cpu(idle, cpu);
+       rcu_read_unlock();
 
        rq->curr = rq->idle = idle;
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -6500,6 +6662,7 @@ struct s_data {
        cpumask_var_t           nodemask;
        cpumask_var_t           this_sibling_map;
        cpumask_var_t           this_core_map;
+       cpumask_var_t           this_book_map;
        cpumask_var_t           send_covered;
        cpumask_var_t           tmpmask;
        struct sched_group      **sched_group_nodes;
@@ -6511,6 +6674,7 @@ enum s_alloc {
        sa_rootdomain,
        sa_tmpmask,
        sa_send_covered,
+       sa_this_book_map,
        sa_this_core_map,
        sa_this_sibling_map,
        sa_nodemask,
@@ -6546,31 +6710,48 @@ cpu_to_cpu_group(int cpu, const struct cpumask *cpu_map,
 #ifdef CONFIG_SCHED_MC
 static DEFINE_PER_CPU(struct static_sched_domain, core_domains);
 static DEFINE_PER_CPU(struct static_sched_group, sched_group_core);
-#endif /* CONFIG_SCHED_MC */
 
-#if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
 static int
 cpu_to_core_group(int cpu, const struct cpumask *cpu_map,
                  struct sched_group **sg, struct cpumask *mask)
 {
        int group;
-
+#ifdef CONFIG_SCHED_SMT
        cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
        group = cpumask_first(mask);
+#else
+       group = cpu;
+#endif
        if (sg)
                *sg = &per_cpu(sched_group_core, group).sg;
        return group;
 }
-#elif defined(CONFIG_SCHED_MC)
+#endif /* CONFIG_SCHED_MC */
+
+/*
+ * book sched-domains:
+ */
+#ifdef CONFIG_SCHED_BOOK
+static DEFINE_PER_CPU(struct static_sched_domain, book_domains);
+static DEFINE_PER_CPU(struct static_sched_group, sched_group_book);
+
 static int
-cpu_to_core_group(int cpu, const struct cpumask *cpu_map,
-                 struct sched_group **sg, struct cpumask *unused)
+cpu_to_book_group(int cpu, const struct cpumask *cpu_map,
+                 struct sched_group **sg, struct cpumask *mask)
 {
+       int group = cpu;
+#ifdef CONFIG_SCHED_MC
+       cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
+       group = cpumask_first(mask);
+#elif defined(CONFIG_SCHED_SMT)
+       cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
+       group = cpumask_first(mask);
+#endif
        if (sg)
-               *sg = &per_cpu(sched_group_core, cpu).sg;
-       return cpu;
+               *sg = &per_cpu(sched_group_book, group).sg;
+       return group;
 }
-#endif
+#endif /* CONFIG_SCHED_BOOK */
 
 static DEFINE_PER_CPU(struct static_sched_domain, phys_domains);
 static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys);
@@ -6580,7 +6761,10 @@ cpu_to_phys_group(int cpu, const struct cpumask *cpu_map,
                  struct sched_group **sg, struct cpumask *mask)
 {
        int group;
-#ifdef CONFIG_SCHED_MC
+#ifdef CONFIG_SCHED_BOOK
+       cpumask_and(mask, cpu_book_mask(cpu), cpu_map);
+       group = cpumask_first(mask);
+#elif defined(CONFIG_SCHED_MC)
        cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
        group = cpumask_first(mask);
 #elif defined(CONFIG_SCHED_SMT)
@@ -6841,6 +7025,9 @@ SD_INIT_FUNC(CPU)
 #ifdef CONFIG_SCHED_MC
  SD_INIT_FUNC(MC)
 #endif
+#ifdef CONFIG_SCHED_BOOK
+ SD_INIT_FUNC(BOOK)
+#endif
 
 static int default_relax_domain_level = -1;
 
@@ -6890,6 +7077,8 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
                free_cpumask_var(d->tmpmask); /* fall through */
        case sa_send_covered:
                free_cpumask_var(d->send_covered); /* fall through */
+       case sa_this_book_map:
+               free_cpumask_var(d->this_book_map); /* fall through */
        case sa_this_core_map:
                free_cpumask_var(d->this_core_map); /* fall through */
        case sa_this_sibling_map:
@@ -6936,8 +7125,10 @@ static enum s_alloc __visit_domain_allocation_hell(struct s_data *d,
                return sa_nodemask;
        if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL))
                return sa_this_sibling_map;
-       if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL))
+       if (!alloc_cpumask_var(&d->this_book_map, GFP_KERNEL))
                return sa_this_core_map;
+       if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL))
+               return sa_this_book_map;
        if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL))
                return sa_send_covered;
        d->rd = alloc_rootdomain();
@@ -6995,6 +7186,23 @@ static struct sched_domain *__build_cpu_sched_domain(struct s_data *d,
        return sd;
 }
 
+static struct sched_domain *__build_book_sched_domain(struct s_data *d,
+       const struct cpumask *cpu_map, struct sched_domain_attr *attr,
+       struct sched_domain *parent, int i)
+{
+       struct sched_domain *sd = parent;
+#ifdef CONFIG_SCHED_BOOK
+       sd = &per_cpu(book_domains, i).sd;
+       SD_INIT(sd, BOOK);
+       set_domain_attribute(sd, attr);
+       cpumask_and(sched_domain_span(sd), cpu_map, cpu_book_mask(i));
+       sd->parent = parent;
+       parent->child = sd;
+       cpu_to_book_group(i, cpu_map, &sd->groups, d->tmpmask);
+#endif
+       return sd;
+}
+
 static struct sched_domain *__build_mc_sched_domain(struct s_data *d,
        const struct cpumask *cpu_map, struct sched_domain_attr *attr,
        struct sched_domain *parent, int i)
@@ -7051,6 +7259,15 @@ static void build_sched_groups(struct s_data *d, enum sched_domain_level l,
                                                &cpu_to_core_group,
                                                d->send_covered, d->tmpmask);
                break;
+#endif
+#ifdef CONFIG_SCHED_BOOK
+       case SD_LV_BOOK: /* set up book groups */
+               cpumask_and(d->this_book_map, cpu_map, cpu_book_mask(cpu));
+               if (cpu == cpumask_first(d->this_book_map))
+                       init_sched_build_groups(d->this_book_map, cpu_map,
+                                               &cpu_to_book_group,
+                                               d->send_covered, d->tmpmask);
+               break;
 #endif
        case SD_LV_CPU: /* set up physical groups */
                cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map);
@@ -7099,12 +7316,14 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
 
                sd = __build_numa_sched_domains(&d, cpu_map, attr, i);
                sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i);
+               sd = __build_book_sched_domain(&d, cpu_map, attr, sd, i);
                sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i);
                sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i);
        }
 
        for_each_cpu(i, cpu_map) {
                build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i);
+               build_sched_groups(&d, SD_LV_BOOK, cpu_map, i);
                build_sched_groups(&d, SD_LV_MC, cpu_map, i);
        }
 
@@ -7135,6 +7354,12 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
                init_sched_groups_power(i, sd);
        }
 #endif
+#ifdef CONFIG_SCHED_BOOK
+       for_each_cpu(i, cpu_map) {
+               sd = &per_cpu(book_domains, i).sd;
+               init_sched_groups_power(i, sd);
+       }
+#endif
 
        for_each_cpu(i, cpu_map) {
                sd = &per_cpu(phys_domains, i).sd;
@@ -7160,6 +7385,8 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
                sd = &per_cpu(cpu_domains, i).sd;
 #elif defined(CONFIG_SCHED_MC)
                sd = &per_cpu(core_domains, i).sd;
+#elif defined(CONFIG_SCHED_BOOK)
+               sd = &per_cpu(book_domains, i).sd;
 #else
                sd = &per_cpu(phys_domains, i).sd;
 #endif
@@ -8064,9 +8291,9 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 
        return 1;
 
- err_free_rq:
+err_free_rq:
        kfree(cfs_rq);
- err:
+err:
        return 0;
 }
 
@@ -8154,9 +8381,9 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 
        return 1;
 
- err_free_rq:
+err_free_rq:
        kfree(rt_rq);
- err:
+err:
        return 0;
 }
 
@@ -8514,7 +8741,7 @@ static int tg_set_bandwidth(struct task_group *tg,
                raw_spin_unlock(&rt_rq->rt_runtime_lock);
        }
        raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
- unlock:
+unlock:
        read_unlock(&tasklist_lock);
        mutex_unlock(&rt_constraints_mutex);
 
index 806d1b227a21060aac100994a8992266c00b59b5..933f3d1b62ea0affb63767f87152545f7659dc6f 100644 (file)
@@ -25,7 +25,7 @@
 
 /*
  * Targeted preemption latency for CPU-bound tasks:
- * (default: 5ms * (1 + ilog(ncpus)), units: nanoseconds)
+ * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
  *
  * NOTE: this latency value is not the same as the concept of
  * 'timeslice length' - timeslices in CFS are of variable length
@@ -52,15 +52,15 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling
 
 /*
  * Minimal preemption granularity for CPU-bound tasks:
- * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds)
+ * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds)
  */
-unsigned int sysctl_sched_min_granularity = 2000000ULL;
-unsigned int normalized_sysctl_sched_min_granularity = 2000000ULL;
+unsigned int sysctl_sched_min_granularity = 750000ULL;
+unsigned int normalized_sysctl_sched_min_granularity = 750000ULL;
 
 /*
  * is kept at sysctl_sched_latency / sysctl_sched_min_granularity
  */
-static unsigned int sched_nr_latency = 3;
+static unsigned int sched_nr_latency = 8;
 
 /*
  * After fork, child runs first. If set to 0 (default) then
@@ -519,7 +519,7 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
 static void update_curr(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *curr = cfs_rq->curr;
-       u64 now = rq_of(cfs_rq)->clock;
+       u64 now = rq_of(cfs_rq)->clock_task;
        unsigned long delta_exec;
 
        if (unlikely(!curr))
@@ -602,7 +602,7 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
        /*
         * We are starting a new run period:
         */
-       se->exec_start = rq_of(cfs_rq)->clock;
+       se->exec_start = rq_of(cfs_rq)->clock_task;
 }
 
 /**************************************************
@@ -1313,7 +1313,7 @@ static struct sched_group *
 find_idlest_group(struct sched_domain *sd, struct task_struct *p,
                  int this_cpu, int load_idx)
 {
-       struct sched_group *idlest = NULL, *this = NULL, *group = sd->groups;
+       struct sched_group *idlest = NULL, *group = sd->groups;
        unsigned long min_load = ULONG_MAX, this_load = 0;
        int imbalance = 100 + (sd->imbalance_pct-100)/2;
 
@@ -1348,7 +1348,6 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 
                if (local_group) {
                        this_load = avg_load;
-                       this = group;
                } else if (avg_load < min_load) {
                        min_load = avg_load;
                        idlest = group;
@@ -1765,6 +1764,10 @@ static void pull_task(struct rq *src_rq, struct task_struct *p,
        set_task_cpu(p, this_cpu);
        activate_task(this_rq, p, 0);
        check_preempt_curr(this_rq, p, 0);
+
+       /* re-arm NEWIDLE balancing when moving tasks */
+       src_rq->avg_idle = this_rq->avg_idle = 2*sysctl_sched_migration_cost;
+       this_rq->idle_stamp = 0;
 }
 
 /*
@@ -1799,7 +1802,7 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
         * 2) too many balance attempts have failed.
         */
 
-       tsk_cache_hot = task_hot(p, rq->clock, sd);
+       tsk_cache_hot = task_hot(p, rq->clock_task, sd);
        if (!tsk_cache_hot ||
                sd->nr_balance_failed > sd->cache_nice_tries) {
 #ifdef CONFIG_SCHEDSTATS
@@ -2031,12 +2034,14 @@ struct sd_lb_stats {
        unsigned long this_load;
        unsigned long this_load_per_task;
        unsigned long this_nr_running;
+       unsigned long this_has_capacity;
 
        /* Statistics of the busiest group */
        unsigned long max_load;
        unsigned long busiest_load_per_task;
        unsigned long busiest_nr_running;
        unsigned long busiest_group_capacity;
+       unsigned long busiest_has_capacity;
 
        int group_imb; /* Is there imbalance in this sd */
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
@@ -2059,6 +2064,7 @@ struct sg_lb_stats {
        unsigned long sum_weighted_load; /* Weighted load of group's tasks */
        unsigned long group_capacity;
        int group_imb; /* Is there an imbalance in the group ? */
+       int group_has_capacity; /* Is there extra capacity in the group? */
 };
 
 /**
@@ -2268,10 +2274,14 @@ unsigned long scale_rt_power(int cpu)
        struct rq *rq = cpu_rq(cpu);
        u64 total, available;
 
-       sched_avg_update(rq);
-
        total = sched_avg_period() + (rq->clock - rq->age_stamp);
-       available = total - rq->rt_avg;
+
+       if (unlikely(total < rq->rt_avg)) {
+               /* Ensures that power won't end up being negative */
+               available = 0;
+       } else {
+               available = total - rq->rt_avg;
+       }
 
        if (unlikely((s64)total < SCHED_LOAD_SCALE))
                total = SCHED_LOAD_SCALE;
@@ -2381,7 +2391,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
                        int local_group, const struct cpumask *cpus,
                        int *balance, struct sg_lb_stats *sgs)
 {
-       unsigned long load, max_cpu_load, min_cpu_load;
+       unsigned long load, max_cpu_load, min_cpu_load, max_nr_running;
        int i;
        unsigned int balance_cpu = -1, first_idle_cpu = 0;
        unsigned long avg_load_per_task = 0;
@@ -2392,6 +2402,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
        /* Tally up the load of all CPUs in the group */
        max_cpu_load = 0;
        min_cpu_load = ~0UL;
+       max_nr_running = 0;
 
        for_each_cpu_and(i, sched_group_cpus(group), cpus) {
                struct rq *rq = cpu_rq(i);
@@ -2409,8 +2420,10 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
                        load = target_load(i, load_idx);
                } else {
                        load = source_load(i, load_idx);
-                       if (load > max_cpu_load)
+                       if (load > max_cpu_load) {
                                max_cpu_load = load;
+                               max_nr_running = rq->nr_running;
+                       }
                        if (min_cpu_load > load)
                                min_cpu_load = load;
                }
@@ -2450,13 +2463,15 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
        if (sgs->sum_nr_running)
                avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
 
-       if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task)
+       if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task && max_nr_running > 1)
                sgs->group_imb = 1;
 
-       sgs->group_capacity =
-               DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
+       sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
        if (!sgs->group_capacity)
                sgs->group_capacity = fix_small_capacity(sd, group);
+
+       if (sgs->group_capacity > sgs->sum_nr_running)
+               sgs->group_has_capacity = 1;
 }
 
 /**
@@ -2545,9 +2560,14 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
                /*
                 * In case the child domain prefers tasks go to siblings
                 * first, lower the sg capacity to one so that we'll try
-                * and move all the excess tasks away.
+                * and move all the excess tasks away. We lower the capacity
+                * of a group only if the local group has the capacity to fit
+                * these excess tasks, i.e. nr_running < group_capacity. The
+                * extra check prevents the case where you always pull from the
+                * heaviest group when it is already under-utilized (possible
+                * with a large weight task outweighs the tasks on the system).
                 */
-               if (prefer_sibling)
+               if (prefer_sibling && !local_group && sds->this_has_capacity)
                        sgs.group_capacity = min(sgs.group_capacity, 1UL);
 
                if (local_group) {
@@ -2555,12 +2575,14 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
                        sds->this = sg;
                        sds->this_nr_running = sgs.sum_nr_running;
                        sds->this_load_per_task = sgs.sum_weighted_load;
+                       sds->this_has_capacity = sgs.group_has_capacity;
                } else if (update_sd_pick_busiest(sd, sds, sg, &sgs, this_cpu)) {
                        sds->max_load = sgs.avg_load;
                        sds->busiest = sg;
                        sds->busiest_nr_running = sgs.sum_nr_running;
                        sds->busiest_group_capacity = sgs.group_capacity;
                        sds->busiest_load_per_task = sgs.sum_weighted_load;
+                       sds->busiest_has_capacity = sgs.group_has_capacity;
                        sds->group_imb = sgs.group_imb;
                }
 
@@ -2757,6 +2779,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
                return fix_small_imbalance(sds, this_cpu, imbalance);
 
 }
+
 /******* find_busiest_group() helpers end here *********************/
 
 /**
@@ -2808,6 +2831,11 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
         * 4) This group is more busy than the avg busieness at this
         *    sched_domain.
         * 5) The imbalance is within the specified limit.
+        *
+        * Note: when doing newidle balance, if the local group has excess
+        * capacity (i.e. nr_running < group_capacity) and the busiest group
+        * does not have any capacity, we force a load balance to pull tasks
+        * to the local group. In this case, we skip past checks 3, 4 and 5.
         */
        if (!(*balance))
                goto ret;
@@ -2819,6 +2847,11 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
        if (!sds.busiest || sds.busiest_nr_running == 0)
                goto out_balanced;
 
+       /*  SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
+       if (idle == CPU_NEWLY_IDLE && sds.this_has_capacity &&
+                       !sds.busiest_has_capacity)
+               goto force_balance;
+
        if (sds.this_load >= sds.max_load)
                goto out_balanced;
 
@@ -2830,6 +2863,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
        if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
                goto out_balanced;
 
+force_balance:
        /* Looks like there is an imbalance. Compute it */
        calculate_imbalance(&sds, this_cpu, imbalance);
        return sds.busiest;
@@ -3034,7 +3068,14 @@ redo:
 
        if (!ld_moved) {
                schedstat_inc(sd, lb_failed[idle]);
-               sd->nr_balance_failed++;
+               /*
+                * Increment the failure counter only on periodic balance.
+                * We do not want newidle balance, which can be very
+                * frequent, pollute the failure counter causing
+                * excessive cache_hot migrations and active balances.
+                */
+               if (idle != CPU_NEWLY_IDLE)
+                       sd->nr_balance_failed++;
 
                if (need_active_balance(sd, sd_idle, idle, cpu_of(busiest),
                                        this_cpu)) {
@@ -3156,10 +3197,8 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
                interval = msecs_to_jiffies(sd->balance_interval);
                if (time_after(next_balance, sd->last_balance + interval))
                        next_balance = sd->last_balance + interval;
-               if (pulled_task) {
-                       this_rq->idle_stamp = 0;
+               if (pulled_task)
                        break;
-               }
        }
 
        raw_spin_lock(&this_rq->lock);
@@ -3633,7 +3672,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
        if (time_before(now, nohz.next_balance))
                return 0;
 
-       if (!rq->nr_running)
+       if (rq->idle_at_tick)
                return 0;
 
        first_pick_cpu = atomic_read(&nohz.first_pick_cpu);
@@ -3752,8 +3791,13 @@ static void task_fork_fair(struct task_struct *p)
 
        raw_spin_lock_irqsave(&rq->lock, flags);
 
-       if (unlikely(task_cpu(p) != this_cpu))
+       update_rq_clock(rq);
+
+       if (unlikely(task_cpu(p) != this_cpu)) {
+               rcu_read_lock();
                __set_task_cpu(p, this_cpu);
+               rcu_read_unlock();
+       }
 
        update_curr(cfs_rq);
 
index 83c66e8ad3ee314704456e14dfc23607d00c5f0d..185f920ec1a2e923b0d966f787c610ff26a7b6cb 100644 (file)
@@ -61,3 +61,8 @@ SCHED_FEAT(ASYM_EFF_LOAD, 1)
  * release the lock. Decreases scheduling overhead.
  */
 SCHED_FEAT(OWNER_SPIN, 1)
+
+/*
+ * Decrement CPU power based on irq activity
+ */
+SCHED_FEAT(NONIRQ_POWER, 1)
index d10c80ebb67a2821038a9c59b912bf8e323d67e3..bea7d79f7e9ca958bba514cbd8eb48ceab47bab3 100644 (file)
@@ -609,7 +609,7 @@ static void update_curr_rt(struct rq *rq)
        if (!task_has_rt_policy(curr))
                return;
 
-       delta_exec = rq->clock - curr->se.exec_start;
+       delta_exec = rq->clock_task - curr->se.exec_start;
        if (unlikely((s64)delta_exec < 0))
                delta_exec = 0;
 
@@ -618,7 +618,7 @@ static void update_curr_rt(struct rq *rq)
        curr->se.sum_exec_runtime += delta_exec;
        account_group_exec_runtime(curr, delta_exec);
 
-       curr->se.exec_start = rq->clock;
+       curr->se.exec_start = rq->clock_task;
        cpuacct_charge(curr, delta_exec);
 
        sched_rt_avg_update(rq, delta_exec);
@@ -960,18 +960,19 @@ select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
         * runqueue. Otherwise simply start this RT task
         * on its current runqueue.
         *
-        * We want to avoid overloading runqueues. Even if
-        * the RT task is of higher priority than the current RT task.
-        * RT tasks behave differently than other tasks. If
-        * one gets preempted, we try to push it off to another queue.
-        * So trying to keep a preempting RT task on the same
-        * cache hot CPU will force the running RT task to
-        * a cold CPU. So we waste all the cache for the lower
-        * RT task in hopes of saving some of a RT task
-        * that is just being woken and probably will have
-        * cold cache anyway.
+        * We want to avoid overloading runqueues. If the woken
+        * task is a higher priority, then it will stay on this CPU
+        * and the lower prio task should be moved to another CPU.
+        * Even though this will probably make the lower prio task
+        * lose its cache, we do not want to bounce a higher task
+        * around just because it gave up its CPU, perhaps for a
+        * lock?
+        *
+        * For equal prio tasks, we just let the scheduler sort it out.
         */
        if (unlikely(rt_task(rq->curr)) &&
+           (rq->curr->rt.nr_cpus_allowed < 2 ||
+            rq->curr->prio < p->prio) &&
            (p->rt.nr_cpus_allowed > 1)) {
                int cpu = find_lowest_rq(p);
 
@@ -1074,7 +1075,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
        } while (rt_rq);
 
        p = rt_task_of(rt_se);
-       p->se.exec_start = rq->clock;
+       p->se.exec_start = rq->clock_task;
 
        return p;
 }
@@ -1139,7 +1140,7 @@ static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu)
        for_each_leaf_rt_rq(rt_rq, rq) {
                array = &rt_rq->active;
                idx = sched_find_first_bit(array->bitmap);
- next_idx:
+next_idx:
                if (idx >= MAX_RT_PRIO)
                        continue;
                if (next && next->prio < idx)
@@ -1315,7 +1316,7 @@ static int push_rt_task(struct rq *rq)
        if (!next_task)
                return 0;
 
- retry:
+retry:
        if (unlikely(next_task == rq->curr)) {
                WARN_ON(1);
                return 0;
@@ -1463,7 +1464,7 @@ static int pull_rt_task(struct rq *this_rq)
                         * but possible)
                         */
                }
- skip:
+skip:
                double_unlock_balance(this_rq, src_rq);
        }
 
@@ -1491,7 +1492,10 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
        if (!task_running(rq, p) &&
            !test_tsk_need_resched(rq->curr) &&
            has_pushable_tasks(rq) &&
-           p->rt.nr_cpus_allowed > 1)
+           p->rt.nr_cpus_allowed > 1 &&
+           rt_task(rq->curr) &&
+           (rq->curr->rt.nr_cpus_allowed < 2 ||
+            rq->curr->prio < p->prio))
                push_rt_tasks(rq);
 }
 
@@ -1709,7 +1713,7 @@ static void set_curr_task_rt(struct rq *rq)
 {
        struct task_struct *p = rq->curr;
 
-       p->se.exec_start = rq->clock;
+       p->se.exec_start = rq->clock_task;
 
        /* The running task is never eligible for pushing */
        dequeue_pushable_task(rq, p);
diff --git a/kernel/sched_stoptask.c b/kernel/sched_stoptask.c
new file mode 100644 (file)
index 0000000..45bddc0
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * stop-task scheduling class.
+ *
+ * The stop task is the highest priority task in the system, it preempts
+ * everything and will be preempted by nothing.
+ *
+ * See kernel/stop_machine.c
+ */
+
+#ifdef CONFIG_SMP
+static int
+select_task_rq_stop(struct rq *rq, struct task_struct *p,
+                   int sd_flag, int flags)
+{
+       return task_cpu(p); /* stop tasks as never migrate */
+}
+#endif /* CONFIG_SMP */
+
+static void
+check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+       resched_task(rq->curr); /* we preempt everything */
+}
+
+static struct task_struct *pick_next_task_stop(struct rq *rq)
+{
+       struct task_struct *stop = rq->stop;
+
+       if (stop && stop->state == TASK_RUNNING)
+               return stop;
+
+       return NULL;
+}
+
+static void
+enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+}
+
+static void
+dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+}
+
+static void yield_task_stop(struct rq *rq)
+{
+       BUG(); /* the stop task should never yield, its pointless. */
+}
+
+static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)
+{
+}
+
+static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued)
+{
+}
+
+static void set_curr_task_stop(struct rq *rq)
+{
+}
+
+static void switched_to_stop(struct rq *rq, struct task_struct *p,
+                            int running)
+{
+       BUG(); /* its impossible to change to this class */
+}
+
+static void prio_changed_stop(struct rq *rq, struct task_struct *p,
+                             int oldprio, int running)
+{
+       BUG(); /* how!?, what priority? */
+}
+
+static unsigned int
+get_rr_interval_stop(struct rq *rq, struct task_struct *task)
+{
+       return 0;
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU stop tasks:
+ */
+static const struct sched_class stop_sched_class = {
+       .next                   = &rt_sched_class,
+
+       .enqueue_task           = enqueue_task_stop,
+       .dequeue_task           = dequeue_task_stop,
+       .yield_task             = yield_task_stop,
+
+       .check_preempt_curr     = check_preempt_curr_stop,
+
+       .pick_next_task         = pick_next_task_stop,
+       .put_prev_task          = put_prev_task_stop,
+
+#ifdef CONFIG_SMP
+       .select_task_rq         = select_task_rq_stop,
+#endif
+
+       .set_curr_task          = set_curr_task_stop,
+       .task_tick              = task_tick_stop,
+
+       .get_rr_interval        = get_rr_interval_stop,
+
+       .prio_changed           = prio_changed_stop,
+       .switched_to            = switched_to_stop,
+
+       /* no .task_new for stop tasks */
+};
index bded65187780f5f288bd779920a5c04c190528dc..919562c3d6b720d58ff246b2c412114d77c0b419 100644 (file)
@@ -2214,6 +2214,14 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)
                err |= __put_user(from->si_addr, &to->si_addr);
 #ifdef __ARCH_SI_TRAPNO
                err |= __put_user(from->si_trapno, &to->si_trapno);
+#endif
+#ifdef BUS_MCEERR_AO
+               /* 
+                * Other callers might not initialize the si_lsb field,
+                * so check explicitely for the right codes here.
+                */
+               if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
+                       err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
 #endif
                break;
        case __SI_CHLD:
index 75c970c715d399f1385d72e92e0c47c509e568dc..ed6aacfcb7efb307fe313ea798e7074f2c8f4f92 100644 (file)
@@ -365,9 +365,10 @@ call:
 EXPORT_SYMBOL_GPL(smp_call_function_any);
 
 /**
- * __smp_call_function_single(): Run a function on another CPU
+ * __smp_call_function_single(): Run a function on a specific CPU
  * @cpu: The CPU to run on.
  * @data: Pre-allocated and setup data structure
+ * @wait: If true, wait until function has completed on specified CPU.
  *
  * Like smp_call_function_single(), but allow caller to pass in a
  * pre-allocated data structure. Useful for embedding @data inside
@@ -376,8 +377,10 @@ EXPORT_SYMBOL_GPL(smp_call_function_any);
 void __smp_call_function_single(int cpu, struct call_single_data *data,
                                int wait)
 {
-       csd_lock(data);
+       unsigned int this_cpu;
+       unsigned long flags;
 
+       this_cpu = get_cpu();
        /*
         * Can deadlock when called with interrupts disabled.
         * We allow cpu's that are not yet online though, as no one else can
@@ -387,7 +390,15 @@ void __smp_call_function_single(int cpu, struct call_single_data *data,
        WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled()
                     && !oops_in_progress);
 
-       generic_exec_single(cpu, data, wait);
+       if (cpu == this_cpu) {
+               local_irq_save(flags);
+               data->func(data->info);
+               local_irq_restore(flags);
+       } else {
+               csd_lock(data);
+               generic_exec_single(cpu, data, wait);
+       }
+       put_cpu();
 }
 
 /**
index 07b4f1b1a73a9b6a309a3e7fe249c813007b5d17..fc978889b1945d2fe6c2520980db3a8410dfdb77 100644 (file)
@@ -76,12 +76,22 @@ void wakeup_softirqd(void)
                wake_up_process(tsk);
 }
 
+/*
+ * preempt_count and SOFTIRQ_OFFSET usage:
+ * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
+ *   softirq processing.
+ * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
+ *   on local_bh_disable or local_bh_enable.
+ * This lets us distinguish between whether we are currently processing
+ * softirq and whether we just have bh disabled.
+ */
+
 /*
  * This one is for softirq.c-internal use,
  * where hardirqs are disabled legitimately:
  */
 #ifdef CONFIG_TRACE_IRQFLAGS
-static void __local_bh_disable(unsigned long ip)
+static void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
        unsigned long flags;
 
@@ -95,32 +105,43 @@ static void __local_bh_disable(unsigned long ip)
         * We must manually increment preempt_count here and manually
         * call the trace_preempt_off later.
         */
-       preempt_count() += SOFTIRQ_OFFSET;
+       preempt_count() += cnt;
        /*
         * Were softirqs turned off above:
         */
-       if (softirq_count() == SOFTIRQ_OFFSET)
+       if (softirq_count() == cnt)
                trace_softirqs_off(ip);
        raw_local_irq_restore(flags);
 
-       if (preempt_count() == SOFTIRQ_OFFSET)
+       if (preempt_count() == cnt)
                trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
 }
 #else /* !CONFIG_TRACE_IRQFLAGS */
-static inline void __local_bh_disable(unsigned long ip)
+static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
-       add_preempt_count(SOFTIRQ_OFFSET);
+       add_preempt_count(cnt);
        barrier();
 }
 #endif /* CONFIG_TRACE_IRQFLAGS */
 
 void local_bh_disable(void)
 {
-       __local_bh_disable((unsigned long)__builtin_return_address(0));
+       __local_bh_disable((unsigned long)__builtin_return_address(0),
+                               SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(local_bh_disable);
 
+static void __local_bh_enable(unsigned int cnt)
+{
+       WARN_ON_ONCE(in_irq());
+       WARN_ON_ONCE(!irqs_disabled());
+
+       if (softirq_count() == cnt)
+               trace_softirqs_on((unsigned long)__builtin_return_address(0));
+       sub_preempt_count(cnt);
+}
+
 /*
  * Special-case - softirqs can safely be enabled in
  * cond_resched_softirq(), or by __do_softirq(),
@@ -128,12 +149,7 @@ EXPORT_SYMBOL(local_bh_disable);
  */
 void _local_bh_enable(void)
 {
-       WARN_ON_ONCE(in_irq());
-       WARN_ON_ONCE(!irqs_disabled());
-
-       if (softirq_count() == SOFTIRQ_OFFSET)
-               trace_softirqs_on((unsigned long)__builtin_return_address(0));
-       sub_preempt_count(SOFTIRQ_OFFSET);
+       __local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(_local_bh_enable);
@@ -147,13 +163,13 @@ static inline void _local_bh_enable_ip(unsigned long ip)
        /*
         * Are softirqs going to be turned on now:
         */
-       if (softirq_count() == SOFTIRQ_OFFSET)
+       if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
                trace_softirqs_on(ip);
        /*
         * Keep preemption disabled until we are done with
         * softirq processing:
         */
-       sub_preempt_count(SOFTIRQ_OFFSET - 1);
+       sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
 
        if (unlikely(!in_interrupt() && local_softirq_pending()))
                do_softirq();
@@ -198,7 +214,8 @@ asmlinkage void __do_softirq(void)
        pending = local_softirq_pending();
        account_system_vtime(current);
 
-       __local_bh_disable((unsigned long)__builtin_return_address(0));
+       __local_bh_disable((unsigned long)__builtin_return_address(0),
+                               SOFTIRQ_OFFSET);
        lockdep_softirq_enter();
 
        cpu = smp_processor_id();
@@ -245,7 +262,7 @@ restart:
        lockdep_softirq_exit();
 
        account_system_vtime(current);
-       _local_bh_enable();
+       __local_bh_enable(SOFTIRQ_OFFSET);
 }
 
 #ifndef __ARCH_HAS_DO_SOFTIRQ
@@ -279,10 +296,16 @@ void irq_enter(void)
 
        rcu_irq_enter();
        if (idle_cpu(cpu) && !in_interrupt()) {
-               __irq_enter();
+               /*
+                * Prevent raise_softirq from needlessly waking up ksoftirqd
+                * here, as softirq will be serviced on return from interrupt.
+                */
+               local_bh_disable();
                tick_check_idle(cpu);
-       } else
-               __irq_enter();
+               _local_bh_enable();
+       }
+
+       __irq_enter();
 }
 
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
@@ -696,6 +719,7 @@ static int run_ksoftirqd(void * __bind_cpu)
 {
        set_current_state(TASK_INTERRUPTIBLE);
 
+       current->flags |= PF_KSOFTIRQD;
        while (!kthread_should_stop()) {
                preempt_disable();
                if (!local_softirq_pending()) {
@@ -886,17 +910,14 @@ int __init __weak early_irq_init(void)
        return 0;
 }
 
+#ifdef CONFIG_GENERIC_HARDIRQS
 int __init __weak arch_probe_nr_irqs(void)
 {
-       return 0;
+       return NR_IRQS_LEGACY;
 }
 
 int __init __weak arch_early_irq_init(void)
 {
        return 0;
 }
-
-int __weak arch_init_chip_data(struct irq_desc *desc, int node)
-{
-       return 0;
-}
+#endif
index 2980da3fd50925f7902a5ba42e64934f6c4b0650..c71e075005368eceff3aab4340f94beca4aee249 100644 (file)
@@ -46,11 +46,9 @@ static int init_srcu_struct_fields(struct srcu_struct *sp)
 int __init_srcu_struct(struct srcu_struct *sp, const char *name,
                       struct lock_class_key *key)
 {
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
        /* Don't re-initialize a lock while it is held. */
        debug_check_no_locks_freed((void *)sp, sizeof(*sp));
        lockdep_init_map(&sp->dep_map, name, key, 0);
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
        return init_srcu_struct_fields(sp);
 }
 EXPORT_SYMBOL_GPL(__init_srcu_struct);
index 4372ccb25127ea8548719c78cb4a610edb94febf..090c28812ce101fbd055821fe12806265bd1ed9b 100644 (file)
@@ -287,11 +287,12 @@ repeat:
        goto repeat;
 }
 
+extern void sched_set_stop_task(int cpu, struct task_struct *stop);
+
 /* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */
 static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
                                           unsigned long action, void *hcpu)
 {
-       struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
        unsigned int cpu = (unsigned long)hcpu;
        struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
        struct task_struct *p;
@@ -304,13 +305,13 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
                                   cpu);
                if (IS_ERR(p))
                        return NOTIFY_BAD;
-               sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
                get_task_struct(p);
+               kthread_bind(p, cpu);
+               sched_set_stop_task(cpu, p);
                stopper->thread = p;
                break;
 
        case CPU_ONLINE:
-               kthread_bind(stopper->thread, cpu);
                /* strictly unnecessary, as first user will wake it */
                wake_up_process(stopper->thread);
                /* mark enabled */
@@ -325,6 +326,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
        {
                struct cpu_stop_work *work;
 
+               sched_set_stop_task(cpu, NULL);
                /* kill the stopper */
                kthread_stop(stopper->thread);
                /* drain remaining works */
index e9ad4448982860af9919df53c3368156a4bf2445..7f5a0cd296a96ca44e43f0db028026094dbbb57a 100644 (file)
@@ -931,6 +931,7 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
                pgid = pid;
        if (pgid < 0)
                return -EINVAL;
+       rcu_read_lock();
 
        /* From this point forward we keep holding onto the tasklist lock
         * so that our parent does not change from under us. -DaveM
@@ -984,6 +985,7 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 out:
        /* All paths lead to here, thus we are safe. -DaveM */
        write_unlock_irq(&tasklist_lock);
+       rcu_read_unlock();
        return err;
 }
 
index bad369ec54036afe9a2c2d87011fc99ea488755b..c782fe9924c79f052e1b81b7d12bdf53f9991a69 100644 (file)
@@ -50,6 +50,7 @@ cond_syscall(compat_sys_sendmsg);
 cond_syscall(sys_recvmsg);
 cond_syscall(sys_recvmmsg);
 cond_syscall(compat_sys_recvmsg);
+cond_syscall(compat_sys_recv);
 cond_syscall(compat_sys_recvfrom);
 cond_syscall(compat_sys_recvmmsg);
 cond_syscall(sys_socketcall);
index ca38e8e3e907557f74faaad7ddb57d330bd43d2d..3a45c224770fb82fa4bd76f9c7d4f2f989ee5aa9 100644 (file)
@@ -1713,10 +1713,7 @@ static __init int sysctl_init(void)
 {
        sysctl_set_parent(NULL, root_table);
 #ifdef CONFIG_SYSCTL_SYSCALL_CHECK
-       {
-               int err;
-               err = sysctl_check_table(current->nsproxy, root_table);
-       }
+       sysctl_check_table(current->nsproxy, root_table);
 #endif
        return 0;
 }
@@ -2488,7 +2485,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                kbuf[left] = 0;
        }
 
-       for (; left && vleft--; i++, min++, max++, first=0) {
+       for (; left && vleft--; i++, first = 0) {
                unsigned long val;
 
                if (write) {
index 04cdcf72c827e7601cdca63ab4c54a3f16473c50..10b90d8a03c48678258c6aaf3de353af7b06ed36 100644 (file)
@@ -143,15 +143,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
                                if (!table->maxlen)
                                        set_fail(&fail, table, "No maxlen");
                        }
-                       if ((table->proc_handler == proc_doulongvec_minmax) ||
-                           (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
-                               if (table->maxlen > sizeof (unsigned long)) {
-                                       if (!table->extra1)
-                                               set_fail(&fail, table, "No min");
-                                       if (!table->extra2)
-                                               set_fail(&fail, table, "No max");
-                               }
-                       }
 #ifdef CONFIG_PROC_SYSCTL
                        if (table->procname && !table->proc_handler)
                                set_fail(&fail, table, "No proc_handler");
index 4f104515a19bcb18ca73226c745786a41d41b4ae..f8b11a283171b65849c5ed3bc0e162397f76fbea 100644 (file)
@@ -115,7 +115,9 @@ static int test_kprobes(void)
        int ret;
        struct kprobe *kps[2] = {&kp, &kp2};
 
-       kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+       /* addr and flags should be cleard for reusing kprobe. */
+       kp.addr = NULL;
+       kp.flags = 0;
        ret = register_kprobes(kps, 2);
        if (ret < 0) {
                printk(KERN_ERR "Kprobe smoke test failed: "
@@ -210,7 +212,9 @@ static int test_jprobes(void)
        int ret;
        struct jprobe *jps[2] = {&jp, &jp2};
 
-       jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+       /* addr and flags should be cleard for reusing kprobe. */
+       jp.kp.addr = NULL;
+       jp.kp.flags = 0;
        ret = register_jprobes(jps, 2);
        if (ret < 0) {
                printk(KERN_ERR "Kprobe smoke test failed: "
@@ -323,7 +327,9 @@ static int test_kretprobes(void)
        int ret;
        struct kretprobe *rps[2] = {&rp, &rp2};
 
-       rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+       /* addr and flags should be cleard for reusing kprobe. */
+       rp.kp.addr = NULL;
+       rp.kp.flags = 0;
        ret = register_kretprobes(rps, 2);
        if (ret < 0) {
                printk(KERN_ERR "Kprobe smoke test failed: "
index c63116863a80294c7ce1545b2089efe1d43258d0..d2321891538f53425430565fe68197b5cde93d12 100644 (file)
@@ -149,10 +149,18 @@ static void ntp_update_offset(long offset)
        time_reftime = get_seconds();
 
        offset64    = offset;
-       freq_adj    = (offset64 * secs) <<
-                       (NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant));
+       freq_adj    = ntp_update_offset_fll(offset64, secs);
 
-       freq_adj    += ntp_update_offset_fll(offset64, secs);
+       /*
+        * Clamp update interval to reduce PLL gain with low
+        * sampling rate (e.g. intermittent network connection)
+        * to avoid instability.
+        */
+       if (unlikely(secs > 1 << (SHIFT_PLL + 1 + time_constant)))
+               secs = 1 << (SHIFT_PLL + 1 + time_constant);
+
+       freq_adj    += (offset64 * secs) <<
+                       (NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant));
 
        freq_adj    = min(freq_adj + time_freq, MAXFREQ_SCALED);
 
index 97bf05baade7cb4b9db4a5b76cf26255b6a67753..68a9ae7679b717f6eb4782ce5114ad405dec5a4c 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/delay.h>
 #include <linux/tick.h>
 #include <linux/kallsyms.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -1279,7 +1279,10 @@ void update_process_times(int user_tick)
        run_local_timers();
        rcu_check_callbacks(cpu, user_tick);
        printk_tick();
-       perf_event_do_pending();
+#ifdef CONFIG_IRQ_WORK
+       if (in_irq())
+               irq_work_run();
+#endif
        scheduler_tick();
        run_posix_cpu_timers(p);
 }
index 538501c6ea5058cf703eaa2608307f03f3aee89a..e04b8bcdef88dc92a3c52c9c53808528b0266b09 100644 (file)
@@ -49,6 +49,11 @@ config HAVE_SYSCALL_TRACEPOINTS
        help
          See Documentation/trace/ftrace-design.txt
 
+config HAVE_C_RECORDMCOUNT
+       bool
+       help
+         C version of recordmcount available?
+
 config TRACER_MAX_TRACE
        bool
 
@@ -121,7 +126,7 @@ if FTRACE
 config FUNCTION_TRACER
        bool "Kernel Function Tracer"
        depends on HAVE_FUNCTION_TRACER
-       select FRAME_POINTER
+       select FRAME_POINTER if (!ARM_UNWIND)
        select KALLSYMS
        select GENERIC_TRACER
        select CONTEXT_SWITCH_TRACER
index 959f8d6c8cc1ddad9b994dc08d096be6738fca64..bc251ed667248fb8c72a0dd59ddf3a9a42e1c23d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
-#include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
 
@@ -326,6 +325,7 @@ static const struct file_operations blk_dropped_fops = {
        .owner =        THIS_MODULE,
        .open =         blk_dropped_open,
        .read =         blk_dropped_read,
+       .llseek =       default_llseek,
 };
 
 static int blk_msg_open(struct inode *inode, struct file *filp)
@@ -365,6 +365,7 @@ static const struct file_operations blk_msg_fops = {
        .owner =        THIS_MODULE,
        .open =         blk_msg_open,
        .write =        blk_msg_write,
+       .llseek =       noop_llseek,
 };
 
 /*
@@ -639,7 +640,6 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
        if (!q)
                return -ENXIO;
 
-       lock_kernel();
        mutex_lock(&bdev->bd_mutex);
 
        switch (cmd) {
@@ -667,7 +667,6 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
        }
 
        mutex_unlock(&bdev->bd_mutex);
-       unlock_kernel();
        return ret;
 }
 
@@ -1652,10 +1651,9 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
        struct block_device *bdev;
        ssize_t ret = -ENXIO;
 
-       lock_kernel();
        bdev = bdget(part_devt(p));
        if (bdev == NULL)
-               goto out_unlock_kernel;
+               goto out;
 
        q = blk_trace_get_queue(bdev);
        if (q == NULL)
@@ -1683,8 +1681,7 @@ out_unlock_bdev:
        mutex_unlock(&bdev->bd_mutex);
 out_bdput:
        bdput(bdev);
-out_unlock_kernel:
-       unlock_kernel();
+out:
        return ret;
 }
 
@@ -1714,11 +1711,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
 
        ret = -ENXIO;
 
-       lock_kernel();
        p = dev_to_part(dev);
        bdev = bdget(part_devt(p));
        if (bdev == NULL)
-               goto out_unlock_kernel;
+               goto out;
 
        q = blk_trace_get_queue(bdev);
        if (q == NULL)
@@ -1753,8 +1749,6 @@ out_unlock_bdev:
        mutex_unlock(&bdev->bd_mutex);
 out_bdput:
        bdput(bdev);
-out_unlock_kernel:
-       unlock_kernel();
 out:
        return ret ? ret : count;
 }
index 0d88ce9b9fb8828c9a81fdffcd47763ae5cc2543..f3dadae83883e89c7f48439531bfc6ac62c0ea99 100644 (file)
@@ -381,12 +381,19 @@ static int function_stat_show(struct seq_file *m, void *v)
 {
        struct ftrace_profile *rec = v;
        char str[KSYM_SYMBOL_LEN];
+       int ret = 0;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       static DEFINE_MUTEX(mutex);
        static struct trace_seq s;
        unsigned long long avg;
        unsigned long long stddev;
 #endif
+       mutex_lock(&ftrace_profile_lock);
+
+       /* we raced with function_profile_reset() */
+       if (unlikely(rec->counter == 0)) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
        seq_printf(m, "  %-30.30s  %10lu", str, rec->counter);
@@ -408,7 +415,6 @@ static int function_stat_show(struct seq_file *m, void *v)
                do_div(stddev, (rec->counter - 1) * 1000);
        }
 
-       mutex_lock(&mutex);
        trace_seq_init(&s);
        trace_print_graph_duration(rec->time, &s);
        trace_seq_puts(&s, "    ");
@@ -416,11 +422,12 @@ static int function_stat_show(struct seq_file *m, void *v)
        trace_seq_puts(&s, "    ");
        trace_print_graph_duration(stddev, &s);
        trace_print_seq(m, &s);
-       mutex_unlock(&mutex);
 #endif
        seq_putc(m, '\n');
+out:
+       mutex_unlock(&ftrace_profile_lock);
 
-       return 0;
+       return ret;
 }
 
 static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
@@ -793,6 +800,7 @@ static const struct file_operations ftrace_profile_fops = {
        .open           = tracing_open_generic,
        .read           = ftrace_profile_read,
        .write          = ftrace_profile_write,
+       .llseek         = default_llseek,
 };
 
 /* used to initialize the real stat files */
@@ -877,10 +885,8 @@ enum {
        FTRACE_ENABLE_CALLS             = (1 << 0),
        FTRACE_DISABLE_CALLS            = (1 << 1),
        FTRACE_UPDATE_TRACE_FUNC        = (1 << 2),
-       FTRACE_ENABLE_MCOUNT            = (1 << 3),
-       FTRACE_DISABLE_MCOUNT           = (1 << 4),
-       FTRACE_START_FUNC_RET           = (1 << 5),
-       FTRACE_STOP_FUNC_RET            = (1 << 6),
+       FTRACE_START_FUNC_RET           = (1 << 3),
+       FTRACE_STOP_FUNC_RET            = (1 << 4),
 };
 
 static int ftrace_filtered;
@@ -1219,8 +1225,6 @@ static void ftrace_shutdown(int command)
 
 static void ftrace_startup_sysctl(void)
 {
-       int command = FTRACE_ENABLE_MCOUNT;
-
        if (unlikely(ftrace_disabled))
                return;
 
@@ -1228,23 +1232,17 @@ static void ftrace_startup_sysctl(void)
        saved_ftrace_func = NULL;
        /* ftrace_start_up is true if we want ftrace running */
        if (ftrace_start_up)
-               command |= FTRACE_ENABLE_CALLS;
-
-       ftrace_run_update_code(command);
+               ftrace_run_update_code(FTRACE_ENABLE_CALLS);
 }
 
 static void ftrace_shutdown_sysctl(void)
 {
-       int command = FTRACE_DISABLE_MCOUNT;
-
        if (unlikely(ftrace_disabled))
                return;
 
        /* ftrace_start_up is true if ftrace is running */
        if (ftrace_start_up)
-               command |= FTRACE_DISABLE_CALLS;
-
-       ftrace_run_update_code(command);
+               ftrace_run_update_code(FTRACE_DISABLE_CALLS);
 }
 
 static cycle_t         ftrace_update_time;
@@ -1361,24 +1359,29 @@ enum {
 #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
 
 struct ftrace_iterator {
-       struct ftrace_page      *pg;
-       int                     hidx;
-       int                     idx;
-       unsigned                flags;
-       struct trace_parser     parser;
+       loff_t                          pos;
+       loff_t                          func_pos;
+       struct ftrace_page              *pg;
+       struct dyn_ftrace               *func;
+       struct ftrace_func_probe        *probe;
+       struct trace_parser             parser;
+       int                             hidx;
+       int                             idx;
+       unsigned                        flags;
 };
 
 static void *
-t_hash_next(struct seq_file *m, void *v, loff_t *pos)
+t_hash_next(struct seq_file *m, loff_t *pos)
 {
        struct ftrace_iterator *iter = m->private;
-       struct hlist_node *hnd = v;
+       struct hlist_node *hnd = NULL;
        struct hlist_head *hhd;
 
-       WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
-
        (*pos)++;
+       iter->pos = *pos;
 
+       if (iter->probe)
+               hnd = &iter->probe->node;
  retry:
        if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
                return NULL;
@@ -1401,7 +1404,12 @@ t_hash_next(struct seq_file *m, void *v, loff_t *pos)
                }
        }
 
-       return hnd;
+       if (WARN_ON_ONCE(!hnd))
+               return NULL;
+
+       iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
+
+       return iter;
 }
 
 static void *t_hash_start(struct seq_file *m, loff_t *pos)
@@ -1410,26 +1418,32 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos)
        void *p = NULL;
        loff_t l;
 
-       if (!(iter->flags & FTRACE_ITER_HASH))
-               *pos = 0;
-
-       iter->flags |= FTRACE_ITER_HASH;
+       if (iter->func_pos > *pos)
+               return NULL;
 
        iter->hidx = 0;
-       for (l = 0; l <= *pos; ) {
-               p = t_hash_next(m, p, &l);
+       for (l = 0; l <= (*pos - iter->func_pos); ) {
+               p = t_hash_next(m, &l);
                if (!p)
                        break;
        }
-       return p;
+       if (!p)
+               return NULL;
+
+       /* Only set this if we have an item */
+       iter->flags |= FTRACE_ITER_HASH;
+
+       return iter;
 }
 
-static int t_hash_show(struct seq_file *m, void *v)
+static int
+t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
 {
        struct ftrace_func_probe *rec;
-       struct hlist_node *hnd = v;
 
-       rec = hlist_entry(hnd, struct ftrace_func_probe, node);
+       rec = iter->probe;
+       if (WARN_ON_ONCE(!rec))
+               return -EIO;
 
        if (rec->ops->print)
                return rec->ops->print(m, rec->ip, rec->ops, rec->data);
@@ -1450,12 +1464,13 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
        struct dyn_ftrace *rec = NULL;
 
        if (iter->flags & FTRACE_ITER_HASH)
-               return t_hash_next(m, v, pos);
+               return t_hash_next(m, pos);
 
        (*pos)++;
+       iter->pos = *pos;
 
        if (iter->flags & FTRACE_ITER_PRINTALL)
-               return NULL;
+               return t_hash_start(m, pos);
 
  retry:
        if (iter->idx >= iter->pg->index) {
@@ -1484,7 +1499,20 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                }
        }
 
-       return rec;
+       if (!rec)
+               return t_hash_start(m, pos);
+
+       iter->func_pos = *pos;
+       iter->func = rec;
+
+       return iter;
+}
+
+static void reset_iter_read(struct ftrace_iterator *iter)
+{
+       iter->pos = 0;
+       iter->func_pos = 0;
+       iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH);
 }
 
 static void *t_start(struct seq_file *m, loff_t *pos)
@@ -1494,6 +1522,12 @@ static void *t_start(struct seq_file *m, loff_t *pos)
        loff_t l;
 
        mutex_lock(&ftrace_lock);
+       /*
+        * If an lseek was done, then reset and start from beginning.
+        */
+       if (*pos < iter->pos)
+               reset_iter_read(iter);
+
        /*
         * For set_ftrace_filter reading, if we have the filter
         * off, we can short cut and just print out that all
@@ -1503,12 +1537,19 @@ static void *t_start(struct seq_file *m, loff_t *pos)
                if (*pos > 0)
                        return t_hash_start(m, pos);
                iter->flags |= FTRACE_ITER_PRINTALL;
+               /* reset in case of seek/pread */
+               iter->flags &= ~FTRACE_ITER_HASH;
                return iter;
        }
 
        if (iter->flags & FTRACE_ITER_HASH)
                return t_hash_start(m, pos);
 
+       /*
+        * Unfortunately, we need to restart at ftrace_pages_start
+        * every time we let go of the ftrace_mutex. This is because
+        * those pointers can change without the lock.
+        */
        iter->pg = ftrace_pages_start;
        iter->idx = 0;
        for (l = 0; l <= *pos; ) {
@@ -1517,10 +1558,14 @@ static void *t_start(struct seq_file *m, loff_t *pos)
                        break;
        }
 
-       if (!p && iter->flags & FTRACE_ITER_FILTER)
-               return t_hash_start(m, pos);
+       if (!p) {
+               if (iter->flags & FTRACE_ITER_FILTER)
+                       return t_hash_start(m, pos);
 
-       return p;
+               return NULL;
+       }
+
+       return iter;
 }
 
 static void t_stop(struct seq_file *m, void *p)
@@ -1531,16 +1576,18 @@ static void t_stop(struct seq_file *m, void *p)
 static int t_show(struct seq_file *m, void *v)
 {
        struct ftrace_iterator *iter = m->private;
-       struct dyn_ftrace *rec = v;
+       struct dyn_ftrace *rec;
 
        if (iter->flags & FTRACE_ITER_HASH)
-               return t_hash_show(m, v);
+               return t_hash_show(m, iter);
 
        if (iter->flags & FTRACE_ITER_PRINTALL) {
                seq_printf(m, "#### all functions enabled ####\n");
                return 0;
        }
 
+       rec = iter->func;
+
        if (!rec)
                return 0;
 
@@ -1592,8 +1639,8 @@ ftrace_failures_open(struct inode *inode, struct file *file)
 
        ret = ftrace_avail_open(inode, file);
        if (!ret) {
-               m = (struct seq_file *)file->private_data;
-               iter = (struct ftrace_iterator *)m->private;
+               m = file->private_data;
+               iter = m->private;
                iter->flags = FTRACE_ITER_FAILURES;
        }
 
@@ -2623,6 +2670,7 @@ static const struct file_operations ftrace_graph_fops = {
        .read           = seq_read,
        .write          = ftrace_graph_write,
        .release        = ftrace_graph_release,
+       .llseek         = seq_lseek,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
index 19cccc3c302871beae5fd39ad937b0791a2e785d..c3dab054d18e2ff43b618ad29693351d0accc872 100644 (file)
@@ -405,7 +405,7 @@ static inline int test_time_stamp(u64 delta)
 #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2))
 
 /* Max number of timestamps that can fit on a page */
-#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_STAMP)
+#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND)
 
 int ring_buffer_print_page_header(struct trace_seq *s)
 {
@@ -2606,6 +2606,19 @@ void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu);
 
+/*
+ * The total entries in the ring buffer is the running counter
+ * of entries entered into the ring buffer, minus the sum of
+ * the entries read from the ring buffer and the number of
+ * entries that were overwritten.
+ */
+static inline unsigned long
+rb_num_of_entries(struct ring_buffer_per_cpu *cpu_buffer)
+{
+       return local_read(&cpu_buffer->entries) -
+               (local_read(&cpu_buffer->overrun) + cpu_buffer->read);
+}
+
 /**
  * ring_buffer_entries_cpu - get the number of entries in a cpu buffer
  * @buffer: The ring buffer
@@ -2614,16 +2627,13 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu);
 unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
-       unsigned long ret;
 
        if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return 0;
 
        cpu_buffer = buffer->buffers[cpu];
-       ret = (local_read(&cpu_buffer->entries) - local_read(&cpu_buffer->overrun))
-               - cpu_buffer->read;
 
-       return ret;
+       return rb_num_of_entries(cpu_buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu);
 
@@ -2684,8 +2694,7 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer)
        /* if you care about this being correct, lock the buffer */
        for_each_buffer_cpu(buffer, cpu) {
                cpu_buffer = buffer->buffers[cpu];
-               entries += (local_read(&cpu_buffer->entries) -
-                           local_read(&cpu_buffer->overrun)) - cpu_buffer->read;
+               entries += rb_num_of_entries(cpu_buffer);
        }
 
        return entries;
@@ -2985,13 +2994,11 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer)
 
 static void rb_advance_iter(struct ring_buffer_iter *iter)
 {
-       struct ring_buffer *buffer;
        struct ring_buffer_per_cpu *cpu_buffer;
        struct ring_buffer_event *event;
        unsigned length;
 
        cpu_buffer = iter->cpu_buffer;
-       buffer = cpu_buffer->buffer;
 
        /*
         * Check if we are at the end of the buffer.
@@ -3967,6 +3974,7 @@ static const struct file_operations rb_simple_fops = {
        .open           = tracing_open_generic,
        .read           = rb_simple_read,
        .write          = rb_simple_write,
+       .llseek         = default_llseek,
 };
 
 
index 9ec59f541156625b5c4b0aea9267086c928ae07a..001bcd2ccf4afb5170cb06d500bcff90844bf90e 100644 (file)
@@ -2196,7 +2196,7 @@ int tracing_open_generic(struct inode *inode, struct file *filp)
 
 static int tracing_release(struct inode *inode, struct file *file)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
+       struct seq_file *m = file->private_data;
        struct trace_iterator *iter;
        int cpu;
 
index d39b3c5454a5e684b8c720e0791894b36529f1cf..9021f8c0c0c3e379edbd8f39770bd9345794e266 100644 (file)
@@ -343,6 +343,10 @@ void trace_function(struct trace_array *tr,
                    unsigned long ip,
                    unsigned long parent_ip,
                    unsigned long flags, int pc);
+void trace_graph_function(struct trace_array *tr,
+                   unsigned long ip,
+                   unsigned long parent_ip,
+                   unsigned long flags, int pc);
 void trace_default_header(struct seq_file *m);
 void print_trace_header(struct seq_file *m, struct trace_iterator *iter);
 int trace_empty(struct trace_iterator *iter);
index 000e6e85b445906893d7003b2f28c615453bb726..39c059ca670e64156e6681782ffa708c6b8d720f 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kprobes.h>
 #include "trace.h"
 
-static char *perf_trace_buf[4];
+static char __percpu *perf_trace_buf[PERF_NR_CONTEXTS];
 
 /*
  * Force it to be aligned to unsigned long to avoid misaligned accesses
@@ -24,7 +24,7 @@ static int    total_ref_count;
 static int perf_trace_event_init(struct ftrace_event_call *tp_event,
                                 struct perf_event *p_event)
 {
-       struct hlist_head *list;
+       struct hlist_head __percpu *list;
        int ret = -ENOMEM;
        int cpu;
 
@@ -42,11 +42,11 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
        tp_event->perf_events = list;
 
        if (!total_ref_count) {
-               char *buf;
+               char __percpu *buf;
                int i;
 
-               for (i = 0; i < 4; i++) {
-                       buf = (char *)alloc_percpu(perf_trace_t);
+               for (i = 0; i < PERF_NR_CONTEXTS; i++) {
+                       buf = (char __percpu *)alloc_percpu(perf_trace_t);
                        if (!buf)
                                goto fail;
 
@@ -65,7 +65,7 @@ fail:
        if (!total_ref_count) {
                int i;
 
-               for (i = 0; i < 4; i++) {
+               for (i = 0; i < PERF_NR_CONTEXTS; i++) {
                        free_percpu(perf_trace_buf[i]);
                        perf_trace_buf[i] = NULL;
                }
@@ -91,6 +91,8 @@ int perf_trace_init(struct perf_event *p_event)
                    tp_event->class && tp_event->class->reg &&
                    try_module_get(tp_event->mod)) {
                        ret = perf_trace_event_init(tp_event, p_event);
+                       if (ret)
+                               module_put(tp_event->mod);
                        break;
                }
        }
@@ -99,22 +101,26 @@ int perf_trace_init(struct perf_event *p_event)
        return ret;
 }
 
-int perf_trace_enable(struct perf_event *p_event)
+int perf_trace_add(struct perf_event *p_event, int flags)
 {
        struct ftrace_event_call *tp_event = p_event->tp_event;
+       struct hlist_head __percpu *pcpu_list;
        struct hlist_head *list;
 
-       list = tp_event->perf_events;
-       if (WARN_ON_ONCE(!list))
+       pcpu_list = tp_event->perf_events;
+       if (WARN_ON_ONCE(!pcpu_list))
                return -EINVAL;
 
-       list = this_cpu_ptr(list);
+       if (!(flags & PERF_EF_START))
+               p_event->hw.state = PERF_HES_STOPPED;
+
+       list = this_cpu_ptr(pcpu_list);
        hlist_add_head_rcu(&p_event->hlist_entry, list);
 
        return 0;
 }
 
-void perf_trace_disable(struct perf_event *p_event)
+void perf_trace_del(struct perf_event *p_event, int flags)
 {
        hlist_del_rcu(&p_event->hlist_entry);
 }
@@ -140,12 +146,13 @@ void perf_trace_destroy(struct perf_event *p_event)
        tp_event->perf_events = NULL;
 
        if (!--total_ref_count) {
-               for (i = 0; i < 4; i++) {
+               for (i = 0; i < PERF_NR_CONTEXTS; i++) {
                        free_percpu(perf_trace_buf[i]);
                        perf_trace_buf[i] = NULL;
                }
        }
 out:
+       module_put(tp_event->mod);
        mutex_unlock(&event_mutex);
 }
 
index 4c758f146328f18ce82a318fb60a0413006aca8f..0725eeab1937ef24a301f2c0b0404f64ce95e026 100644 (file)
@@ -600,21 +600,29 @@ out:
 
 enum {
        FORMAT_HEADER           = 1,
-       FORMAT_PRINTFMT         = 2,
+       FORMAT_FIELD_SEPERATOR  = 2,
+       FORMAT_PRINTFMT         = 3,
 };
 
 static void *f_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct ftrace_event_call *call = m->private;
        struct ftrace_event_field *field;
-       struct list_head *head;
+       struct list_head *common_head = &ftrace_common_fields;
+       struct list_head *head = trace_get_fields(call);
 
        (*pos)++;
 
        switch ((unsigned long)v) {
        case FORMAT_HEADER:
-               head = &ftrace_common_fields;
+               if (unlikely(list_empty(common_head)))
+                       return NULL;
+
+               field = list_entry(common_head->prev,
+                                  struct ftrace_event_field, link);
+               return field;
 
+       case FORMAT_FIELD_SEPERATOR:
                if (unlikely(list_empty(head)))
                        return NULL;
 
@@ -626,31 +634,10 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos)
                return NULL;
        }
 
-       head = trace_get_fields(call);
-
-       /*
-        * To separate common fields from event fields, the
-        * LSB is set on the first event field. Clear it in case.
-        */
-       v = (void *)((unsigned long)v & ~1L);
-
        field = v;
-       /*
-        * If this is a common field, and at the end of the list, then
-        * continue with main list.
-        */
-       if (field->link.prev == &ftrace_common_fields) {
-               if (unlikely(list_empty(head)))
-                       return NULL;
-               field = list_entry(head->prev, struct ftrace_event_field, link);
-               /* Set the LSB to notify f_show to print an extra newline */
-               field = (struct ftrace_event_field *)
-                       ((unsigned long)field | 1);
-               return field;
-       }
-
-       /* If we are done tell f_show to print the format */
-       if (field->link.prev == head)
+       if (field->link.prev == common_head)
+               return (void *)FORMAT_FIELD_SEPERATOR;
+       else if (field->link.prev == head)
                return (void *)FORMAT_PRINTFMT;
 
        field = list_entry(field->link.prev, struct ftrace_event_field, link);
@@ -688,22 +675,16 @@ static int f_show(struct seq_file *m, void *v)
                seq_printf(m, "format:\n");
                return 0;
 
+       case FORMAT_FIELD_SEPERATOR:
+               seq_putc(m, '\n');
+               return 0;
+
        case FORMAT_PRINTFMT:
                seq_printf(m, "\nprint fmt: %s\n",
                           call->print_fmt);
                return 0;
        }
 
-       /*
-        * To separate common fields from event fields, the
-        * LSB is set on the first event field. Clear it and
-        * print a newline if it is set.
-        */
-       if ((unsigned long)v & 1) {
-               seq_putc(m, '\n');
-               v = (void *)((unsigned long)v & ~1L);
-       }
-
        field = v;
 
        /*
@@ -951,6 +932,7 @@ static const struct file_operations ftrace_enable_fops = {
        .open = tracing_open_generic,
        .read = event_enable_read,
        .write = event_enable_write,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_format_fops = {
@@ -963,29 +945,34 @@ static const struct file_operations ftrace_event_format_fops = {
 static const struct file_operations ftrace_event_id_fops = {
        .open = tracing_open_generic,
        .read = event_id_read,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_filter_fops = {
        .open = tracing_open_generic,
        .read = event_filter_read,
        .write = event_filter_write,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_subsystem_filter_fops = {
        .open = tracing_open_generic,
        .read = subsystem_filter_read,
        .write = subsystem_filter_write,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_system_enable_fops = {
        .open = tracing_open_generic,
        .read = system_enable_read,
        .write = system_enable_write,
+       .llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_show_header_fops = {
        .open = tracing_open_generic,
        .read = show_header,
+       .llseek = default_llseek,
 };
 
 static struct dentry *event_trace_events_dir(void)
index 6f233698518ede15cc9302e889de9f108aa0f1cb..76b05980225cb79df8bfad7bb35cd64bd52bcaf2 100644 (file)
 #include "trace.h"
 #include "trace_output.h"
 
+/* When set, irq functions will be ignored */
+static int ftrace_graph_skip_irqs;
+
 struct fgraph_cpu_data {
        pid_t           last_pid;
        int             depth;
+       int             depth_irq;
        int             ignore;
        unsigned long   enter_funcs[FTRACE_RETFUNC_DEPTH];
 };
 
 struct fgraph_data {
-       struct fgraph_cpu_data          *cpu_data;
+       struct fgraph_cpu_data __percpu *cpu_data;
 
        /* Place to preserve last processed entry. */
        struct ftrace_graph_ent_entry   ent;
@@ -41,6 +45,7 @@ struct fgraph_data {
 #define TRACE_GRAPH_PRINT_PROC         0x8
 #define TRACE_GRAPH_PRINT_DURATION     0x10
 #define TRACE_GRAPH_PRINT_ABS_TIME     0x20
+#define TRACE_GRAPH_PRINT_IRQS         0x40
 
 static struct tracer_opt trace_opts[] = {
        /* Display overruns? (for self-debug purpose) */
@@ -55,13 +60,15 @@ static struct tracer_opt trace_opts[] = {
        { TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
        /* Display absolute time of an entry */
        { TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
+       /* Display interrupts */
+       { TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) },
        { } /* Empty entry */
 };
 
 static struct tracer_flags tracer_flags = {
        /* Don't display overruns and proc by default */
        .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
-              TRACE_GRAPH_PRINT_DURATION,
+              TRACE_GRAPH_PRINT_DURATION | TRACE_GRAPH_PRINT_IRQS,
        .opts = trace_opts
 };
 
@@ -204,6 +211,14 @@ int __trace_graph_entry(struct trace_array *tr,
        return 1;
 }
 
+static inline int ftrace_graph_ignore_irqs(void)
+{
+       if (!ftrace_graph_skip_irqs)
+               return 0;
+
+       return in_irq();
+}
+
 int trace_graph_entry(struct ftrace_graph_ent *trace)
 {
        struct trace_array *tr = graph_array;
@@ -218,7 +233,8 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
                return 0;
 
        /* trace it when it is-nested-in or is a function enabled. */
-       if (!(trace->depth || ftrace_graph_addr(trace->func)))
+       if (!(trace->depth || ftrace_graph_addr(trace->func)) ||
+             ftrace_graph_ignore_irqs())
                return 0;
 
        local_irq_save(flags);
@@ -246,6 +262,34 @@ int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
                return trace_graph_entry(trace);
 }
 
+static void
+__trace_graph_function(struct trace_array *tr,
+               unsigned long ip, unsigned long flags, int pc)
+{
+       u64 time = trace_clock_local();
+       struct ftrace_graph_ent ent = {
+               .func  = ip,
+               .depth = 0,
+       };
+       struct ftrace_graph_ret ret = {
+               .func     = ip,
+               .depth    = 0,
+               .calltime = time,
+               .rettime  = time,
+       };
+
+       __trace_graph_entry(tr, &ent, flags, pc);
+       __trace_graph_return(tr, &ret, flags, pc);
+}
+
+void
+trace_graph_function(struct trace_array *tr,
+               unsigned long ip, unsigned long parent_ip,
+               unsigned long flags, int pc)
+{
+       __trace_graph_function(tr, ip, flags, pc);
+}
+
 void __trace_graph_return(struct trace_array *tr,
                                struct ftrace_graph_ret *trace,
                                unsigned long flags,
@@ -649,8 +693,9 @@ trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
 
        /* Print nsecs (we don't want to exceed 7 numbers) */
        if (len < 7) {
-               snprintf(nsecs_str, min(sizeof(nsecs_str), 8UL - len), "%03lu",
-                        nsecs_rem);
+               size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len);
+
+               snprintf(nsecs_str, slen, "%03lu", nsecs_rem);
                ret = trace_seq_printf(s, ".%s", nsecs_str);
                if (!ret)
                        return TRACE_TYPE_PARTIAL_LINE;
@@ -855,6 +900,108 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
        return 0;
 }
 
+/*
+ * Entry check for irq code
+ *
+ * returns 1 if
+ *  - we are inside irq code
+ *  - we just extered irq code
+ *
+ * retunns 0 if
+ *  - funcgraph-interrupts option is set
+ *  - we are not inside irq code
+ */
+static int
+check_irq_entry(struct trace_iterator *iter, u32 flags,
+               unsigned long addr, int depth)
+{
+       int cpu = iter->cpu;
+       int *depth_irq;
+       struct fgraph_data *data = iter->private;
+
+       /*
+        * If we are either displaying irqs, or we got called as
+        * a graph event and private data does not exist,
+        * then we bypass the irq check.
+        */
+       if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
+           (!data))
+               return 0;
+
+       depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
+       /*
+        * We are inside the irq code
+        */
+       if (*depth_irq >= 0)
+               return 1;
+
+       if ((addr < (unsigned long)__irqentry_text_start) ||
+           (addr >= (unsigned long)__irqentry_text_end))
+               return 0;
+
+       /*
+        * We are entering irq code.
+        */
+       *depth_irq = depth;
+       return 1;
+}
+
+/*
+ * Return check for irq code
+ *
+ * returns 1 if
+ *  - we are inside irq code
+ *  - we just left irq code
+ *
+ * returns 0 if
+ *  - funcgraph-interrupts option is set
+ *  - we are not inside irq code
+ */
+static int
+check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
+{
+       int cpu = iter->cpu;
+       int *depth_irq;
+       struct fgraph_data *data = iter->private;
+
+       /*
+        * If we are either displaying irqs, or we got called as
+        * a graph event and private data does not exist,
+        * then we bypass the irq check.
+        */
+       if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
+           (!data))
+               return 0;
+
+       depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
+       /*
+        * We are not inside the irq code.
+        */
+       if (*depth_irq == -1)
+               return 0;
+
+       /*
+        * We are inside the irq code, and this is returning entry.
+        * Let's not trace it and clear the entry depth, since
+        * we are out of irq code.
+        *
+        * This condition ensures that we 'leave the irq code' once
+        * we are out of the entry depth. Thus protecting us from
+        * the RETURN entry loss.
+        */
+       if (*depth_irq >= depth) {
+               *depth_irq = -1;
+               return 1;
+       }
+
+       /*
+        * We are inside the irq code, and this is not the entry.
+        */
+       return 1;
+}
+
 static enum print_line_t
 print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
                        struct trace_iterator *iter, u32 flags)
@@ -865,6 +1012,9 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
        static enum print_line_t ret;
        int cpu = iter->cpu;
 
+       if (check_irq_entry(iter, flags, call->func, call->depth))
+               return TRACE_TYPE_HANDLED;
+
        if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags))
                return TRACE_TYPE_PARTIAL_LINE;
 
@@ -902,6 +1052,9 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
        int ret;
        int i;
 
+       if (check_irq_return(iter, flags, trace->depth))
+               return TRACE_TYPE_HANDLED;
+
        if (data) {
                struct fgraph_cpu_data *cpu_data;
                int cpu = iter->cpu;
@@ -1054,7 +1207,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
 
 
 enum print_line_t
-print_graph_function_flags(struct trace_iterator *iter, u32 flags)
+__print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 {
        struct ftrace_graph_ent_entry *field;
        struct fgraph_data *data = iter->private;
@@ -1117,7 +1270,18 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 static enum print_line_t
 print_graph_function(struct trace_iterator *iter)
 {
-       return print_graph_function_flags(iter, tracer_flags.val);
+       return __print_graph_function_flags(iter, tracer_flags.val);
+}
+
+enum print_line_t print_graph_function_flags(struct trace_iterator *iter,
+                                            u32 flags)
+{
+       if (trace_flags & TRACE_ITER_LATENCY_FMT)
+               flags |= TRACE_GRAPH_PRINT_DURATION;
+       else
+               flags |= TRACE_GRAPH_PRINT_ABS_TIME;
+
+       return __print_graph_function_flags(iter, flags);
 }
 
 static enum print_line_t
@@ -1149,7 +1313,7 @@ static void print_lat_header(struct seq_file *s, u32 flags)
        seq_printf(s, "#%.*s|||| /                     \n", size, spaces);
 }
 
-void print_graph_headers_flags(struct seq_file *s, u32 flags)
+static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
 {
        int lat = trace_flags & TRACE_ITER_LATENCY_FMT;
 
@@ -1190,6 +1354,23 @@ void print_graph_headers(struct seq_file *s)
        print_graph_headers_flags(s, tracer_flags.val);
 }
 
+void print_graph_headers_flags(struct seq_file *s, u32 flags)
+{
+       struct trace_iterator *iter = s->private;
+
+       if (trace_flags & TRACE_ITER_LATENCY_FMT) {
+               /* print nothing if the buffers are empty */
+               if (trace_empty(iter))
+                       return;
+
+               print_trace_header(s, iter);
+               flags |= TRACE_GRAPH_PRINT_DURATION;
+       } else
+               flags |= TRACE_GRAPH_PRINT_ABS_TIME;
+
+       __print_graph_headers_flags(s, flags);
+}
+
 void graph_trace_open(struct trace_iterator *iter)
 {
        /* pid and depth on the last trace processed */
@@ -1210,9 +1391,12 @@ void graph_trace_open(struct trace_iterator *iter)
                pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
                int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
                int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore);
+               int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
                *pid = -1;
                *depth = 0;
                *ignore = 0;
+               *depth_irq = -1;
        }
 
        iter->private = data;
@@ -1235,6 +1419,14 @@ void graph_trace_close(struct trace_iterator *iter)
        }
 }
 
+static int func_graph_set_flag(u32 old_flags, u32 bit, int set)
+{
+       if (bit == TRACE_GRAPH_PRINT_IRQS)
+               ftrace_graph_skip_irqs = !set;
+
+       return 0;
+}
+
 static struct trace_event_functions graph_functions = {
        .trace          = print_graph_function_event,
 };
@@ -1261,6 +1453,7 @@ static struct tracer graph_trace __read_mostly = {
        .print_line     = print_graph_function,
        .print_header   = print_graph_headers,
        .flags          = &tracer_flags,
+       .set_flag       = func_graph_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest       = trace_selftest_startup_function_graph,
 #endif
index 73a6b0601f2e301c0cd5575cc96f7f0b788853d9..5cf8c602b8804c054bbed65475b4815fd29d5b82 100644 (file)
@@ -87,14 +87,22 @@ static __cacheline_aligned_in_smp   unsigned long max_sequence;
 
 #ifdef CONFIG_FUNCTION_TRACER
 /*
- * irqsoff uses its own tracer function to keep the overhead down:
+ * Prologue for the preempt and irqs off function tracers.
+ *
+ * Returns 1 if it is OK to continue, and data->disabled is
+ *            incremented.
+ *         0 if the trace is to be ignored, and data->disabled
+ *            is kept the same.
+ *
+ * Note, this function is also used outside this ifdef but
+ *  inside the #ifdef of the function graph tracer below.
+ *  This is OK, since the function graph tracer is
+ *  dependent on the function tracer.
  */
-static void
-irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
+static int func_prolog_dec(struct trace_array *tr,
+                          struct trace_array_cpu **data,
+                          unsigned long *flags)
 {
-       struct trace_array *tr = irqsoff_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
        long disabled;
        int cpu;
 
@@ -106,18 +114,38 @@ irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
         */
        cpu = raw_smp_processor_id();
        if (likely(!per_cpu(tracing_cpu, cpu)))
-               return;
+               return 0;
 
-       local_save_flags(flags);
+       local_save_flags(*flags);
        /* slight chance to get a false positive on tracing_cpu */
-       if (!irqs_disabled_flags(flags))
-               return;
+       if (!irqs_disabled_flags(*flags))
+               return 0;
 
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
+       *data = tr->data[cpu];
+       disabled = atomic_inc_return(&(*data)->disabled);
 
        if (likely(disabled == 1))
-               trace_function(tr, ip, parent_ip, flags, preempt_count());
+               return 1;
+
+       atomic_dec(&(*data)->disabled);
+
+       return 0;
+}
+
+/*
+ * irqsoff uses its own tracer function to keep the overhead down:
+ */
+static void
+irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
+{
+       struct trace_array *tr = irqsoff_trace;
+       struct trace_array_cpu *data;
+       unsigned long flags;
+
+       if (!func_prolog_dec(tr, &data, &flags))
+               return;
+
+       trace_function(tr, ip, parent_ip, flags, preempt_count());
 
        atomic_dec(&data->disabled);
 }
@@ -155,30 +183,16 @@ static int irqsoff_graph_entry(struct ftrace_graph_ent *trace)
        struct trace_array *tr = irqsoff_trace;
        struct trace_array_cpu *data;
        unsigned long flags;
-       long disabled;
        int ret;
-       int cpu;
        int pc;
 
-       cpu = raw_smp_processor_id();
-       if (likely(!per_cpu(tracing_cpu, cpu)))
+       if (!func_prolog_dec(tr, &data, &flags))
                return 0;
 
-       local_save_flags(flags);
-       /* slight chance to get a false positive on tracing_cpu */
-       if (!irqs_disabled_flags(flags))
-               return 0;
-
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
-
-       if (likely(disabled == 1)) {
-               pc = preempt_count();
-               ret = __trace_graph_entry(tr, trace, flags, pc);
-       } else
-               ret = 0;
-
+       pc = preempt_count();
+       ret = __trace_graph_entry(tr, trace, flags, pc);
        atomic_dec(&data->disabled);
+
        return ret;
 }
 
@@ -187,27 +201,13 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
        struct trace_array *tr = irqsoff_trace;
        struct trace_array_cpu *data;
        unsigned long flags;
-       long disabled;
-       int cpu;
        int pc;
 
-       cpu = raw_smp_processor_id();
-       if (likely(!per_cpu(tracing_cpu, cpu)))
+       if (!func_prolog_dec(tr, &data, &flags))
                return;
 
-       local_save_flags(flags);
-       /* slight chance to get a false positive on tracing_cpu */
-       if (!irqs_disabled_flags(flags))
-               return;
-
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
-
-       if (likely(disabled == 1)) {
-               pc = preempt_count();
-               __trace_graph_return(tr, trace, flags, pc);
-       }
-
+       pc = preempt_count();
+       __trace_graph_return(tr, trace, flags, pc);
        atomic_dec(&data->disabled);
 }
 
@@ -229,75 +229,33 @@ static void irqsoff_trace_close(struct trace_iterator *iter)
 
 static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
 {
-       u32 flags = GRAPH_TRACER_FLAGS;
-
-       if (trace_flags & TRACE_ITER_LATENCY_FMT)
-               flags |= TRACE_GRAPH_PRINT_DURATION;
-       else
-               flags |= TRACE_GRAPH_PRINT_ABS_TIME;
-
        /*
         * In graph mode call the graph tracer output function,
         * otherwise go with the TRACE_FN event handler
         */
        if (is_graph())
-               return print_graph_function_flags(iter, flags);
+               return print_graph_function_flags(iter, GRAPH_TRACER_FLAGS);
 
        return TRACE_TYPE_UNHANDLED;
 }
 
 static void irqsoff_print_header(struct seq_file *s)
 {
-       if (is_graph()) {
-               struct trace_iterator *iter = s->private;
-               u32 flags = GRAPH_TRACER_FLAGS;
-
-               if (trace_flags & TRACE_ITER_LATENCY_FMT) {
-                       /* print nothing if the buffers are empty */
-                       if (trace_empty(iter))
-                               return;
-
-                       print_trace_header(s, iter);
-                       flags |= TRACE_GRAPH_PRINT_DURATION;
-               } else
-                       flags |= TRACE_GRAPH_PRINT_ABS_TIME;
-
-               print_graph_headers_flags(s, flags);
-       } else
+       if (is_graph())
+               print_graph_headers_flags(s, GRAPH_TRACER_FLAGS);
+       else
                trace_default_header(s);
 }
 
-static void
-trace_graph_function(struct trace_array *tr,
-                unsigned long ip, unsigned long flags, int pc)
-{
-       u64 time = trace_clock_local();
-       struct ftrace_graph_ent ent = {
-               .func  = ip,
-               .depth = 0,
-       };
-       struct ftrace_graph_ret ret = {
-               .func     = ip,
-               .depth    = 0,
-               .calltime = time,
-               .rettime  = time,
-       };
-
-       __trace_graph_entry(tr, &ent, flags, pc);
-       __trace_graph_return(tr, &ret, flags, pc);
-}
-
 static void
 __trace_function(struct trace_array *tr,
                 unsigned long ip, unsigned long parent_ip,
                 unsigned long flags, int pc)
 {
-       if (!is_graph())
+       if (is_graph())
+               trace_graph_function(tr, ip, parent_ip, flags, pc);
+       else
                trace_function(tr, ip, parent_ip, flags, pc);
-       else {
-               trace_graph_function(tr, parent_ip, flags, pc);
-               trace_graph_function(tr, ip, flags, pc);
-       }
 }
 
 #else
index 8b27c9849b427905ea9a5ef83864a88526afe405..544301d29dee45b0dc089db788bcfe89687bfa45 100644 (file)
@@ -514,8 +514,8 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
 static int kretprobe_dispatcher(struct kretprobe_instance *ri,
                                struct pt_regs *regs);
 
-/* Check the name is good for event/group */
-static int check_event_name(const char *name)
+/* Check the name is good for event/group/fields */
+static int is_good_name(const char *name)
 {
        if (!isalpha(*name) && *name != '_')
                return 0;
@@ -557,7 +557,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
        else
                tp->rp.kp.pre_handler = kprobe_dispatcher;
 
-       if (!event || !check_event_name(event)) {
+       if (!event || !is_good_name(event)) {
                ret = -EINVAL;
                goto error;
        }
@@ -567,7 +567,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
        if (!tp->call.name)
                goto error;
 
-       if (!group || !check_event_name(group)) {
+       if (!group || !is_good_name(group)) {
                ret = -EINVAL;
                goto error;
        }
@@ -883,7 +883,7 @@ static int create_trace_probe(int argc, char **argv)
        int i, ret = 0;
        int is_return = 0, is_delete = 0;
        char *symbol = NULL, *event = NULL, *group = NULL;
-       char *arg, *tmp;
+       char *arg;
        unsigned long offset = 0;
        void *addr = NULL;
        char buf[MAX_EVENT_NAME_LEN];
@@ -992,26 +992,36 @@ static int create_trace_probe(int argc, char **argv)
        /* parse arguments */
        ret = 0;
        for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
+               /* Increment count for freeing args in error case */
+               tp->nr_args++;
+
                /* Parse argument name */
                arg = strchr(argv[i], '=');
-               if (arg)
+               if (arg) {
                        *arg++ = '\0';
-               else
+                       tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
+               } else {
                        arg = argv[i];
+                       /* If argument name is omitted, set "argN" */
+                       snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
+                       tp->args[i].name = kstrdup(buf, GFP_KERNEL);
+               }
 
-               tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
                if (!tp->args[i].name) {
-                       pr_info("Failed to allocate argument%d name '%s'.\n",
-                               i, argv[i]);
+                       pr_info("Failed to allocate argument[%d] name.\n", i);
                        ret = -ENOMEM;
                        goto error;
                }
-               tmp = strchr(tp->args[i].name, ':');
-               if (tmp)
-                       *tmp = '_';     /* convert : to _ */
+
+               if (!is_good_name(tp->args[i].name)) {
+                       pr_info("Invalid argument[%d] name: %s\n",
+                               i, tp->args[i].name);
+                       ret = -EINVAL;
+                       goto error;
+               }
 
                if (conflict_field_name(tp->args[i].name, tp->args, i)) {
-                       pr_info("Argument%d name '%s' conflicts with "
+                       pr_info("Argument[%d] name '%s' conflicts with "
                                "another field.\n", i, argv[i]);
                        ret = -EINVAL;
                        goto error;
@@ -1020,12 +1030,9 @@ static int create_trace_probe(int argc, char **argv)
                /* Parse fetch argument */
                ret = parse_probe_arg(arg, tp, &tp->args[i], is_return);
                if (ret) {
-                       pr_info("Parse error at argument%d. (%d)\n", i, ret);
-                       kfree(tp->args[i].name);
+                       pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
                        goto error;
                }
-
-               tp->nr_args++;
        }
 
        ret = register_trace_probe(tp);
index 4086eae6e81b1c1b9762edc01600d3294c6bc130..7319559ed59f0a10197a15dc9d62a99a1fa7aeb7 100644 (file)
@@ -31,48 +31,98 @@ static int                  wakeup_rt;
 static arch_spinlock_t wakeup_lock =
        (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 
+static void wakeup_reset(struct trace_array *tr);
 static void __wakeup_reset(struct trace_array *tr);
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
+static void wakeup_graph_return(struct ftrace_graph_ret *trace);
 
 static int save_lat_flag;
 
+#define TRACE_DISPLAY_GRAPH     1
+
+static struct tracer_opt trace_opts[] = {
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       /* display latency trace as call graph */
+       { TRACER_OPT(display-graph, TRACE_DISPLAY_GRAPH) },
+#endif
+       { } /* Empty entry */
+};
+
+static struct tracer_flags tracer_flags = {
+       .val  = 0,
+       .opts = trace_opts,
+};
+
+#define is_graph() (tracer_flags.val & TRACE_DISPLAY_GRAPH)
+
 #ifdef CONFIG_FUNCTION_TRACER
+
 /*
- * irqsoff uses its own tracer function to keep the overhead down:
+ * Prologue for the wakeup function tracers.
+ *
+ * Returns 1 if it is OK to continue, and preemption
+ *            is disabled and data->disabled is incremented.
+ *         0 if the trace is to be ignored, and preemption
+ *            is not disabled and data->disabled is
+ *            kept the same.
+ *
+ * Note, this function is also used outside this ifdef but
+ *  inside the #ifdef of the function graph tracer below.
+ *  This is OK, since the function graph tracer is
+ *  dependent on the function tracer.
  */
-static void
-wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
+static int
+func_prolog_preempt_disable(struct trace_array *tr,
+                           struct trace_array_cpu **data,
+                           int *pc)
 {
-       struct trace_array *tr = wakeup_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
        long disabled;
        int cpu;
-       int pc;
 
        if (likely(!wakeup_task))
-               return;
+               return 0;
 
-       pc = preempt_count();
+       *pc = preempt_count();
        preempt_disable_notrace();
 
        cpu = raw_smp_processor_id();
        if (cpu != wakeup_current_cpu)
                goto out_enable;
 
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
+       *data = tr->data[cpu];
+       disabled = atomic_inc_return(&(*data)->disabled);
        if (unlikely(disabled != 1))
                goto out;
 
-       local_irq_save(flags);
+       return 1;
 
-       trace_function(tr, ip, parent_ip, flags, pc);
+out:
+       atomic_dec(&(*data)->disabled);
+
+out_enable:
+       preempt_enable_notrace();
+       return 0;
+}
 
+/*
+ * wakeup uses its own tracer function to keep the overhead down:
+ */
+static void
+wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
+{
+       struct trace_array *tr = wakeup_trace;
+       struct trace_array_cpu *data;
+       unsigned long flags;
+       int pc;
+
+       if (!func_prolog_preempt_disable(tr, &data, &pc))
+               return;
+
+       local_irq_save(flags);
+       trace_function(tr, ip, parent_ip, flags, pc);
        local_irq_restore(flags);
 
- out:
        atomic_dec(&data->disabled);
- out_enable:
        preempt_enable_notrace();
 }
 
@@ -82,6 +132,156 @@ static struct ftrace_ops trace_ops __read_mostly =
 };
 #endif /* CONFIG_FUNCTION_TRACER */
 
+static int start_func_tracer(int graph)
+{
+       int ret;
+
+       if (!graph)
+               ret = register_ftrace_function(&trace_ops);
+       else
+               ret = register_ftrace_graph(&wakeup_graph_return,
+                                           &wakeup_graph_entry);
+
+       if (!ret && tracing_is_enabled())
+               tracer_enabled = 1;
+       else
+               tracer_enabled = 0;
+
+       return ret;
+}
+
+static void stop_func_tracer(int graph)
+{
+       tracer_enabled = 0;
+
+       if (!graph)
+               unregister_ftrace_function(&trace_ops);
+       else
+               unregister_ftrace_graph();
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static int wakeup_set_flag(u32 old_flags, u32 bit, int set)
+{
+
+       if (!(bit & TRACE_DISPLAY_GRAPH))
+               return -EINVAL;
+
+       if (!(is_graph() ^ set))
+               return 0;
+
+       stop_func_tracer(!set);
+
+       wakeup_reset(wakeup_trace);
+       tracing_max_latency = 0;
+
+       return start_func_tracer(set);
+}
+
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
+{
+       struct trace_array *tr = wakeup_trace;
+       struct trace_array_cpu *data;
+       unsigned long flags;
+       int pc, ret = 0;
+
+       if (!func_prolog_preempt_disable(tr, &data, &pc))
+               return 0;
+
+       local_save_flags(flags);
+       ret = __trace_graph_entry(tr, trace, flags, pc);
+       atomic_dec(&data->disabled);
+       preempt_enable_notrace();
+
+       return ret;
+}
+
+static void wakeup_graph_return(struct ftrace_graph_ret *trace)
+{
+       struct trace_array *tr = wakeup_trace;
+       struct trace_array_cpu *data;
+       unsigned long flags;
+       int pc;
+
+       if (!func_prolog_preempt_disable(tr, &data, &pc))
+               return;
+
+       local_save_flags(flags);
+       __trace_graph_return(tr, trace, flags, pc);
+       atomic_dec(&data->disabled);
+
+       preempt_enable_notrace();
+       return;
+}
+
+static void wakeup_trace_open(struct trace_iterator *iter)
+{
+       if (is_graph())
+               graph_trace_open(iter);
+}
+
+static void wakeup_trace_close(struct trace_iterator *iter)
+{
+       if (iter->private)
+               graph_trace_close(iter);
+}
+
+#define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC)
+
+static enum print_line_t wakeup_print_line(struct trace_iterator *iter)
+{
+       /*
+        * In graph mode call the graph tracer output function,
+        * otherwise go with the TRACE_FN event handler
+        */
+       if (is_graph())
+               return print_graph_function_flags(iter, GRAPH_TRACER_FLAGS);
+
+       return TRACE_TYPE_UNHANDLED;
+}
+
+static void wakeup_print_header(struct seq_file *s)
+{
+       if (is_graph())
+               print_graph_headers_flags(s, GRAPH_TRACER_FLAGS);
+       else
+               trace_default_header(s);
+}
+
+static void
+__trace_function(struct trace_array *tr,
+                unsigned long ip, unsigned long parent_ip,
+                unsigned long flags, int pc)
+{
+       if (is_graph())
+               trace_graph_function(tr, ip, parent_ip, flags, pc);
+       else
+               trace_function(tr, ip, parent_ip, flags, pc);
+}
+#else
+#define __trace_function trace_function
+
+static int wakeup_set_flag(u32 old_flags, u32 bit, int set)
+{
+       return -EINVAL;
+}
+
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
+{
+       return -1;
+}
+
+static enum print_line_t wakeup_print_line(struct trace_iterator *iter)
+{
+       return TRACE_TYPE_UNHANDLED;
+}
+
+static void wakeup_graph_return(struct ftrace_graph_ret *trace) { }
+static void wakeup_print_header(struct seq_file *s) { }
+static void wakeup_trace_open(struct trace_iterator *iter) { }
+static void wakeup_trace_close(struct trace_iterator *iter) { }
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 /*
  * Should this new latency be reported/recorded?
  */
@@ -152,7 +352,7 @@ probe_wakeup_sched_switch(void *ignore,
        /* The task we are waiting for is waking up */
        data = wakeup_trace->data[wakeup_cpu];
 
-       trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
+       __trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
        tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc);
 
        T0 = data->preempt_timestamp;
@@ -252,7 +452,7 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
         * is not called by an assembly function  (where as schedule is)
         * it should be safe to use it here.
         */
-       trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
+       __trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
 
 out_locked:
        arch_spin_unlock(&wakeup_lock);
@@ -303,12 +503,8 @@ static void start_wakeup_tracer(struct trace_array *tr)
         */
        smp_wmb();
 
-       register_ftrace_function(&trace_ops);
-
-       if (tracing_is_enabled())
-               tracer_enabled = 1;
-       else
-               tracer_enabled = 0;
+       if (start_func_tracer(is_graph()))
+               printk(KERN_ERR "failed to start wakeup tracer\n");
 
        return;
 fail_deprobe_wake_new:
@@ -320,7 +516,7 @@ fail_deprobe:
 static void stop_wakeup_tracer(struct trace_array *tr)
 {
        tracer_enabled = 0;
-       unregister_ftrace_function(&trace_ops);
+       stop_func_tracer(is_graph());
        unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
        unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
        unregister_trace_sched_wakeup(probe_wakeup, NULL);
@@ -379,9 +575,15 @@ static struct tracer wakeup_tracer __read_mostly =
        .start          = wakeup_tracer_start,
        .stop           = wakeup_tracer_stop,
        .print_max      = 1,
+       .print_header   = wakeup_print_header,
+       .print_line     = wakeup_print_line,
+       .flags          = &tracer_flags,
+       .set_flag       = wakeup_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_wakeup,
 #endif
+       .open           = wakeup_trace_open,
+       .close          = wakeup_trace_close,
        .use_max_tr     = 1,
 };
 
@@ -394,9 +596,15 @@ static struct tracer wakeup_rt_tracer __read_mostly =
        .stop           = wakeup_tracer_stop,
        .wait_pipe      = poll_wait_pipe,
        .print_max      = 1,
+       .print_header   = wakeup_print_header,
+       .print_line     = wakeup_print_line,
+       .flags          = &tracer_flags,
+       .set_flag       = wakeup_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_wakeup,
 #endif
+       .open           = wakeup_trace_open,
+       .close          = wakeup_trace_close,
        .use_max_tr     = 1,
 };
 
index 056468eae7cfce7a76bf5c2364f71c722adeb325..4c5dead0c239fc7d47d23065cf033669d036efb1 100644 (file)
@@ -195,6 +195,7 @@ static const struct file_operations stack_max_size_fops = {
        .open           = tracing_open_generic,
        .read           = stack_max_size_read,
        .write          = stack_max_size_write,
+       .llseek         = default_llseek,
 };
 
 static void *
@@ -249,7 +250,7 @@ static int trace_lookup_stack(struct seq_file *m, long i)
 {
        unsigned long addr = stack_dump_trace[i];
 
-       return seq_printf(m, "%pF\n", (void *)addr);
+       return seq_printf(m, "%pS\n", (void *)addr);
 }
 
 static void print_disabled(struct seq_file *m)
index a7cc3793baf6897d2535737a52322552040d2737..209b379a47210dad4170e5914e5ecc68207f8784 100644 (file)
@@ -263,6 +263,11 @@ int __init trace_workqueue_early_init(void)
 {
        int ret, cpu;
 
+       for_each_possible_cpu(cpu) {
+               spin_lock_init(&workqueue_cpu_stat(cpu)->lock);
+               INIT_LIST_HEAD(&workqueue_cpu_stat(cpu)->list);
+       }
+
        ret = register_trace_workqueue_insertion(probe_workqueue_insertion, NULL);
        if (ret)
                goto out;
@@ -279,11 +284,6 @@ int __init trace_workqueue_early_init(void)
        if (ret)
                goto no_creation;
 
-       for_each_possible_cpu(cpu) {
-               spin_lock_init(&workqueue_cpu_stat(cpu)->lock);
-               INIT_LIST_HEAD(&workqueue_cpu_stat(cpu)->list);
-       }
-
        return 0;
 
 no_creation:
index c77f3eceea250e49b0ff001959f8df9eeb8e0716..e95ee7f31d43309949893d9e63d1703e619a6ca9 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/jump_label.h>
 
 extern struct tracepoint __start___tracepoints[];
 extern struct tracepoint __stop___tracepoints[];
@@ -263,7 +264,13 @@ static void set_tracepoint(struct tracepoint_entry **entry,
         * is used.
         */
        rcu_assign_pointer(elem->funcs, (*entry)->funcs);
-       elem->state = active;
+       if (!elem->state && active) {
+               jump_label_enable(&elem->state);
+               elem->state = active;
+       } else if (elem->state && !active) {
+               jump_label_disable(&elem->state);
+               elem->state = active;
+       }
 }
 
 /*
@@ -277,7 +284,10 @@ static void disable_tracepoint(struct tracepoint *elem)
        if (elem->unregfunc && elem->state)
                elem->unregfunc();
 
-       elem->state = 0;
+       if (elem->state) {
+               jump_label_disable(&elem->state);
+               elem->state = 0;
+       }
        rcu_assign_pointer(elem->funcs, NULL);
 }
 
index 613bc1f046108ec52b8f7372fe2e7e66aa8fe4c7..bafba687a6d849a11f0201acd3d7ae5e63e9301e 100644 (file)
@@ -43,7 +43,6 @@ static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
 static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
 #endif
 
-static int __read_mostly did_panic;
 static int __initdata no_watchdog;
 
 
@@ -122,7 +121,7 @@ static void __touch_watchdog(void)
 
 void touch_softlockup_watchdog(void)
 {
-       __get_cpu_var(watchdog_touch_ts) = 0;
+       __raw_get_cpu_var(watchdog_touch_ts) = 0;
 }
 EXPORT_SYMBOL(touch_softlockup_watchdog);
 
@@ -142,7 +141,14 @@ void touch_all_softlockup_watchdogs(void)
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 void touch_nmi_watchdog(void)
 {
-       __get_cpu_var(watchdog_nmi_touch) = true;
+       if (watchdog_enabled) {
+               unsigned cpu;
+
+               for_each_present_cpu(cpu) {
+                       if (per_cpu(watchdog_nmi_touch, cpu) != true)
+                               per_cpu(watchdog_nmi_touch, cpu) = true;
+               }
+       }
        touch_softlockup_watchdog();
 }
 EXPORT_SYMBOL(touch_nmi_watchdog);
@@ -180,18 +186,6 @@ static int is_softlockup(unsigned long touch_ts)
        return 0;
 }
 
-static int
-watchdog_panic(struct notifier_block *this, unsigned long event, void *ptr)
-{
-       did_panic = 1;
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
-       .notifier_call = watchdog_panic,
-};
-
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 static struct perf_event_attr wd_hw_attr = {
        .type           = PERF_TYPE_HARDWARE,
@@ -202,10 +196,13 @@ static struct perf_event_attr wd_hw_attr = {
 };
 
 /* Callback function for perf event subsystem */
-void watchdog_overflow_callback(struct perf_event *event, int nmi,
+static void watchdog_overflow_callback(struct perf_event *event, int nmi,
                 struct perf_sample_data *data,
                 struct pt_regs *regs)
 {
+       /* Ensure the watchdog never gets throttled */
+       event->hw.interrupts = 0;
+
        if (__get_cpu_var(watchdog_nmi_touch) == true) {
                __get_cpu_var(watchdog_nmi_touch) = false;
                return;
@@ -361,14 +358,14 @@ static int watchdog_nmi_enable(int cpu)
        /* Try to register using hardware perf events */
        wd_attr = &wd_hw_attr;
        wd_attr->sample_period = hw_nmi_get_sample_period();
-       event = perf_event_create_kernel_counter(wd_attr, cpu, -1, watchdog_overflow_callback);
+       event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback);
        if (!IS_ERR(event)) {
                printk(KERN_INFO "NMI watchdog enabled, takes one hw-pmu counter.\n");
                goto out_save;
        }
 
        printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event);
-       return -1;
+       return PTR_ERR(event);
 
        /* success path */
 out_save:
@@ -412,17 +409,19 @@ static int watchdog_prepare_cpu(int cpu)
 static int watchdog_enable(int cpu)
 {
        struct task_struct *p = per_cpu(softlockup_watchdog, cpu);
+       int err;
 
        /* enable the perf event */
-       if (watchdog_nmi_enable(cpu) != 0)
-               return -1;
+       err = watchdog_nmi_enable(cpu);
+       if (err)
+               return err;
 
        /* create the watchdog thread */
        if (!p) {
                p = kthread_create(watchdog, (void *)(unsigned long)cpu, "watchdog/%d", cpu);
                if (IS_ERR(p)) {
                        printk(KERN_ERR "softlockup watchdog for %i failed\n", cpu);
-                       return -1;
+                       return PTR_ERR(p);
                }
                kthread_bind(p, cpu);
                per_cpu(watchdog_touch_ts, cpu) = 0;
@@ -430,6 +429,9 @@ static int watchdog_enable(int cpu)
                wake_up_process(p);
        }
 
+       /* if any cpu succeeds, watchdog is considered enabled for the system */
+       watchdog_enabled = 1;
+
        return 0;
 }
 
@@ -452,9 +454,6 @@ static void watchdog_disable(int cpu)
                per_cpu(softlockup_watchdog, cpu) = NULL;
                kthread_stop(p);
        }
-
-       /* if any cpu succeeds, watchdog is considered enabled for the system */
-       watchdog_enabled = 1;
 }
 
 static void watchdog_enable_all_cpus(void)
@@ -474,6 +473,9 @@ static void watchdog_disable_all_cpus(void)
 {
        int cpu;
 
+       if (no_watchdog)
+               return;
+
        for_each_online_cpu(cpu)
                watchdog_disable(cpu);
 
@@ -516,17 +518,16 @@ static int __cpuinit
 cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
        int hotcpu = (unsigned long)hcpu;
+       int err = 0;
 
        switch (action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
-               if (watchdog_prepare_cpu(hotcpu))
-                       return NOTIFY_BAD;
+               err = watchdog_prepare_cpu(hotcpu);
                break;
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
-               if (watchdog_enable(hotcpu))
-                       return NOTIFY_BAD;
+               err = watchdog_enable(hotcpu);
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
@@ -539,7 +540,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
                break;
 #endif /* CONFIG_HOTPLUG_CPU */
        }
-       return NOTIFY_OK;
+       return notifier_from_errno(err);
 }
 
 static struct notifier_block __cpuinitdata cpu_nfb = {
@@ -555,13 +556,11 @@ static int __init spawn_watchdog_task(void)
                return 0;
 
        err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
-       WARN_ON(err == NOTIFY_BAD);
+       WARN_ON(notifier_to_errno(err));
 
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
 
-       atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
        return 0;
 }
 early_initcall(spawn_watchdog_task);
index 8bd600c020e5cdf5f2454681bc2e89fcc99c47d0..f77afd93922968d0c216bee148c0f10ed0ccaa72 100644 (file)
@@ -1,19 +1,26 @@
 /*
- * linux/kernel/workqueue.c
+ * kernel/workqueue.c - generic async execution with shared worker pool
  *
- * Generic mechanism for defining kernel helper threads for running
- * arbitrary tasks in process context.
+ * Copyright (C) 2002          Ingo Molnar
  *
- * Started by Ingo Molnar, Copyright (C) 2002
+ *   Derived from the taskqueue/keventd code by:
+ *     David Woodhouse <dwmw2@infradead.org>
+ *     Andrew Morton
+ *     Kai Petzke <wpp@marie.physik.tu-berlin.de>
+ *     Theodore Ts'o <tytso@mit.edu>
  *
- * Derived from the taskqueue/keventd code by:
+ * Made to use alloc_percpu by Christoph Lameter.
  *
- *   David Woodhouse <dwmw2@infradead.org>
- *   Andrew Morton
- *   Kai Petzke <wpp@marie.physik.tu-berlin.de>
- *   Theodore Ts'o <tytso@mit.edu>
+ * Copyright (C) 2010          SUSE Linux Products GmbH
+ * Copyright (C) 2010          Tejun Heo <tj@kernel.org>
  *
- * Made to use alloc_percpu by Christoph Lameter.
+ * This is the generic async execution mechanism.  Work items as are
+ * executed in process context.  The worker pool is shared and
+ * automatically managed.  There is one worker pool for each CPU and
+ * one extra for works which are better served by workers which are
+ * not bound to any specific CPU.
+ *
+ * Please read Documentation/workqueue.txt for details.
  */
 
 #include <linux/module.h>
@@ -90,7 +97,8 @@ enum {
 /*
  * Structure fields follow one of the following exclusion rules.
  *
- * I: Set during initialization and read-only afterwards.
+ * I: Modifiable by initialization/destruction paths and read-only for
+ *    everyone else.
  *
  * P: Preemption protected.  Disabling preemption is enough and should
  *    only be modified and accessed from the local cpu.
@@ -198,7 +206,7 @@ typedef cpumask_var_t mayday_mask_t;
        cpumask_test_and_set_cpu((cpu), (mask))
 #define mayday_clear_cpu(cpu, mask)            cpumask_clear_cpu((cpu), (mask))
 #define for_each_mayday_cpu(cpu, mask)         for_each_cpu((cpu), (mask))
-#define alloc_mayday_mask(maskp, gfp)          alloc_cpumask_var((maskp), (gfp))
+#define alloc_mayday_mask(maskp, gfp)          zalloc_cpumask_var((maskp), (gfp))
 #define free_mayday_mask(mask)                 free_cpumask_var((mask))
 #else
 typedef unsigned long mayday_mask_t;
@@ -943,10 +951,14 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
        struct global_cwq *gcwq;
        struct cpu_workqueue_struct *cwq;
        struct list_head *worklist;
+       unsigned int work_flags;
        unsigned long flags;
 
        debug_work_activate(work);
 
+       if (WARN_ON_ONCE(wq->flags & WQ_DYING))
+               return;
+
        /* determine gcwq to use */
        if (!(wq->flags & WQ_UNBOUND)) {
                struct global_cwq *last_gcwq;
@@ -989,14 +1001,17 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
        BUG_ON(!list_empty(&work->entry));
 
        cwq->nr_in_flight[cwq->work_color]++;
+       work_flags = work_color_to_flags(cwq->work_color);
 
        if (likely(cwq->nr_active < cwq->max_active)) {
                cwq->nr_active++;
                worklist = gcwq_determine_ins_pos(gcwq, cwq);
-       } else
+       } else {
+               work_flags |= WORK_STRUCT_DELAYED;
                worklist = &cwq->delayed_works;
+       }
 
-       insert_work(cwq, work, worklist, work_color_to_flags(cwq->work_color));
+       insert_work(cwq, work, worklist, work_flags);
 
        spin_unlock_irqrestore(&gcwq->lock, flags);
 }
@@ -1215,6 +1230,7 @@ static void worker_leave_idle(struct worker *worker)
  * bound), %false if offline.
  */
 static bool worker_maybe_bind_and_lock(struct worker *worker)
+__acquires(&gcwq->lock)
 {
        struct global_cwq *gcwq = worker->gcwq;
        struct task_struct *task = worker->task;
@@ -1488,6 +1504,8 @@ static void gcwq_mayday_timeout(unsigned long __gcwq)
  * otherwise.
  */
 static bool maybe_create_worker(struct global_cwq *gcwq)
+__releases(&gcwq->lock)
+__acquires(&gcwq->lock)
 {
        if (!need_to_create_worker(gcwq))
                return false;
@@ -1662,6 +1680,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
        struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq);
 
        move_linked_works(work, pos, NULL);
+       __clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
        cwq->nr_active++;
 }
 
@@ -1669,6 +1688,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
  * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
  * @cwq: cwq of interest
  * @color: color of work which left the queue
+ * @delayed: for a delayed work
  *
  * A work either has completed or is removed from pending queue,
  * decrement nr_in_flight of its cwq and handle workqueue flushing.
@@ -1676,19 +1696,22 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
  * CONTEXT:
  * spin_lock_irq(gcwq->lock).
  */
-static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color)
+static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color,
+                                bool delayed)
 {
        /* ignore uncolored works */
        if (color == WORK_NO_COLOR)
                return;
 
        cwq->nr_in_flight[color]--;
-       cwq->nr_active--;
 
-       if (!list_empty(&cwq->delayed_works)) {
-               /* one down, submit a delayed one */
-               if (cwq->nr_active < cwq->max_active)
-                       cwq_activate_first_delayed(cwq);
+       if (!delayed) {
+               cwq->nr_active--;
+               if (!list_empty(&cwq->delayed_works)) {
+                       /* one down, submit a delayed one */
+                       if (cwq->nr_active < cwq->max_active)
+                               cwq_activate_first_delayed(cwq);
+               }
        }
 
        /* is flush in progress and are we at the flushing tip? */
@@ -1725,6 +1748,8 @@ static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color)
  * spin_lock_irq(gcwq->lock) which is released and regrabbed.
  */
 static void process_one_work(struct worker *worker, struct work_struct *work)
+__releases(&gcwq->lock)
+__acquires(&gcwq->lock)
 {
        struct cpu_workqueue_struct *cwq = get_work_cwq(work);
        struct global_cwq *gcwq = cwq->gcwq;
@@ -1823,7 +1848,7 @@ static void process_one_work(struct worker *worker, struct work_struct *work)
        hlist_del_init(&worker->hentry);
        worker->current_work = NULL;
        worker->current_cwq = NULL;
-       cwq_dec_nr_in_flight(cwq, work_color);
+       cwq_dec_nr_in_flight(cwq, work_color, false);
 }
 
 /**
@@ -2388,7 +2413,8 @@ static int try_to_grab_pending(struct work_struct *work)
                        debug_work_deactivate(work);
                        list_del_init(&work->entry);
                        cwq_dec_nr_in_flight(get_work_cwq(work),
-                                            get_work_color(work));
+                               get_work_color(work),
+                               *work_data_bits(work) & WORK_STRUCT_DELAYED);
                        ret = 1;
                }
        }
@@ -2791,7 +2817,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
                if (IS_ERR(rescuer->task))
                        goto err;
 
-               wq->rescuer = rescuer;
                rescuer->task->flags |= PF_THREAD_BOUND;
                wake_up_process(rescuer->task);
        }
@@ -2833,6 +2858,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
 {
        unsigned int cpu;
 
+       wq->flags |= WQ_DYING;
        flush_workqueue(wq);
 
        /*
@@ -2857,6 +2883,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
        if (wq->flags & WQ_RESCUER) {
                kthread_stop(wq->rescuer->task);
                free_mayday_mask(wq->mayday_mask);
+               kfree(wq->rescuer);
        }
 
        free_cwqs(wq);
@@ -3239,6 +3266,8 @@ static int __cpuinit trustee_thread(void *__gcwq)
  * multiple times.  To be used by cpu_callback.
  */
 static void __cpuinit wait_trustee_state(struct global_cwq *gcwq, int state)
+__releases(&gcwq->lock)
+__acquires(&gcwq->lock)
 {
        if (!(gcwq->trustee_state == state ||
              gcwq->trustee_state == TRUSTEE_DONE)) {
@@ -3545,8 +3574,7 @@ static int __init init_workqueues(void)
                spin_lock_init(&gcwq->lock);
                INIT_LIST_HEAD(&gcwq->worklist);
                gcwq->cpu = cpu;
-               if (cpu == WORK_CPU_UNBOUND)
-                       gcwq->flags |= GCWQ_DISASSOCIATED;
+               gcwq->flags |= GCWQ_DISASSOCIATED;
 
                INIT_LIST_HEAD(&gcwq->idle_list);
                for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++)
@@ -3570,6 +3598,8 @@ static int __init init_workqueues(void)
                struct global_cwq *gcwq = get_gcwq(cpu);
                struct worker *worker;
 
+               if (cpu != WORK_CPU_UNBOUND)
+                       gcwq->flags &= ~GCWQ_DISASSOCIATED;
                worker = create_worker(gcwq, true);
                BUG_ON(!worker);
                spin_lock_irq(&gcwq->lock);
index 1b4afd2e6ca089de0babdacc5781426ef118da5c..7b2a8ca97ada66b90c786c69bd44dc71b84c492c 100644 (file)
@@ -461,6 +461,15 @@ config DEBUG_MUTEXES
         This feature allows mutex semantics violations to be detected and
         reported.
 
+config BKL
+       bool "Big Kernel Lock" if (SMP || PREEMPT)
+       default y
+       help
+         This is the traditional lock that is used in old code instead
+         of proper locking. All drivers that use the BKL should depend
+         on this symbol.
+         Say Y here unless you are working on removing the BKL.
+
 config DEBUG_LOCK_ALLOC
        bool "Lock debugging: detect incorrect freeing of live locks"
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@ -482,6 +491,7 @@ config PROVE_LOCKING
        select DEBUG_SPINLOCK
        select DEBUG_MUTEXES
        select DEBUG_LOCK_ALLOC
+       select TRACE_IRQFLAGS
        default n
        help
         This feature enables the kernel to prove that all locking
@@ -539,6 +549,23 @@ config PROVE_RCU_REPEATEDLY
         disabling, allowing multiple RCU-lockdep warnings to be printed
         on a single reboot.
 
+        Say Y to allow multiple RCU-lockdep warnings per boot.
+
+        Say N if you are unsure.
+
+config SPARSE_RCU_POINTER
+       bool "RCU debugging: sparse-based checks for pointer usage"
+       default n
+       help
+        This feature enables the __rcu sparse annotation for
+        RCU-protected pointers.  This annotation will cause sparse
+        to flag any non-RCU used of annotated pointers.  This can be
+        helpful when debugging RCU usage.  Please note that this feature
+        is not intended to enforce code cleanliness; it is instead merely
+        a debugging aid.
+
+        Say Y to make sparse flag questionable use of RCU-protected pointers
+
         Say N if you are unsure.
 
 config LOCKDEP
@@ -579,11 +606,10 @@ config DEBUG_LOCKDEP
          of more runtime overhead.
 
 config TRACE_IRQFLAGS
-       depends on DEBUG_KERNEL
        bool
-       default y
-       depends on TRACE_IRQFLAGS_SUPPORT
-       depends on PROVE_LOCKING
+       help
+         Enables hooks to interrupt enabling and disabling for
+         either tracing or lock debugging.
 
 config DEBUG_SPINLOCK_SLEEP
        bool "Spinlock debugging: sleep-inside-spinlock checking"
@@ -832,6 +858,30 @@ config RCU_CPU_STALL_DETECTOR
 
          Say Y if you are unsure.
 
+config RCU_CPU_STALL_TIMEOUT
+       int "RCU CPU stall timeout in seconds"
+       depends on RCU_CPU_STALL_DETECTOR
+       range 3 300
+       default 60
+       help
+         If a given RCU grace period extends more than the specified
+         number of seconds, a CPU stall warning is printed.  If the
+         RCU grace period persists, additional CPU stall warnings are
+         printed at more widely spaced intervals.
+
+config RCU_CPU_STALL_DETECTOR_RUNNABLE
+       bool "RCU CPU stall checking starts automatically at boot"
+       depends on RCU_CPU_STALL_DETECTOR
+       default y
+       help
+         If set, start checking for RCU CPU stalls immediately on
+         boot.  Otherwise, RCU CPU stall checking must be manually
+         enabled.
+
+         Say Y if you are unsure.
+
+         Say N if you wish to suppress RCU CPU stall checking during boot.
+
 config RCU_CPU_STALL_VERBOSE
        bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
        depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
index 7cdfad88128fa5d3d3076d552fbde276ef500d66..19552096d16b06bd2dac2a9b10212e482a4d0da3 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -72,8 +72,8 @@ static const struct bug_entry *module_find_bug(unsigned long bugaddr)
        return NULL;
 }
 
-int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
-                       struct module *mod)
+void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+                        struct module *mod)
 {
        char *secstrings;
        unsigned int i;
@@ -97,8 +97,6 @@ int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
         * could potentially lead to deadlock and thus be counter-productive.
         */
        list_add(&mod->bug_list, &module_bug_list);
-
-       return 0;
 }
 
 void module_bug_cleanup(struct module *mod)
index 01e64270e246bef1070c9e68a3603051b02bf919..4bfb0471f10684f230e4351db489a1292b83f414 100644 (file)
@@ -590,6 +590,7 @@ out_unlock:
 static const struct file_operations filter_fops = {
        .read  = filter_read,
        .write = filter_write,
+       .llseek = default_llseek,
 };
 
 static int dma_debug_fs_init(void)
index 02afc25337284329d23a998e636240d5a41d337d..7bd6df781ce50198689fae375eef696751c0a47a 100644 (file)
 #include <linux/dynamic_debug.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/jump_label.h>
 
 extern struct _ddebug __start___verbose[];
 extern struct _ddebug __stop___verbose[];
 
-/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-long long dynamic_debug_enabled;
-EXPORT_SYMBOL_GPL(dynamic_debug_enabled);
-long long dynamic_debug_enabled2;
-EXPORT_SYMBOL_GPL(dynamic_debug_enabled2);
-
 struct ddebug_table {
        struct list_head link;
        char *mod_name;
@@ -87,26 +79,6 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
        return buf;
 }
 
-/*
- * must be called with ddebug_lock held
- */
-
-static int disabled_hash(char hash, bool first_table)
-{
-       struct ddebug_table *dt;
-       char table_hash_value;
-
-       list_for_each_entry(dt, &ddebug_tables, link) {
-               if (first_table)
-                       table_hash_value = dt->ddebugs->primary_hash;
-               else
-                       table_hash_value = dt->ddebugs->secondary_hash;
-               if (dt->num_enabled && (hash == table_hash_value))
-                       return 0;
-       }
-       return 1;
-}
-
 /*
  * Search the tables for _ddebug's which match the given
  * `query' and apply the `flags' and `mask' to them.  Tells
@@ -170,17 +142,9 @@ static void ddebug_change(const struct ddebug_query *query,
                                dt->num_enabled++;
                        dp->flags = newflags;
                        if (newflags) {
-                               dynamic_debug_enabled |=
-                                               (1LL << dp->primary_hash);
-                               dynamic_debug_enabled2 |=
-                                               (1LL << dp->secondary_hash);
+                               jump_label_enable(&dp->enabled);
                        } else {
-                               if (disabled_hash(dp->primary_hash, true))
-                                       dynamic_debug_enabled &=
-                                               ~(1LL << dp->primary_hash);
-                               if (disabled_hash(dp->secondary_hash, false))
-                                       dynamic_debug_enabled2 &=
-                                               ~(1LL << dp->secondary_hash);
+                               jump_label_disable(&dp->enabled);
                        }
                        if (verbose)
                                printk(KERN_INFO
index b93579504dfaaafee092156c113b36130b0758a7..70af0a7f97c0eb4801e177458d182ab6baad2767 100644 (file)
@@ -123,7 +123,7 @@ static int kobj_usermode_filter(struct kobject *kobj)
  * @kobj: struct kobject that the action is happening to
  * @envp_ext: pointer to environmental data
  *
- * Returns 0 if kobject_uevent() is completed with success or the
+ * Returns 0 if kobject_uevent_env() is completed with success or the
  * corresponding error when it fails.
  */
 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
@@ -317,7 +317,7 @@ exit:
 EXPORT_SYMBOL_GPL(kobject_uevent_env);
 
 /**
- * kobject_uevent - notify userspace by ending an uevent
+ * kobject_uevent - notify userspace by sending an uevent
  *
  * @action: action that is happening
  * @kobj: struct kobject that the action is happening to
index 4b5cb794c38bb270b8b72b70a47de265ec05c210..a7616fa3162e844f5b3c7090c1911543c826147e 100644 (file)
@@ -70,7 +70,7 @@ static void merge_and_restore_back_links(void *priv,
                 * element comparison is needed, so the client's cmp()
                 * routine can invoke cond_resched() periodically.
                 */
-               (*cmp)(priv, tail, tail);
+               (*cmp)(priv, tail->next, tail->next);
 
                tail->next->prev = tail;
                tail = tail->next;
index 5b7d4623f0b70aee189deda3bc8318a590476160..6f412ab4c24f812fc8b7290c4a1e06cc0250ea62 100644 (file)
@@ -49,7 +49,7 @@ struct radix_tree_node {
        unsigned int    height;         /* Height from the bottom */
        unsigned int    count;
        struct rcu_head rcu_head;
-       void            *slots[RADIX_TREE_MAP_SIZE];
+       void __rcu      *slots[RADIX_TREE_MAP_SIZE];
        unsigned long   tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
 };
 
@@ -174,14 +174,16 @@ static void radix_tree_node_rcu_free(struct rcu_head *head)
 {
        struct radix_tree_node *node =
                        container_of(head, struct radix_tree_node, rcu_head);
+       int i;
 
        /*
         * must only free zeroed nodes into the slab. radix_tree_shrink
         * can leave us with a non-NULL entry in the first slot, so clear
         * that here to make sure.
         */
-       tag_clear(node, 0, 0);
-       tag_clear(node, 1, 0);
+       for (i = 0; i < RADIX_TREE_MAX_TAGS; i++)
+               tag_clear(node, i, 0);
+
        node->slots[0] = NULL;
        node->count = 0;
 
@@ -623,6 +625,13 @@ EXPORT_SYMBOL(radix_tree_tag_get);
  * also settag. The function stops either after tagging nr_to_tag items or
  * after reaching last_index.
  *
+ * The tags must be set from the leaf level only and propagated back up the
+ * path to the root. We must do this so that we resolve the full path before
+ * setting any tags on intermediate nodes. If we set tags as we descend, then
+ * we can get to the leaf node and find that the index that has the iftag
+ * set is outside the range we are scanning. This reults in dangling tags and
+ * can lead to problems with later tag operations (e.g. livelocks on lookups).
+ *
  * The function returns number of leaves where the tag was set and sets
  * *first_indexp to the first unscanned index.
  * WARNING! *first_indexp can wrap if last_index is ULONG_MAX. Caller must
@@ -633,9 +642,13 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                unsigned long nr_to_tag,
                unsigned int iftag, unsigned int settag)
 {
-       unsigned int height = root->height, shift;
-       unsigned long tagged = 0, index = *first_indexp;
-       struct radix_tree_node *open_slots[height], *slot;
+       unsigned int height = root->height;
+       struct radix_tree_path path[height];
+       struct radix_tree_path *pathp = path;
+       struct radix_tree_node *slot;
+       unsigned int shift;
+       unsigned long tagged = 0;
+       unsigned long index = *first_indexp;
 
        last_index = min(last_index, radix_tree_maxindex(height));
        if (index > last_index)
@@ -655,6 +668,13 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
        slot = radix_tree_indirect_to_ptr(root->rnode);
 
+       /*
+        * we fill the path from (root->height - 2) to 0, leaving the index at
+        * (root->height - 1) as a terminator. Zero the node in the terminator
+        * so that we can use this to end walk loops back up the path.
+        */
+       path[height - 1].node = NULL;
+
        for (;;) {
                int offset;
 
@@ -663,17 +683,30 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                        goto next;
                if (!tag_get(slot, iftag, offset))
                        goto next;
+               if (height > 1) {
+                       /* Go down one level */
+                       height--;
+                       shift -= RADIX_TREE_MAP_SHIFT;
+                       path[height - 1].node = slot;
+                       path[height - 1].offset = offset;
+                       slot = slot->slots[offset];
+                       continue;
+               }
+
+               /* tag the leaf */
+               tagged++;
                tag_set(slot, settag, offset);
-               if (height == 1) {
-                       tagged++;
-                       goto next;
+
+               /* walk back up the path tagging interior nodes */
+               pathp = &path[0];
+               while (pathp->node) {
+                       /* stop if we find a node with the tag already set */
+                       if (tag_get(pathp->node, settag, pathp->offset))
+                               break;
+                       tag_set(pathp->node, settag, pathp->offset);
+                       pathp++;
                }
-               /* Go down one level */
-               height--;
-               shift -= RADIX_TREE_MAP_SHIFT;
-               open_slots[height] = slot;
-               slot = slot->slots[offset];
-               continue;
+
 next:
                /* Go to next item at level determined by 'shift' */
                index = ((index >> shift) + 1) << shift;
@@ -688,7 +721,7 @@ next:
                         * last_index is guaranteed to be in the tree, what
                         * we do below cannot wander astray.
                         */
-                       slot = open_slots[height];
+                       slot = path[height - 1].node;
                        height++;
                        shift += RADIX_TREE_MAP_SHIFT;
                }
diff --git a/lib/raid6/.gitignore b/lib/raid6/.gitignore
new file mode 100644 (file)
index 0000000..162beca
--- /dev/null
@@ -0,0 +1,4 @@
+mktables
+altivec*.c
+int*.c
+tables.c
index a5ec42868f99d8d6700f34ca81c061c1ef21d15b..4ceb05d772aed12d392d618358284ea71cb51dd2 100644 (file)
@@ -248,8 +248,18 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
                left -= sg_size;
 
                sg = alloc_fn(alloc_size, gfp_mask);
-               if (unlikely(!sg))
-                       return -ENOMEM;
+               if (unlikely(!sg)) {
+                       /*
+                        * Adjust entry count to reflect that the last
+                        * entry of the previous table won't be used for
+                        * linkage.  Without this, sg_kfree() may get
+                        * confused.
+                        */
+                       if (prv)
+                               table->nents = ++table->orig_nents;
+
+                       return -ENOMEM;
+               }
 
                sg_init_table(sg, alloc_size);
                table->nents = table->orig_nents += sg_size;
index 34e3082632d8311575e27c6d2a4b87c9985dd574..7c06ee51a29a9bfbf79692af3b7e211751005e3c 100644 (file)
@@ -70,7 +70,7 @@ static unsigned long io_tlb_nslabs;
  */
 static unsigned long io_tlb_overflow = 32*1024;
 
-void *io_tlb_overflow_buffer;
+static void *io_tlb_overflow_buffer;
 
 /*
  * This is a free list describing the number of free entries available from
@@ -147,16 +147,16 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
         * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
         * between io_tlb_start and io_tlb_end.
         */
-       io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
+       io_tlb_list = alloc_bootmem_pages(PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
        for (i = 0; i < io_tlb_nslabs; i++)
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
        io_tlb_index = 0;
-       io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t));
+       io_tlb_orig_addr = alloc_bootmem_pages(PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
 
        /*
         * Get the overflow emergency buffer
         */
-       io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+       io_tlb_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow));
        if (!io_tlb_overflow_buffer)
                panic("Cannot allocate SWIOTLB overflow buffer!\n");
        if (verbose)
@@ -182,7 +182,7 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
        /*
         * Get IO TLB memory from the low pages
         */
-       io_tlb_start = alloc_bootmem_low_pages(bytes);
+       io_tlb_start = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
        if (!io_tlb_start)
                panic("Cannot allocate SWIOTLB buffer");
 
@@ -308,13 +308,13 @@ void __init swiotlb_free(void)
                           get_order(io_tlb_nslabs << IO_TLB_SHIFT));
        } else {
                free_bootmem_late(__pa(io_tlb_overflow_buffer),
-                                 io_tlb_overflow);
+                                 PAGE_ALIGN(io_tlb_overflow));
                free_bootmem_late(__pa(io_tlb_orig_addr),
-                                 io_tlb_nslabs * sizeof(phys_addr_t));
+                                 PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
                free_bootmem_late(__pa(io_tlb_list),
-                                 io_tlb_nslabs * sizeof(int));
+                                 PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
                free_bootmem_late(__pa(io_tlb_start),
-                                 io_tlb_nslabs << IO_TLB_SHIFT);
+                                 PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
 }
 
index f4e516e9c37cc4c62f93faf92131a632098d2ca5..f0fb9124e410c436c0f240d69f089f4935af2e92 100644 (file)
@@ -189,7 +189,7 @@ config COMPACTION
 config MIGRATION
        bool "Page migration"
        def_bool y
-       depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE
+       depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE || COMPACTION
        help
          Allows the migration of the physical location of pages of processes
          while the virtual addresses are not changed. This is useful in
index eaa4a5bbe0634390fc802ebffdbad4291fa3b991..65d420499a615bf68a3be8313c3b0d8b1b330178 100644 (file)
@@ -30,6 +30,7 @@ EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 struct backing_dev_info noop_backing_dev_info = {
        .name           = "noop",
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 EXPORT_SYMBOL_GPL(noop_backing_dev_info);
 
@@ -243,6 +244,7 @@ static int __init default_bdi_init(void)
        err = bdi_init(&default_backing_dev_info);
        if (!err)
                bdi_register(&default_backing_dev_info, NULL, "default");
+       err = bdi_init(&noop_backing_dev_info);
 
        return err;
 }
@@ -445,8 +447,8 @@ static int bdi_forker_thread(void *ptr)
                switch (action) {
                case FORK_THREAD:
                        __set_current_state(TASK_RUNNING);
-                       task = kthread_run(bdi_writeback_thread, &bdi->wb, "flush-%s",
-                                          dev_name(bdi->dev));
+                       task = kthread_create(bdi_writeback_thread, &bdi->wb,
+                                             "flush-%s", dev_name(bdi->dev));
                        if (IS_ERR(task)) {
                                /*
                                 * If thread creation fails, force writeout of
@@ -457,10 +459,13 @@ static int bdi_forker_thread(void *ptr)
                                /*
                                 * The spinlock makes sure we do not lose
                                 * wake-ups when racing with 'bdi_queue_work()'.
+                                * And as soon as the bdi thread is visible, we
+                                * can start it.
                                 */
                                spin_lock_bh(&bdi->wb_lock);
                                bdi->wb.task = task;
                                spin_unlock_bh(&bdi->wb_lock);
+                               wake_up_process(task);
                        }
                        break;
 
index 142c84a54993a75ca2fbd5346e3eb5b16552f390..13b0caa9793c008b7fafa09cbe5c586faa6c7447 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/kmemleak.h>
 #include <linux/range.h>
+#include <linux/memblock.h>
 
 #include <asm/bug.h>
 #include <asm/io.h>
@@ -434,7 +435,8 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
                              unsigned long size)
 {
 #ifdef CONFIG_NO_BOOTMEM
-       free_early(physaddr, physaddr + size);
+       kmemleak_free_part(__va(physaddr), size);
+       memblock_x86_free_range(physaddr, physaddr + size);
 #else
        unsigned long start, end;
 
@@ -459,7 +461,8 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 void __init free_bootmem(unsigned long addr, unsigned long size)
 {
 #ifdef CONFIG_NO_BOOTMEM
-       free_early(addr, addr + size);
+       kmemleak_free_part(__va(addr), size);
+       memblock_x86_free_range(addr, addr + size);
 #else
        unsigned long start, end;
 
@@ -526,6 +529,12 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size,
 }
 
 #ifndef CONFIG_NO_BOOTMEM
+int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+                                  int flags)
+{
+       return reserve_bootmem(phys, len, flags);
+}
+
 static unsigned long __init align_idx(struct bootmem_data *bdata,
                                      unsigned long idx, unsigned long step)
 {
index 13b6dad1eed272bec61a388d17f116be62cb1bb5..1481de68184bce6d8fae978d3b6be8e3223319a5 100644 (file)
@@ -116,8 +116,8 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
                 */
                vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
 
-               flush_dcache_page(tovec->bv_page);
                bounce_copy_vec(tovec, vfrom);
+               flush_dcache_page(tovec->bv_page);
        }
 }
 
index 94cce51b0b3535af75c20f29ecb86a11aba32a71..4d709ee5901370842534224a9f81e7d13943e196 100644 (file)
@@ -214,15 +214,16 @@ static void acct_isolated(struct zone *zone, struct compact_control *cc)
 /* Similar to reclaim, but different enough that they don't share logic */
 static bool too_many_isolated(struct zone *zone)
 {
-
-       unsigned long inactive, isolated;
+       unsigned long active, inactive, isolated;
 
        inactive = zone_page_state(zone, NR_INACTIVE_FILE) +
                                        zone_page_state(zone, NR_INACTIVE_ANON);
+       active = zone_page_state(zone, NR_ACTIVE_FILE) +
+                                       zone_page_state(zone, NR_ACTIVE_ANON);
        isolated = zone_page_state(zone, NR_ISOLATED_FILE) +
                                        zone_page_state(zone, NR_ISOLATED_ANON);
 
-       return isolated > inactive;
+       return isolated > (inactive + active) / 2;
 }
 
 /*
index 46f5dacf90a2cd62427fdf89b67fa01ef8af68e0..ec520c7b28dffedb5027de6b27834831938671cd 100644 (file)
@@ -125,7 +125,6 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
 {
        struct mm_struct *mm = current->mm;
        struct address_space *mapping;
-       unsigned long end = start + size;
        struct vm_area_struct *vma;
        int err = -EINVAL;
        int has_write_lock = 0;
@@ -142,6 +141,10 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        if (start + size <= start)
                return err;
 
+       /* Does pgoff wrap? */
+       if (pgoff + (size >> PAGE_SHIFT) < pgoff)
+               return err;
+
        /* Can we represent this offset inside this architecture's pte's? */
 #if PTE_FILE_MAX_BITS < BITS_PER_LONG
        if (pgoff + (size >> PAGE_SHIFT) >= (1UL << PTE_FILE_MAX_BITS))
@@ -168,7 +171,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        if (!(vma->vm_flags & VM_CAN_NONLINEAR))
                goto out;
 
-       if (end <= start || start < vma->vm_start || end > vma->vm_end)
+       if (start < vma->vm_start || start + size > vma->vm_end)
                goto out;
 
        /* Must set VM_NONLINEAR before any pages are populated. */
index cc5be788a39fe132c72cbc1d2fb1c03f71708575..c03273807182dde1d9dd2e905c0db11a6dfe2441 100644 (file)
@@ -2324,11 +2324,8 @@ retry_avoidcopy:
         * and just make the page writable */
        avoidcopy = (page_mapcount(old_page) == 1);
        if (avoidcopy) {
-               if (!trylock_page(old_page)) {
-                       if (PageAnon(old_page))
-                               page_move_anon_rmap(old_page, vma, address);
-               } else
-                       unlock_page(old_page);
+               if (PageAnon(old_page))
+                       page_move_anon_rmap(old_page, vma, address);
                set_huge_ptep_writable(vma, address, ptep);
                return 0;
        }
@@ -2404,7 +2401,7 @@ retry_avoidcopy:
                set_huge_pte_at(mm, address, ptep,
                                make_huge_pte(vma, new_page, 1));
                page_remove_rmap(old_page);
-               hugepage_add_anon_rmap(new_page, vma, address);
+               hugepage_add_new_anon_rmap(new_page, vma, address);
                /* Make the old page be freed below */
                new_page = old_page;
                mmu_notifier_invalidate_range_end(mm,
@@ -2631,10 +2628,16 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                                                                vma, address);
        }
 
-       if (!pagecache_page) {
-               page = pte_page(entry);
+       /*
+        * hugetlb_cow() requires page locks of pte_page(entry) and
+        * pagecache_page, so here we need take the former one
+        * when page != pagecache_page or !pagecache_page.
+        * Note that locking order is always pagecache_page -> page,
+        * so no worry about deadlock.
+        */
+       page = pte_page(entry);
+       if (page != pagecache_page)
                lock_page(page);
-       }
 
        spin_lock(&mm->page_table_lock);
        /* Check for a racing update before calling hugetlb_cow */
@@ -2661,9 +2664,8 @@ out_page_table_lock:
        if (pagecache_page) {
                unlock_page(pagecache_page);
                put_page(pagecache_page);
-       } else {
-               unlock_page(page);
        }
+       unlock_page(page);
 
 out_mutex:
        mutex_unlock(&hugetlb_instantiation_mutex);
index e2ae00458320786a380a1ab370efe0dc6cfd6e1a..65ab5c7067d994ad934c4f4bd5fd5809235a0756 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -712,7 +712,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
        if (!ptep)
                goto out;
 
-       if (pte_write(*ptep)) {
+       if (pte_write(*ptep) || pte_dirty(*ptep)) {
                pte_t entry;
 
                swapped = PageSwapCache(page);
@@ -735,7 +735,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
                        set_pte_at(mm, addr, ptep, entry);
                        goto out_unlock;
                }
-               entry = pte_wrprotect(entry);
+               if (pte_dirty(entry))
+                       set_page_dirty(page);
+               entry = pte_mkclean(pte_wrprotect(entry));
                set_pte_at_notify(mm, addr, ptep, entry);
        }
        *orig_pte = *ptep;
@@ -1504,8 +1506,6 @@ struct page *ksm_does_need_to_copy(struct page *page,
 {
        struct page *new_page;
 
-       unlock_page(page);      /* any racers will COW it, not modify it */
-
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
        if (new_page) {
                copy_user_highpage(new_page, page, address, vma);
@@ -1521,7 +1521,6 @@ struct page *ksm_does_need_to_copy(struct page *page,
                        add_page_to_unevictable_list(new_page);
        }
 
-       page_cache_release(page);
        return new_page;
 }
 
index 43840b305ecb2c01ac478d1c3c67aff7993016a7..400dc62697d78056eaa12c7a91ca9f9daa1d4c77 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/poison.h>
+#include <linux/pfn.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/memblock.h>
 
-#define MEMBLOCK_ALLOC_ANYWHERE        0
+struct memblock memblock __initdata_memblock;
 
-struct memblock memblock;
+int memblock_debug __initdata_memblock;
+int memblock_can_resize __initdata_memblock;
+static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
+static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
 
-static int memblock_debug;
+/* inline so we don't get a warning when pr_debug is compiled out */
+static inline const char *memblock_type_name(struct memblock_type *type)
+{
+       if (type == &memblock.memory)
+               return "memory";
+       else if (type == &memblock.reserved)
+               return "reserved";
+       else
+               return "unknown";
+}
 
-static int __init early_memblock(char *p)
+/*
+ * Address comparison utilities
+ */
+
+static phys_addr_t __init_memblock memblock_align_down(phys_addr_t addr, phys_addr_t size)
 {
-       if (p && strstr(p, "debug"))
-               memblock_debug = 1;
+       return addr & ~(size - 1);
+}
+
+static phys_addr_t __init_memblock memblock_align_up(phys_addr_t addr, phys_addr_t size)
+{
+       return (addr + (size - 1)) & ~(size - 1);
+}
+
+static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
+                                      phys_addr_t base2, phys_addr_t size2)
+{
+       return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
+}
+
+static long __init_memblock memblock_addrs_adjacent(phys_addr_t base1, phys_addr_t size1,
+                              phys_addr_t base2, phys_addr_t size2)
+{
+       if (base2 == base1 + size1)
+               return 1;
+       else if (base1 == base2 + size2)
+               return -1;
+
        return 0;
 }
-early_param("memblock", early_memblock);
 
-static void memblock_dump(struct memblock_region *region, char *name)
+static long __init_memblock memblock_regions_adjacent(struct memblock_type *type,
+                                unsigned long r1, unsigned long r2)
 {
-       unsigned long long base, size;
-       int i;
+       phys_addr_t base1 = type->regions[r1].base;
+       phys_addr_t size1 = type->regions[r1].size;
+       phys_addr_t base2 = type->regions[r2].base;
+       phys_addr_t size2 = type->regions[r2].size;
 
-       pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
+       return memblock_addrs_adjacent(base1, size1, base2, size2);
+}
 
-       for (i = 0; i < region->cnt; i++) {
-               base = region->region[i].base;
-               size = region->region[i].size;
+long __init_memblock memblock_overlaps_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
+{
+       unsigned long i;
 
-               pr_info(" %s[0x%x]\t0x%016llx - 0x%016llx, 0x%llx bytes\n",
-                   name, i, base, base + size - 1, size);
+       for (i = 0; i < type->cnt; i++) {
+               phys_addr_t rgnbase = type->regions[i].base;
+               phys_addr_t rgnsize = type->regions[i].size;
+               if (memblock_addrs_overlap(base, size, rgnbase, rgnsize))
+                       break;
        }
+
+       return (i < type->cnt) ? i : -1;
 }
 
-void memblock_dump_all(void)
+/*
+ * Find, allocate, deallocate or reserve unreserved regions. All allocations
+ * are top-down.
+ */
+
+static phys_addr_t __init_memblock memblock_find_region(phys_addr_t start, phys_addr_t end,
+                                         phys_addr_t size, phys_addr_t align)
 {
-       if (!memblock_debug)
-               return;
+       phys_addr_t base, res_base;
+       long j;
 
-       pr_info("MEMBLOCK configuration:\n");
-       pr_info(" rmo_size    = 0x%llx\n", (unsigned long long)memblock.rmo_size);
-       pr_info(" memory.size = 0x%llx\n", (unsigned long long)memblock.memory.size);
+       /* In case, huge size is requested */
+       if (end < size)
+               return MEMBLOCK_ERROR;
 
-       memblock_dump(&memblock.memory, "memory");
-       memblock_dump(&memblock.reserved, "reserved");
+       base = memblock_align_down((end - size), align);
+
+       /* Prevent allocations returning 0 as it's also used to
+        * indicate an allocation failure
+        */
+       if (start == 0)
+               start = PAGE_SIZE;
+
+       while (start <= base) {
+               j = memblock_overlaps_region(&memblock.reserved, base, size);
+               if (j < 0)
+                       return base;
+               res_base = memblock.reserved.regions[j].base;
+               if (res_base < size)
+                       break;
+               base = memblock_align_down(res_base - size, align);
+       }
+
+       return MEMBLOCK_ERROR;
 }
 
-static unsigned long memblock_addrs_overlap(u64 base1, u64 size1, u64 base2,
-                                       u64 size2)
+static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
+                       phys_addr_t align, phys_addr_t start, phys_addr_t end)
 {
-       return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
+       long i;
+
+       BUG_ON(0 == size);
+
+       size = memblock_align_up(size, align);
+
+       /* Pump up max_addr */
+       if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
+               end = memblock.current_limit;
+
+       /* We do a top-down search, this tends to limit memory
+        * fragmentation by keeping early boot allocs near the
+        * top of memory
+        */
+       for (i = memblock.memory.cnt - 1; i >= 0; i--) {
+               phys_addr_t memblockbase = memblock.memory.regions[i].base;
+               phys_addr_t memblocksize = memblock.memory.regions[i].size;
+               phys_addr_t bottom, top, found;
+
+               if (memblocksize < size)
+                       continue;
+               if ((memblockbase + memblocksize) <= start)
+                       break;
+               bottom = max(memblockbase, start);
+               top = min(memblockbase + memblocksize, end);
+               if (bottom >= top)
+                       continue;
+               found = memblock_find_region(bottom, top, size, align);
+               if (found != MEMBLOCK_ERROR)
+                       return found;
+       }
+       return MEMBLOCK_ERROR;
 }
 
-static long memblock_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
+/*
+ * Find a free area with specified alignment in a specific range.
+ */
+u64 __init_memblock memblock_find_in_range(u64 start, u64 end, u64 size, u64 align)
 {
-       if (base2 == base1 + size1)
-               return 1;
-       else if (base1 == base2 + size2)
-               return -1;
+       return memblock_find_base(size, align, start, end);
+}
 
-       return 0;
+/*
+ * Free memblock.reserved.regions
+ */
+int __init_memblock memblock_free_reserved_regions(void)
+{
+       if (memblock.reserved.regions == memblock_reserved_init_regions)
+               return 0;
+
+       return memblock_free(__pa(memblock.reserved.regions),
+                sizeof(struct memblock_region) * memblock.reserved.max);
 }
 
-static long memblock_regions_adjacent(struct memblock_region *rgn,
-               unsigned long r1, unsigned long r2)
+/*
+ * Reserve memblock.reserved.regions
+ */
+int __init_memblock memblock_reserve_reserved_regions(void)
 {
-       u64 base1 = rgn->region[r1].base;
-       u64 size1 = rgn->region[r1].size;
-       u64 base2 = rgn->region[r2].base;
-       u64 size2 = rgn->region[r2].size;
+       if (memblock.reserved.regions == memblock_reserved_init_regions)
+               return 0;
 
-       return memblock_addrs_adjacent(base1, size1, base2, size2);
+       return memblock_reserve(__pa(memblock.reserved.regions),
+                sizeof(struct memblock_region) * memblock.reserved.max);
 }
 
-static void memblock_remove_region(struct memblock_region *rgn, unsigned long r)
+static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
 {
        unsigned long i;
 
-       for (i = r; i < rgn->cnt - 1; i++) {
-               rgn->region[i].base = rgn->region[i + 1].base;
-               rgn->region[i].size = rgn->region[i + 1].size;
+       for (i = r; i < type->cnt - 1; i++) {
+               type->regions[i].base = type->regions[i + 1].base;
+               type->regions[i].size = type->regions[i + 1].size;
        }
-       rgn->cnt--;
+       type->cnt--;
 }
 
 /* Assumption: base addr of region 1 < base addr of region 2 */
-static void memblock_coalesce_regions(struct memblock_region *rgn,
+static void __init_memblock memblock_coalesce_regions(struct memblock_type *type,
                unsigned long r1, unsigned long r2)
 {
-       rgn->region[r1].size += rgn->region[r2].size;
-       memblock_remove_region(rgn, r2);
+       type->regions[r1].size += type->regions[r2].size;
+       memblock_remove_region(type, r2);
 }
 
-void __init memblock_init(void)
+/* Defined below but needed now */
+static long memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size);
+
+static int __init_memblock memblock_double_array(struct memblock_type *type)
 {
-       /* Create a dummy zero size MEMBLOCK which will get coalesced away later.
-        * This simplifies the memblock_add() code below...
+       struct memblock_region *new_array, *old_array;
+       phys_addr_t old_size, new_size, addr;
+       int use_slab = slab_is_available();
+
+       /* We don't allow resizing until we know about the reserved regions
+        * of memory that aren't suitable for allocation
         */
-       memblock.memory.region[0].base = 0;
-       memblock.memory.region[0].size = 0;
-       memblock.memory.cnt = 1;
+       if (!memblock_can_resize)
+               return -1;
 
-       /* Ditto. */
-       memblock.reserved.region[0].base = 0;
-       memblock.reserved.region[0].size = 0;
-       memblock.reserved.cnt = 1;
-}
+       /* Calculate new doubled size */
+       old_size = type->max * sizeof(struct memblock_region);
+       new_size = old_size << 1;
+
+       /* Try to find some space for it.
+        *
+        * WARNING: We assume that either slab_is_available() and we use it or
+        * we use MEMBLOCK for allocations. That means that this is unsafe to use
+        * when bootmem is currently active (unless bootmem itself is implemented
+        * on top of MEMBLOCK which isn't the case yet)
+        *
+        * This should however not be an issue for now, as we currently only
+        * call into MEMBLOCK while it's still active, or much later when slab is
+        * active for memory hotplug operations
+        */
+       if (use_slab) {
+               new_array = kmalloc(new_size, GFP_KERNEL);
+               addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array);
+       } else
+               addr = memblock_find_base(new_size, sizeof(phys_addr_t), 0, MEMBLOCK_ALLOC_ACCESSIBLE);
+       if (addr == MEMBLOCK_ERROR) {
+               pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
+                      memblock_type_name(type), type->max, type->max * 2);
+               return -1;
+       }
+       new_array = __va(addr);
 
-void __init memblock_analyze(void)
-{
-       int i;
+       memblock_dbg("memblock: %s array is doubled to %ld at [%#010llx-%#010llx]",
+                memblock_type_name(type), type->max * 2, (u64)addr, (u64)addr + new_size - 1);
 
-       memblock.memory.size = 0;
+       /* Found space, we now need to move the array over before
+        * we add the reserved region since it may be our reserved
+        * array itself that is full.
+        */
+       memcpy(new_array, type->regions, old_size);
+       memset(new_array + type->max, 0, old_size);
+       old_array = type->regions;
+       type->regions = new_array;
+       type->max <<= 1;
+
+       /* If we use SLAB that's it, we are done */
+       if (use_slab)
+               return 0;
 
-       for (i = 0; i < memblock.memory.cnt; i++)
-               memblock.memory.size += memblock.memory.region[i].size;
+       /* Add the new reserved region now. Should not fail ! */
+       BUG_ON(memblock_add_region(&memblock.reserved, addr, new_size) < 0);
+
+       /* If the array wasn't our static init one, then free it. We only do
+        * that before SLAB is available as later on, we don't know whether
+        * to use kfree or free_bootmem_pages(). Shouldn't be a big deal
+        * anyways
+        */
+       if (old_array != memblock_memory_init_regions &&
+           old_array != memblock_reserved_init_regions)
+               memblock_free(__pa(old_array), old_size);
+
+       return 0;
 }
 
-static long memblock_add_region(struct memblock_region *rgn, u64 base, u64 size)
+extern int __init_memblock __weak memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
+                                         phys_addr_t addr2, phys_addr_t size2)
+{
+       return 1;
+}
+
+static long __init_memblock memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
 {
        unsigned long coalesced = 0;
        long adjacent, i;
 
-       if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
-               rgn->region[0].base = base;
-               rgn->region[0].size = size;
+       if ((type->cnt == 1) && (type->regions[0].size == 0)) {
+               type->regions[0].base = base;
+               type->regions[0].size = size;
                return 0;
        }
 
        /* First try and coalesce this MEMBLOCK with another. */
-       for (i = 0; i < rgn->cnt; i++) {
-               u64 rgnbase = rgn->region[i].base;
-               u64 rgnsize = rgn->region[i].size;
+       for (i = 0; i < type->cnt; i++) {
+               phys_addr_t rgnbase = type->regions[i].base;
+               phys_addr_t rgnsize = type->regions[i].size;
 
                if ((rgnbase == base) && (rgnsize == size))
                        /* Already have this region, so we're done */
                        return 0;
 
                adjacent = memblock_addrs_adjacent(base, size, rgnbase, rgnsize);
+               /* Check if arch allows coalescing */
+               if (adjacent != 0 && type == &memblock.memory &&
+                   !memblock_memory_can_coalesce(base, size, rgnbase, rgnsize))
+                       break;
                if (adjacent > 0) {
-                       rgn->region[i].base -= size;
-                       rgn->region[i].size += size;
+                       type->regions[i].base -= size;
+                       type->regions[i].size += size;
                        coalesced++;
                        break;
                } else if (adjacent < 0) {
-                       rgn->region[i].size += size;
+                       type->regions[i].size += size;
                        coalesced++;
                        break;
                }
        }
 
-       if ((i < rgn->cnt - 1) && memblock_regions_adjacent(rgn, i, i+1)) {
-               memblock_coalesce_regions(rgn, i, i+1);
+       /* If we plugged a hole, we may want to also coalesce with the
+        * next region
+        */
+       if ((i < type->cnt - 1) && memblock_regions_adjacent(type, i, i+1) &&
+           ((type != &memblock.memory || memblock_memory_can_coalesce(type->regions[i].base,
+                                                            type->regions[i].size,
+                                                            type->regions[i+1].base,
+                                                            type->regions[i+1].size)))) {
+               memblock_coalesce_regions(type, i, i+1);
                coalesced++;
        }
 
        if (coalesced)
                return coalesced;
-       if (rgn->cnt >= MAX_MEMBLOCK_REGIONS)
+
+       /* If we are out of space, we fail. It's too late to resize the array
+        * but then this shouldn't have happened in the first place.
+        */
+       if (WARN_ON(type->cnt >= type->max))
                return -1;
 
        /* Couldn't coalesce the MEMBLOCK, so add it to the sorted table. */
-       for (i = rgn->cnt - 1; i >= 0; i--) {
-               if (base < rgn->region[i].base) {
-                       rgn->region[i+1].base = rgn->region[i].base;
-                       rgn->region[i+1].size = rgn->region[i].size;
+       for (i = type->cnt - 1; i >= 0; i--) {
+               if (base < type->regions[i].base) {
+                       type->regions[i+1].base = type->regions[i].base;
+                       type->regions[i+1].size = type->regions[i].size;
                } else {
-                       rgn->region[i+1].base = base;
-                       rgn->region[i+1].size = size;
+                       type->regions[i+1].base = base;
+                       type->regions[i+1].size = size;
                        break;
                }
        }
 
-       if (base < rgn->region[0].base) {
-               rgn->region[0].base = base;
-               rgn->region[0].size = size;
+       if (base < type->regions[0].base) {
+               type->regions[0].base = base;
+               type->regions[0].size = size;
+       }
+       type->cnt++;
+
+       /* The array is full ? Try to resize it. If that fails, we undo
+        * our allocation and return an error
+        */
+       if (type->cnt == type->max && memblock_double_array(type)) {
+               type->cnt--;
+               return -1;
        }
-       rgn->cnt++;
 
        return 0;
 }
 
-long memblock_add(u64 base, u64 size)
+long __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
 {
-       struct memblock_region *_rgn = &memblock.memory;
-
-       /* On pSeries LPAR systems, the first MEMBLOCK is our RMO region. */
-       if (base == 0)
-               memblock.rmo_size = size;
-
-       return memblock_add_region(_rgn, base, size);
+       return memblock_add_region(&memblock.memory, base, size);
 
 }
 
-static long __memblock_remove(struct memblock_region *rgn, u64 base, u64 size)
+static long __init_memblock __memblock_remove(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
 {
-       u64 rgnbegin, rgnend;
-       u64 end = base + size;
+       phys_addr_t rgnbegin, rgnend;
+       phys_addr_t end = base + size;
        int i;
 
        rgnbegin = rgnend = 0; /* supress gcc warnings */
 
        /* Find the region where (base, size) belongs to */
-       for (i=0; i < rgn->cnt; i++) {
-               rgnbegin = rgn->region[i].base;
-               rgnend = rgnbegin + rgn->region[i].size;
+       for (i=0; i < type->cnt; i++) {
+               rgnbegin = type->regions[i].base;
+               rgnend = rgnbegin + type->regions[i].size;
 
                if ((rgnbegin <= base) && (end <= rgnend))
                        break;
        }
 
        /* Didn't find the region */
-       if (i == rgn->cnt)
+       if (i == type->cnt)
                return -1;
 
        /* Check to see if we are removing entire region */
        if ((rgnbegin == base) && (rgnend == end)) {
-               memblock_remove_region(rgn, i);
+               memblock_remove_region(type, i);
                return 0;
        }
 
        /* Check to see if region is matching at the front */
        if (rgnbegin == base) {
-               rgn->region[i].base = end;
-               rgn->region[i].size -= size;
+               type->regions[i].base = end;
+               type->regions[i].size -= size;
                return 0;
        }
 
        /* Check to see if the region is matching at the end */
        if (rgnend == end) {
-               rgn->region[i].size -= size;
+               type->regions[i].size -= size;
                return 0;
        }
 
@@ -249,208 +435,189 @@ static long __memblock_remove(struct memblock_region *rgn, u64 base, u64 size)
         * We need to split the entry -  adjust the current one to the
         * beginging of the hole and add the region after hole.
         */
-       rgn->region[i].size = base - rgn->region[i].base;
-       return memblock_add_region(rgn, end, rgnend - end);
+       type->regions[i].size = base - type->regions[i].base;
+       return memblock_add_region(type, end, rgnend - end);
 }
 
-long memblock_remove(u64 base, u64 size)
+long __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
 {
        return __memblock_remove(&memblock.memory, base, size);
 }
 
-long __init memblock_free(u64 base, u64 size)
+long __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 {
        return __memblock_remove(&memblock.reserved, base, size);
 }
 
-long __init memblock_reserve(u64 base, u64 size)
+long __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
 {
-       struct memblock_region *_rgn = &memblock.reserved;
+       struct memblock_type *_rgn = &memblock.reserved;
 
        BUG_ON(0 == size);
 
        return memblock_add_region(_rgn, base, size);
 }
 
-long memblock_overlaps_region(struct memblock_region *rgn, u64 base, u64 size)
+phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
-       unsigned long i;
+       phys_addr_t found;
 
-       for (i = 0; i < rgn->cnt; i++) {
-               u64 rgnbase = rgn->region[i].base;
-               u64 rgnsize = rgn->region[i].size;
-               if (memblock_addrs_overlap(base, size, rgnbase, rgnsize))
-                       break;
-       }
+       /* We align the size to limit fragmentation. Without this, a lot of
+        * small allocs quickly eat up the whole reserve array on sparc
+        */
+       size = memblock_align_up(size, align);
 
-       return (i < rgn->cnt) ? i : -1;
+       found = memblock_find_base(size, align, 0, max_addr);
+       if (found != MEMBLOCK_ERROR &&
+           memblock_add_region(&memblock.reserved, found, size) >= 0)
+               return found;
+
+       return 0;
 }
 
-static u64 memblock_align_down(u64 addr, u64 size)
+phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
-       return addr & ~(size - 1);
+       phys_addr_t alloc;
+
+       alloc = __memblock_alloc_base(size, align, max_addr);
+
+       if (alloc == 0)
+               panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
+                     (unsigned long long) size, (unsigned long long) max_addr);
+
+       return alloc;
 }
 
-static u64 memblock_align_up(u64 addr, u64 size)
+phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
-       return (addr + (size - 1)) & ~(size - 1);
+       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 }
 
-static u64 __init memblock_alloc_nid_unreserved(u64 start, u64 end,
-                                          u64 size, u64 align)
+
+/*
+ * Additional node-local allocators. Search for node memory is bottom up
+ * and walks memblock regions within that node bottom-up as well, but allocation
+ * within an memblock region is top-down. XXX I plan to fix that at some stage
+ *
+ * WARNING: Only available after early_node_map[] has been populated,
+ * on some architectures, that is after all the calls to add_active_range()
+ * have been done to populate it.
+ */
+
+phys_addr_t __weak __init memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid)
 {
-       u64 base, res_base;
-       long j;
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+       /*
+        * This code originates from sparc which really wants use to walk by addresses
+        * and returns the nid. This is not very convenient for early_pfn_map[] users
+        * as the map isn't sorted yet, and it really wants to be walked by nid.
+        *
+        * For now, I implement the inefficient method below which walks the early
+        * map multiple times. Eventually we may want to use an ARCH config option
+        * to implement a completely different method for both case.
+        */
+       unsigned long start_pfn, end_pfn;
+       int i;
 
-       base = memblock_align_down((end - size), align);
-       while (start <= base) {
-               j = memblock_overlaps_region(&memblock.reserved, base, size);
-               if (j < 0) {
-                       /* this area isn't reserved, take it */
-                       if (memblock_add_region(&memblock.reserved, base, size) < 0)
-                               base = ~(u64)0;
-                       return base;
-               }
-               res_base = memblock.reserved.region[j].base;
-               if (res_base < size)
-                       break;
-               base = memblock_align_down(res_base - size, align);
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               get_pfn_range_for_nid(i, &start_pfn, &end_pfn);
+               if (start < PFN_PHYS(start_pfn) || start >= PFN_PHYS(end_pfn))
+                       continue;
+               *nid = i;
+               return min(end, PFN_PHYS(end_pfn));
        }
+#endif
+       *nid = 0;
 
-       return ~(u64)0;
+       return end;
 }
 
-static u64 __init memblock_alloc_nid_region(struct memblock_property *mp,
-                                      u64 (*nid_range)(u64, u64, int *),
-                                      u64 size, u64 align, int nid)
+static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp,
+                                              phys_addr_t size,
+                                              phys_addr_t align, int nid)
 {
-       u64 start, end;
+       phys_addr_t start, end;
 
        start = mp->base;
        end = start + mp->size;
 
        start = memblock_align_up(start, align);
        while (start < end) {
-               u64 this_end;
+               phys_addr_t this_end;
                int this_nid;
 
-               this_end = nid_range(start, end, &this_nid);
+               this_end = memblock_nid_range(start, end, &this_nid);
                if (this_nid == nid) {
-                       u64 ret = memblock_alloc_nid_unreserved(start, this_end,
-                                                          size, align);
-                       if (ret != ~(u64)0)
+                       phys_addr_t ret = memblock_find_region(start, this_end, size, align);
+                       if (ret != MEMBLOCK_ERROR &&
+                           memblock_add_region(&memblock.reserved, ret, size) >= 0)
                                return ret;
                }
                start = this_end;
        }
 
-       return ~(u64)0;
+       return MEMBLOCK_ERROR;
 }
 
-u64 __init memblock_alloc_nid(u64 size, u64 align, int nid,
-                        u64 (*nid_range)(u64 start, u64 end, int *nid))
+phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-       struct memblock_region *mem = &memblock.memory;
+       struct memblock_type *mem = &memblock.memory;
        int i;
 
        BUG_ON(0 == size);
 
+       /* We align the size to limit fragmentation. Without this, a lot of
+        * small allocs quickly eat up the whole reserve array on sparc
+        */
        size = memblock_align_up(size, align);
 
+       /* We do a bottom-up search for a region with the right
+        * nid since that's easier considering how memblock_nid_range()
+        * works
+        */
        for (i = 0; i < mem->cnt; i++) {
-               u64 ret = memblock_alloc_nid_region(&mem->region[i],
-                                              nid_range,
+               phys_addr_t ret = memblock_alloc_nid_region(&mem->regions[i],
                                               size, align, nid);
-               if (ret != ~(u64)0)
+               if (ret != MEMBLOCK_ERROR)
                        return ret;
        }
 
-       return memblock_alloc(size, align);
-}
-
-u64 __init memblock_alloc(u64 size, u64 align)
-{
-       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
+       return 0;
 }
 
-u64 __init memblock_alloc_base(u64 size, u64 align, u64 max_addr)
+phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-       u64 alloc;
-
-       alloc = __memblock_alloc_base(size, align, max_addr);
+       phys_addr_t res = memblock_alloc_nid(size, align, nid);
 
-       if (alloc == 0)
-               panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
-                     (unsigned long long) size, (unsigned long long) max_addr);
-
-       return alloc;
+       if (res)
+               return res;
+       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
 }
 
-u64 __init __memblock_alloc_base(u64 size, u64 align, u64 max_addr)
-{
-       long i, j;
-       u64 base = 0;
-       u64 res_base;
-
-       BUG_ON(0 == size);
 
-       size = memblock_align_up(size, align);
-
-       /* On some platforms, make sure we allocate lowmem */
-       /* Note that MEMBLOCK_REAL_LIMIT may be MEMBLOCK_ALLOC_ANYWHERE */
-       if (max_addr == MEMBLOCK_ALLOC_ANYWHERE)
-               max_addr = MEMBLOCK_REAL_LIMIT;
-
-       for (i = memblock.memory.cnt - 1; i >= 0; i--) {
-               u64 memblockbase = memblock.memory.region[i].base;
-               u64 memblocksize = memblock.memory.region[i].size;
-
-               if (memblocksize < size)
-                       continue;
-               if (max_addr == MEMBLOCK_ALLOC_ANYWHERE)
-                       base = memblock_align_down(memblockbase + memblocksize - size, align);
-               else if (memblockbase < max_addr) {
-                       base = min(memblockbase + memblocksize, max_addr);
-                       base = memblock_align_down(base - size, align);
-               } else
-                       continue;
-
-               while (base && memblockbase <= base) {
-                       j = memblock_overlaps_region(&memblock.reserved, base, size);
-                       if (j < 0) {
-                               /* this area isn't reserved, take it */
-                               if (memblock_add_region(&memblock.reserved, base, size) < 0)
-                                       return 0;
-                               return base;
-                       }
-                       res_base = memblock.reserved.region[j].base;
-                       if (res_base < size)
-                               break;
-                       base = memblock_align_down(res_base - size, align);
-               }
-       }
-       return 0;
-}
+/*
+ * Remaining API functions
+ */
 
 /* You must call memblock_analyze() before this. */
-u64 __init memblock_phys_mem_size(void)
+phys_addr_t __init memblock_phys_mem_size(void)
 {
-       return memblock.memory.size;
+       return memblock.memory_size;
 }
 
-u64 memblock_end_of_DRAM(void)
+phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 {
        int idx = memblock.memory.cnt - 1;
 
-       return (memblock.memory.region[idx].base + memblock.memory.region[idx].size);
+       return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
 /* You must call memblock_analyze() after this. */
-void __init memblock_enforce_memory_limit(u64 memory_limit)
+void __init memblock_enforce_memory_limit(phys_addr_t memory_limit)
 {
        unsigned long i;
-       u64 limit;
-       struct memblock_property *p;
+       phys_addr_t limit;
+       struct memblock_region *p;
 
        if (!memory_limit)
                return;
@@ -458,24 +625,21 @@ void __init memblock_enforce_memory_limit(u64 memory_limit)
        /* Truncate the memblock regions to satisfy the memory limit. */
        limit = memory_limit;
        for (i = 0; i < memblock.memory.cnt; i++) {
-               if (limit > memblock.memory.region[i].size) {
-                       limit -= memblock.memory.region[i].size;
+               if (limit > memblock.memory.regions[i].size) {
+                       limit -= memblock.memory.regions[i].size;
                        continue;
                }
 
-               memblock.memory.region[i].size = limit;
+               memblock.memory.regions[i].size = limit;
                memblock.memory.cnt = i + 1;
                break;
        }
 
-       if (memblock.memory.region[0].size < memblock.rmo_size)
-               memblock.rmo_size = memblock.memory.region[0].size;
-
        memory_limit = memblock_end_of_DRAM();
 
        /* And truncate any reserves above the limit also. */
        for (i = 0; i < memblock.reserved.cnt; i++) {
-               p = &memblock.reserved.region[i];
+               p = &memblock.reserved.regions[i];
 
                if (p->base > memory_limit)
                        p->size = 0;
@@ -489,53 +653,190 @@ void __init memblock_enforce_memory_limit(u64 memory_limit)
        }
 }
 
-int __init memblock_is_reserved(u64 addr)
+static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
+{
+       unsigned int left = 0, right = type->cnt;
+
+       do {
+               unsigned int mid = (right + left) / 2;
+
+               if (addr < type->regions[mid].base)
+                       right = mid;
+               else if (addr >= (type->regions[mid].base +
+                                 type->regions[mid].size))
+                       left = mid + 1;
+               else
+                       return mid;
+       } while (left < right);
+       return -1;
+}
+
+int __init memblock_is_reserved(phys_addr_t addr)
+{
+       return memblock_search(&memblock.reserved, addr) != -1;
+}
+
+int __init_memblock memblock_is_memory(phys_addr_t addr)
+{
+       return memblock_search(&memblock.memory, addr) != -1;
+}
+
+int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
+{
+       int idx = memblock_search(&memblock.reserved, base);
+
+       if (idx == -1)
+               return 0;
+       return memblock.reserved.regions[idx].base <= base &&
+               (memblock.reserved.regions[idx].base +
+                memblock.reserved.regions[idx].size) >= (base + size);
+}
+
+int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
+{
+       return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
+}
+
+
+void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
+       memblock.current_limit = limit;
+}
+
+static void __init_memblock memblock_dump(struct memblock_type *region, char *name)
+{
+       unsigned long long base, size;
        int i;
 
-       for (i = 0; i < memblock.reserved.cnt; i++) {
-               u64 upper = memblock.reserved.region[i].base +
-                       memblock.reserved.region[i].size - 1;
-               if ((addr >= memblock.reserved.region[i].base) && (addr <= upper))
-                       return 1;
+       pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
+
+       for (i = 0; i < region->cnt; i++) {
+               base = region->regions[i].base;
+               size = region->regions[i].size;
+
+               pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes\n",
+                   name, i, base, base + size - 1, size);
        }
-       return 0;
 }
 
-int memblock_is_region_reserved(u64 base, u64 size)
+void __init_memblock memblock_dump_all(void)
 {
-       return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
+       if (!memblock_debug)
+               return;
+
+       pr_info("MEMBLOCK configuration:\n");
+       pr_info(" memory size = 0x%llx\n", (unsigned long long)memblock.memory_size);
+
+       memblock_dump(&memblock.memory, "memory");
+       memblock_dump(&memblock.reserved, "reserved");
 }
 
-/*
- * Given a <base, len>, find which memory regions belong to this range.
- * Adjust the request and return a contiguous chunk.
- */
-int memblock_find(struct memblock_property *res)
+void __init memblock_analyze(void)
 {
        int i;
-       u64 rstart, rend;
 
-       rstart = res->base;
-       rend = rstart + res->size - 1;
+       /* Check marker in the unused last array entry */
+       WARN_ON(memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS].base
+               != (phys_addr_t)RED_INACTIVE);
+       WARN_ON(memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS].base
+               != (phys_addr_t)RED_INACTIVE);
+
+       memblock.memory_size = 0;
+
+       for (i = 0; i < memblock.memory.cnt; i++)
+               memblock.memory_size += memblock.memory.regions[i].size;
+
+       /* We allow resizing from there */
+       memblock_can_resize = 1;
+}
+
+void __init memblock_init(void)
+{
+       static int init_done __initdata = 0;
+
+       if (init_done)
+               return;
+       init_done = 1;
+
+       /* Hookup the initial arrays */
+       memblock.memory.regions = memblock_memory_init_regions;
+       memblock.memory.max             = INIT_MEMBLOCK_REGIONS;
+       memblock.reserved.regions       = memblock_reserved_init_regions;
+       memblock.reserved.max   = INIT_MEMBLOCK_REGIONS;
+
+       /* Write a marker in the unused last array entry */
+       memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
+       memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
+
+       /* Create a dummy zero size MEMBLOCK which will get coalesced away later.
+        * This simplifies the memblock_add() code below...
+        */
+       memblock.memory.regions[0].base = 0;
+       memblock.memory.regions[0].size = 0;
+       memblock.memory.cnt = 1;
+
+       /* Ditto. */
+       memblock.reserved.regions[0].base = 0;
+       memblock.reserved.regions[0].size = 0;
+       memblock.reserved.cnt = 1;
+
+       memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
+}
+
+static int __init early_memblock(char *p)
+{
+       if (p && strstr(p, "debug"))
+               memblock_debug = 1;
+       return 0;
+}
+early_param("memblock", early_memblock);
+
+#if defined(CONFIG_DEBUG_FS) && !defined(ARCH_DISCARD_MEMBLOCK)
+
+static int memblock_debug_show(struct seq_file *m, void *private)
+{
+       struct memblock_type *type = m->private;
+       struct memblock_region *reg;
+       int i;
+
+       for (i = 0; i < type->cnt; i++) {
+               reg = &type->regions[i];
+               seq_printf(m, "%4d: ", i);
+               if (sizeof(phys_addr_t) == 4)
+                       seq_printf(m, "0x%08lx..0x%08lx\n",
+                                  (unsigned long)reg->base,
+                                  (unsigned long)(reg->base + reg->size - 1));
+               else
+                       seq_printf(m, "0x%016llx..0x%016llx\n",
+                                  (unsigned long long)reg->base,
+                                  (unsigned long long)(reg->base + reg->size - 1));
 
-       for (i = 0; i < memblock.memory.cnt; i++) {
-               u64 start = memblock.memory.region[i].base;
-               u64 end = start + memblock.memory.region[i].size - 1;
-
-               if (start > rend)
-                       return -1;
-
-               if ((end >= rstart) && (start < rend)) {
-                       /* adjust the request */
-                       if (rstart < start)
-                               rstart = start;
-                       if (rend > end)
-                               rend = end;
-                       res->base = rstart;
-                       res->size = rend - rstart + 1;
-                       return 0;
-               }
        }
-       return -1;
+       return 0;
+}
+
+static int memblock_debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, memblock_debug_show, inode->i_private);
 }
+
+static const struct file_operations memblock_debug_fops = {
+       .open = memblock_debug_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int __init memblock_init_debugfs(void)
+{
+       struct dentry *root = debugfs_create_dir("memblock", NULL);
+       if (!root)
+               return -ENXIO;
+       debugfs_create_file("memory", S_IRUGO, root, &memblock.memory, &memblock_debug_fops);
+       debugfs_create_file("reserved", S_IRUGO, root, &memblock.reserved, &memblock_debug_fops);
+
+       return 0;
+}
+__initcall(memblock_init_debugfs);
+
+#endif /* CONFIG_DEBUG_FS */
index 3eed583895a6f31eb434a252697371c7daa6bbd4..9be3cf8a5da462d4b1b4103eef61f8d5a9a6e06c 100644 (file)
@@ -3587,9 +3587,13 @@ unlock:
 
 static void mem_cgroup_threshold(struct mem_cgroup *memcg)
 {
-       __mem_cgroup_threshold(memcg, false);
-       if (do_swap_account)
-               __mem_cgroup_threshold(memcg, true);
+       while (memcg) {
+               __mem_cgroup_threshold(memcg, false);
+               if (do_swap_account)
+                       __mem_cgroup_threshold(memcg, true);
+
+               memcg = parent_mem_cgroup(memcg);
+       }
 }
 
 static int compare_thresholds(const void *a, const void *b)
index 9c26eeca13425886690cddaf6dd45954fd3f0097..757f6b0accfe84d959b7fe5899b5916ad0ed1f14 100644 (file)
@@ -183,7 +183,7 @@ EXPORT_SYMBOL_GPL(hwpoison_filter);
  * signal.
  */
 static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno,
-                       unsigned long pfn)
+                       unsigned long pfn, struct page *page)
 {
        struct siginfo si;
        int ret;
@@ -198,7 +198,7 @@ static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno,
 #ifdef __ARCH_SI_TRAPNO
        si.si_trapno = trapno;
 #endif
-       si.si_addr_lsb = PAGE_SHIFT;
+       si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
        /*
         * Don't use force here, it's convenient if the signal
         * can be temporarily blocked.
@@ -235,7 +235,7 @@ void shake_page(struct page *p, int access)
                int nr;
                do {
                        nr = shrink_slab(1000, GFP_KERNEL, 1000);
-                       if (page_count(p) == 0)
+                       if (page_count(p) == 1)
                                break;
                } while (nr > 10);
        }
@@ -327,7 +327,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
  * wrong earlier.
  */
 static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno,
-                         int fail, unsigned long pfn)
+                         int fail, struct page *page, unsigned long pfn)
 {
        struct to_kill *tk, *next;
 
@@ -352,7 +352,7 @@ static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno,
                         * process anyways.
                         */
                        else if (kill_proc_ao(tk->tsk, tk->addr, trapno,
-                                             pfn) < 0)
+                                             pfn, page) < 0)
                                printk(KERN_ERR
                "MCE %#lx: Cannot send advisory machine check signal to %s:%d\n",
                                        pfn, tk->tsk->comm, tk->tsk->pid);
@@ -928,7 +928,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * any accesses to the poisoned memory.
         */
        kill_procs_ao(&tokill, !!PageDirty(hpage), trapno,
-                     ret != SWAP_SUCCESS, pfn);
+                     ret != SWAP_SUCCESS, p, pfn);
 
        return ret;
 }
index 2ed2267439df0f894011ab62adef6d7efe68db9a..98b58fecedeffc236a9c7285689fe4720409bd30 100644 (file)
@@ -2623,7 +2623,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned int flags, pte_t orig_pte)
 {
        spinlock_t *ptl;
-       struct page *page;
+       struct page *page, *swapcache = NULL;
        swp_entry_t entry;
        pte_t pte;
        struct mem_cgroup *ptr = NULL;
@@ -2679,10 +2679,25 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        lock_page(page);
        delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
 
-       page = ksm_might_need_to_copy(page, vma, address);
-       if (!page) {
-               ret = VM_FAULT_OOM;
-               goto out;
+       /*
+        * Make sure try_to_free_swap or reuse_swap_page or swapoff did not
+        * release the swapcache from under us.  The page pin, and pte_same
+        * test below, are not enough to exclude that.  Even if it is still
+        * swapcache, we need to check that the page's swap has not changed.
+        */
+       if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val))
+               goto out_page;
+
+       if (ksm_might_need_to_copy(page, vma, address)) {
+               swapcache = page;
+               page = ksm_does_need_to_copy(page, vma, address);
+
+               if (unlikely(!page)) {
+                       ret = VM_FAULT_OOM;
+                       page = swapcache;
+                       swapcache = NULL;
+                       goto out_page;
+               }
        }
 
        if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) {
@@ -2735,6 +2750,18 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
                try_to_free_swap(page);
        unlock_page(page);
+       if (swapcache) {
+               /*
+                * Hold the lock to avoid the swap entry to be reused
+                * until we take the PT lock for the pte_same() check
+                * (to avoid false positives from pte_same). For
+                * further safety release the lock after the swap_free
+                * so that the swap count won't change under a
+                * parallel locked swapcache.
+                */
+               unlock_page(swapcache);
+               page_cache_release(swapcache);
+       }
 
        if (flags & FAULT_FLAG_WRITE) {
                ret |= do_wp_page(mm, vma, address, page_table, pmd, ptl, pte);
@@ -2756,15 +2783,17 @@ out_page:
        unlock_page(page);
 out_release:
        page_cache_release(page);
+       if (swapcache) {
+               unlock_page(swapcache);
+               page_cache_release(swapcache);
+       }
        return ret;
 }
 
 /*
- * This is like a special single-page "expand_downwards()",
- * except we must first make sure that 'address-PAGE_SIZE'
+ * This is like a special single-page "expand_{down|up}wards()",
+ * except we must first make sure that 'address{-|+}PAGE_SIZE'
  * doesn't hit another vma.
- *
- * The "find_vma()" will do the right thing even if we wrap
  */
 static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
 {
@@ -2783,6 +2812,15 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
 
                expand_stack(vma, address - PAGE_SIZE);
        }
+       if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
+               struct vm_area_struct *next = vma->vm_next;
+
+               /* As VM_GROWSDOWN but s/below/above/ */
+               if (next && next->vm_start == address + PAGE_SIZE)
+                       return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
+
+               expand_upwards(vma, address + PAGE_SIZE);
+       }
        return 0;
 }
 
@@ -3147,7 +3185,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
                 * with threads.
                 */
                if (flags & FAULT_FLAG_WRITE)
-                       flush_tlb_page(vma, address);
+                       flush_tlb_fix_spurious_fault(vma, address);
        }
 unlock:
        pte_unmap_unlock(pte, ptl);
index a4cfcdc00455de4be15fcec98c76e45f8de5feab..dd186c1a5d53f9ebd27de4c1bedcaac471d6c93e 100644 (file)
@@ -584,19 +584,19 @@ static inline int pageblock_free(struct page *page)
 /* Return the start of the next active pageblock after a given page */
 static struct page *next_active_pageblock(struct page *page)
 {
-       int pageblocks_stride;
-
        /* Ensure the starting page is pageblock-aligned */
        BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1));
 
-       /* Move forward by at least 1 * pageblock_nr_pages */
-       pageblocks_stride = 1;
-
        /* If the entire pageblock is free, move to the end of free page */
-       if (pageblock_free(page))
-               pageblocks_stride += page_order(page) - pageblock_order;
+       if (pageblock_free(page)) {
+               int order;
+               /* be careful. we don't have locks, page_order can be changed.*/
+               order = page_order(page);
+               if ((order < MAX_ORDER) && (order >= pageblock_order))
+                       return page + (1 << order);
+       }
 
-       return page + (pageblocks_stride * pageblock_nr_pages);
+       return page + pageblock_nr_pages;
 }
 
 /* Checks if this range of memory is likely to be hot-removable. */
index cbae7c5b95680a1bfca1df7e11a215bfce15b57c..b70919ce4f72e6941f67b1a5462f5f270c231536 100644 (file)
@@ -135,12 +135,6 @@ void munlock_vma_page(struct page *page)
        }
 }
 
-/* Is the vma a continuation of the stack vma above it? */
-static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
-{
-       return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
-}
-
 static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
 {
        return (vma->vm_flags & VM_GROWSDOWN) &&
index 331e51af38c9c950c8295fa125c67d00ba540025..00161a48a45100c611ebaa053f0b1f1486d09f29 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1716,9 +1716,6 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
  * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
  * vma is the last one with address > vma->vm_end.  Have to extend vma.
  */
-#ifndef CONFIG_IA64
-static
-#endif
 int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
        int error;
@@ -2012,6 +2009,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
                        removed_exe_file_vma(mm);
                fput(new->vm_file);
        }
+       unlink_anon_vmas(new);
  out_free_mpol:
        mpol_put(pol);
  out_free_vma:
index f5b7d1760213e53db3c46e84dde56daf219ea0cd..e35bfb82c8555b7377334dbea42bfcf588b0bab8 100644 (file)
@@ -87,3 +87,24 @@ int memmap_valid_within(unsigned long pfn,
        return 1;
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
+
+#ifdef CONFIG_SMP
+/* Called when a more accurate view of NR_FREE_PAGES is needed */
+unsigned long zone_nr_free_pages(struct zone *zone)
+{
+       unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES);
+
+       /*
+        * While kswapd is awake, it is considered the zone is under some
+        * memory pressure. Under pressure, there is a risk that
+        * per-cpu-counter-drift will allow the min watermark to be breached
+        * potentially causing a live-lock. While kswapd is awake and
+        * free pages are low, get a better estimate for free pages
+        */
+       if (nr_free_pages < zone->percpu_drift_mark &&
+                       !waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+               return zone_page_state_snapshot(zone, NR_FREE_PAGES);
+
+       return nr_free_pages;
+}
+#endif /* CONFIG_SMP */
index fc81cb22869ef54e6871daf39f51b32e3377aa98..4029583a10241aaa84e3937ee216740e0a88a363 100644 (file)
@@ -121,8 +121,8 @@ struct task_struct *find_lock_task_mm(struct task_struct *p)
 }
 
 /* return true if the task is not adequate as candidate victim task. */
-static bool oom_unkillable_task(struct task_struct *p, struct mem_cgroup *mem,
-                          const nodemask_t *nodemask)
+static bool oom_unkillable_task(struct task_struct *p,
+               const struct mem_cgroup *mem, const nodemask_t *nodemask)
 {
        if (is_global_init(p))
                return true;
@@ -208,8 +208,13 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
         */
        points += p->signal->oom_score_adj;
 
-       if (points < 0)
-               return 0;
+       /*
+        * Never return 0 for an eligible task that may be killed since it's
+        * possible that no single user task uses more than 0.1% of memory and
+        * no single admin tasks uses more than 3.0%.
+        */
+       if (points <= 0)
+               return 1;
        return (points < 1000) ? points : 1000;
 }
 
@@ -339,26 +344,24 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 /**
  * dump_tasks - dump current memory state of all system tasks
  * @mem: current's memory controller, if constrained
+ * @nodemask: nodemask passed to page allocator for mempolicy ooms
  *
- * Dumps the current memory state of all system tasks, excluding kernel threads.
+ * Dumps the current memory state of all eligible tasks.  Tasks not in the same
+ * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes
+ * are not shown.
  * State information includes task's pid, uid, tgid, vm size, rss, cpu, oom_adj
  * value, oom_score_adj value, and name.
  *
- * If the actual is non-NULL, only tasks that are a member of the mem_cgroup are
- * shown.
- *
  * Call with tasklist_lock read-locked.
  */
-static void dump_tasks(const struct mem_cgroup *mem)
+static void dump_tasks(const struct mem_cgroup *mem, const nodemask_t *nodemask)
 {
        struct task_struct *p;
        struct task_struct *task;
 
        pr_info("[ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name\n");
        for_each_process(p) {
-               if (p->flags & PF_KTHREAD)
-                       continue;
-               if (mem && !task_in_mem_cgroup(p, mem))
+               if (oom_unkillable_task(p, mem, nodemask))
                        continue;
 
                task = find_lock_task_mm(p);
@@ -381,7 +384,7 @@ static void dump_tasks(const struct mem_cgroup *mem)
 }
 
 static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
-                                                       struct mem_cgroup *mem)
+                       struct mem_cgroup *mem, const nodemask_t *nodemask)
 {
        task_lock(current);
        pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
@@ -394,7 +397,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
        mem_cgroup_print_oom_info(mem, p);
        show_mem();
        if (sysctl_oom_dump_tasks)
-               dump_tasks(mem);
+               dump_tasks(mem, nodemask);
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
@@ -436,7 +439,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
        unsigned int victim_points = 0;
 
        if (printk_ratelimit())
-               dump_header(p, gfp_mask, order, mem);
+               dump_header(p, gfp_mask, order, mem, nodemask);
 
        /*
         * If the task is already exiting, don't alarm the sysadmin or kill
@@ -482,7 +485,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.
  */
 static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
-                               int order)
+                               int order, const nodemask_t *nodemask)
 {
        if (likely(!sysctl_panic_on_oom))
                return;
@@ -496,7 +499,7 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
                        return;
        }
        read_lock(&tasklist_lock);
-       dump_header(NULL, gfp_mask, order, NULL);
+       dump_header(NULL, gfp_mask, order, NULL, nodemask);
        read_unlock(&tasklist_lock);
        panic("Out of memory: %s panic_on_oom is enabled\n",
                sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide");
@@ -509,7 +512,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
        unsigned int points = 0;
        struct task_struct *p;
 
-       check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0);
+       check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
        limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT;
        read_lock(&tasklist_lock);
 retry:
@@ -641,6 +644,7 @@ static void clear_system_oom(void)
 void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
                int order, nodemask_t *nodemask)
 {
+       const nodemask_t *mpol_mask;
        struct task_struct *p;
        unsigned long totalpages;
        unsigned long freed = 0;
@@ -670,7 +674,8 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
         */
        constraint = constrained_alloc(zonelist, gfp_mask, nodemask,
                                                &totalpages);
-       check_panic_on_oom(constraint, gfp_mask, order);
+       mpol_mask = (constraint == CONSTRAINT_MEMORY_POLICY) ? nodemask : NULL;
+       check_panic_on_oom(constraint, gfp_mask, order, mpol_mask);
 
        read_lock(&tasklist_lock);
        if (sysctl_oom_kill_allocating_task &&
@@ -688,15 +693,13 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
        }
 
 retry:
-       p = select_bad_process(&points, totalpages, NULL,
-                       constraint == CONSTRAINT_MEMORY_POLICY ? nodemask :
-                                                                NULL);
+       p = select_bad_process(&points, totalpages, NULL, mpol_mask);
        if (PTR_ERR(p) == -1UL)
                goto out;
 
        /* Found nothing?!?! Either we hang forever, or we panic. */
        if (!p) {
-               dump_header(NULL, gfp_mask, order, NULL);
+               dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
                read_unlock(&tasklist_lock);
                panic("Out of memory and no killable processes...\n");
        }
index c09ef5219cbe36f267a37f55d6fc670815082522..e3bccac1f0255bb78373e6268aab787a370ee520 100644 (file)
@@ -985,22 +985,16 @@ continue_unlock:
                                }
                        }
 
-                       if (wbc->nr_to_write > 0) {
-                               if (--wbc->nr_to_write == 0 &&
-                                   wbc->sync_mode == WB_SYNC_NONE) {
-                                       /*
-                                        * We stop writing back only if we are
-                                        * not doing integrity sync. In case of
-                                        * integrity sync we have to keep going
-                                        * because someone may be concurrently
-                                        * dirtying pages, and we might have
-                                        * synced a lot of newly appeared dirty
-                                        * pages, but have not synced all of the
-                                        * old dirty pages.
-                                        */
-                                       done = 1;
-                                       break;
-                               }
+                       /*
+                        * We stop writing back only if we are not doing
+                        * integrity sync. In case of integrity sync we have to
+                        * keep going until we have written all the pages
+                        * we tagged for writeback prior to entering this loop.
+                        */
+                       if (--wbc->nr_to_write <= 0 &&
+                           wbc->sync_mode == WB_SYNC_NONE) {
+                               done = 1;
+                               break;
                        }
                }
                pagevec_release(&pvec);
@@ -1132,6 +1126,7 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
                task_io_account_write(PAGE_CACHE_SIZE);
        }
 }
+EXPORT_SYMBOL(account_page_dirtied);
 
 /*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
index a9649f4b261e6b3c01632939c46a77f19f447de1..2a362c52fdf482144eac24111059f56b5147bd42 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/pagemap.h>
 #include <linux/jiffies.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/kmemcheck.h>
@@ -588,13 +589,13 @@ static void free_pcppages_bulk(struct zone *zone, int count,
 {
        int migratetype = 0;
        int batch_free = 0;
+       int to_free = count;
 
        spin_lock(&zone->lock);
        zone->all_unreclaimable = 0;
        zone->pages_scanned = 0;
 
-       __mod_zone_page_state(zone, NR_FREE_PAGES, count);
-       while (count) {
+       while (to_free) {
                struct page *page;
                struct list_head *list;
 
@@ -619,8 +620,9 @@ static void free_pcppages_bulk(struct zone *zone, int count,
                        /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
                        __free_one_page(page, zone, 0, page_private(page));
                        trace_mm_page_pcpu_drain(page, 0, page_private(page));
-               } while (--count && --batch_free && !list_empty(list));
+               } while (--to_free && --batch_free && !list_empty(list));
        }
+       __mod_zone_page_state(zone, NR_FREE_PAGES, count);
        spin_unlock(&zone->lock);
 }
 
@@ -631,8 +633,8 @@ static void free_one_page(struct zone *zone, struct page *page, int order,
        zone->all_unreclaimable = 0;
        zone->pages_scanned = 0;
 
-       __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
        __free_one_page(page, zone, order, migratetype);
+       __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
        spin_unlock(&zone->lock);
 }
 
@@ -1461,7 +1463,7 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 {
        /* free_pages my go negative - that's OK */
        long min = mark;
-       long free_pages = zone_page_state(z, NR_FREE_PAGES) - (1 << order) + 1;
+       long free_pages = zone_nr_free_pages(z) - (1 << order) + 1;
        int o;
 
        if (alloc_flags & ALLOC_HIGH)
@@ -1846,6 +1848,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
        struct page *page = NULL;
        struct reclaim_state reclaim_state;
        struct task_struct *p = current;
+       bool drained = false;
 
        cond_resched();
 
@@ -1864,14 +1867,25 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
 
        cond_resched();
 
-       if (order != 0)
-               drain_all_pages();
+       if (unlikely(!(*did_some_progress)))
+               return NULL;
 
-       if (likely(*did_some_progress))
-               page = get_page_from_freelist(gfp_mask, nodemask, order,
+retry:
+       page = get_page_from_freelist(gfp_mask, nodemask, order,
                                        zonelist, high_zoneidx,
                                        alloc_flags, preferred_zone,
                                        migratetype);
+
+       /*
+        * If an allocation failed after direct reclaim, it could be because
+        * pages are pinned on the per-cpu lists. Drain them and try again
+        */
+       if (!page && !drained) {
+               drain_all_pages();
+               drained = true;
+               goto retry;
+       }
+
        return page;
 }
 
@@ -2423,7 +2437,7 @@ void show_free_areas(void)
                        " all_unreclaimable? %s"
                        "\n",
                        zone->name,
-                       K(zone_page_state(zone, NR_FREE_PAGES)),
+                       K(zone_nr_free_pages(zone)),
                        K(min_wmark_pages(zone)),
                        K(low_wmark_pages(zone)),
                        K(high_wmark_pages(zone)),
@@ -3623,6 +3637,41 @@ void __init free_bootmem_with_active_regions(int nid,
        }
 }
 
+#ifdef CONFIG_HAVE_MEMBLOCK
+u64 __init find_memory_core_early(int nid, u64 size, u64 align,
+                                       u64 goal, u64 limit)
+{
+       int i;
+
+       /* Need to go over early_node_map to find out good range for node */
+       for_each_active_range_index_in_nid(i, nid) {
+               u64 addr;
+               u64 ei_start, ei_last;
+               u64 final_start, final_end;
+
+               ei_last = early_node_map[i].end_pfn;
+               ei_last <<= PAGE_SHIFT;
+               ei_start = early_node_map[i].start_pfn;
+               ei_start <<= PAGE_SHIFT;
+
+               final_start = max(ei_start, goal);
+               final_end = min(ei_last, limit);
+
+               if (final_start >= final_end)
+                       continue;
+
+               addr = memblock_find_in_range(final_start, final_end, size, align);
+
+               if (addr == MEMBLOCK_ERROR)
+                       continue;
+
+               return addr;
+       }
+
+       return MEMBLOCK_ERROR;
+}
+#endif
+
 int __init add_from_early_node_map(struct range *range, int az,
                                   int nr_range, int nid)
 {
@@ -3642,46 +3691,26 @@ int __init add_from_early_node_map(struct range *range, int az,
 void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
                                        u64 goal, u64 limit)
 {
-       int i;
        void *ptr;
+       u64 addr;
 
-       if (limit > get_max_mapped())
-               limit = get_max_mapped();
+       if (limit > memblock.current_limit)
+               limit = memblock.current_limit;
 
-       /* need to go over early_node_map to find out good range for node */
-       for_each_active_range_index_in_nid(i, nid) {
-               u64 addr;
-               u64 ei_start, ei_last;
+       addr = find_memory_core_early(nid, size, align, goal, limit);
 
-               ei_last = early_node_map[i].end_pfn;
-               ei_last <<= PAGE_SHIFT;
-               ei_start = early_node_map[i].start_pfn;
-               ei_start <<= PAGE_SHIFT;
-               addr = find_early_area(ei_start, ei_last,
-                                        goal, limit, size, align);
-
-               if (addr == -1ULL)
-                       continue;
-
-#if 0
-               printk(KERN_DEBUG "alloc (nid=%d %llx - %llx) (%llx - %llx) %llx %llx => %llx\n",
-                               nid,
-                               ei_start, ei_last, goal, limit, size,
-                               align, addr);
-#endif
-
-               ptr = phys_to_virt(addr);
-               memset(ptr, 0, size);
-               reserve_early_without_check(addr, addr + size, "BOOTMEM");
-               /*
-                * The min_count is set to 0 so that bootmem allocated blocks
-                * are never reported as leaks.
-                */
-               kmemleak_alloc(ptr, size, 0, 0);
-               return ptr;
-       }
+       if (addr == MEMBLOCK_ERROR)
+               return NULL;
 
-       return NULL;
+       ptr = phys_to_virt(addr);
+       memset(ptr, 0, size);
+       memblock_x86_reserve_range(addr, addr + size, "BOOTMEM");
+       /*
+        * The min_count is set to 0 so that bootmem allocated blocks
+        * are never reported as leaks.
+        */
+       kmemleak_alloc(ptr, size, 0, 0);
+       return ptr;
 }
 #endif
 
@@ -5169,9 +5198,9 @@ void *__init alloc_large_system_hash(const char *tablename,
        if (!table)
                panic("Failed to allocate %s hash table\n", tablename);
 
-       printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n",
+       printk(KERN_INFO "%s hash table entries: %ld (order: %d, %lu bytes)\n",
               tablename,
-              (1U << log2qty),
+              (1UL << log2qty),
               ilog2(size) - PAGE_SHIFT,
               size);
 
index e61dc2cc5873d7d89efc45609a4f4f2a8ae75732..c76ef3891e0da1c71ac3d1b2d4b1db0abdfe8b9f 100644 (file)
@@ -393,7 +393,9 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)
                goto out_unlock;
 
        old_size = chunk->map_alloc * sizeof(chunk->map[0]);
-       memcpy(new, chunk->map, old_size);
+       old = chunk->map;
+
+       memcpy(new, old, old_size);
 
        chunk->map_alloc = new_alloc;
        chunk->map = new;
@@ -1162,7 +1164,7 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info(
                }
 
                /*
-                * Don't accept if wastage is over 25%.  The
+                * Don't accept if wastage is over 1/3.  The
                 * greater-than comparison ensures upa==1 always
                 * passes the following check.
                 */
@@ -1399,9 +1401,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
 
                        if (pcpu_first_unit_cpu == NR_CPUS)
                                pcpu_first_unit_cpu = cpu;
+                       pcpu_last_unit_cpu = cpu;
                }
        }
-       pcpu_last_unit_cpu = cpu;
        pcpu_nr_units = unit;
 
        for_each_possible_cpu(cpu)
index c4351c7f57d21db63487d0c06728a64d0c0f1318..db884fae5721749e57990d9f9ac33398efb1ca37 100644 (file)
@@ -14,13 +14,13 @@ void __percpu *__alloc_percpu(size_t size, size_t align)
         * percpu sections on SMP for which this path isn't used.
         */
        WARN_ON_ONCE(align > SMP_CACHE_BYTES);
-       return kzalloc(size, GFP_KERNEL);
+       return (void __percpu __force *)kzalloc(size, GFP_KERNEL);
 }
 EXPORT_SYMBOL_GPL(__alloc_percpu);
 
 void free_percpu(void __percpu *p)
 {
-       kfree(p);
+       kfree(this_cpu_ptr(p));
 }
 EXPORT_SYMBOL_GPL(free_percpu);
 
index 87b9e8ad450962afa1159b763f0aa0a977ab9a88..92e6757f196ed4e3b3598c1f8b7214616a4cbe39 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -316,7 +316,7 @@ void __init anon_vma_init(void)
  */
 struct anon_vma *page_lock_anon_vma(struct page *page)
 {
-       struct anon_vma *anon_vma;
+       struct anon_vma *anon_vma, *root_anon_vma;
        unsigned long anon_mapping;
 
        rcu_read_lock();
@@ -327,8 +327,21 @@ struct anon_vma *page_lock_anon_vma(struct page *page)
                goto out;
 
        anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
-       anon_vma_lock(anon_vma);
-       return anon_vma;
+       root_anon_vma = ACCESS_ONCE(anon_vma->root);
+       spin_lock(&root_anon_vma->lock);
+
+       /*
+        * If this page is still mapped, then its anon_vma cannot have been
+        * freed.  But if it has been unmapped, we have no security against
+        * the anon_vma structure being freed and reused (for another anon_vma:
+        * SLAB_DESTROY_BY_RCU guarantees that - so the spin_lock above cannot
+        * corrupt): with anon_vma_prepare() or anon_vma_fork() redirecting
+        * anon_vma->root before page_unlock_anon_vma() is called to unlock.
+        */
+       if (page_mapped(page))
+               return anon_vma;
+
+       spin_unlock(&root_anon_vma->lock);
 out:
        rcu_read_unlock();
        return NULL;
@@ -368,7 +381,13 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
        if (PageAnon(page)) {
-               if (vma->anon_vma->root != page_anon_vma(page)->root)
+               struct anon_vma *page__anon_vma = page_anon_vma(page);
+               /*
+                * Note: swapoff's unuse_vma() is more efficient with this
+                * check, and needs it to match anon_vma when KSM is active.
+                */
+               if (!vma->anon_vma || !page__anon_vma ||
+                   vma->anon_vma->root != page__anon_vma->root)
                        return -EFAULT;
        } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
                if (!vma->vm_file ||
@@ -1551,13 +1570,14 @@ static void __hugepage_set_anon_rmap(struct page *page,
        struct vm_area_struct *vma, unsigned long address, int exclusive)
 {
        struct anon_vma *anon_vma = vma->anon_vma;
+
        BUG_ON(!anon_vma);
-       if (!exclusive) {
-               struct anon_vma_chain *avc;
-               avc = list_entry(vma->anon_vma_chain.prev,
-                                struct anon_vma_chain, same_vma);
-               anon_vma = avc->anon_vma;
-       }
+
+       if (PageAnon(page))
+               return;
+       if (!exclusive)
+               anon_vma = anon_vma->root;
+
        anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
        page->mapping = (struct address_space *) anon_vma;
        page->index = linear_page_index(vma, address);
@@ -1568,6 +1588,8 @@ void hugepage_add_anon_rmap(struct page *page,
 {
        struct anon_vma *anon_vma = vma->anon_vma;
        int first;
+
+       BUG_ON(!PageLocked(page));
        BUG_ON(!anon_vma);
        BUG_ON(address < vma->vm_start || address >= vma->vm_end);
        first = atomic_inc_and_test(&page->_mapcount);
index aa33fd67fa412bee2cef32e18c163d626e88bd00..29d6cbffb28306323847f0d8daa6b091048dd397 100644 (file)
@@ -220,18 +220,7 @@ void __init sparse_mem_maps_populate_node(struct page **map_map,
 
        if (vmemmap_buf_start) {
                /* need to free left buf */
-#ifdef CONFIG_NO_BOOTMEM
-               free_early(__pa(vmemmap_buf_start), __pa(vmemmap_buf_end));
-               if (vmemmap_buf_start < vmemmap_buf) {
-                       char name[15];
-
-                       snprintf(name, sizeof(name), "MEMMAP %d", nodeid);
-                       reserve_early_without_check(__pa(vmemmap_buf_start),
-                                                   __pa(vmemmap_buf), name);
-               }
-#else
                free_bootmem(__pa(vmemmap_buf), vmemmap_buf_end - vmemmap_buf);
-#endif
                vmemmap_buf = NULL;
                vmemmap_buf_end = NULL;
        }
index 1f3f9c59a73ab5be4ff4bb37f428364df7544706..7c703ff2f36f0b760b79eb36149084f07621a0a1 100644 (file)
@@ -47,8 +47,6 @@ long nr_swap_pages;
 long total_swap_pages;
 static int least_priority;
 
-static bool swap_for_hibernation;
-
 static const char Bad_file[] = "Bad swap file entry ";
 static const char Unused_file[] = "Unused swap file entry ";
 static const char Bad_offset[] = "Bad swap offset entry ";
@@ -141,8 +139,7 @@ static int discard_swap(struct swap_info_struct *si)
        nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
        if (nr_blocks) {
                err = blkdev_issue_discard(si->bdev, start_block,
-                               nr_blocks, GFP_KERNEL,
-                               BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+                               nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
                if (err)
                        return err;
                cond_resched();
@@ -153,8 +150,7 @@ static int discard_swap(struct swap_info_struct *si)
                nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
 
                err = blkdev_issue_discard(si->bdev, start_block,
-                               nr_blocks, GFP_KERNEL,
-                               BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+                               nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
                if (err)
                        break;
 
@@ -193,8 +189,7 @@ static void discard_swap_cluster(struct swap_info_struct *si,
                        start_block <<= PAGE_SHIFT - 9;
                        nr_blocks <<= PAGE_SHIFT - 9;
                        if (blkdev_issue_discard(si->bdev, start_block,
-                                   nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT |
-                                                       BLKDEV_IFL_BARRIER))
+                                   nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT))
                                break;
                }
 
@@ -320,10 +315,8 @@ checks:
        if (offset > si->highest_bit)
                scan_base = offset = si->lowest_bit;
 
-       /* reuse swap entry of cache-only swap if not hibernation. */
-       if (vm_swap_full()
-               && usage == SWAP_HAS_CACHE
-               && si->swap_map[offset] == SWAP_HAS_CACHE) {
+       /* reuse swap entry of cache-only swap if not busy. */
+       if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
                int swap_was_freed;
                spin_unlock(&swap_lock);
                swap_was_freed = __try_to_reclaim_swap(si, offset);
@@ -453,8 +446,6 @@ swp_entry_t get_swap_page(void)
        spin_lock(&swap_lock);
        if (nr_swap_pages <= 0)
                goto noswap;
-       if (swap_for_hibernation)
-               goto noswap;
        nr_swap_pages--;
 
        for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) {
@@ -487,6 +478,28 @@ noswap:
        return (swp_entry_t) {0};
 }
 
+/* The only caller of this function is now susupend routine */
+swp_entry_t get_swap_page_of_type(int type)
+{
+       struct swap_info_struct *si;
+       pgoff_t offset;
+
+       spin_lock(&swap_lock);
+       si = swap_info[type];
+       if (si && (si->flags & SWP_WRITEOK)) {
+               nr_swap_pages--;
+               /* This is called for allocating swap entry, not cache */
+               offset = scan_swap_map(si, 1);
+               if (offset) {
+                       spin_unlock(&swap_lock);
+                       return swp_entry(type, offset);
+               }
+               nr_swap_pages++;
+       }
+       spin_unlock(&swap_lock);
+       return (swp_entry_t) {0};
+}
+
 static struct swap_info_struct *swap_info_get(swp_entry_t entry)
 {
        struct swap_info_struct *p;
@@ -670,6 +683,24 @@ int try_to_free_swap(struct page *page)
        if (page_swapcount(page))
                return 0;
 
+       /*
+        * Once hibernation has begun to create its image of memory,
+        * there's a danger that one of the calls to try_to_free_swap()
+        * - most probably a call from __try_to_reclaim_swap() while
+        * hibernation is allocating its own swap pages for the image,
+        * but conceivably even a call from memory reclaim - will free
+        * the swap from a page which has already been recorded in the
+        * image as a clean swapcache page, and then reuse its swap for
+        * another page of the image.  On waking from hibernation, the
+        * original page might be freed under memory pressure, then
+        * later read back in from swap, now with the wrong data.
+        *
+        * Hibernation clears bits from gfp_allowed_mask to prevent
+        * memory reclaim from writing to disk, so check that here.
+        */
+       if (!(gfp_allowed_mask & __GFP_IO))
+               return 0;
+
        delete_from_swap_cache(page);
        SetPageDirty(page);
        return 1;
@@ -746,74 +777,6 @@ int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep)
 #endif
 
 #ifdef CONFIG_HIBERNATION
-
-static pgoff_t hibernation_offset[MAX_SWAPFILES];
-/*
- * Once hibernation starts to use swap, we freeze swap_map[]. Otherwise,
- * saved swap_map[] image to the disk will be an incomplete because it's
- * changing without synchronization with hibernation snap shot.
- * At resume, we just make swap_for_hibernation=false. We can forget
- * used maps easily.
- */
-void hibernation_freeze_swap(void)
-{
-       int i;
-
-       spin_lock(&swap_lock);
-
-       printk(KERN_INFO "PM: Freeze Swap\n");
-       swap_for_hibernation = true;
-       for (i = 0; i < MAX_SWAPFILES; i++)
-               hibernation_offset[i] = 1;
-       spin_unlock(&swap_lock);
-}
-
-void hibernation_thaw_swap(void)
-{
-       spin_lock(&swap_lock);
-       if (swap_for_hibernation) {
-               printk(KERN_INFO "PM: Thaw Swap\n");
-               swap_for_hibernation = false;
-       }
-       spin_unlock(&swap_lock);
-}
-
-/*
- * Because updateing swap_map[] can make not-saved-status-change,
- * we use our own easy allocator.
- * Please see kernel/power/swap.c, Used swaps are recorded into
- * RB-tree.
- */
-swp_entry_t get_swap_for_hibernation(int type)
-{
-       pgoff_t off;
-       swp_entry_t val = {0};
-       struct swap_info_struct *si;
-
-       spin_lock(&swap_lock);
-
-       si = swap_info[type];
-       if (!si || !(si->flags & SWP_WRITEOK))
-               goto done;
-
-       for (off = hibernation_offset[type]; off < si->max; ++off) {
-               if (!si->swap_map[off])
-                       break;
-       }
-       if (off < si->max) {
-               val = swp_entry(type, off);
-               hibernation_offset[type] = off + 1;
-       }
-done:
-       spin_unlock(&swap_lock);
-       return val;
-}
-
-void swap_free_for_hibernation(swp_entry_t ent)
-{
-       /* Nothing to do */
-}
-
 /*
  * Find the swap type that corresponds to given device (if any).
  *
@@ -2084,7 +2047,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                        p->flags |= SWP_SOLIDSTATE;
                        p->cluster_next = 1 + (random32() % p->highest_bit);
                }
-               if (discard_swap(p) == 0)
+               if (discard_swap(p) == 0 && (swap_flags & SWAP_FLAG_DISCARD))
                        p->flags |= SWP_DISCARDABLE;
        }
 
index 6b8889da69a60612301c2bd26244ae0f3e1e1966..d8087f0db5073fc9ed3f879c7bc582c4fc462d0f 100644 (file)
@@ -516,6 +516,15 @@ static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
 /* for per-CPU blocks */
 static void purge_fragmented_blocks_allcpus(void);
 
+/*
+ * called before a call to iounmap() if the caller wants vm_area_struct's
+ * immediately freed.
+ */
+void set_iounmap_nonlazy(void)
+{
+       atomic_set(&vmap_lazy_nr, lazy_max_pages()+1);
+}
+
 /*
  * Purges all lazily-freed vmap areas.
  *
index c391c320dbafcda04260923f36336891283b614f..c5dfabf25f115a34df8f9111843af28a8d58d906 100644 (file)
@@ -1804,12 +1804,11 @@ static void shrink_zone(int priority, struct zone *zone,
  * If a zone is deemed to be full of pinned pages then just give it a light
  * scan then give up on it.
  */
-static bool shrink_zones(int priority, struct zonelist *zonelist,
+static void shrink_zones(int priority, struct zonelist *zonelist,
                                        struct scan_control *sc)
 {
        struct zoneref *z;
        struct zone *zone;
-       bool all_unreclaimable = true;
 
        for_each_zone_zonelist_nodemask(zone, z, zonelist,
                                        gfp_zone(sc->gfp_mask), sc->nodemask) {
@@ -1827,8 +1826,38 @@ static bool shrink_zones(int priority, struct zonelist *zonelist,
                }
 
                shrink_zone(priority, zone, sc);
-               all_unreclaimable = false;
        }
+}
+
+static bool zone_reclaimable(struct zone *zone)
+{
+       return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
+}
+
+/*
+ * As hibernation is going on, kswapd is freezed so that it can't mark
+ * the zone into all_unreclaimable. It can't handle OOM during hibernation.
+ * So let's check zone's unreclaimable in direct reclaim as well as kswapd.
+ */
+static bool all_unreclaimable(struct zonelist *zonelist,
+               struct scan_control *sc)
+{
+       struct zoneref *z;
+       struct zone *zone;
+       bool all_unreclaimable = true;
+
+       for_each_zone_zonelist_nodemask(zone, z, zonelist,
+                       gfp_zone(sc->gfp_mask), sc->nodemask) {
+               if (!populated_zone(zone))
+                       continue;
+               if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
+                       continue;
+               if (zone_reclaimable(zone)) {
+                       all_unreclaimable = false;
+                       break;
+               }
+       }
+
        return all_unreclaimable;
 }
 
@@ -1852,7 +1881,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                                        struct scan_control *sc)
 {
        int priority;
-       bool all_unreclaimable;
        unsigned long total_scanned = 0;
        struct reclaim_state *reclaim_state = current->reclaim_state;
        struct zoneref *z;
@@ -1869,7 +1897,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                sc->nr_scanned = 0;
                if (!priority)
                        disable_swap_token();
-               all_unreclaimable = shrink_zones(priority, zonelist, sc);
+               shrink_zones(priority, zonelist, sc);
                /*
                 * Don't shrink slabs when reclaiming memory from
                 * over limit cgroups
@@ -1931,7 +1959,7 @@ out:
                return sc->nr_reclaimed;
 
        /* top priority shrink_zones still had more to do? don't OOM, then */
-       if (scanning_global_lru(sc) && !all_unreclaimable)
+       if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc))
                return 1;
 
        return 0;
@@ -2197,8 +2225,7 @@ loop_again:
                        total_scanned += sc.nr_scanned;
                        if (zone->all_unreclaimable)
                                continue;
-                       if (nr_slab == 0 &&
-                           zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6))
+                       if (nr_slab == 0 && !zone_reclaimable(zone))
                                zone->all_unreclaimable = 1;
                        /*
                         * If we've done a decent amount of scanning and
index f389168f9a837b9c6be4e1f9bb3d0892396315de..355a9e669aaa800d62fa31d2b83110bf76cce9d7 100644 (file)
@@ -138,11 +138,24 @@ static void refresh_zone_stat_thresholds(void)
        int threshold;
 
        for_each_populated_zone(zone) {
+               unsigned long max_drift, tolerate_drift;
+
                threshold = calculate_threshold(zone);
 
                for_each_online_cpu(cpu)
                        per_cpu_ptr(zone->pageset, cpu)->stat_threshold
                                                        = threshold;
+
+               /*
+                * Only set percpu_drift_mark if there is a danger that
+                * NR_FREE_PAGES reports the low watermark is ok when in fact
+                * the min watermark could be breached by an allocation
+                */
+               tolerate_drift = low_wmark_pages(zone) - min_wmark_pages(zone);
+               max_drift = num_online_cpus() * threshold;
+               if (max_drift > tolerate_drift)
+                       zone->percpu_drift_mark = high_wmark_pages(zone) +
+                                       max_drift;
        }
 }
 
@@ -813,7 +826,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
                   "\n        scanned  %lu"
                   "\n        spanned  %lu"
                   "\n        present  %lu",
-                  zone_page_state(zone, NR_FREE_PAGES),
+                  zone_nr_free_pages(zone),
                   min_wmark_pages(zone),
                   low_wmark_pages(zone),
                   high_wmark_pages(zone),
@@ -998,6 +1011,7 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
        switch (action) {
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
+               refresh_zone_stat_thresholds();
                start_cpu_timer(cpu);
                node_set_state(cpu_to_node(cpu), N_CPU);
                break;
index 01ddb0472f86c511f49ff8a602a726dd60550ff0..0eb96f7e44befb0155e364749f38eb37af0c2354 100644 (file)
@@ -24,8 +24,11 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
 
        if (vlan_dev)
                skb->dev = vlan_dev;
-       else if (vlan_id)
-               goto drop;
+       else if (vlan_id) {
+               if (!(skb->dev->flags & IFF_PROMISC))
+                       goto drop;
+               skb->pkt_type = PACKET_OTHERHOST;
+       }
 
        return (polling ? netif_receive_skb(skb) : netif_rx(skb));
 
@@ -102,8 +105,11 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
 
        if (vlan_dev)
                skb->dev = vlan_dev;
-       else if (vlan_id)
-               goto drop;
+       else if (vlan_id) {
+               if (!(skb->dev->flags & IFF_PROMISC))
+                       goto drop;
+               skb->pkt_type = PACKET_OTHERHOST;
+       }
 
        for (p = napi->gro_list; p; p = p->next) {
                NAPI_GRO_CB(p)->same_flow =
index 3d59c9bf8febf5064150ff50d22db9d569453131..3bccdd12a2642a06e1c5078b5c4065419a57428a 100644 (file)
@@ -510,7 +510,8 @@ static int vlan_dev_open(struct net_device *dev)
        if (vlan->flags & VLAN_FLAG_GVRP)
                vlan_gvrp_request_join(dev);
 
-       netif_carrier_on(dev);
+       if (netif_carrier_ok(real_dev))
+               netif_carrier_on(dev);
        return 0;
 
 clear_allmulti:
index dc6f2f26d0230b1462ea1ea583c6fda5dc5b49c5..9eb72505308fc697d2857737f8dd3f4ec04d5bd3 100644 (file)
@@ -331,8 +331,10 @@ static void p9_tag_cleanup(struct p9_client *c)
                }
        }
 
-       if (c->tagpool)
+       if (c->tagpool) {
+               p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
                p9_idpool_destroy(c->tagpool);
+       }
 
        /* free requests associated with tags */
        for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
@@ -944,6 +946,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
        int16_t nwqids, count;
 
        err = 0;
+       wqids = NULL;
        clnt = oldfid->clnt;
        if (clone) {
                fid = p9_fid_create(clnt);
@@ -994,9 +997,11 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
        else
                fid->qid = oldfid->qid;
 
+       kfree(wqids);
        return fid;
 
 clunk_fid:
+       kfree(wqids);
        p9_client_clunk(fid);
        fid = NULL;
 
index 0ea20c30466c7b5758e419fd51c3cba70c9797d7..17c5ba7551a55e79c2c38e22a8fe2fdaa8e00979 100644 (file)
@@ -426,8 +426,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
 
        /* Allocate an fcall for the reply */
        rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL);
-       if (!rpl_context)
+       if (!rpl_context) {
+               err = -ENOMEM;
                goto err_close;
+       }
 
        /*
         * If the request has a buffer, steal it, otherwise
@@ -445,8 +447,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
        }
        rpl_context->rc = req->rc;
        if (!rpl_context->rc) {
-               kfree(rpl_context);
-               goto err_close;
+               err = -ENOMEM;
+               goto err_free2;
        }
 
        /*
@@ -458,11 +460,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
         */
        if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) {
                err = post_recv(client, rpl_context);
-               if (err) {
-                       kfree(rpl_context->rc);
-                       kfree(rpl_context);
-                       goto err_close;
-               }
+               if (err)
+                       goto err_free1;
        } else
                atomic_dec(&rdma->rq_count);
 
@@ -471,8 +470,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
 
        /* Post the request */
        c = kmalloc(sizeof *c, GFP_KERNEL);
-       if (!c)
-               goto err_close;
+       if (!c) {
+               err = -ENOMEM;
+               goto err_free1;
+       }
        c->req = req;
 
        c->busa = ib_dma_map_single(rdma->cm_id->device,
@@ -499,9 +500,15 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
        return ib_post_send(rdma->qp, &wr, &bad_wr);
 
  error:
+       kfree(c);
+       kfree(rpl_context->rc);
+       kfree(rpl_context);
        P9_DPRINTK(P9_DEBUG_ERROR, "EIO\n");
        return -EIO;
-
+ err_free1:
+       kfree(rpl_context->rc);
+ err_free2:
+       kfree(rpl_context);
  err_close:
        spin_lock_irqsave(&rdma->req_lock, flags);
        if (rdma->state < P9_RDMA_CLOSING) {
index dcfbe99ff81c8c0ac56031e1cbbd56bb7ed2fcd4..b88515936e4b3310741e6beefac62376bfe9d832 100644 (file)
@@ -329,7 +329,8 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
 
        mutex_lock(&virtio_9p_lock);
        list_for_each_entry(chan, &virtio_chan_list, chan_list) {
-               if (!strncmp(devname, chan->tag, chan->tag_len)) {
+               if (!strncmp(devname, chan->tag, chan->tag_len) &&
+                   strlen(devname) == chan->tag_len) {
                        if (!chan->inuse) {
                                chan->inuse = true;
                                found = 1;
index e330594d3709e6d382b2e5168cea989127793aa1..55fd82e9ffd91e9fd48878147f3068923373ce16 100644 (file)
@@ -217,7 +217,7 @@ source "net/dns_resolver/Kconfig"
 
 config RPS
        boolean
-       depends on SMP && SYSFS
+       depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
        default y
 
 menu "Network testing"
@@ -293,6 +293,7 @@ source "net/wimax/Kconfig"
 source "net/rfkill/Kconfig"
 source "net/9p/Kconfig"
 source "net/caif/Kconfig"
+source "net/ceph/Kconfig"
 
 
 endif   # if NET
index ea60fbce9b1ba3e623ee9f1ec9ce622169a3596d..6b7bfd7f1416d9950e90cb3ddd065d998c0e78ee 100644 (file)
@@ -68,3 +68,4 @@ obj-$(CONFIG_SYSCTL)          += sysctl_net.o
 endif
 obj-$(CONFIG_WIMAX)            += wimax/
 obj-$(CONFIG_DNS_RESOLVER)     += dns_resolver/
+obj-$(CONFIG_CEPH_LIB)         += ceph/
index 651babdfab3845ebd11eb6cc89fe85eae1d3f8ca..ad2b232a2055fbc241828832078087c62e4c4315 100644 (file)
@@ -399,12 +399,6 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                        unregister_netdev(net_dev);
                        free_netdev(net_dev);
                }
-               read_lock_irq(&devs_lock);
-               if (list_empty(&br2684_devs)) {
-                       /* last br2684 device */
-                       unregister_atmdevice_notifier(&atm_dev_notifier);
-               }
-               read_unlock_irq(&devs_lock);
                return;
        }
 
@@ -675,7 +669,6 @@ static int br2684_create(void __user *arg)
 
        if (list_empty(&br2684_devs)) {
                /* 1st br2684 device */
-               register_atmdevice_notifier(&atm_dev_notifier);
                brdev->number = 1;
        } else
                brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
@@ -815,6 +808,7 @@ static int __init br2684_init(void)
                return -ENOMEM;
 #endif
        register_atm_ioctl(&br2684_ioctl_ops);
+       register_atmdevice_notifier(&atm_dev_notifier);
        return 0;
 }
 
@@ -830,9 +824,7 @@ static void __exit br2684_exit(void)
 #endif
 
 
-       /* if not already empty */
-       if (!list_empty(&br2684_devs))
-               unregister_atmdevice_notifier(&atm_dev_notifier);
+       unregister_atmdevice_notifier(&atm_dev_notifier);
 
        while (!list_empty(&br2684_devs)) {
                net_dev = list_entry_brdev(br2684_devs.next);
index 622b471e14e03dbc3752697851022a59aebffbe0..74bcc662c3dd8c5e7ec33a393560cc9bbf313b57 100644 (file)
@@ -778,7 +778,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
        eg->packets_rcvd++;
        mpc->eg_ops->put(eg);
 
-       memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
+       memset(ATM_SKB(new_skb), 0, sizeof(struct atm_skb_data));
        netif_rx(new_skb);
 }
 
index 6262aeae398e8a242eae84f70287b7f07f5768c3..f85da0779e5ee162015ae88aa00e48e2114aa5e3 100644 (file)
@@ -38,6 +38,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
 static const struct file_operations proc_atm_dev_ops = {
        .owner =        THIS_MODULE,
        .read =         proc_dev_atm_read,
+       .llseek =       noop_llseek,
 };
 
 static void add_stats(struct seq_file *seq, const char *aal,
index 2ce79df00680eee3d9d290fd1156ac1d2ab74557..c7d81436213d13e24e67edf2630930e5c4ed08c0 100644 (file)
@@ -112,8 +112,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
                        if (sk) {
                                sock_hold(sk);
                                ax25_destroy_socket(ax25);
-                               sock_put(sk);
                                bh_unlock_sock(sk);
+                               sock_put(sk);
                        } else
                                ax25_destroy_socket(ax25);
                        return;
index fadf26b4ed7c432eba09800b4532683fc44cc02d..0b54b7dd84010a52147a54155c4f8db2b61752a7 100644 (file)
@@ -1441,33 +1441,23 @@ static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
 
 static void l2cap_streaming_send(struct sock *sk)
 {
-       struct sk_buff *skb, *tx_skb;
+       struct sk_buff *skb;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        u16 control, fcs;
 
-       while ((skb = sk->sk_send_head)) {
-               tx_skb = skb_clone(skb, GFP_ATOMIC);
-
-               control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+       while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
+               control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
                control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
-               put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+               put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
 
                if (pi->fcs == L2CAP_FCS_CRC16) {
-                       fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
-                       put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
+                       fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
+                       put_unaligned_le16(fcs, skb->data + skb->len - 2);
                }
 
-               l2cap_do_send(sk, tx_skb);
+               l2cap_do_send(sk, skb);
 
                pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
-
-               if (skb_queue_is_last(TX_QUEUE(sk), skb))
-                       sk->sk_send_head = NULL;
-               else
-                       sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
-
-               skb = skb_dequeue(TX_QUEUE(sk));
-               kfree_skb(skb);
        }
 }
 
@@ -1960,6 +1950,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               if (sk->sk_state == BT_CONNECTED) {
+                       err = -EINVAL;
+                       break;
+               }
+
                opts.imtu     = l2cap_pi(sk)->imtu;
                opts.omtu     = l2cap_pi(sk)->omtu;
                opts.flush_to = l2cap_pi(sk)->flush_to;
@@ -2771,10 +2766,10 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
                case L2CAP_CONF_MTU:
                        if (val < L2CAP_DEFAULT_MIN_MTU) {
                                *result = L2CAP_CONF_UNACCEPT;
-                               pi->omtu = L2CAP_DEFAULT_MIN_MTU;
+                               pi->imtu = L2CAP_DEFAULT_MIN_MTU;
                        } else
-                               pi->omtu = val;
-                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+                               pi->imtu = val;
+                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
                        break;
 
                case L2CAP_CONF_FLUSH_TO:
@@ -3071,6 +3066,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
        return 0;
 }
 
+static inline void set_default_fcs(struct l2cap_pinfo *pi)
+{
+       /* FCS is enabled only in ERTM or streaming mode, if one or both
+        * sides request it.
+        */
+       if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
+               pi->fcs = L2CAP_FCS_NONE;
+       else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
+               pi->fcs = L2CAP_FCS_CRC16;
+}
+
 static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
 {
        struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
@@ -3088,14 +3094,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        if (!sk)
                return -ENOENT;
 
-       if (sk->sk_state != BT_CONFIG) {
-               struct l2cap_cmd_rej rej;
-
-               rej.reason = cpu_to_le16(0x0002);
-               l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
-                               sizeof(rej), &rej);
+       if (sk->sk_state == BT_DISCONN)
                goto unlock;
-       }
 
        /* Reject if config buffer is too small. */
        len = cmd_len - sizeof(*req);
@@ -3135,9 +3135,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                goto unlock;
 
        if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
-               if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-                   l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-                       l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+               set_default_fcs(l2cap_pi(sk));
 
                sk->sk_state = BT_CONNECTED;
 
@@ -3225,9 +3223,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
 
        if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
-               if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-                   l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-                       l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+               set_default_fcs(l2cap_pi(sk));
 
                sk->sk_state = BT_CONNECTED;
                l2cap_pi(sk)->next_tx_seq = 0;
index 44a623275951e4b481abf1942fb2587867891dca..194b3a04cfd38a3b4a13817d5aecace4f355ea49 100644 (file)
@@ -82,11 +82,14 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb)
 static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
 {
        struct sock *sk = d->owner, *parent;
+       unsigned long flags;
+
        if (!sk)
                return;
 
        BT_DBG("dlc %p state %ld err %d", d, d->state, err);
 
+       local_irq_save(flags);
        bh_lock_sock(sk);
 
        if (err)
@@ -108,6 +111,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
        }
 
        bh_unlock_sock(sk);
+       local_irq_restore(flags);
 
        if (parent && sock_flag(sk, SOCK_ZAPPED)) {
                /* We have to drop DLC lock here, otherwise
index 2c911c0759c27bb6e4867b3bce9af0af3946d288..137f23259a93947ce581a9d14c8f6048f3ca2c19 100644 (file)
@@ -162,8 +162,8 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
                if (tmp) {
                        memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
                        atomic_set(&tmp->use, 1);
-                       nf_bridge_put(nf_bridge);
                }
+               nf_bridge_put(nf_bridge);
                nf_bridge = tmp;
        }
        return nf_bridge;
@@ -761,9 +761,11 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
 {
        if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
            skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
-           !skb_is_gso(skb))
+           !skb_is_gso(skb)) {
+               /* BUG: Should really parse the IP options here. */
+               memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
                return ip_fragment(skb, br_dev_queue_push_xmit);
-       else
+       else
                return br_dev_queue_push_xmit(skb);
 }
 #else
index 8ce9047861166740a17a2448cb1d4f668fba1d21..4bf28f25f368b399a6ef220e06c08c0f5d2621f5 100644 (file)
@@ -827,6 +827,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
        long timeo;
        int err;
        int ifindex, headroom, tailroom;
+       unsigned int mtu;
        struct net_device *dev;
 
        lock_sock(sk);
@@ -896,15 +897,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
                cf_sk->sk.sk_state = CAIF_DISCONNECTED;
                goto out;
        }
-       dev = dev_get_by_index(sock_net(sk), ifindex);
+
+       err = -ENODEV;
+       rcu_read_lock();
+       dev = dev_get_by_index_rcu(sock_net(sk), ifindex);
+       if (!dev) {
+               rcu_read_unlock();
+               goto out;
+       }
        cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom);
+       mtu = dev->mtu;
+       rcu_read_unlock();
+
        cf_sk->tailroom = tailroom;
-       cf_sk->maxframe = dev->mtu - (headroom + tailroom);
-       dev_put(dev);
+       cf_sk->maxframe = mtu - (headroom + tailroom);
        if (cf_sk->maxframe < 1) {
-               pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n",
-                       __func__, dev->mtu);
-               err = -ENODEV;
+               pr_warning("CAIF: %s(): CAIF Interface MTU too small (%u)\n",
+                          __func__, mtu);
                goto out;
        }
 
index eb1602022ac0643af4e4ad655c3de4ae42a200f4..9a699242d104be7fbef70ed4560d6ca3a63ebda3 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/unaligned/le_byteshift.h>
+#include <asm/unaligned.h>
 #include <net/caif/caif_layer.h>
 #include <net/caif/cfsrvl.h>
 #include <net/caif/cfpkt.h>
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig
new file mode 100644 (file)
index 0000000..ad42404
--- /dev/null
@@ -0,0 +1,28 @@
+config CEPH_LIB
+        tristate "Ceph core library (EXPERIMENTAL)"
+       depends on INET && EXPERIMENTAL
+       select LIBCRC32C
+       select CRYPTO_AES
+       select CRYPTO
+       default n
+       help
+         Choose Y or M here to include cephlib, which provides the
+         common functionality to both the Ceph filesystem and
+         to the rados block device (rbd).
+
+         More information at http://ceph.newdream.net/.
+
+         If unsure, say N.
+
+config CEPH_LIB_PRETTYDEBUG
+       bool "Include file:line in ceph debug output"
+       depends on CEPH_LIB
+       default n
+       help
+         If you say Y here, debug output will include a filename and
+         line to aid debugging.  This increases kernel size and slows
+         execution slightly when debug call sites are enabled (e.g.,
+         via CONFIG_DYNAMIC_DEBUG).
+
+         If unsure, say N.
+
diff --git a/net/ceph/Makefile b/net/ceph/Makefile
new file mode 100644 (file)
index 0000000..aab1cab
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Makefile for CEPH filesystem.
+#
+
+ifneq ($(KERNELRELEASE),)
+
+obj-$(CONFIG_CEPH_LIB) += libceph.o
+
+libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
+       mon_client.o \
+       osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
+       debugfs.o \
+       auth.o auth_none.o \
+       crypto.o armor.o \
+       auth_x.o \
+       ceph_fs.o ceph_strings.o ceph_hash.o \
+       pagevec.o
+
+else
+#Otherwise we were called directly from the command
+# line; invoke the kernel build system.
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default: all
+
+all:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
+
+modules_install:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
+
+clean:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+
+endif
similarity index 100%
rename from fs/ceph/armor.c
rename to net/ceph/armor.c
similarity index 97%
rename from fs/ceph/auth.c
rename to net/ceph/auth.c
index 6d2e30600627e71d25c2f93d5862952a078472b8..549c1f43e1d53b134c045954e103260fee9033b7 100644 (file)
@@ -1,16 +1,16 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 
-#include "types.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/messenger.h>
 #include "auth_none.h"
 #include "auth_x.h"
-#include "decode.h"
-#include "super.h"
 
-#include "messenger.h"
 
 /*
  * get protocol handler
similarity index 96%
rename from fs/ceph/auth_none.c
rename to net/ceph/auth_none.c
index ad1dc21286c7f3ca9c84d75d7a2630bc0069dae4..214c2bb43d6252056a7a77dcd2d8eb5877c719d1 100644 (file)
@@ -1,14 +1,15 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+
 #include "auth_none.h"
-#include "auth.h"
-#include "decode.h"
 
 static void reset(struct ceph_auth_client *ac)
 {
similarity index 94%
rename from fs/ceph/auth_none.h
rename to net/ceph/auth_none.h
index 8164df1a08be5060aa065106bdbeb539f9caabec..ed7d088b1bc92e14372e2f24c8f5016750e07014 100644 (file)
@@ -2,8 +2,7 @@
 #define _FS_CEPH_AUTH_NONE_H
 
 #include <linux/slab.h>
-
-#include "auth.h"
+#include <linux/ceph/auth.h>
 
 /*
  * null security mode.
similarity index 98%
rename from fs/ceph/auth_x.c
rename to net/ceph/auth_x.c
index 582e0b2caf8a3ce6c2b943c0980c119be7950a63..7fd5dfcf6e188551f9a25638129239d79df9d874 100644 (file)
@@ -1,16 +1,17 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+
+#include "crypto.h"
 #include "auth_x.h"
 #include "auth_x_protocol.h"
-#include "crypto.h"
-#include "auth.h"
-#include "decode.h"
 
 #define TEMP_TICKET_BUF_LEN    256
 
@@ -376,7 +377,7 @@ static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed)
 
                th = get_ticket_handler(ac, service);
 
-               if (!th) {
+               if (IS_ERR(th)) {
                        *pneed |= service;
                        continue;
                }
@@ -399,6 +400,9 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
        struct ceph_x_ticket_handler *th =
                get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
 
+       if (IS_ERR(th))
+               return PTR_ERR(th);
+
        ceph_x_validate_tickets(ac, &need);
 
        dout("build_request want %x have %x need %x\n",
@@ -450,7 +454,6 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
                        return -ERANGE;
                head->op = cpu_to_le16(CEPHX_GET_PRINCIPAL_SESSION_KEY);
 
-               BUG_ON(!th);
                ret = ceph_x_build_authorizer(ac, th, &xi->auth_authorizer);
                if (ret)
                        return ret;
@@ -505,7 +508,8 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
 
        case CEPHX_GET_PRINCIPAL_SESSION_KEY:
                th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
-               BUG_ON(!th);
+               if (IS_ERR(th))
+                       return PTR_ERR(th);
                ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
                                               buf + sizeof(*head), end);
                break;
@@ -563,8 +567,8 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
        void *end = p + sizeof(au->reply_buf);
 
        th = get_ticket_handler(ac, au->service);
-       if (!th)
-               return -EIO;  /* hrm! */
+       if (IS_ERR(th))
+               return PTR_ERR(th);
        ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
        if (ret < 0)
                return ret;
@@ -626,7 +630,7 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
        struct ceph_x_ticket_handler *th;
 
        th = get_ticket_handler(ac, peer_type);
-       if (th && !IS_ERR(th))
+       if (!IS_ERR(th))
                remove_ticket_handler(ac, th);
 }
 
similarity index 96%
rename from fs/ceph/auth_x.h
rename to net/ceph/auth_x.h
index ff6f8180e6816a352ca5184d8db1b47e110b64f4..e02da7a5c5a1052b881f383e7fca318da0675421 100644 (file)
@@ -3,8 +3,9 @@
 
 #include <linux/rbtree.h>
 
+#include <linux/ceph/auth.h>
+
 #include "crypto.h"
-#include "auth.h"
 #include "auth_x_protocol.h"
 
 /*
similarity index 86%
rename from fs/ceph/buffer.c
rename to net/ceph/buffer.c
index cd39f17021de9ab6cde35ce444a727970f4f8fab..53d8abfa25d5ede4b487c88a5341b376c4921c26 100644 (file)
@@ -1,10 +1,11 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/slab.h>
 
-#include "buffer.h"
-#include "decode.h"
+#include <linux/ceph/buffer.h>
+#include <linux/ceph/decode.h>
 
 struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
 {
@@ -32,6 +33,7 @@ struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
        dout("buffer_new %p\n", b);
        return b;
 }
+EXPORT_SYMBOL(ceph_buffer_new);
 
 void ceph_buffer_release(struct kref *kref)
 {
@@ -46,6 +48,7 @@ void ceph_buffer_release(struct kref *kref)
        }
        kfree(b);
 }
+EXPORT_SYMBOL(ceph_buffer_release);
 
 int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end)
 {
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
new file mode 100644 (file)
index 0000000..f3e4a13
--- /dev/null
@@ -0,0 +1,529 @@
+
+#include <linux/ceph/ceph_debug.h>
+#include <linux/backing-dev.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/inet.h>
+#include <linux/in6.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/parser.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/statfs.h>
+#include <linux/string.h>
+
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+
+
+
+/*
+ * find filename portion of a path (/foo/bar/baz -> baz)
+ */
+const char *ceph_file_part(const char *s, int len)
+{
+       const char *e = s + len;
+
+       while (e != s && *(e-1) != '/')
+               e--;
+       return e;
+}
+EXPORT_SYMBOL(ceph_file_part);
+
+const char *ceph_msg_type_name(int type)
+{
+       switch (type) {
+       case CEPH_MSG_SHUTDOWN: return "shutdown";
+       case CEPH_MSG_PING: return "ping";
+       case CEPH_MSG_AUTH: return "auth";
+       case CEPH_MSG_AUTH_REPLY: return "auth_reply";
+       case CEPH_MSG_MON_MAP: return "mon_map";
+       case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
+       case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
+       case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
+       case CEPH_MSG_STATFS: return "statfs";
+       case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
+       case CEPH_MSG_MDS_MAP: return "mds_map";
+       case CEPH_MSG_CLIENT_SESSION: return "client_session";
+       case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
+       case CEPH_MSG_CLIENT_REQUEST: return "client_request";
+       case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
+       case CEPH_MSG_CLIENT_REPLY: return "client_reply";
+       case CEPH_MSG_CLIENT_CAPS: return "client_caps";
+       case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
+       case CEPH_MSG_CLIENT_SNAP: return "client_snap";
+       case CEPH_MSG_CLIENT_LEASE: return "client_lease";
+       case CEPH_MSG_OSD_MAP: return "osd_map";
+       case CEPH_MSG_OSD_OP: return "osd_op";
+       case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
+       default: return "unknown";
+       }
+}
+EXPORT_SYMBOL(ceph_msg_type_name);
+
+/*
+ * Initially learn our fsid, or verify an fsid matches.
+ */
+int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
+{
+       if (client->have_fsid) {
+               if (ceph_fsid_compare(&client->fsid, fsid)) {
+                       pr_err("bad fsid, had %pU got %pU",
+                              &client->fsid, fsid);
+                       return -1;
+               }
+       } else {
+               pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
+               memcpy(&client->fsid, fsid, sizeof(*fsid));
+               ceph_debugfs_client_init(client);
+               client->have_fsid = true;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(ceph_check_fsid);
+
+static int strcmp_null(const char *s1, const char *s2)
+{
+       if (!s1 && !s2)
+               return 0;
+       if (s1 && !s2)
+               return -1;
+       if (!s1 && s2)
+               return 1;
+       return strcmp(s1, s2);
+}
+
+int ceph_compare_options(struct ceph_options *new_opt,
+                        struct ceph_client *client)
+{
+       struct ceph_options *opt1 = new_opt;
+       struct ceph_options *opt2 = client->options;
+       int ofs = offsetof(struct ceph_options, mon_addr);
+       int i;
+       int ret;
+
+       ret = memcmp(opt1, opt2, ofs);
+       if (ret)
+               return ret;
+
+       ret = strcmp_null(opt1->name, opt2->name);
+       if (ret)
+               return ret;
+
+       ret = strcmp_null(opt1->secret, opt2->secret);
+       if (ret)
+               return ret;
+
+       /* any matching mon ip implies a match */
+       for (i = 0; i < opt1->num_mon; i++) {
+               if (ceph_monmap_contains(client->monc.monmap,
+                                &opt1->mon_addr[i]))
+                       return 0;
+       }
+       return -1;
+}
+EXPORT_SYMBOL(ceph_compare_options);
+
+
+static int parse_fsid(const char *str, struct ceph_fsid *fsid)
+{
+       int i = 0;
+       char tmp[3];
+       int err = -EINVAL;
+       int d;
+
+       dout("parse_fsid '%s'\n", str);
+       tmp[2] = 0;
+       while (*str && i < 16) {
+               if (ispunct(*str)) {
+                       str++;
+                       continue;
+               }
+               if (!isxdigit(str[0]) || !isxdigit(str[1]))
+                       break;
+               tmp[0] = str[0];
+               tmp[1] = str[1];
+               if (sscanf(tmp, "%x", &d) < 1)
+                       break;
+               fsid->fsid[i] = d & 0xff;
+               i++;
+               str += 2;
+       }
+
+       if (i == 16)
+               err = 0;
+       dout("parse_fsid ret %d got fsid %pU", err, fsid);
+       return err;
+}
+
+/*
+ * ceph options
+ */
+enum {
+       Opt_osdtimeout,
+       Opt_osdkeepalivetimeout,
+       Opt_mount_timeout,
+       Opt_osd_idle_ttl,
+       Opt_last_int,
+       /* int args above */
+       Opt_fsid,
+       Opt_name,
+       Opt_secret,
+       Opt_ip,
+       Opt_last_string,
+       /* string args above */
+       Opt_noshare,
+       Opt_nocrc,
+};
+
+static match_table_t opt_tokens = {
+       {Opt_osdtimeout, "osdtimeout=%d"},
+       {Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
+       {Opt_mount_timeout, "mount_timeout=%d"},
+       {Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
+       /* int args above */
+       {Opt_fsid, "fsid=%s"},
+       {Opt_name, "name=%s"},
+       {Opt_secret, "secret=%s"},
+       {Opt_ip, "ip=%s"},
+       /* string args above */
+       {Opt_noshare, "noshare"},
+       {Opt_nocrc, "nocrc"},
+       {-1, NULL}
+};
+
+void ceph_destroy_options(struct ceph_options *opt)
+{
+       dout("destroy_options %p\n", opt);
+       kfree(opt->name);
+       kfree(opt->secret);
+       kfree(opt);
+}
+EXPORT_SYMBOL(ceph_destroy_options);
+
+int ceph_parse_options(struct ceph_options **popt, char *options,
+                      const char *dev_name, const char *dev_name_end,
+                      int (*parse_extra_token)(char *c, void *private),
+                      void *private)
+{
+       struct ceph_options *opt;
+       const char *c;
+       int err = -ENOMEM;
+       substring_t argstr[MAX_OPT_ARGS];
+
+       opt = kzalloc(sizeof(*opt), GFP_KERNEL);
+       if (!opt)
+               return err;
+       opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
+                               GFP_KERNEL);
+       if (!opt->mon_addr)
+               goto out;
+
+       dout("parse_options %p options '%s' dev_name '%s'\n", opt, options,
+            dev_name);
+
+       /* start with defaults */
+       opt->flags = CEPH_OPT_DEFAULT;
+       opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
+       opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
+       opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
+       opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
+
+       /* get mon ip(s) */
+       /* ip1[:port1][,ip2[:port2]...] */
+       err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr,
+                            CEPH_MAX_MON, &opt->num_mon);
+       if (err < 0)
+               goto out;
+
+       /* parse mount options */
+       while ((c = strsep(&options, ",")) != NULL) {
+               int token, intval, ret;
+               if (!*c)
+                       continue;
+               err = -EINVAL;
+               token = match_token((char *)c, opt_tokens, argstr);
+               if (token < 0 && parse_extra_token) {
+                       /* extra? */
+                       err = parse_extra_token((char *)c, private);
+                       if (err < 0) {
+                               pr_err("bad option at '%s'\n", c);
+                               goto out;
+                       }
+                       continue;
+               }
+               if (token < Opt_last_int) {
+                       ret = match_int(&argstr[0], &intval);
+                       if (ret < 0) {
+                               pr_err("bad mount option arg (not int) "
+                                      "at '%s'\n", c);
+                               continue;
+                       }
+                       dout("got int token %d val %d\n", token, intval);
+               } else if (token > Opt_last_int && token < Opt_last_string) {
+                       dout("got string token %d val %s\n", token,
+                            argstr[0].from);
+               } else {
+                       dout("got token %d\n", token);
+               }
+               switch (token) {
+               case Opt_ip:
+                       err = ceph_parse_ips(argstr[0].from,
+                                            argstr[0].to,
+                                            &opt->my_addr,
+                                            1, NULL);
+                       if (err < 0)
+                               goto out;
+                       opt->flags |= CEPH_OPT_MYIP;
+                       break;
+
+               case Opt_fsid:
+                       err = parse_fsid(argstr[0].from, &opt->fsid);
+                       if (err == 0)
+                               opt->flags |= CEPH_OPT_FSID;
+                       break;
+               case Opt_name:
+                       opt->name = kstrndup(argstr[0].from,
+                                             argstr[0].to-argstr[0].from,
+                                             GFP_KERNEL);
+                       break;
+               case Opt_secret:
+                       opt->secret = kstrndup(argstr[0].from,
+                                               argstr[0].to-argstr[0].from,
+                                               GFP_KERNEL);
+                       break;
+
+                       /* misc */
+               case Opt_osdtimeout:
+                       opt->osd_timeout = intval;
+                       break;
+               case Opt_osdkeepalivetimeout:
+                       opt->osd_keepalive_timeout = intval;
+                       break;
+               case Opt_osd_idle_ttl:
+                       opt->osd_idle_ttl = intval;
+                       break;
+               case Opt_mount_timeout:
+                       opt->mount_timeout = intval;
+                       break;
+
+               case Opt_noshare:
+                       opt->flags |= CEPH_OPT_NOSHARE;
+                       break;
+
+               case Opt_nocrc:
+                       opt->flags |= CEPH_OPT_NOCRC;
+                       break;
+
+               default:
+                       BUG_ON(token);
+               }
+       }
+
+       /* success */
+       *popt = opt;
+       return 0;
+
+out:
+       ceph_destroy_options(opt);
+       return err;
+}
+EXPORT_SYMBOL(ceph_parse_options);
+
+u64 ceph_client_id(struct ceph_client *client)
+{
+       return client->monc.auth->global_id;
+}
+EXPORT_SYMBOL(ceph_client_id);
+
+/*
+ * create a fresh client instance
+ */
+struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
+{
+       struct ceph_client *client;
+       int err = -ENOMEM;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       client->private = private;
+       client->options = opt;
+
+       mutex_init(&client->mount_mutex);
+       init_waitqueue_head(&client->auth_wq);
+       client->auth_err = 0;
+
+       client->extra_mon_dispatch = NULL;
+       client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT;
+       client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT;
+
+       client->msgr = NULL;
+
+       /* subsystems */
+       err = ceph_monc_init(&client->monc, client);
+       if (err < 0)
+               goto fail;
+       err = ceph_osdc_init(&client->osdc, client);
+       if (err < 0)
+               goto fail_monc;
+
+       return client;
+
+fail_monc:
+       ceph_monc_stop(&client->monc);
+fail:
+       kfree(client);
+       return ERR_PTR(err);
+}
+EXPORT_SYMBOL(ceph_create_client);
+
+void ceph_destroy_client(struct ceph_client *client)
+{
+       dout("destroy_client %p\n", client);
+
+       /* unmount */
+       ceph_osdc_stop(&client->osdc);
+
+       /*
+        * make sure mds and osd connections close out before destroying
+        * the auth module, which is needed to free those connections'
+        * ceph_authorizers.
+        */
+       ceph_msgr_flush();
+
+       ceph_monc_stop(&client->monc);
+
+       ceph_debugfs_client_cleanup(client);
+
+       if (client->msgr)
+               ceph_messenger_destroy(client->msgr);
+
+       ceph_destroy_options(client->options);
+
+       kfree(client);
+       dout("destroy_client %p done\n", client);
+}
+EXPORT_SYMBOL(ceph_destroy_client);
+
+/*
+ * true if we have the mon map (and have thus joined the cluster)
+ */
+static int have_mon_and_osd_map(struct ceph_client *client)
+{
+       return client->monc.monmap && client->monc.monmap->epoch &&
+              client->osdc.osdmap && client->osdc.osdmap->epoch;
+}
+
+/*
+ * mount: join the ceph cluster, and open root directory.
+ */
+int __ceph_open_session(struct ceph_client *client, unsigned long started)
+{
+       struct ceph_entity_addr *myaddr = NULL;
+       int err;
+       unsigned long timeout = client->options->mount_timeout * HZ;
+
+       /* initialize the messenger */
+       if (client->msgr == NULL) {
+               if (ceph_test_opt(client, MYIP))
+                       myaddr = &client->options->my_addr;
+               client->msgr = ceph_messenger_create(myaddr,
+                                       client->supported_features,
+                                       client->required_features);
+               if (IS_ERR(client->msgr)) {
+                       client->msgr = NULL;
+                       return PTR_ERR(client->msgr);
+               }
+               client->msgr->nocrc = ceph_test_opt(client, NOCRC);
+       }
+
+       /* open session, and wait for mon and osd maps */
+       err = ceph_monc_open_session(&client->monc);
+       if (err < 0)
+               return err;
+
+       while (!have_mon_and_osd_map(client)) {
+               err = -EIO;
+               if (timeout && time_after_eq(jiffies, started + timeout))
+                       return err;
+
+               /* wait */
+               dout("mount waiting for mon_map\n");
+               err = wait_event_interruptible_timeout(client->auth_wq,
+                       have_mon_and_osd_map(client) || (client->auth_err < 0),
+                       timeout);
+               if (err == -EINTR || err == -ERESTARTSYS)
+                       return err;
+               if (client->auth_err < 0)
+                       return client->auth_err;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(__ceph_open_session);
+
+
+int ceph_open_session(struct ceph_client *client)
+{
+       int ret;
+       unsigned long started = jiffies;  /* note the start time */
+
+       dout("open_session start\n");
+       mutex_lock(&client->mount_mutex);
+
+       ret = __ceph_open_session(client, started);
+
+       mutex_unlock(&client->mount_mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_open_session);
+
+
+static int __init init_ceph_lib(void)
+{
+       int ret = 0;
+
+       ret = ceph_debugfs_init();
+       if (ret < 0)
+               goto out;
+
+       ret = ceph_msgr_init();
+       if (ret < 0)
+               goto out_debugfs;
+
+       pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n",
+               CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL,
+               CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT,
+               CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT);
+
+       return 0;
+
+out_debugfs:
+       ceph_debugfs_cleanup();
+out:
+       return ret;
+}
+
+static void __exit exit_ceph_lib(void)
+{
+       dout("exit_ceph_lib\n");
+       ceph_msgr_exit();
+       ceph_debugfs_cleanup();
+}
+
+module_init(init_ceph_lib);
+module_exit(exit_ceph_lib);
+
+MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
+MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
+MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
+MODULE_DESCRIPTION("Ceph filesystem for Linux");
+MODULE_LICENSE("GPL");
similarity index 92%
rename from fs/ceph/ceph_fs.c
rename to net/ceph/ceph_fs.c
index 3ac6cc7c1156dafd78262e7290edf914c3f01e31..a3a3a31d3c37b0006d0e9bfe26fd06a7ebe3b47d 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Some non-inline ceph helpers
  */
-#include "types.h"
+#include <linux/module.h>
+#include <linux/ceph/types.h>
 
 /*
  * return true if @layout appears to be valid
@@ -52,6 +53,7 @@ int ceph_flags_to_mode(int flags)
 
        return mode;
 }
+EXPORT_SYMBOL(ceph_flags_to_mode);
 
 int ceph_caps_for_mode(int mode)
 {
@@ -70,3 +72,4 @@ int ceph_caps_for_mode(int mode)
 
        return caps;
 }
+EXPORT_SYMBOL(ceph_caps_for_mode);
similarity index 98%
rename from fs/ceph/ceph_hash.c
rename to net/ceph/ceph_hash.c
index bd570015d147ca2b1ce52061d359a56bb936a4df..815ef8826796a82b6b80030830a1663e9421b417 100644 (file)
@@ -1,5 +1,5 @@
 
-#include "types.h"
+#include <linux/ceph/types.h>
 
 /*
  * Robert Jenkin's hash function.
diff --git a/net/ceph/ceph_strings.c b/net/ceph/ceph_strings.c
new file mode 100644 (file)
index 0000000..3fbda04
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Ceph string constants
+ */
+#include <linux/module.h>
+#include <linux/ceph/types.h>
+
+const char *ceph_entity_type_name(int type)
+{
+       switch (type) {
+       case CEPH_ENTITY_TYPE_MDS: return "mds";
+       case CEPH_ENTITY_TYPE_OSD: return "osd";
+       case CEPH_ENTITY_TYPE_MON: return "mon";
+       case CEPH_ENTITY_TYPE_CLIENT: return "client";
+       case CEPH_ENTITY_TYPE_AUTH: return "auth";
+       default: return "unknown";
+       }
+}
+
+const char *ceph_osd_op_name(int op)
+{
+       switch (op) {
+       case CEPH_OSD_OP_READ: return "read";
+       case CEPH_OSD_OP_STAT: return "stat";
+
+       case CEPH_OSD_OP_MASKTRUNC: return "masktrunc";
+
+       case CEPH_OSD_OP_WRITE: return "write";
+       case CEPH_OSD_OP_DELETE: return "delete";
+       case CEPH_OSD_OP_TRUNCATE: return "truncate";
+       case CEPH_OSD_OP_ZERO: return "zero";
+       case CEPH_OSD_OP_WRITEFULL: return "writefull";
+       case CEPH_OSD_OP_ROLLBACK: return "rollback";
+
+       case CEPH_OSD_OP_APPEND: return "append";
+       case CEPH_OSD_OP_STARTSYNC: return "startsync";
+       case CEPH_OSD_OP_SETTRUNC: return "settrunc";
+       case CEPH_OSD_OP_TRIMTRUNC: return "trimtrunc";
+
+       case CEPH_OSD_OP_TMAPUP: return "tmapup";
+       case CEPH_OSD_OP_TMAPGET: return "tmapget";
+       case CEPH_OSD_OP_TMAPPUT: return "tmapput";
+
+       case CEPH_OSD_OP_GETXATTR: return "getxattr";
+       case CEPH_OSD_OP_GETXATTRS: return "getxattrs";
+       case CEPH_OSD_OP_SETXATTR: return "setxattr";
+       case CEPH_OSD_OP_SETXATTRS: return "setxattrs";
+       case CEPH_OSD_OP_RESETXATTRS: return "resetxattrs";
+       case CEPH_OSD_OP_RMXATTR: return "rmxattr";
+       case CEPH_OSD_OP_CMPXATTR: return "cmpxattr";
+
+       case CEPH_OSD_OP_PULL: return "pull";
+       case CEPH_OSD_OP_PUSH: return "push";
+       case CEPH_OSD_OP_BALANCEREADS: return "balance-reads";
+       case CEPH_OSD_OP_UNBALANCEREADS: return "unbalance-reads";
+       case CEPH_OSD_OP_SCRUB: return "scrub";
+
+       case CEPH_OSD_OP_WRLOCK: return "wrlock";
+       case CEPH_OSD_OP_WRUNLOCK: return "wrunlock";
+       case CEPH_OSD_OP_RDLOCK: return "rdlock";
+       case CEPH_OSD_OP_RDUNLOCK: return "rdunlock";
+       case CEPH_OSD_OP_UPLOCK: return "uplock";
+       case CEPH_OSD_OP_DNLOCK: return "dnlock";
+
+       case CEPH_OSD_OP_CALL: return "call";
+
+       case CEPH_OSD_OP_PGLS: return "pgls";
+       }
+       return "???";
+}
+
+
+const char *ceph_pool_op_name(int op)
+{
+       switch (op) {
+       case POOL_OP_CREATE: return "create";
+       case POOL_OP_DELETE: return "delete";
+       case POOL_OP_AUID_CHANGE: return "auid change";
+       case POOL_OP_CREATE_SNAP: return "create snap";
+       case POOL_OP_DELETE_SNAP: return "delete snap";
+       case POOL_OP_CREATE_UNMANAGED_SNAP: return "create unmanaged snap";
+       case POOL_OP_DELETE_UNMANAGED_SNAP: return "delete unmanaged snap";
+       }
+       return "???";
+}
similarity index 99%
rename from fs/ceph/crush/crush.c
rename to net/ceph/crush/crush.c
index fabd302e5779c0188b55916be81d7913dce84105..d6ebb13a18a4bc787eb249ad3e4b62ec1c174f97 100644 (file)
@@ -8,7 +8,7 @@
 # define BUG_ON(x) assert(!(x))
 #endif
 
-#include "crush.h"
+#include <linux/crush/crush.h>
 
 const char *crush_bucket_alg_name(int alg)
 {
similarity index 99%
rename from fs/ceph/crush/hash.c
rename to net/ceph/crush/hash.c
index 5873aed694bf5a06a092102a2209c5ad71a9aff8..5bb63e37a8a10f3419a399b32339cf5baf279762 100644 (file)
@@ -1,6 +1,6 @@
 
 #include <linux/types.h>
-#include "hash.h"
+#include <linux/crush/hash.h>
 
 /*
  * Robert Jenkins' function for mixing 32-bit values
similarity index 99%
rename from fs/ceph/crush/mapper.c
rename to net/ceph/crush/mapper.c
index a4eec133258e80a880a8cecca0282c54e11982ac..42599e31dcad8a6ceb1f3b29d9171f6a249e56a3 100644 (file)
@@ -18,8 +18,8 @@
 # define kfree(x) free(x)
 #endif
 
-#include "crush.h"
-#include "hash.h"
+#include <linux/crush/crush.h>
+#include <linux/crush/hash.h>
 
 /*
  * Implement the core CRUSH mapping algorithm.
similarity index 99%
rename from fs/ceph/crypto.c
rename to net/ceph/crypto.c
index a3e627f63293b2d329f620525328280a9ae15291..7b505b0c983f74eaffa51e306e38f2cd90aad3fb 100644 (file)
@@ -1,13 +1,13 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/err.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <crypto/hash.h>
 
+#include <linux/ceph/decode.h>
 #include "crypto.h"
-#include "decode.h"
 
 int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
 {
similarity index 95%
rename from fs/ceph/crypto.h
rename to net/ceph/crypto.h
index bdf38607323c2da2eb87d2c3ebf7b3d158bd7d0d..f9eccace592b63b10a68c8f7d5d99abe2b2eba55 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef _FS_CEPH_CRYPTO_H
 #define _FS_CEPH_CRYPTO_H
 
-#include "types.h"
-#include "buffer.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/buffer.h>
 
 /*
  * cryptographic secret
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c
new file mode 100644 (file)
index 0000000..27d4ea3
--- /dev/null
@@ -0,0 +1,267 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
+
+#ifdef CONFIG_DEBUG_FS
+
+/*
+ * Implement /sys/kernel/debug/ceph fun
+ *
+ * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
+ *      .../osdmap      - current osdmap
+ *      .../monmap      - current monmap
+ *      .../osdc        - active osd requests
+ *      .../monc        - mon client state
+ *      .../dentry_lru  - dump contents of dentry lru
+ *      .../caps        - expose cap (reservation) stats
+ *      .../bdi         - symlink to ../../bdi/something
+ */
+
+static struct dentry *ceph_debugfs_dir;
+
+static int monmap_show(struct seq_file *s, void *p)
+{
+       int i;
+       struct ceph_client *client = s->private;
+
+       if (client->monc.monmap == NULL)
+               return 0;
+
+       seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
+       for (i = 0; i < client->monc.monmap->num_mon; i++) {
+               struct ceph_entity_inst *inst =
+                       &client->monc.monmap->mon_inst[i];
+
+               seq_printf(s, "\t%s%lld\t%s\n",
+                          ENTITY_NAME(inst->name),
+                          ceph_pr_addr(&inst->addr.in_addr));
+       }
+       return 0;
+}
+
+static int osdmap_show(struct seq_file *s, void *p)
+{
+       int i;
+       struct ceph_client *client = s->private;
+       struct rb_node *n;
+
+       if (client->osdc.osdmap == NULL)
+               return 0;
+       seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch);
+       seq_printf(s, "flags%s%s\n",
+                  (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ?
+                  " NEARFULL" : "",
+                  (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ?
+                  " FULL" : "");
+       for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) {
+               struct ceph_pg_pool_info *pool =
+                       rb_entry(n, struct ceph_pg_pool_info, node);
+               seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n",
+                          pool->id, pool->v.pg_num, pool->pg_num_mask,
+                          pool->v.lpg_num, pool->lpg_num_mask);
+       }
+       for (i = 0; i < client->osdc.osdmap->max_osd; i++) {
+               struct ceph_entity_addr *addr =
+                       &client->osdc.osdmap->osd_addr[i];
+               int state = client->osdc.osdmap->osd_state[i];
+               char sb[64];
+
+               seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n",
+                          i, ceph_pr_addr(&addr->in_addr),
+                          ((client->osdc.osdmap->osd_weight[i]*100) >> 16),
+                          ceph_osdmap_state_str(sb, sizeof(sb), state));
+       }
+       return 0;
+}
+
+static int monc_show(struct seq_file *s, void *p)
+{
+       struct ceph_client *client = s->private;
+       struct ceph_mon_generic_request *req;
+       struct ceph_mon_client *monc = &client->monc;
+       struct rb_node *rp;
+
+       mutex_lock(&monc->mutex);
+
+       if (monc->have_mdsmap)
+               seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap);
+       if (monc->have_osdmap)
+               seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap);
+       if (monc->want_next_osdmap)
+               seq_printf(s, "want next osdmap\n");
+
+       for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
+               __u16 op;
+               req = rb_entry(rp, struct ceph_mon_generic_request, node);
+               op = le16_to_cpu(req->request->hdr.type);
+               if (op == CEPH_MSG_STATFS)
+                       seq_printf(s, "%lld statfs\n", req->tid);
+               else
+                       seq_printf(s, "%lld unknown\n", req->tid);
+       }
+
+       mutex_unlock(&monc->mutex);
+       return 0;
+}
+
+static int osdc_show(struct seq_file *s, void *pp)
+{
+       struct ceph_client *client = s->private;
+       struct ceph_osd_client *osdc = &client->osdc;
+       struct rb_node *p;
+
+       mutex_lock(&osdc->request_mutex);
+       for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
+               struct ceph_osd_request *req;
+               struct ceph_osd_request_head *head;
+               struct ceph_osd_op *op;
+               int num_ops;
+               int opcode, olen;
+               int i;
+
+               req = rb_entry(p, struct ceph_osd_request, r_node);
+
+               seq_printf(s, "%lld\tosd%d\t%d.%x\t", req->r_tid,
+                          req->r_osd ? req->r_osd->o_osd : -1,
+                          le32_to_cpu(req->r_pgid.pool),
+                          le16_to_cpu(req->r_pgid.ps));
+
+               head = req->r_request->front.iov_base;
+               op = (void *)(head + 1);
+
+               num_ops = le16_to_cpu(head->num_ops);
+               olen = le32_to_cpu(head->object_len);
+               seq_printf(s, "%.*s", olen,
+                          (const char *)(head->ops + num_ops));
+
+               if (req->r_reassert_version.epoch)
+                       seq_printf(s, "\t%u'%llu",
+                          (unsigned)le32_to_cpu(req->r_reassert_version.epoch),
+                          le64_to_cpu(req->r_reassert_version.version));
+               else
+                       seq_printf(s, "\t");
+
+               for (i = 0; i < num_ops; i++) {
+                       opcode = le16_to_cpu(op->op);
+                       seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
+                       op++;
+               }
+
+               seq_printf(s, "\n");
+       }
+       mutex_unlock(&osdc->request_mutex);
+       return 0;
+}
+
+CEPH_DEFINE_SHOW_FUNC(monmap_show)
+CEPH_DEFINE_SHOW_FUNC(osdmap_show)
+CEPH_DEFINE_SHOW_FUNC(monc_show)
+CEPH_DEFINE_SHOW_FUNC(osdc_show)
+
+int ceph_debugfs_init(void)
+{
+       ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
+       if (!ceph_debugfs_dir)
+               return -ENOMEM;
+       return 0;
+}
+
+void ceph_debugfs_cleanup(void)
+{
+       debugfs_remove(ceph_debugfs_dir);
+}
+
+int ceph_debugfs_client_init(struct ceph_client *client)
+{
+       int ret = -ENOMEM;
+       char name[80];
+
+       snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
+                client->monc.auth->global_id);
+
+       client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
+       if (!client->debugfs_dir)
+               goto out;
+
+       client->monc.debugfs_file = debugfs_create_file("monc",
+                                                     0600,
+                                                     client->debugfs_dir,
+                                                     client,
+                                                     &monc_show_fops);
+       if (!client->monc.debugfs_file)
+               goto out;
+
+       client->osdc.debugfs_file = debugfs_create_file("osdc",
+                                                     0600,
+                                                     client->debugfs_dir,
+                                                     client,
+                                                     &osdc_show_fops);
+       if (!client->osdc.debugfs_file)
+               goto out;
+
+       client->debugfs_monmap = debugfs_create_file("monmap",
+                                       0600,
+                                       client->debugfs_dir,
+                                       client,
+                                       &monmap_show_fops);
+       if (!client->debugfs_monmap)
+               goto out;
+
+       client->debugfs_osdmap = debugfs_create_file("osdmap",
+                                       0600,
+                                       client->debugfs_dir,
+                                       client,
+                                       &osdmap_show_fops);
+       if (!client->debugfs_osdmap)
+               goto out;
+
+       return 0;
+
+out:
+       ceph_debugfs_client_cleanup(client);
+       return ret;
+}
+
+void ceph_debugfs_client_cleanup(struct ceph_client *client)
+{
+       debugfs_remove(client->debugfs_osdmap);
+       debugfs_remove(client->debugfs_monmap);
+       debugfs_remove(client->osdc.debugfs_file);
+       debugfs_remove(client->monc.debugfs_file);
+       debugfs_remove(client->debugfs_dir);
+}
+
+#else  /* CONFIG_DEBUG_FS */
+
+int ceph_debugfs_init(void)
+{
+       return 0;
+}
+
+void ceph_debugfs_cleanup(void)
+{
+}
+
+int ceph_debugfs_client_init(struct ceph_client *client)
+{
+       return 0;
+}
+
+void ceph_debugfs_client_cleanup(struct ceph_client *client)
+{
+}
+
+#endif  /* CONFIG_DEBUG_FS */
+
+EXPORT_SYMBOL(ceph_debugfs_init);
+EXPORT_SYMBOL(ceph_debugfs_cleanup);
similarity index 89%
rename from fs/ceph/messenger.c
rename to net/ceph/messenger.c
index 2502d76fcec175ddb8500bcd1863c52add1208e5..0e8157ee5d4382a32992f34c2b1cf0d78f2868b4 100644 (file)
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/crc32c.h>
 #include <linux/ctype.h>
@@ -9,12 +9,14 @@
 #include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/string.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
 #include <net/tcp.h>
 
-#include "super.h"
-#include "messenger.h"
-#include "decode.h"
-#include "pagelist.h"
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/pagelist.h>
 
 /*
  * Ceph uses the messenger to exchange ceph_msg messages with other
@@ -48,7 +50,7 @@ static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN];
 static DEFINE_SPINLOCK(addr_str_lock);
 static int last_addr_str;
 
-const char *pr_addr(const struct sockaddr_storage *ss)
+const char *ceph_pr_addr(const struct sockaddr_storage *ss)
 {
        int i;
        char *s;
@@ -79,6 +81,7 @@ const char *pr_addr(const struct sockaddr_storage *ss)
 
        return s;
 }
+EXPORT_SYMBOL(ceph_pr_addr);
 
 static void encode_my_addr(struct ceph_messenger *msgr)
 {
@@ -91,7 +94,7 @@ static void encode_my_addr(struct ceph_messenger *msgr)
  */
 struct workqueue_struct *ceph_msgr_wq;
 
-int __init ceph_msgr_init(void)
+int ceph_msgr_init(void)
 {
        ceph_msgr_wq = create_workqueue("ceph-msgr");
        if (IS_ERR(ceph_msgr_wq)) {
@@ -102,16 +105,19 @@ int __init ceph_msgr_init(void)
        }
        return 0;
 }
+EXPORT_SYMBOL(ceph_msgr_init);
 
 void ceph_msgr_exit(void)
 {
        destroy_workqueue(ceph_msgr_wq);
 }
+EXPORT_SYMBOL(ceph_msgr_exit);
 
 void ceph_msgr_flush(void)
 {
        flush_workqueue(ceph_msgr_wq);
 }
+EXPORT_SYMBOL(ceph_msgr_flush);
 
 
 /*
@@ -221,19 +227,19 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con)
 
        set_sock_callbacks(sock, con);
 
-       dout("connect %s\n", pr_addr(&con->peer_addr.in_addr));
+       dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr));
 
        ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
                                 O_NONBLOCK);
        if (ret == -EINPROGRESS) {
                dout("connect %s EINPROGRESS sk_state = %u\n",
-                    pr_addr(&con->peer_addr.in_addr),
+                    ceph_pr_addr(&con->peer_addr.in_addr),
                     sock->sk->sk_state);
                ret = 0;
        }
        if (ret < 0) {
                pr_err("connect %s error %d\n",
-                      pr_addr(&con->peer_addr.in_addr), ret);
+                      ceph_pr_addr(&con->peer_addr.in_addr), ret);
                sock_release(sock);
                con->sock = NULL;
                con->error_msg = "connect error";
@@ -334,7 +340,8 @@ static void reset_connection(struct ceph_connection *con)
  */
 void ceph_con_close(struct ceph_connection *con)
 {
-       dout("con_close %p peer %s\n", con, pr_addr(&con->peer_addr.in_addr));
+       dout("con_close %p peer %s\n", con,
+            ceph_pr_addr(&con->peer_addr.in_addr));
        set_bit(CLOSED, &con->state);  /* in case there's queued work */
        clear_bit(STANDBY, &con->state);  /* avoid connect_seq bump */
        clear_bit(LOSSYTX, &con->state);  /* so we retry next connect */
@@ -347,19 +354,21 @@ void ceph_con_close(struct ceph_connection *con)
        mutex_unlock(&con->mutex);
        queue_con(con);
 }
+EXPORT_SYMBOL(ceph_con_close);
 
 /*
  * Reopen a closed connection, with a new peer address.
  */
 void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr)
 {
-       dout("con_open %p %s\n", con, pr_addr(&addr->in_addr));
+       dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
        set_bit(OPENING, &con->state);
        clear_bit(CLOSED, &con->state);
        memcpy(&con->peer_addr, addr, sizeof(*addr));
        con->delay = 0;      /* reset backoff memory */
        queue_con(con);
 }
+EXPORT_SYMBOL(ceph_con_open);
 
 /*
  * return true if this connection ever successfully opened
@@ -406,6 +415,7 @@ void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con)
        INIT_LIST_HEAD(&con->out_sent);
        INIT_DELAYED_WORK(&con->work, con_work);
 }
+EXPORT_SYMBOL(ceph_con_init);
 
 
 /*
@@ -529,8 +539,11 @@ static void prepare_write_message(struct ceph_connection *con)
        if (le32_to_cpu(m->hdr.data_len) > 0) {
                /* initialize page iterator */
                con->out_msg_pos.page = 0;
-               con->out_msg_pos.page_pos =
-                       le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK;
+               if (m->pages)
+                       con->out_msg_pos.page_pos =
+                               le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK;
+               else
+                       con->out_msg_pos.page_pos = 0;
                con->out_msg_pos.data_pos = 0;
                con->out_msg_pos.did_page_crc = 0;
                con->out_more = 1;  /* data + footer will follow */
@@ -647,7 +660,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
        dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
             con->connect_seq, global_seq, proto);
 
-       con->out_connect.features = cpu_to_le64(CEPH_FEATURE_SUPPORTED);
+       con->out_connect.features = cpu_to_le64(msgr->supported_features);
        con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
        con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
        con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -712,6 +725,31 @@ out:
        return ret;  /* done! */
 }
 
+#ifdef CONFIG_BLOCK
+static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg)
+{
+       if (!bio) {
+               *iter = NULL;
+               *seg = 0;
+               return;
+       }
+       *iter = bio;
+       *seg = bio->bi_idx;
+}
+
+static void iter_bio_next(struct bio **bio_iter, int *seg)
+{
+       if (*bio_iter == NULL)
+               return;
+
+       BUG_ON(*seg >= (*bio_iter)->bi_vcnt);
+
+       (*seg)++;
+       if (*seg == (*bio_iter)->bi_vcnt)
+               init_bio_iter((*bio_iter)->bi_next, bio_iter, seg);
+}
+#endif
+
 /*
  * Write as much message data payload as we can.  If we finish, queue
  * up the footer.
@@ -726,21 +764,46 @@ static int write_partial_msg_pages(struct ceph_connection *con)
        size_t len;
        int crc = con->msgr->nocrc;
        int ret;
+       int total_max_write;
+       int in_trail = 0;
+       size_t trail_len = (msg->trail ? msg->trail->length : 0);
 
        dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n",
             con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages,
             con->out_msg_pos.page_pos);
 
-       while (con->out_msg_pos.page < con->out_msg->nr_pages) {
+#ifdef CONFIG_BLOCK
+       if (msg->bio && !msg->bio_iter)
+               init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
+#endif
+
+       while (data_len > con->out_msg_pos.data_pos) {
                struct page *page = NULL;
                void *kaddr = NULL;
+               int max_write = PAGE_SIZE;
+               int page_shift = 0;
+
+               total_max_write = data_len - trail_len -
+                       con->out_msg_pos.data_pos;
 
                /*
                 * if we are calculating the data crc (the default), we need
                 * to map the page.  if our pages[] has been revoked, use the
                 * zero page.
                 */
-               if (msg->pages) {
+
+               /* have we reached the trail part of the data? */
+               if (con->out_msg_pos.data_pos >= data_len - trail_len) {
+                       in_trail = 1;
+
+                       total_max_write = data_len - con->out_msg_pos.data_pos;
+
+                       page = list_first_entry(&msg->trail->head,
+                                               struct page, lru);
+                       if (crc)
+                               kaddr = kmap(page);
+                       max_write = PAGE_SIZE;
+               } else if (msg->pages) {
                        page = msg->pages[con->out_msg_pos.page];
                        if (crc)
                                kaddr = kmap(page);
@@ -749,13 +812,25 @@ static int write_partial_msg_pages(struct ceph_connection *con)
                                                struct page, lru);
                        if (crc)
                                kaddr = kmap(page);
+#ifdef CONFIG_BLOCK
+               } else if (msg->bio) {
+                       struct bio_vec *bv;
+
+                       bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg);
+                       page = bv->bv_page;
+                       page_shift = bv->bv_offset;
+                       if (crc)
+                               kaddr = kmap(page) + page_shift;
+                       max_write = bv->bv_len;
+#endif
                } else {
                        page = con->msgr->zero_page;
                        if (crc)
                                kaddr = page_address(con->msgr->zero_page);
                }
-               len = min((int)(PAGE_SIZE - con->out_msg_pos.page_pos),
-                         (int)(data_len - con->out_msg_pos.data_pos));
+               len = min_t(int, max_write - con->out_msg_pos.page_pos,
+                           total_max_write);
+
                if (crc && !con->out_msg_pos.did_page_crc) {
                        void *base = kaddr + con->out_msg_pos.page_pos;
                        u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc);
@@ -765,13 +840,14 @@ static int write_partial_msg_pages(struct ceph_connection *con)
                                cpu_to_le32(crc32c(tmpcrc, base, len));
                        con->out_msg_pos.did_page_crc = 1;
                }
-
                ret = kernel_sendpage(con->sock, page,
-                                     con->out_msg_pos.page_pos, len,
+                                     con->out_msg_pos.page_pos + page_shift,
+                                     len,
                                      MSG_DONTWAIT | MSG_NOSIGNAL |
                                      MSG_MORE);
 
-               if (crc && (msg->pages || msg->pagelist))
+               if (crc &&
+                   (msg->pages || msg->pagelist || msg->bio || in_trail))
                        kunmap(page);
 
                if (ret <= 0)
@@ -783,9 +859,16 @@ static int write_partial_msg_pages(struct ceph_connection *con)
                        con->out_msg_pos.page_pos = 0;
                        con->out_msg_pos.page++;
                        con->out_msg_pos.did_page_crc = 0;
-                       if (msg->pagelist)
+                       if (in_trail)
+                               list_move_tail(&page->lru,
+                                              &msg->trail->head);
+                       else if (msg->pagelist)
                                list_move_tail(&page->lru,
                                               &msg->pagelist->head);
+#ifdef CONFIG_BLOCK
+                       else if (msg->bio)
+                               iter_bio_next(&msg->bio_iter, &msg->bio_seg);
+#endif
                }
        }
 
@@ -938,7 +1021,7 @@ static int verify_hello(struct ceph_connection *con)
 {
        if (memcmp(con->in_banner, CEPH_BANNER, strlen(CEPH_BANNER))) {
                pr_err("connect to %s got bad banner\n",
-                      pr_addr(&con->peer_addr.in_addr));
+                      ceph_pr_addr(&con->peer_addr.in_addr));
                con->error_msg = "protocol error, bad banner";
                return -1;
        }
@@ -1041,7 +1124,7 @@ int ceph_parse_ips(const char *c, const char *end,
 
                addr_set_port(ss, port);
 
-               dout("parse_ips got %s\n", pr_addr(ss));
+               dout("parse_ips got %s\n", ceph_pr_addr(ss));
 
                if (p == end)
                        break;
@@ -1061,6 +1144,7 @@ bad:
        pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
        return -EINVAL;
 }
+EXPORT_SYMBOL(ceph_parse_ips);
 
 static int process_banner(struct ceph_connection *con)
 {
@@ -1082,9 +1166,9 @@ static int process_banner(struct ceph_connection *con)
            !(addr_is_blank(&con->actual_peer_addr.in_addr) &&
              con->actual_peer_addr.nonce == con->peer_addr.nonce)) {
                pr_warning("wrong peer, want %s/%d, got %s/%d\n",
-                          pr_addr(&con->peer_addr.in_addr),
+                          ceph_pr_addr(&con->peer_addr.in_addr),
                           (int)le32_to_cpu(con->peer_addr.nonce),
-                          pr_addr(&con->actual_peer_addr.in_addr),
+                          ceph_pr_addr(&con->actual_peer_addr.in_addr),
                           (int)le32_to_cpu(con->actual_peer_addr.nonce));
                con->error_msg = "wrong peer at address";
                return -1;
@@ -1102,7 +1186,7 @@ static int process_banner(struct ceph_connection *con)
                addr_set_port(&con->msgr->inst.addr.in_addr, port);
                encode_my_addr(con->msgr);
                dout("process_banner learned my addr is %s\n",
-                    pr_addr(&con->msgr->inst.addr.in_addr));
+                    ceph_pr_addr(&con->msgr->inst.addr.in_addr));
        }
 
        set_bit(NEGOTIATING, &con->state);
@@ -1123,8 +1207,8 @@ static void fail_protocol(struct ceph_connection *con)
 
 static int process_connect(struct ceph_connection *con)
 {
-       u64 sup_feat = CEPH_FEATURE_SUPPORTED;
-       u64 req_feat = CEPH_FEATURE_REQUIRED;
+       u64 sup_feat = con->msgr->supported_features;
+       u64 req_feat = con->msgr->required_features;
        u64 server_feat = le64_to_cpu(con->in_reply.features);
 
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
@@ -1134,7 +1218,7 @@ static int process_connect(struct ceph_connection *con)
                pr_err("%s%lld %s feature set mismatch,"
                       " my %llx < server's %llx, missing %llx\n",
                       ENTITY_NAME(con->peer_name),
-                      pr_addr(&con->peer_addr.in_addr),
+                      ceph_pr_addr(&con->peer_addr.in_addr),
                       sup_feat, server_feat, server_feat & ~sup_feat);
                con->error_msg = "missing required protocol features";
                fail_protocol(con);
@@ -1144,7 +1228,7 @@ static int process_connect(struct ceph_connection *con)
                pr_err("%s%lld %s protocol version mismatch,"
                       " my %d != server's %d\n",
                       ENTITY_NAME(con->peer_name),
-                      pr_addr(&con->peer_addr.in_addr),
+                      ceph_pr_addr(&con->peer_addr.in_addr),
                       le32_to_cpu(con->out_connect.protocol_version),
                       le32_to_cpu(con->in_reply.protocol_version));
                con->error_msg = "protocol version mismatch";
@@ -1178,7 +1262,7 @@ static int process_connect(struct ceph_connection *con)
                     le32_to_cpu(con->in_connect.connect_seq));
                pr_err("%s%lld %s connection reset\n",
                       ENTITY_NAME(con->peer_name),
-                      pr_addr(&con->peer_addr.in_addr));
+                      ceph_pr_addr(&con->peer_addr.in_addr));
                reset_connection(con);
                prepare_write_connect(con->msgr, con, 0);
                prepare_read_connect(con);
@@ -1223,7 +1307,7 @@ static int process_connect(struct ceph_connection *con)
                        pr_err("%s%lld %s protocol feature mismatch,"
                               " my required %llx > server's %llx, need %llx\n",
                               ENTITY_NAME(con->peer_name),
-                              pr_addr(&con->peer_addr.in_addr),
+                              ceph_pr_addr(&con->peer_addr.in_addr),
                               req_feat, server_feat, req_feat & ~server_feat);
                        con->error_msg = "missing required protocol features";
                        fail_protocol(con);
@@ -1305,8 +1389,7 @@ static int read_partial_message_section(struct ceph_connection *con,
                                        struct kvec *section,
                                        unsigned int sec_len, u32 *crc)
 {
-       int left;
-       int ret;
+       int ret, left;
 
        BUG_ON(!section);
 
@@ -1329,13 +1412,83 @@ static int read_partial_message_section(struct ceph_connection *con,
 static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
                                struct ceph_msg_header *hdr,
                                int *skip);
+
+
+static int read_partial_message_pages(struct ceph_connection *con,
+                                     struct page **pages,
+                                     unsigned data_len, int datacrc)
+{
+       void *p;
+       int ret;
+       int left;
+
+       left = min((int)(data_len - con->in_msg_pos.data_pos),
+                  (int)(PAGE_SIZE - con->in_msg_pos.page_pos));
+       /* (page) data */
+       BUG_ON(pages == NULL);
+       p = kmap(pages[con->in_msg_pos.page]);
+       ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
+                              left);
+       if (ret > 0 && datacrc)
+               con->in_data_crc =
+                       crc32c(con->in_data_crc,
+                                 p + con->in_msg_pos.page_pos, ret);
+       kunmap(pages[con->in_msg_pos.page]);
+       if (ret <= 0)
+               return ret;
+       con->in_msg_pos.data_pos += ret;
+       con->in_msg_pos.page_pos += ret;
+       if (con->in_msg_pos.page_pos == PAGE_SIZE) {
+               con->in_msg_pos.page_pos = 0;
+               con->in_msg_pos.page++;
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_BLOCK
+static int read_partial_message_bio(struct ceph_connection *con,
+                                   struct bio **bio_iter, int *bio_seg,
+                                   unsigned data_len, int datacrc)
+{
+       struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg);
+       void *p;
+       int ret, left;
+
+       if (IS_ERR(bv))
+               return PTR_ERR(bv);
+
+       left = min((int)(data_len - con->in_msg_pos.data_pos),
+                  (int)(bv->bv_len - con->in_msg_pos.page_pos));
+
+       p = kmap(bv->bv_page) + bv->bv_offset;
+
+       ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
+                              left);
+       if (ret > 0 && datacrc)
+               con->in_data_crc =
+                       crc32c(con->in_data_crc,
+                                 p + con->in_msg_pos.page_pos, ret);
+       kunmap(bv->bv_page);
+       if (ret <= 0)
+               return ret;
+       con->in_msg_pos.data_pos += ret;
+       con->in_msg_pos.page_pos += ret;
+       if (con->in_msg_pos.page_pos == bv->bv_len) {
+               con->in_msg_pos.page_pos = 0;
+               iter_bio_next(bio_iter, bio_seg);
+       }
+
+       return ret;
+}
+#endif
+
 /*
  * read (part of) a message.
  */
 static int read_partial_message(struct ceph_connection *con)
 {
        struct ceph_msg *m = con->in_msg;
-       void *p;
        int ret;
        int to, left;
        unsigned front_len, middle_len, data_len, data_off;
@@ -1381,7 +1534,7 @@ static int read_partial_message(struct ceph_connection *con)
        if ((s64)seq - (s64)con->in_seq < 1) {
                pr_info("skipping %s%lld %s seq %lld, expected %lld\n",
                        ENTITY_NAME(con->peer_name),
-                       pr_addr(&con->peer_addr.in_addr),
+                       ceph_pr_addr(&con->peer_addr.in_addr),
                        seq, con->in_seq + 1);
                con->in_base_pos = -front_len - middle_len - data_len -
                        sizeof(m->footer);
@@ -1422,7 +1575,10 @@ static int read_partial_message(struct ceph_connection *con)
                        m->middle->vec.iov_len = 0;
 
                con->in_msg_pos.page = 0;
-               con->in_msg_pos.page_pos = data_off & ~PAGE_MASK;
+               if (m->pages)
+                       con->in_msg_pos.page_pos = data_off & ~PAGE_MASK;
+               else
+                       con->in_msg_pos.page_pos = 0;
                con->in_msg_pos.data_pos = 0;
        }
 
@@ -1440,27 +1596,29 @@ static int read_partial_message(struct ceph_connection *con)
                if (ret <= 0)
                        return ret;
        }
+#ifdef CONFIG_BLOCK
+       if (m->bio && !m->bio_iter)
+               init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg);
+#endif
 
        /* (page) data */
        while (con->in_msg_pos.data_pos < data_len) {
-               left = min((int)(data_len - con->in_msg_pos.data_pos),
-                          (int)(PAGE_SIZE - con->in_msg_pos.page_pos));
-               BUG_ON(m->pages == NULL);
-               p = kmap(m->pages[con->in_msg_pos.page]);
-               ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
-                                      left);
-               if (ret > 0 && datacrc)
-                       con->in_data_crc =
-                               crc32c(con->in_data_crc,
-                                         p + con->in_msg_pos.page_pos, ret);
-               kunmap(m->pages[con->in_msg_pos.page]);
-               if (ret <= 0)
-                       return ret;
-               con->in_msg_pos.data_pos += ret;
-               con->in_msg_pos.page_pos += ret;
-               if (con->in_msg_pos.page_pos == PAGE_SIZE) {
-                       con->in_msg_pos.page_pos = 0;
-                       con->in_msg_pos.page++;
+               if (m->pages) {
+                       ret = read_partial_message_pages(con, m->pages,
+                                                data_len, datacrc);
+                       if (ret <= 0)
+                               return ret;
+#ifdef CONFIG_BLOCK
+               } else if (m->bio) {
+
+                       ret = read_partial_message_bio(con,
+                                                &m->bio_iter, &m->bio_seg,
+                                                data_len, datacrc);
+                       if (ret <= 0)
+                               return ret;
+#endif
+               } else {
+                       BUG_ON(1);
                }
        }
 
@@ -1874,9 +2032,9 @@ out:
 static void ceph_fault(struct ceph_connection *con)
 {
        pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
-              pr_addr(&con->peer_addr.in_addr), con->error_msg);
+              ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
        dout("fault %p state %lu to peer %s\n",
-            con, con->state, pr_addr(&con->peer_addr.in_addr));
+            con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
 
        if (test_bit(LOSSYTX, &con->state)) {
                dout("fault on LOSSYTX channel\n");
@@ -1936,7 +2094,9 @@ out:
 /*
  * create a new messenger instance
  */
-struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr)
+struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr,
+                                            u32 supported_features,
+                                            u32 required_features)
 {
        struct ceph_messenger *msgr;
 
@@ -1944,6 +2104,9 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr)
        if (msgr == NULL)
                return ERR_PTR(-ENOMEM);
 
+       msgr->supported_features = supported_features;
+       msgr->required_features = required_features;
+
        spin_lock_init(&msgr->global_seq_lock);
 
        /* the zero page is needed if a request is "canceled" while the message
@@ -1966,6 +2129,7 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr)
        dout("messenger_create %p\n", msgr);
        return msgr;
 }
+EXPORT_SYMBOL(ceph_messenger_create);
 
 void ceph_messenger_destroy(struct ceph_messenger *msgr)
 {
@@ -1975,6 +2139,7 @@ void ceph_messenger_destroy(struct ceph_messenger *msgr)
        kfree(msgr);
        dout("destroyed messenger %p\n", msgr);
 }
+EXPORT_SYMBOL(ceph_messenger_destroy);
 
 /*
  * Queue up an outgoing message on the given connection.
@@ -2011,6 +2176,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
        if (test_and_set_bit(WRITE_PENDING, &con->state) == 0)
                queue_con(con);
 }
+EXPORT_SYMBOL(ceph_con_send);
 
 /*
  * Revoke a message that was previously queued for send
@@ -2076,6 +2242,7 @@ void ceph_con_keepalive(struct ceph_connection *con)
            test_and_set_bit(WRITE_PENDING, &con->state) == 0)
                queue_con(con);
 }
+EXPORT_SYMBOL(ceph_con_keepalive);
 
 
 /*
@@ -2136,6 +2303,10 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
        m->nr_pages = 0;
        m->pages = NULL;
        m->pagelist = NULL;
+       m->bio = NULL;
+       m->bio_iter = NULL;
+       m->bio_seg = 0;
+       m->trail = NULL;
 
        dout("ceph_msg_new %p front %d\n", m, front_len);
        return m;
@@ -2146,6 +2317,7 @@ out:
        pr_err("msg_new can't create type %d front %d\n", type, front_len);
        return NULL;
 }
+EXPORT_SYMBOL(ceph_msg_new);
 
 /*
  * Allocate "middle" portion of a message, if it is needed and wasn't
@@ -2250,11 +2422,14 @@ void ceph_msg_last_put(struct kref *kref)
                m->pagelist = NULL;
        }
 
+       m->trail = NULL;
+
        if (m->pool)
                ceph_msgpool_put(m->pool, m);
        else
                ceph_msg_kfree(m);
 }
+EXPORT_SYMBOL(ceph_msg_last_put);
 
 void ceph_msg_dump(struct ceph_msg *msg)
 {
@@ -2275,3 +2450,4 @@ void ceph_msg_dump(struct ceph_msg *msg)
                       DUMP_PREFIX_OFFSET, 16, 1,
                       &msg->footer, sizeof(msg->footer), true);
 }
+EXPORT_SYMBOL(ceph_msg_dump);
similarity index 94%
rename from fs/ceph/mon_client.c
rename to net/ceph/mon_client.c
index b2a5a3e4a671c336fc7495d473792ddc25f71110..8a079399174a27fc0c86e50e0891318cbb33cf97 100644 (file)
@@ -1,14 +1,16 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/sched.h>
 
-#include "mon_client.h"
-#include "super.h"
-#include "auth.h"
-#include "decode.h"
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/decode.h>
+
+#include <linux/ceph/auth.h>
 
 /*
  * Interact with Ceph monitor cluster.  Handle requests for new map
@@ -74,7 +76,7 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
             m->num_mon);
        for (i = 0; i < m->num_mon; i++)
                dout("monmap_decode  mon%d is %s\n", i,
-                    pr_addr(&m->mon_inst[i].addr.in_addr));
+                    ceph_pr_addr(&m->mon_inst[i].addr.in_addr));
        return m;
 
 bad:
@@ -191,30 +193,33 @@ static void __send_subscribe(struct ceph_mon_client *monc)
                struct ceph_msg *msg = monc->m_subscribe;
                struct ceph_mon_subscribe_item *i;
                void *p, *end;
+               int num;
 
                p = msg->front.iov_base;
                end = p + msg->front_max;
 
-               dout("__send_subscribe to 'mdsmap' %u+\n",
-                    (unsigned)monc->have_mdsmap);
+               num = 1 + !!monc->want_next_osdmap + !!monc->want_mdsmap;
+               ceph_encode_32(&p, num);
+
                if (monc->want_next_osdmap) {
                        dout("__send_subscribe to 'osdmap' %u\n",
                             (unsigned)monc->have_osdmap);
-                       ceph_encode_32(&p, 3);
                        ceph_encode_string(&p, end, "osdmap", 6);
                        i = p;
                        i->have = cpu_to_le64(monc->have_osdmap);
                        i->onetime = 1;
                        p += sizeof(*i);
                        monc->want_next_osdmap = 2;  /* requested */
-               } else {
-                       ceph_encode_32(&p, 2);
                }
-               ceph_encode_string(&p, end, "mdsmap", 6);
-               i = p;
-               i->have = cpu_to_le64(monc->have_mdsmap);
-               i->onetime = 0;
-               p += sizeof(*i);
+               if (monc->want_mdsmap) {
+                       dout("__send_subscribe to 'mdsmap' %u+\n",
+                            (unsigned)monc->have_mdsmap);
+                       ceph_encode_string(&p, end, "mdsmap", 6);
+                       i = p;
+                       i->have = cpu_to_le64(monc->have_mdsmap);
+                       i->onetime = 0;
+                       p += sizeof(*i);
+               }
                ceph_encode_string(&p, end, "monmap", 6);
                i = p;
                i->have = 0;
@@ -243,7 +248,8 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc,
        mutex_lock(&monc->mutex);
        if (monc->hunting) {
                pr_info("mon%d %s session established\n",
-                       monc->cur_mon, pr_addr(&monc->con->peer_addr.in_addr));
+                       monc->cur_mon,
+                       ceph_pr_addr(&monc->con->peer_addr.in_addr));
                monc->hunting = false;
        }
        dout("handle_subscribe_ack after %d seconds\n", seconds);
@@ -266,6 +272,7 @@ int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got)
        mutex_unlock(&monc->mutex);
        return 0;
 }
+EXPORT_SYMBOL(ceph_monc_got_mdsmap);
 
 int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 got)
 {
@@ -310,6 +317,7 @@ int ceph_monc_open_session(struct ceph_mon_client *monc)
        mutex_unlock(&monc->mutex);
        return 0;
 }
+EXPORT_SYMBOL(ceph_monc_open_session);
 
 /*
  * The monitor responds with mount ack indicate mount success.  The
@@ -540,6 +548,7 @@ out:
        kref_put(&req->kref, release_generic_request);
        return err;
 }
+EXPORT_SYMBOL(ceph_monc_do_statfs);
 
 /*
  * pool ops
@@ -651,6 +660,7 @@ int ceph_monc_create_snapid(struct ceph_mon_client *monc,
                                   pool, 0, (char *)snapid, sizeof(*snapid));
 
 }
+EXPORT_SYMBOL(ceph_monc_create_snapid);
 
 int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
                            u32 pool, u64 snapid)
@@ -708,9 +718,9 @@ static void delayed_work(struct work_struct *work)
  */
 static int build_initial_monmap(struct ceph_mon_client *monc)
 {
-       struct ceph_mount_args *args = monc->client->mount_args;
-       struct ceph_entity_addr *mon_addr = args->mon_addr;
-       int num_mon = args->num_mon;
+       struct ceph_options *opt = monc->client->options;
+       struct ceph_entity_addr *mon_addr = opt->mon_addr;
+       int num_mon = opt->num_mon;
        int i;
 
        /* build initial monmap */
@@ -728,11 +738,6 @@ static int build_initial_monmap(struct ceph_mon_client *monc)
        }
        monc->monmap->num_mon = num_mon;
        monc->have_fsid = false;
-
-       /* release addr memory */
-       kfree(args->mon_addr);
-       args->mon_addr = NULL;
-       args->num_mon = 0;
        return 0;
 }
 
@@ -753,8 +758,8 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
        monc->con = NULL;
 
        /* authentication */
-       monc->auth = ceph_auth_init(cl->mount_args->name,
-                                   cl->mount_args->secret);
+       monc->auth = ceph_auth_init(cl->options->name,
+                                   cl->options->secret);
        if (IS_ERR(monc->auth))
                return PTR_ERR(monc->auth);
        monc->auth->want_keys =
@@ -808,6 +813,7 @@ out_monmap:
 out:
        return err;
 }
+EXPORT_SYMBOL(ceph_monc_init);
 
 void ceph_monc_stop(struct ceph_mon_client *monc)
 {
@@ -832,6 +838,7 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
 
        kfree(monc->monmap);
 }
+EXPORT_SYMBOL(ceph_monc_stop);
 
 static void handle_auth_reply(struct ceph_mon_client *monc,
                              struct ceph_msg *msg)
@@ -889,6 +896,7 @@ int ceph_monc_validate_auth(struct ceph_mon_client *monc)
        mutex_unlock(&monc->mutex);
        return ret;
 }
+EXPORT_SYMBOL(ceph_monc_validate_auth);
 
 /*
  * handle incoming message
@@ -922,15 +930,16 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
                ceph_monc_handle_map(monc, msg);
                break;
 
-       case CEPH_MSG_MDS_MAP:
-               ceph_mdsc_handle_map(&monc->client->mdsc, msg);
-               break;
-
        case CEPH_MSG_OSD_MAP:
                ceph_osdc_handle_map(&monc->client->osdc, msg);
                break;
 
        default:
+               /* can the chained handler handle it? */
+               if (monc->client->extra_mon_dispatch &&
+                   monc->client->extra_mon_dispatch(monc->client, msg) == 0)
+                       break;
+                       
                pr_err("received unknown message type %d %s\n", type,
                       ceph_msg_type_name(type));
        }
@@ -994,7 +1003,7 @@ static void mon_fault(struct ceph_connection *con)
        if (monc->con && !monc->hunting)
                pr_info("mon%d %s session lost, "
                        "hunting for new mon\n", monc->cur_mon,
-                       pr_addr(&monc->con->peer_addr.in_addr));
+                       ceph_pr_addr(&monc->con->peer_addr.in_addr));
 
        __close_session(monc);
        if (!monc->hunting) {
similarity index 95%
rename from fs/ceph/msgpool.c
rename to net/ceph/msgpool.c
index dd65a6438131c5f08cbe97085b6b1ba3f671076d..d5f2d97ac05caf40124fe4f628efe77a514d8e55 100644 (file)
@@ -1,11 +1,11 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 
-#include "msgpool.h"
+#include <linux/ceph/msgpool.h>
 
 static void *alloc_fn(gfp_t gfp_mask, void *arg)
 {
similarity index 84%
rename from fs/ceph/osd_client.c
rename to net/ceph/osd_client.c
index bed6391e52c7109c966d5e642e472c665bd7d1f5..79391994b3edee7d531b823c0720262090db6618 100644 (file)
@@ -1,17 +1,22 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#ifdef CONFIG_BLOCK
+#include <linux/bio.h>
+#endif
 
-#include "super.h"
-#include "osd_client.h"
-#include "messenger.h"
-#include "decode.h"
-#include "auth.h"
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osd_client.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/pagelist.h>
 
 #define OSD_OP_FRONT_LEN       4096
 #define OSD_OPREPLY_FRONT_LEN  512
@@ -22,6 +27,59 @@ static int __kick_requests(struct ceph_osd_client *osdc,
 
 static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd);
 
+static int op_needs_trail(int op)
+{
+       switch (op) {
+       case CEPH_OSD_OP_GETXATTR:
+       case CEPH_OSD_OP_SETXATTR:
+       case CEPH_OSD_OP_CMPXATTR:
+       case CEPH_OSD_OP_CALL:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int op_has_extent(int op)
+{
+       return (op == CEPH_OSD_OP_READ ||
+               op == CEPH_OSD_OP_WRITE);
+}
+
+void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+                       struct ceph_file_layout *layout,
+                       u64 snapid,
+                       u64 off, u64 *plen, u64 *bno,
+                       struct ceph_osd_request *req,
+                       struct ceph_osd_req_op *op)
+{
+       struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
+       u64 orig_len = *plen;
+       u64 objoff, objlen;    /* extent in object */
+
+       reqhead->snapid = cpu_to_le64(snapid);
+
+       /* object extent? */
+       ceph_calc_file_object_mapping(layout, off, plen, bno,
+                                     &objoff, &objlen);
+       if (*plen < orig_len)
+               dout(" skipping last %llu, final file extent %llu~%llu\n",
+                    orig_len - *plen, off, *plen);
+
+       if (op_has_extent(op->op)) {
+               op->extent.offset = objoff;
+               op->extent.length = objlen;
+       }
+       req->r_num_pages = calc_pages_for(off, *plen);
+       if (op->op == CEPH_OSD_OP_WRITE)
+               op->payload_len = *plen;
+
+       dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
+            *bno, objoff, objlen, req->r_num_pages);
+
+}
+EXPORT_SYMBOL(ceph_calc_raw_layout);
+
 /*
  * Implement client access to distributed object storage cluster.
  *
@@ -48,34 +106,19 @@ static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd);
  * fill osd op in request message.
  */
 static void calc_layout(struct ceph_osd_client *osdc,
-                       struct ceph_vino vino, struct ceph_file_layout *layout,
+                       struct ceph_vino vino,
+                       struct ceph_file_layout *layout,
                        u64 off, u64 *plen,
-                       struct ceph_osd_request *req)
+                       struct ceph_osd_request *req,
+                       struct ceph_osd_req_op *op)
 {
-       struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
-       struct ceph_osd_op *op = (void *)(reqhead + 1);
-       u64 orig_len = *plen;
-       u64 objoff, objlen;    /* extent in object */
        u64 bno;
 
-       reqhead->snapid = cpu_to_le64(vino.snap);
-
-       /* object extent? */
-       ceph_calc_file_object_mapping(layout, off, plen, &bno,
-                                     &objoff, &objlen);
-       if (*plen < orig_len)
-               dout(" skipping last %llu, final file extent %llu~%llu\n",
-                    orig_len - *plen, off, *plen);
+       ceph_calc_raw_layout(osdc, layout, vino.snap, off,
+                            plen, &bno, req, op);
 
        sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno);
        req->r_oid_len = strlen(req->r_oid);
-
-       op->extent.offset = cpu_to_le64(objoff);
-       op->extent.length = cpu_to_le64(objlen);
-       req->r_num_pages = calc_pages_for(off, *plen);
-
-       dout("calc_layout %s (%d) %llu~%llu (%d pages)\n",
-            req->r_oid, req->r_oid_len, objoff, objlen, req->r_num_pages);
 }
 
 /*
@@ -101,56 +144,66 @@ void ceph_osdc_release_request(struct kref *kref)
        if (req->r_own_pages)
                ceph_release_page_vector(req->r_pages,
                                         req->r_num_pages);
+#ifdef CONFIG_BLOCK
+       if (req->r_bio)
+               bio_put(req->r_bio);
+#endif
        ceph_put_snap_context(req->r_snapc);
+       if (req->r_trail) {
+               ceph_pagelist_release(req->r_trail);
+               kfree(req->r_trail);
+       }
        if (req->r_mempool)
                mempool_free(req, req->r_osdc->req_mempool);
        else
                kfree(req);
 }
+EXPORT_SYMBOL(ceph_osdc_release_request);
 
-/*
- * build new request AND message, calculate layout, and adjust file
- * extent as needed.
- *
- * if the file was recently truncated, we include information about its
- * old and new size so that the object can be updated appropriately.  (we
- * avoid synchronously deleting truncated objects because it's slow.)
- *
- * if @do_sync, include a 'startsync' command so that the osd will flush
- * data quickly.
- */
-struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
-                                              struct ceph_file_layout *layout,
-                                              struct ceph_vino vino,
-                                              u64 off, u64 *plen,
-                                              int opcode, int flags,
+static int get_num_ops(struct ceph_osd_req_op *ops, int *needs_trail)
+{
+       int i = 0;
+
+       if (needs_trail)
+               *needs_trail = 0;
+       while (ops[i].op) {
+               if (needs_trail && op_needs_trail(ops[i].op))
+                       *needs_trail = 1;
+               i++;
+       }
+
+       return i;
+}
+
+struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
+                                              int flags,
                                               struct ceph_snap_context *snapc,
-                                              int do_sync,
-                                              u32 truncate_seq,
-                                              u64 truncate_size,
-                                              struct timespec *mtime,
-                                              bool use_mempool, int num_reply)
+                                              struct ceph_osd_req_op *ops,
+                                              bool use_mempool,
+                                              gfp_t gfp_flags,
+                                              struct page **pages,
+                                              struct bio *bio)
 {
        struct ceph_osd_request *req;
        struct ceph_msg *msg;
-       struct ceph_osd_request_head *head;
-       struct ceph_osd_op *op;
-       void *p;
-       int num_op = 1 + do_sync;
-       size_t msg_size = sizeof(*head) + num_op*sizeof(*op);
-       int i;
+       int needs_trail;
+       int num_op = get_num_ops(ops, &needs_trail);
+       size_t msg_size = sizeof(struct ceph_osd_request_head);
+
+       msg_size += num_op*sizeof(struct ceph_osd_op);
 
        if (use_mempool) {
-               req = mempool_alloc(osdc->req_mempool, GFP_NOFS);
+               req = mempool_alloc(osdc->req_mempool, gfp_flags);
                memset(req, 0, sizeof(*req));
        } else {
-               req = kzalloc(sizeof(*req), GFP_NOFS);
+               req = kzalloc(sizeof(*req), gfp_flags);
        }
        if (req == NULL)
                return NULL;
 
        req->r_osdc = osdc;
        req->r_mempool = use_mempool;
+
        kref_init(&req->r_kref);
        init_completion(&req->r_completion);
        init_completion(&req->r_safe_completion);
@@ -164,13 +217,22 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
        else
                msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY,
-                                  OSD_OPREPLY_FRONT_LEN, GFP_NOFS);
+                                  OSD_OPREPLY_FRONT_LEN, gfp_flags);
        if (!msg) {
                ceph_osdc_put_request(req);
                return NULL;
        }
        req->r_reply = msg;
 
+       /* allocate space for the trailing data */
+       if (needs_trail) {
+               req->r_trail = kmalloc(sizeof(struct ceph_pagelist), gfp_flags);
+               if (!req->r_trail) {
+                       ceph_osdc_put_request(req);
+                       return NULL;
+               }
+               ceph_pagelist_init(req->r_trail);
+       }
        /* create request message; allow space for oid */
        msg_size += 40;
        if (snapc)
@@ -178,18 +240,115 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
        if (use_mempool)
                msg = ceph_msgpool_get(&osdc->msgpool_op, 0);
        else
-               msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, GFP_NOFS);
+               msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp_flags);
        if (!msg) {
                ceph_osdc_put_request(req);
                return NULL;
        }
+
        msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP);
        memset(msg->front.iov_base, 0, msg->front.iov_len);
+
+       req->r_request = msg;
+       req->r_pages = pages;
+#ifdef CONFIG_BLOCK
+       if (bio) {
+               req->r_bio = bio;
+               bio_get(req->r_bio);
+       }
+#endif
+
+       return req;
+}
+EXPORT_SYMBOL(ceph_osdc_alloc_request);
+
+static void osd_req_encode_op(struct ceph_osd_request *req,
+                             struct ceph_osd_op *dst,
+                             struct ceph_osd_req_op *src)
+{
+       dst->op = cpu_to_le16(src->op);
+
+       switch (dst->op) {
+       case CEPH_OSD_OP_READ:
+       case CEPH_OSD_OP_WRITE:
+               dst->extent.offset =
+                       cpu_to_le64(src->extent.offset);
+               dst->extent.length =
+                       cpu_to_le64(src->extent.length);
+               dst->extent.truncate_size =
+                       cpu_to_le64(src->extent.truncate_size);
+               dst->extent.truncate_seq =
+                       cpu_to_le32(src->extent.truncate_seq);
+               break;
+
+       case CEPH_OSD_OP_GETXATTR:
+       case CEPH_OSD_OP_SETXATTR:
+       case CEPH_OSD_OP_CMPXATTR:
+               BUG_ON(!req->r_trail);
+
+               dst->xattr.name_len = cpu_to_le32(src->xattr.name_len);
+               dst->xattr.value_len = cpu_to_le32(src->xattr.value_len);
+               dst->xattr.cmp_op = src->xattr.cmp_op;
+               dst->xattr.cmp_mode = src->xattr.cmp_mode;
+               ceph_pagelist_append(req->r_trail, src->xattr.name,
+                                    src->xattr.name_len);
+               ceph_pagelist_append(req->r_trail, src->xattr.val,
+                                    src->xattr.value_len);
+               break;
+       case CEPH_OSD_OP_CALL:
+               BUG_ON(!req->r_trail);
+
+               dst->cls.class_len = src->cls.class_len;
+               dst->cls.method_len = src->cls.method_len;
+               dst->cls.indata_len = cpu_to_le32(src->cls.indata_len);
+
+               ceph_pagelist_append(req->r_trail, src->cls.class_name,
+                                    src->cls.class_len);
+               ceph_pagelist_append(req->r_trail, src->cls.method_name,
+                                    src->cls.method_len);
+               ceph_pagelist_append(req->r_trail, src->cls.indata,
+                                    src->cls.indata_len);
+               break;
+       case CEPH_OSD_OP_ROLLBACK:
+               dst->snap.snapid = cpu_to_le64(src->snap.snapid);
+               break;
+       case CEPH_OSD_OP_STARTSYNC:
+               break;
+       default:
+               pr_err("unrecognized osd opcode %d\n", dst->op);
+               WARN_ON(1);
+               break;
+       }
+       dst->payload_len = cpu_to_le32(src->payload_len);
+}
+
+/*
+ * build new request AND message
+ *
+ */
+void ceph_osdc_build_request(struct ceph_osd_request *req,
+                            u64 off, u64 *plen,
+                            struct ceph_osd_req_op *src_ops,
+                            struct ceph_snap_context *snapc,
+                            struct timespec *mtime,
+                            const char *oid,
+                            int oid_len)
+{
+       struct ceph_msg *msg = req->r_request;
+       struct ceph_osd_request_head *head;
+       struct ceph_osd_req_op *src_op;
+       struct ceph_osd_op *op;
+       void *p;
+       int num_op = get_num_ops(src_ops, NULL);
+       size_t msg_size = sizeof(*head) + num_op*sizeof(*op);
+       int flags = req->r_flags;
+       u64 data_len = 0;
+       int i;
+
        head = msg->front.iov_base;
        op = (void *)(head + 1);
        p = (void *)(op + num_op);
 
-       req->r_request = msg;
        req->r_snapc = ceph_get_snap_context(snapc);
 
        head->client_inc = cpu_to_le32(1); /* always, for now. */
@@ -197,29 +356,23 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
        if (flags & CEPH_OSD_FLAG_WRITE)
                ceph_encode_timespec(&head->mtime, mtime);
        head->num_ops = cpu_to_le16(num_op);
-       op->op = cpu_to_le16(opcode);
 
-       /* calculate max write size */
-       calc_layout(osdc, vino, layout, off, plen, req);
-       req->r_file_layout = *layout;  /* keep a copy */
-
-       if (flags & CEPH_OSD_FLAG_WRITE) {
-               req->r_request->hdr.data_off = cpu_to_le16(off);
-               req->r_request->hdr.data_len = cpu_to_le32(*plen);
-               op->payload_len = cpu_to_le32(*plen);
-       }
-       op->extent.truncate_size = cpu_to_le64(truncate_size);
-       op->extent.truncate_seq = cpu_to_le32(truncate_seq);
 
        /* fill in oid */
-       head->object_len = cpu_to_le32(req->r_oid_len);
-       memcpy(p, req->r_oid, req->r_oid_len);
-       p += req->r_oid_len;
-
-       if (do_sync) {
+       head->object_len = cpu_to_le32(oid_len);
+       memcpy(p, oid, oid_len);
+       p += oid_len;
+
+       src_op = src_ops;
+       while (src_op->op) {
+               osd_req_encode_op(req, op, src_op);
+               src_op++;
                op++;
-               op->op = cpu_to_le16(CEPH_OSD_OP_STARTSYNC);
        }
+
+       if (req->r_trail)
+               data_len += req->r_trail->length;
+
        if (snapc) {
                head->snap_seq = cpu_to_le64(snapc->seq);
                head->num_snaps = cpu_to_le32(snapc->num_snaps);
@@ -229,12 +382,79 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                }
        }
 
+       if (flags & CEPH_OSD_FLAG_WRITE) {
+               req->r_request->hdr.data_off = cpu_to_le16(off);
+               req->r_request->hdr.data_len = cpu_to_le32(*plen + data_len);
+       } else if (data_len) {
+               req->r_request->hdr.data_off = 0;
+               req->r_request->hdr.data_len = cpu_to_le32(data_len);
+       }
+
        BUG_ON(p > msg->front.iov_base + msg->front.iov_len);
        msg_size = p - msg->front.iov_base;
        msg->front.iov_len = msg_size;
        msg->hdr.front_len = cpu_to_le32(msg_size);
+       return;
+}
+EXPORT_SYMBOL(ceph_osdc_build_request);
+
+/*
+ * build new request AND message, calculate layout, and adjust file
+ * extent as needed.
+ *
+ * if the file was recently truncated, we include information about its
+ * old and new size so that the object can be updated appropriately.  (we
+ * avoid synchronously deleting truncated objects because it's slow.)
+ *
+ * if @do_sync, include a 'startsync' command so that the osd will flush
+ * data quickly.
+ */
+struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
+                                              struct ceph_file_layout *layout,
+                                              struct ceph_vino vino,
+                                              u64 off, u64 *plen,
+                                              int opcode, int flags,
+                                              struct ceph_snap_context *snapc,
+                                              int do_sync,
+                                              u32 truncate_seq,
+                                              u64 truncate_size,
+                                              struct timespec *mtime,
+                                              bool use_mempool, int num_reply)
+{
+       struct ceph_osd_req_op ops[3];
+       struct ceph_osd_request *req;
+
+       ops[0].op = opcode;
+       ops[0].extent.truncate_seq = truncate_seq;
+       ops[0].extent.truncate_size = truncate_size;
+       ops[0].payload_len = 0;
+
+       if (do_sync) {
+               ops[1].op = CEPH_OSD_OP_STARTSYNC;
+               ops[1].payload_len = 0;
+               ops[2].op = 0;
+       } else
+               ops[1].op = 0;
+
+       req = ceph_osdc_alloc_request(osdc, flags,
+                                        snapc, ops,
+                                        use_mempool,
+                                        GFP_NOFS, NULL, NULL);
+       if (IS_ERR(req))
+               return req;
+
+       /* calculate max write size */
+       calc_layout(osdc, vino, layout, off, plen, req, ops);
+       req->r_file_layout = *layout;  /* keep a copy */
+
+       ceph_osdc_build_request(req, off, plen, ops,
+                               snapc,
+                               mtime,
+                               req->r_oid, req->r_oid_len);
+
        return req;
 }
+EXPORT_SYMBOL(ceph_osdc_new_request);
 
 /*
  * We keep osd requests in an rbtree, sorted by ->r_tid.
@@ -389,7 +609,7 @@ static void __move_osd_to_lru(struct ceph_osd_client *osdc,
        dout("__move_osd_to_lru %p\n", osd);
        BUG_ON(!list_empty(&osd->o_osd_lru));
        list_add_tail(&osd->o_osd_lru, &osdc->osd_lru);
-       osd->lru_ttl = jiffies + osdc->client->mount_args->osd_idle_ttl * HZ;
+       osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl * HZ;
 }
 
 static void __remove_osd_from_lru(struct ceph_osd *osd)
@@ -483,7 +703,7 @@ static struct ceph_osd *__lookup_osd(struct ceph_osd_client *osdc, int o)
 static void __schedule_osd_timeout(struct ceph_osd_client *osdc)
 {
        schedule_delayed_work(&osdc->timeout_work,
-                       osdc->client->mount_args->osd_keepalive_timeout * HZ);
+                       osdc->client->options->osd_keepalive_timeout * HZ);
 }
 
 static void __cancel_osd_timeout(struct ceph_osd_client *osdc)
@@ -549,7 +769,7 @@ static void __unregister_request(struct ceph_osd_client *osdc,
  */
 static void __cancel_request(struct ceph_osd_request *req)
 {
-       if (req->r_sent) {
+       if (req->r_sent && req->r_osd) {
                ceph_con_revoke(&req->r_osd->o_con, req->r_request);
                req->r_sent = 0;
        }
@@ -661,7 +881,7 @@ static int __send_request(struct ceph_osd_client *osdc,
        reqhead->reassert_version = req->r_reassert_version;
 
        req->r_stamp = jiffies;
-       list_move_tail(&osdc->req_lru, &req->r_req_lru_item);
+       list_move_tail(&req->r_req_lru_item, &osdc->req_lru);
 
        ceph_msg_get(req->r_request); /* send consumes a ref */
        ceph_con_send(&req->r_osd->o_con, req->r_request);
@@ -684,9 +904,9 @@ static void handle_timeout(struct work_struct *work)
                container_of(work, struct ceph_osd_client, timeout_work.work);
        struct ceph_osd_request *req, *last_req = NULL;
        struct ceph_osd *osd;
-       unsigned long timeout = osdc->client->mount_args->osd_timeout * HZ;
+       unsigned long timeout = osdc->client->options->osd_timeout * HZ;
        unsigned long keepalive =
-               osdc->client->mount_args->osd_keepalive_timeout * HZ;
+               osdc->client->options->osd_keepalive_timeout * HZ;
        unsigned long last_stamp = 0;
        struct rb_node *p;
        struct list_head slow_osds;
@@ -773,7 +993,7 @@ static void handle_osds_timeout(struct work_struct *work)
                container_of(work, struct ceph_osd_client,
                             osds_timeout_work.work);
        unsigned long delay =
-               osdc->client->mount_args->osd_idle_ttl * HZ >> 2;
+               osdc->client->options->osd_idle_ttl * HZ >> 2;
 
        dout("osds timeout\n");
        down_read(&osdc->map_sem);
@@ -1104,6 +1324,10 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
 
        req->r_request->pages = req->r_pages;
        req->r_request->nr_pages = req->r_num_pages;
+#ifdef CONFIG_BLOCK
+       req->r_request->bio = req->r_bio;
+#endif
+       req->r_request->trail = req->r_trail;
 
        register_request(osdc, req);
 
@@ -1131,6 +1355,7 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
        up_read(&osdc->map_sem);
        return rc;
 }
+EXPORT_SYMBOL(ceph_osdc_start_request);
 
 /*
  * wait for a request to complete
@@ -1153,6 +1378,7 @@ int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
        dout("wait_request tid %llu result %d\n", req->r_tid, req->r_result);
        return req->r_result;
 }
+EXPORT_SYMBOL(ceph_osdc_wait_request);
 
 /*
  * sync - wait for all in-flight requests to flush.  avoid starvation.
@@ -1186,6 +1412,7 @@ void ceph_osdc_sync(struct ceph_osd_client *osdc)
        mutex_unlock(&osdc->request_mutex);
        dout("sync done (thru tid %llu)\n", last_tid);
 }
+EXPORT_SYMBOL(ceph_osdc_sync);
 
 /*
  * init, shutdown
@@ -1211,7 +1438,7 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
        INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout);
 
        schedule_delayed_work(&osdc->osds_timeout_work,
-          round_jiffies_relative(osdc->client->mount_args->osd_idle_ttl * HZ));
+          round_jiffies_relative(osdc->client->options->osd_idle_ttl * HZ));
 
        err = -ENOMEM;
        osdc->req_mempool = mempool_create_kmalloc_pool(10,
@@ -1237,6 +1464,7 @@ out_mempool:
 out:
        return err;
 }
+EXPORT_SYMBOL(ceph_osdc_init);
 
 void ceph_osdc_stop(struct ceph_osd_client *osdc)
 {
@@ -1251,6 +1479,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
        ceph_msgpool_destroy(&osdc->msgpool_op);
        ceph_msgpool_destroy(&osdc->msgpool_op_reply);
 }
+EXPORT_SYMBOL(ceph_osdc_stop);
 
 /*
  * Read some contiguous pages.  If we cross a stripe boundary, shorten
@@ -1288,6 +1517,7 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc,
        dout("readpages result %d\n", rc);
        return rc;
 }
+EXPORT_SYMBOL(ceph_osdc_readpages);
 
 /*
  * do a synchronous write on N pages
@@ -1330,6 +1560,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
        dout("writepages result %d\n", rc);
        return rc;
 }
+EXPORT_SYMBOL(ceph_osdc_writepages);
 
 /*
  * handle incoming message
@@ -1420,6 +1651,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
                }
                m->pages = req->r_pages;
                m->nr_pages = req->r_num_pages;
+#ifdef CONFIG_BLOCK
+               m->bio = req->r_bio;
+#endif
        }
        *skip = 0;
        req->r_con_filling_msg = ceph_con_get(con);
similarity index 97%
rename from fs/ceph/osdmap.c
rename to net/ceph/osdmap.c
index e31f118f1392988351257d2385863c37228bc7df..d73f3f6efa36ff6cf9efc33cada1853afa8073e7 100644 (file)
@@ -1,14 +1,15 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/div64.h>
 
-#include "super.h"
-#include "osdmap.h"
-#include "crush/hash.h"
-#include "crush/mapper.h"
-#include "decode.h"
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osdmap.h>
+#include <linux/ceph/decode.h>
+#include <linux/crush/hash.h>
+#include <linux/crush/mapper.h>
 
 char *ceph_osdmap_state_str(char *str, int len, int state)
 {
@@ -417,6 +418,20 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id)
        return NULL;
 }
 
+int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name)
+{
+       struct rb_node *rbp;
+
+       for (rbp = rb_first(&map->pg_pools); rbp; rbp = rb_next(rbp)) {
+               struct ceph_pg_pool_info *pi =
+                       rb_entry(rbp, struct ceph_pg_pool_info, node);
+               if (pi->name && strcmp(pi->name, name) == 0)
+                       return pi->id;
+       }
+       return -ENOENT;
+}
+EXPORT_SYMBOL(ceph_pg_poolid_by_name);
+
 static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi)
 {
        rb_erase(&pi->node, root);
@@ -966,6 +981,7 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
 
        dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
 }
+EXPORT_SYMBOL(ceph_calc_file_object_mapping);
 
 /*
  * calculate an object layout (i.e. pgid) from an oid,
@@ -1011,6 +1027,7 @@ int ceph_calc_object_layout(struct ceph_object_layout *ol,
        ol->ol_stripe_unit = fl->fl_object_stripe_unit;
        return 0;
 }
+EXPORT_SYMBOL(ceph_calc_object_layout);
 
 /*
  * Calculate raw osd vector for the given pgid.  Return pointer to osd
@@ -1108,3 +1125,4 @@ int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid)
                        return osds[i];
        return -1;
 }
+EXPORT_SYMBOL(ceph_calc_pg_primary);
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
new file mode 100644 (file)
index 0000000..13cb409
--- /dev/null
@@ -0,0 +1,154 @@
+
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/ceph/pagelist.h>
+
+static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
+{
+       if (pl->mapped_tail) {
+               struct page *page = list_entry(pl->head.prev, struct page, lru);
+               kunmap(page);
+               pl->mapped_tail = NULL;
+       }
+}
+
+int ceph_pagelist_release(struct ceph_pagelist *pl)
+{
+       ceph_pagelist_unmap_tail(pl);
+       while (!list_empty(&pl->head)) {
+               struct page *page = list_first_entry(&pl->head, struct page,
+                                                    lru);
+               list_del(&page->lru);
+               __free_page(page);
+       }
+       ceph_pagelist_free_reserve(pl);
+       return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_release);
+
+static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
+{
+       struct page *page;
+
+       if (!pl->num_pages_free) {
+               page = __page_cache_alloc(GFP_NOFS);
+       } else {
+               page = list_first_entry(&pl->free_list, struct page, lru);
+               list_del(&page->lru);
+               --pl->num_pages_free;
+       }
+       if (!page)
+               return -ENOMEM;
+       pl->room += PAGE_SIZE;
+       ceph_pagelist_unmap_tail(pl);
+       list_add_tail(&page->lru, &pl->head);
+       pl->mapped_tail = kmap(page);
+       return 0;
+}
+
+int ceph_pagelist_append(struct ceph_pagelist *pl, const void *buf, size_t len)
+{
+       while (pl->room < len) {
+               size_t bit = pl->room;
+               int ret;
+
+               memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
+                      buf, bit);
+               pl->length += bit;
+               pl->room -= bit;
+               buf += bit;
+               len -= bit;
+               ret = ceph_pagelist_addpage(pl);
+               if (ret)
+                       return ret;
+       }
+
+       memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
+       pl->length += len;
+       pl->room -= len;
+       return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_append);
+
+/**
+ * Allocate enough pages for a pagelist to append the given amount
+ * of data without without allocating.
+ * Returns: 0 on success, -ENOMEM on error.
+ */
+int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space)
+{
+       if (space <= pl->room)
+               return 0;
+       space -= pl->room;
+       space = (space + PAGE_SIZE - 1) >> PAGE_SHIFT;   /* conv to num pages */
+
+       while (space > pl->num_pages_free) {
+               struct page *page = __page_cache_alloc(GFP_NOFS);
+               if (!page)
+                       return -ENOMEM;
+               list_add_tail(&page->lru, &pl->free_list);
+               ++pl->num_pages_free;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_reserve);
+
+/**
+ * Free any pages that have been preallocated.
+ */
+int ceph_pagelist_free_reserve(struct ceph_pagelist *pl)
+{
+       while (!list_empty(&pl->free_list)) {
+               struct page *page = list_first_entry(&pl->free_list,
+                                                    struct page, lru);
+               list_del(&page->lru);
+               __free_page(page);
+               --pl->num_pages_free;
+       }
+       BUG_ON(pl->num_pages_free);
+       return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_free_reserve);
+
+/**
+ * Create a truncation point.
+ */
+void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
+                             struct ceph_pagelist_cursor *c)
+{
+       c->pl = pl;
+       c->page_lru = pl->head.prev;
+       c->room = pl->room;
+}
+EXPORT_SYMBOL(ceph_pagelist_set_cursor);
+
+/**
+ * Truncate a pagelist to the given point. Move extra pages to reserve.
+ * This won't sleep.
+ * Returns: 0 on success,
+ *          -EINVAL if the pagelist doesn't match the trunc point pagelist
+ */
+int ceph_pagelist_truncate(struct ceph_pagelist *pl,
+                          struct ceph_pagelist_cursor *c)
+{
+       struct page *page;
+
+       if (pl != c->pl)
+               return -EINVAL;
+       ceph_pagelist_unmap_tail(pl);
+       while (pl->head.prev != c->page_lru) {
+               page = list_entry(pl->head.prev, struct page, lru);
+               list_del(&page->lru);                /* remove from pagelist */
+               list_add_tail(&page->lru, &pl->free_list); /* add to reserve */
+               ++pl->num_pages_free;
+       }
+       pl->room = c->room;
+       if (!list_empty(&pl->head)) {
+               page = list_entry(pl->head.prev, struct page, lru);
+               pl->mapped_tail = kmap(page);
+       }
+       return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_truncate);
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
new file mode 100644 (file)
index 0000000..54caf06
--- /dev/null
@@ -0,0 +1,223 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/writeback.h>
+
+#include <linux/ceph/libceph.h>
+
+/*
+ * build a vector of user pages
+ */
+struct page **ceph_get_direct_page_vector(const char __user *data,
+                                                int num_pages,
+                                                loff_t off, size_t len)
+{
+       struct page **pages;
+       int rc;
+
+       pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);
+       if (!pages)
+               return ERR_PTR(-ENOMEM);
+
+       down_read(&current->mm->mmap_sem);
+       rc = get_user_pages(current, current->mm, (unsigned long)data,
+                           num_pages, 0, 0, pages, NULL);
+       up_read(&current->mm->mmap_sem);
+       if (rc < 0)
+               goto fail;
+       return pages;
+
+fail:
+       kfree(pages);
+       return ERR_PTR(rc);
+}
+EXPORT_SYMBOL(ceph_get_direct_page_vector);
+
+void ceph_put_page_vector(struct page **pages, int num_pages)
+{
+       int i;
+
+       for (i = 0; i < num_pages; i++)
+               put_page(pages[i]);
+       kfree(pages);
+}
+EXPORT_SYMBOL(ceph_put_page_vector);
+
+void ceph_release_page_vector(struct page **pages, int num_pages)
+{
+       int i;
+
+       for (i = 0; i < num_pages; i++)
+               __free_pages(pages[i], 0);
+       kfree(pages);
+}
+EXPORT_SYMBOL(ceph_release_page_vector);
+
+/*
+ * allocate a vector new pages
+ */
+struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
+{
+       struct page **pages;
+       int i;
+
+       pages = kmalloc(sizeof(*pages) * num_pages, flags);
+       if (!pages)
+               return ERR_PTR(-ENOMEM);
+       for (i = 0; i < num_pages; i++) {
+               pages[i] = __page_cache_alloc(flags);
+               if (pages[i] == NULL) {
+                       ceph_release_page_vector(pages, i);
+                       return ERR_PTR(-ENOMEM);
+               }
+       }
+       return pages;
+}
+EXPORT_SYMBOL(ceph_alloc_page_vector);
+
+/*
+ * copy user data into a page vector
+ */
+int ceph_copy_user_to_page_vector(struct page **pages,
+                                        const char __user *data,
+                                        loff_t off, size_t len)
+{
+       int i = 0;
+       int po = off & ~PAGE_CACHE_MASK;
+       int left = len;
+       int l, bad;
+
+       while (left > 0) {
+               l = min_t(int, PAGE_CACHE_SIZE-po, left);
+               bad = copy_from_user(page_address(pages[i]) + po, data, l);
+               if (bad == l)
+                       return -EFAULT;
+               data += l - bad;
+               left -= l - bad;
+               po += l - bad;
+               if (po == PAGE_CACHE_SIZE) {
+                       po = 0;
+                       i++;
+               }
+       }
+       return len;
+}
+EXPORT_SYMBOL(ceph_copy_user_to_page_vector);
+
+int ceph_copy_to_page_vector(struct page **pages,
+                                   const char *data,
+                                   loff_t off, size_t len)
+{
+       int i = 0;
+       size_t po = off & ~PAGE_CACHE_MASK;
+       size_t left = len;
+       size_t l;
+
+       while (left > 0) {
+               l = min_t(size_t, PAGE_CACHE_SIZE-po, left);
+               memcpy(page_address(pages[i]) + po, data, l);
+               data += l;
+               left -= l;
+               po += l;
+               if (po == PAGE_CACHE_SIZE) {
+                       po = 0;
+                       i++;
+               }
+       }
+       return len;
+}
+EXPORT_SYMBOL(ceph_copy_to_page_vector);
+
+int ceph_copy_from_page_vector(struct page **pages,
+                                   char *data,
+                                   loff_t off, size_t len)
+{
+       int i = 0;
+       size_t po = off & ~PAGE_CACHE_MASK;
+       size_t left = len;
+       size_t l;
+
+       while (left > 0) {
+               l = min_t(size_t, PAGE_CACHE_SIZE-po, left);
+               memcpy(data, page_address(pages[i]) + po, l);
+               data += l;
+               left -= l;
+               po += l;
+               if (po == PAGE_CACHE_SIZE) {
+                       po = 0;
+                       i++;
+               }
+       }
+       return len;
+}
+EXPORT_SYMBOL(ceph_copy_from_page_vector);
+
+/*
+ * copy user data from a page vector into a user pointer
+ */
+int ceph_copy_page_vector_to_user(struct page **pages,
+                                        char __user *data,
+                                        loff_t off, size_t len)
+{
+       int i = 0;
+       int po = off & ~PAGE_CACHE_MASK;
+       int left = len;
+       int l, bad;
+
+       while (left > 0) {
+               l = min_t(int, left, PAGE_CACHE_SIZE-po);
+               bad = copy_to_user(data, page_address(pages[i]) + po, l);
+               if (bad == l)
+                       return -EFAULT;
+               data += l - bad;
+               left -= l - bad;
+               if (po) {
+                       po += l - bad;
+                       if (po == PAGE_CACHE_SIZE)
+                               po = 0;
+               }
+               i++;
+       }
+       return len;
+}
+EXPORT_SYMBOL(ceph_copy_page_vector_to_user);
+
+/*
+ * Zero an extent within a page vector.  Offset is relative to the
+ * start of the first page.
+ */
+void ceph_zero_page_vector_range(int off, int len, struct page **pages)
+{
+       int i = off >> PAGE_CACHE_SHIFT;
+
+       off &= ~PAGE_CACHE_MASK;
+
+       dout("zero_page_vector_page %u~%u\n", off, len);
+
+       /* leading partial page? */
+       if (off) {
+               int end = min((int)PAGE_CACHE_SIZE, off + len);
+               dout("zeroing %d %p head from %d\n", i, pages[i],
+                    (int)off);
+               zero_user_segment(pages[i], off, end);
+               len -= (end - off);
+               i++;
+       }
+       while (len >= PAGE_CACHE_SIZE) {
+               dout("zeroing %d %p len=%d\n", i, pages[i], len);
+               zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
+               len -= PAGE_CACHE_SIZE;
+               i++;
+       }
+       /* trailing partial page? */
+       if (len) {
+               dout("zeroing %d %p tail to %d\n", i, pages[i], (int)len);
+               zero_user_segment(pages[i], 0, len);
+       }
+}
+EXPORT_SYMBOL(ceph_zero_page_vector_range);
+
index 251997a9548362c5ebc8a0a34842971a0198539a..282806ba7a57e60991f2f7806bc3015d9b8596a5 100644 (file)
@@ -243,6 +243,7 @@ void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
        unlock_sock_fast(sk, slow);
 
        /* skb is now orphaned, can be freed outside of locked section */
+       trace_kfree_skb(skb, skb_free_datagram_locked);
        __kfree_skb(skb);
 }
 EXPORT_SYMBOL(skb_free_datagram_locked);
index 3721fbb9a83c3c7761c05ae39d8acab21b6f6b66..7ec85e27beed840b8da5f9dae620bcd48453f3f7 100644 (file)
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <trace/events/napi.h>
+#include <trace/events/net.h>
+#include <trace/events/skb.h>
 #include <linux/pci.h>
 
 #include "net-sysfs.h"
@@ -1978,6 +1980,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                }
 
                rc = ops->ndo_start_xmit(skb, dev);
+               trace_net_dev_xmit(skb, rc);
                if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
@@ -1998,6 +2001,7 @@ gso:
                        skb_dst_drop(nskb);
 
                rc = ops->ndo_start_xmit(nskb, dev);
+               trace_net_dev_xmit(nskb, rc);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
                                goto out_kfree_gso_skb;
@@ -2058,16 +2062,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
                                        struct sk_buff *skb)
 {
        int queue_index;
-       struct sock *sk = skb->sk;
+       const struct net_device_ops *ops = dev->netdev_ops;
 
-       queue_index = sk_tx_queue_get(sk);
-       if (queue_index < 0) {
-               const struct net_device_ops *ops = dev->netdev_ops;
+       if (ops->ndo_select_queue) {
+               queue_index = ops->ndo_select_queue(dev, skb);
+               queue_index = dev_cap_txqueue(dev, queue_index);
+       } else {
+               struct sock *sk = skb->sk;
+               queue_index = sk_tx_queue_get(sk);
+               if (queue_index < 0) {
 
-               if (ops->ndo_select_queue) {
-                       queue_index = ops->ndo_select_queue(dev, skb);
-                       queue_index = dev_cap_txqueue(dev, queue_index);
-               } else {
                        queue_index = 0;
                        if (dev->real_num_tx_queues > 1)
                                queue_index = skb_tx_hash(dev, skb);
@@ -2186,6 +2190,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 #ifdef CONFIG_NET_CLS_ACT
        skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
 #endif
+       trace_net_dev_queue(skb);
        if (q->enqueue) {
                rc = __dev_xmit_skb(skb, q, dev, txq);
                goto out;
@@ -2512,6 +2517,7 @@ int netif_rx(struct sk_buff *skb)
        if (netdev_tstamp_prequeue)
                net_timestamp_check(skb);
 
+       trace_netif_rx(skb);
 #ifdef CONFIG_RPS
        {
                struct rps_dev_flow voidflow, *rflow = &voidflow;
@@ -2571,6 +2577,7 @@ static void net_tx_action(struct softirq_action *h)
                        clist = clist->next;
 
                        WARN_ON(atomic_read(&skb->users));
+                       trace_kfree_skb(skb, net_tx_action);
                        __kfree_skb(skb);
                }
        }
@@ -2828,6 +2835,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
        if (!netdev_tstamp_prequeue)
                net_timestamp_check(skb);
 
+       trace_netif_receive_skb(skb);
        if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
                return NET_RX_SUCCESS;
 
@@ -4845,7 +4853,7 @@ static void rollback_registered_many(struct list_head *head)
        dev = list_first_entry(head, struct net_device, unreg_list);
        call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
 
-       synchronize_net();
+       rcu_barrier();
 
        list_for_each_entry(dev, head, unreg_list)
                dev_put(dev);
index 7a85367b3c2f8010af24bbd6b6f4249698f9d78d..8451ab481095fc523c47fa01ccb11392b15dbc30 100644 (file)
@@ -348,7 +348,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
        if (info.cmd == ETHTOOL_GRXCLSRLALL) {
                if (info.rule_cnt > 0) {
                        if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
-                               rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
+                               rule_buf = kzalloc(info.rule_cnt * sizeof(u32),
                                                   GFP_USER);
                        if (!rule_buf)
                                return -ENOMEM;
@@ -397,7 +397,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
            (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
                return -ENOMEM;
        full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
-       indir = kmalloc(full_size, GFP_USER);
+       indir = kzalloc(full_size, GFP_USER);
        if (!indir)
                return -ENOMEM;
 
@@ -538,7 +538,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
 
        gstrings.len = ret;
 
-       data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+       data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
        if (!data)
                return -ENOMEM;
 
@@ -775,7 +775,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
        if (regs.len > reglen)
                regs.len = reglen;
 
-       regbuf = kmalloc(reglen, GFP_USER);
+       regbuf = kzalloc(reglen, GFP_USER);
        if (!regbuf)
                return -ENOMEM;
 
index 9fbe7f7429b0efd036cc9e4a7df06293f85a8f0b..6743146e4d6b49a61204395b49e4ded721de2703 100644 (file)
@@ -232,7 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
        est->last_packets = bstats->packets;
        est->avpps = rate_est->pps<<10;
 
-       spin_lock(&est_tree_lock);
+       spin_lock_bh(&est_tree_lock);
        if (!elist[idx].timer.function) {
                INIT_LIST_HEAD(&elist[idx].list);
                setup_timer(&elist[idx].timer, est_timer, idx);
@@ -243,7 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
 
        list_add_rcu(&est->list, &elist[idx].list);
        gen_add_node(est);
-       spin_unlock(&est_tree_lock);
+       spin_unlock_bh(&est_tree_lock);
 
        return 0;
 }
@@ -270,7 +270,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
 {
        struct gen_estimator *e;
 
-       spin_lock(&est_tree_lock);
+       spin_lock_bh(&est_tree_lock);
        while ((e = gen_find_node(bstats, rate_est))) {
                rb_erase(&e->node, &est_root);
 
@@ -281,7 +281,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                list_del_rcu(&e->list);
                call_rcu(&e->e_rcu, __gen_kill_estimator);
        }
-       spin_unlock(&est_tree_lock);
+       spin_unlock_bh(&est_tree_lock);
 }
 EXPORT_SYMBOL(gen_kill_estimator);
 
@@ -320,9 +320,9 @@ bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
 
        ASSERT_RTNL();
 
-       spin_lock(&est_tree_lock);
+       spin_lock_bh(&est_tree_lock);
        res = gen_find_node(bstats, rate_est) != NULL;
-       spin_unlock(&est_tree_lock);
+       spin_unlock_bh(&est_tree_lock);
 
        return res;
 }
index 1cd98df412dfd52daee9cc9105ceddfea0d87a59..e6b133b77ccb5615d65bcdac0ecc01b759808c76 100644 (file)
  *     in any case.
  */
 
-int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
+long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
 {
-       int size, err, ct;
+       int size, ct;
+       long err;
 
        if (m->msg_namelen) {
                if (mode == VERIFY_READ) {
index afa6380ed88ac2ee0b5cd8c8a731dcb9f3dcb809..7f1bb2aba03bf0e501ee1625ba6f07163b528ab9 100644 (file)
@@ -26,6 +26,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/skb.h>
+#include <trace/events/net.h>
 #include <trace/events/napi.h>
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
index 3a2513f0d0c3036bf6c3f688f7e94b3e1d8f197c..56ba3c4e4761c6584375a8acf45022bc5c40d6e8 100644 (file)
@@ -466,6 +466,7 @@ void consume_skb(struct sk_buff *skb)
                smp_rmb();
        else if (likely(!atomic_dec_and_test(&skb->users)))
                return;
+       trace_consume_skb(skb);
        __kfree_skb(skb);
 }
 EXPORT_SYMBOL(consume_skb);
@@ -2573,6 +2574,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
                __copy_skb_header(nskb, skb);
                nskb->mac_len = skb->mac_len;
 
+               /* nskb and skb might have different headroom */
+               if (nskb->ip_summed == CHECKSUM_PARTIAL)
+                       nskb->csum_start += skb_headroom(nskb) - headroom;
+
                skb_reset_mac_header(nskb);
                skb_set_network_header(nskb, skb->mac_len);
                nskb->transport_header = (nskb->network_header +
@@ -2703,7 +2708,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
                return -E2BIG;
 
        headroom = skb_headroom(p);
-       nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p));
+       nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
        if (unlikely(!nskb))
                return -ENOMEM;
 
index b05b9b6ddb8700989e63e8597f6946ffd205bdba..7d99e13148e6287f1cca0f5e3417ee5d535c366c 100644 (file)
@@ -1078,8 +1078,11 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 #ifdef CONFIG_CGROUPS
 void sock_update_classid(struct sock *sk)
 {
-       u32 classid = task_cls_classid(current);
+       u32 classid;
 
+       rcu_read_lock();  /* doing current task, which cannot vanish. */
+       classid = task_cls_classid(current);
+       rcu_read_unlock();
        if (classid && classid != sk->sk_classid)
                sk->sk_classid = classid;
 }
@@ -1351,9 +1354,9 @@ int sock_i_uid(struct sock *sk)
 {
        int uid;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0;
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        return uid;
 }
 EXPORT_SYMBOL(sock_i_uid);
@@ -1362,9 +1365,9 @@ unsigned long sock_i_ino(struct sock *sk)
 {
        unsigned long ino;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        return ino;
 }
 EXPORT_SYMBOL(sock_i_ino);
index d959e0f41528ce71d69f4aafea0f6d028d72607a..f5df85dcd20bc7f790aec8f58967f55e02586444 100644 (file)
@@ -141,10 +141,10 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
 
                set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                sk->sk_write_pending++;
-               sk_wait_event(sk, &current_timeo, !sk->sk_err &&
-                                                 !(sk->sk_shutdown & SEND_SHUTDOWN) &&
-                                                 sk_stream_memory_free(sk) &&
-                                                 vm_wait);
+               sk_wait_event(sk, &current_timeo, sk->sk_err ||
+                                                 (sk->sk_shutdown & SEND_SHUTDOWN) ||
+                                                 (sk_stream_memory_free(sk) &&
+                                                 !vm_wait));
                sk->sk_write_pending--;
 
                if (vm_wait) {
index 078e48d442fd2df6c5e500b2db4958df7a82a534..33d0e6297c213810a71beeb29f17c3c928727ff3 100644 (file)
@@ -149,6 +149,7 @@ static const struct file_operations dccpprobe_fops = {
        .owner   = THIS_MODULE,
        .open    = dccpprobe_open,
        .read    = dccpprobe_read,
+       .llseek  = noop_llseek,
 };
 
 static __init int dccpprobe_init(void)
index 7c3a7d19124995fd89034a4db2254566aab4cdfd..7cd7760144f7dd1998276f4e2976e4a4a1c8135d 100644 (file)
@@ -46,7 +46,7 @@ config IP_ADVANCED_ROUTER
          rp_filter on use:
 
          echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter
-          and
+          or
          echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
 
          Note that some distributions enable it in startup scripts.
@@ -217,6 +217,7 @@ config NET_IPIP
 
 config NET_IPGRE
        tristate "IP: GRE tunnels over IP"
+       depends on IPV6 || IPV6=n
        help
          Tunneling means encapsulating data of one protocol type within
          another protocol and sending it over a channel that understands the
@@ -412,7 +413,7 @@ config INET_XFRM_MODE_BEET
          If unsure, say Y.
 
 config INET_LRO
-       bool "Large Receive Offload (ipv4/tcp)"
+       tristate "Large Receive Offload (ipv4/tcp)"
        default y
        ---help---
          Support for Large Receive Offload (ipv4/tcp).
index f0550941df7b9e1ac63468384eba7ede1bf6d537..721a8a37b45c77ce1d3ae78afffe57cf9eaeedf1 100644 (file)
@@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        }
        if (!inet->inet_saddr)
                inet->inet_saddr = rt->rt_src;  /* Update source address */
-       if (!inet->inet_rcv_saddr)
+       if (!inet->inet_rcv_saddr) {
                inet->inet_rcv_saddr = rt->rt_src;
+               if (sk->sk_prot->rehash)
+                       sk->sk_prot->rehash(sk);
+       }
        inet->inet_daddr = rt->rt_dst;
        inet->inet_dport = usin->sin_port;
        sk->sk_state = TCP_ESTABLISHED;
index a43968918350244a057e6f3364727d6a2aa7baf2..7d02a9f999fabcebeb61800816d722e6f6c054ff 100644 (file)
@@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 
        struct fib_result res;
        int no_addr, rpf, accept_local;
+       bool dev_match;
        int ret;
        struct net *net;
 
@@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
        }
        *spec_dst = FIB_RES_PREFSRC(res);
        fib_combine_itag(itag, &res);
+       dev_match = false;
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-       if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
+       for (ret = 0; ret < res.fi->fib_nhs; ret++) {
+               struct fib_nh *nh = &res.fi->fib_nh[ret];
+
+               if (nh->nh_dev == dev) {
+                       dev_match = true;
+                       break;
+               }
+       }
 #else
        if (FIB_RES_DEV(res) == dev)
+               dev_match = true;
 #endif
-       {
+       if (dev_match) {
                ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
                fib_res_put(&res);
                return ret;
index 79d057a939ba6404d4e7553008a2613815a9b049..4a8e370862bca453cd6e939162ded09de6bdf831 100644 (file)
@@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node)
 {
        struct tnode *ret = node_parent(node);
 
-       return rcu_dereference(ret);
+       return rcu_dereference_check(ret,
+                                    rcu_read_lock_held() ||
+                                    lockdep_rtnl_is_held());
 }
 
 /* Same as rcu_assign_pointer
@@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
 
 static struct leaf *trie_firstleaf(struct trie *t)
 {
-       struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
+       struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
+                                                       rcu_read_lock_held() ||
+                                                       lockdep_rtnl_is_held());
 
        if (!n)
                return NULL;
index a1ad0e7180d2bd7051df4f78bed75fbb7612da40..2a4bb76f2132957da25326ce98653b249d9ccaaf 100644 (file)
@@ -856,6 +856,18 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
                igmpv3_clear_delrec(in_dev);
        } else if (len < 12) {
                return; /* ignore bogus packet; freed by caller */
+       } else if (IGMP_V1_SEEN(in_dev)) {
+               /* This is a v3 query with v1 queriers present */
+               max_delay = IGMP_Query_Response_Interval;
+               group = 0;
+       } else if (IGMP_V2_SEEN(in_dev)) {
+               /* this is a v3 query with v2 queriers present;
+                * Interpretation of the max_delay code is problematic here.
+                * A real v2 host would use ih_code directly, while v3 has a
+                * different encoding. We use the v3 encoding as more likely
+                * to be intended in a v3 query.
+                */
+               max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
        } else { /* v3 */
                if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
                        return;
index 945b20a5ad5006b6a8ebf84b22756f7573436c1f..35c93e8b6a4694561c838641e546b609e8cbfaa0 100644 (file)
@@ -45,7 +45,7 @@
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
 
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
@@ -699,7 +699,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        if ((dst = rt->rt_gateway) == 0)
                                goto tx_error_icmp;
                }
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
                else if (skb->protocol == htons(ETH_P_IPV6)) {
                        struct in6_addr *addr6;
                        int addr_type;
@@ -774,7 +774,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        goto tx_error;
                }
        }
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        else if (skb->protocol == htons(ETH_P_IPV6)) {
                struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
 
@@ -850,7 +850,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        if ((iph->ttl = tiph->ttl) == 0) {
                if (skb->protocol == htons(ETH_P_IP))
                        iph->ttl = old_iph->ttl;
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
                else if (skb->protocol == htons(ETH_P_IPV6))
                        iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;
 #endif
index 04b69896df5fc743021efd4d4a1705b7de146333..7649d7750075d184896a9da6d37ed9a35ea5f403 100644 (file)
@@ -488,9 +488,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
         * we can switch to copy when see the first bad fragment.
         */
        if (skb_has_frags(skb)) {
-               struct sk_buff *frag;
+               struct sk_buff *frag, *frag2;
                int first_len = skb_pagelen(skb);
-               int truesizes = 0;
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
@@ -503,18 +502,18 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                        if (frag->len > mtu ||
                            ((frag->len & 7) && frag->next) ||
                            skb_headroom(frag) < hlen)
-                           goto slow_path;
+                               goto slow_path_clean;
 
                        /* Partially cloned skb? */
                        if (skb_shared(frag))
-                               goto slow_path;
+                               goto slow_path_clean;
 
                        BUG_ON(frag->sk);
                        if (skb->sk) {
                                frag->sk = skb->sk;
                                frag->destructor = sock_wfree;
                        }
-                       truesizes += frag->truesize;
+                       skb->truesize -= frag->truesize;
                }
 
                /* Everything is OK. Generate! */
@@ -524,7 +523,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                frag = skb_shinfo(skb)->frag_list;
                skb_frag_list_init(skb);
                skb->data_len = first_len - skb_headlen(skb);
-               skb->truesize -= truesizes;
                skb->len = first_len;
                iph->tot_len = htons(first_len);
                iph->frag_off = htons(IP_MF);
@@ -576,6 +574,15 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                }
                IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
                return err;
+
+slow_path_clean:
+               skb_walk_frags(skb, frag2) {
+                       if (frag2 == frag)
+                               break;
+                       frag2->sk = NULL;
+                       frag2->destructor = NULL;
+                       skb->truesize += frag2->truesize;
+               }
        }
 
 slow_path:
index 6c40a8c46e7984843275af12bfbac9a241e8e4c6..64b70ad162e370dbeb5b60adda5dd811182fc0f5 100644 (file)
@@ -1129,6 +1129,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_HDRINCL:
                val = inet->hdrincl;
                break;
+       case IP_NODEFRAG:
+               val = inet->nodefrag;
+               break;
        case IP_MTU_DISCOVER:
                val = inet->pmtudisc;
                break;
index 51d6c31679757f58e62368a42edba16d9bfc4d09..e8f4f9a57f1258fb1a589c87a956797019c67504 100644 (file)
@@ -1420,6 +1420,9 @@ static int translate_compat_table(const char *name,
                if (ret != 0)
                        break;
                ++i;
+               if (strcmp(arpt_get_target(iter1)->u.user.name,
+                   XT_ERROR_TARGET) == 0)
+                       ++newinfo->stacksize;
        }
        if (ret) {
                /*
index 97b64b22c41214858d6ddb1fb9cf8e292468e23d..d163f2e3b2e99e5f18ae9997d3c74867b3e79354 100644 (file)
@@ -1751,6 +1751,9 @@ translate_compat_table(struct net *net,
                if (ret != 0)
                        break;
                ++i;
+               if (strcmp(ipt_get_target(iter1)->u.user.name,
+                   XT_ERROR_TARGET) == 0)
+                       ++newinfo->stacksize;
        }
        if (ret) {
                /*
index b254dafaf4294548b7d36d9b54ce29832f8658e3..43eec80c0e7c55a2f6dc20790a30603236b7d93f 100644 (file)
@@ -112,6 +112,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        /* ip_route_me_harder expects skb->dst to be set */
        skb_dst_set_noref(nskb, skb_dst(oldskb));
 
+       nskb->protocol = htons(ETH_P_IP);
        if (ip_route_me_harder(nskb, addr_type))
                goto free_nskb;
 
index 244f7cb08d681d35f9a08744ca449ce90f5b8972..37f8adb68c79e8619d1a45a496ca6e1ef37c7c8a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
+#include <linux/security.h>
 #include <net/net_namespace.h>
 
 #include <linux/netfilter.h>
@@ -87,6 +88,29 @@ static void ct_seq_stop(struct seq_file *s, void *v)
        rcu_read_unlock();
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+       int ret;
+       u32 len;
+       char *secctx;
+
+       ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+       if (ret)
+               return ret;
+
+       ret = seq_printf(s, "secctx=%s ", secctx);
+
+       security_release_secctx(secctx, len);
+       return ret;
+}
+#else
+static inline int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+       return 0;
+}
+#endif
+
 static int ct_seq_show(struct seq_file *s, void *v)
 {
        struct nf_conntrack_tuple_hash *hash = v;
@@ -148,10 +172,8 @@ static int ct_seq_show(struct seq_file *s, void *v)
                goto release;
 #endif
 
-#ifdef CONFIG_NF_CONNTRACK_SECMARK
-       if (seq_printf(s, "secmark=%u ", ct->secmark))
+       if (ct_show_secctx(s, ct))
                goto release;
-#endif
 
        if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
                goto release;
index eab8de32f200af74828bbf0fb3187ff578451e9b..f3a9b42b16c620a7f569e00039beea13bc75bc3c 100644 (file)
@@ -66,9 +66,11 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
                                          const struct net_device *out,
                                          int (*okfn)(struct sk_buff *))
 {
+       struct sock *sk = skb->sk;
        struct inet_sock *inet = inet_sk(skb->sk);
 
-       if (inet && inet->nodefrag)
+       if (sk && (sk->sk_family == PF_INET) &&
+           inet->nodefrag)
                return NF_ACCEPT;
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
index 8c8632d9b93cead0cd115945a9566d1e57829667..957c9241fb0ce1d91cde6c1b098f81b52337690a 100644 (file)
@@ -38,7 +38,7 @@ static DEFINE_SPINLOCK(nf_nat_lock);
 static struct nf_conntrack_l3proto *l3proto __read_mostly;
 
 #define MAX_IP_NAT_PROTO 256
-static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
+static const struct nf_nat_protocol __rcu *nf_nat_protos[MAX_IP_NAT_PROTO]
                                                __read_mostly;
 
 static inline const struct nf_nat_protocol *
index 1679e2c0963d9b83e34f1f8d6a34b7702a603e2c..ee5f419d0a56d01c6533d6ee45f70a7405480150 100644 (file)
@@ -893,13 +893,15 @@ static void fast_csum(__sum16 *csum,
        unsigned char s[4];
 
        if (offset & 1) {
-               s[0] = s[2] = 0;
+               s[0] = ~0;
                s[1] = ~*optr;
+               s[2] = 0;
                s[3] = *nptr;
        } else {
-               s[1] = s[3] = 0;
                s[0] = ~*optr;
+               s[1] = ~0;
                s[2] = *nptr;
+               s[3] = 0;
        }
 
        *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
index 3f56b6e6c6aab583d65902e7190bbf1a6eaa60b6..ac6559cb54f9f650986e4dd86996349e328cd92a 100644 (file)
@@ -1231,7 +1231,7 @@ restart:
                        }
 
                        if (net_ratelimit())
-                               printk(KERN_WARNING "Neighbour table overflow.\n");
+                               printk(KERN_WARNING "ipv4: Neighbour table overflow.\n");
                        rt_drop(rt);
                        return -ENOBUFS;
                }
@@ -2738,6 +2738,11 @@ slow_output:
 }
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
+static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
+{
+       return NULL;
+}
+
 static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
@@ -2746,7 +2751,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
        .family                 =       AF_INET,
        .protocol               =       cpu_to_be16(ETH_P_IP),
        .destroy                =       ipv4_dst_destroy,
-       .check                  =       ipv4_dst_check,
+       .check                  =       ipv4_blackhole_dst_check,
        .update_pmtu            =       ipv4_rt_blackhole_update_pmtu,
        .entries                =       ATOMIC_INIT(0),
 };
index 176e11aaea771795b21c0be6b1453b46c6349f0c..f115ea68a4efa264c59b20f61222db97a6050a9d 100644 (file)
@@ -386,8 +386,6 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
         */
 
        mask = 0;
-       if (sk->sk_err)
-               mask = POLLERR;
 
        /*
         * POLLHUP is certainly not done right. But poll() doesn't
@@ -451,11 +449,17 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
                                if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
                                        mask |= POLLOUT | POLLWRNORM;
                        }
-               }
+               } else
+                       mask |= POLLOUT | POLLWRNORM;
 
                if (tp->urg_data & TCP_URG_VALID)
                        mask |= POLLPRI;
        }
+       /* This barrier is coupled with smp_wmb() in tcp_reset() */
+       smp_rmb();
+       if (sk->sk_err)
+               mask |= POLLERR;
+
        return mask;
 }
 EXPORT_SYMBOL(tcp_poll);
@@ -939,7 +943,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        sg = sk->sk_route_caps & NETIF_F_SG;
 
        while (--iovlen >= 0) {
-               int seglen = iov->iov_len;
+               size_t seglen = iov->iov_len;
                unsigned char __user *from = iov->iov_base;
 
                iov++;
@@ -2011,11 +2015,8 @@ adjudge_to_death:
                }
        }
        if (sk->sk_state != TCP_CLOSE) {
-               int orphan_count = percpu_counter_read_positive(
-                                               sk->sk_prot->orphan_count);
-
                sk_mem_reclaim(sk);
-               if (tcp_too_many_orphans(sk, orphan_count)) {
+               if (tcp_too_many_orphans(sk, 0)) {
                        if (net_ratelimit())
                                printk(KERN_INFO "TCP: too many of orphaned "
                                       "sockets\n");
@@ -3212,7 +3213,7 @@ void __init tcp_init(void)
 {
        struct sk_buff *skb = NULL;
        unsigned long nr_pages, limit;
-       int order, i, max_share;
+       int i, max_share, cnt;
        unsigned long jiffy = jiffies;
 
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -3261,22 +3262,12 @@ void __init tcp_init(void)
                INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
        }
 
-       /* Try to be a bit smarter and adjust defaults depending
-        * on available memory.
-        */
-       for (order = 0; ((1 << order) << PAGE_SHIFT) <
-                       (tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket));
-                       order++)
-               ;
-       if (order >= 4) {
-               tcp_death_row.sysctl_max_tw_buckets = 180000;
-               sysctl_tcp_max_orphans = 4096 << (order - 4);
-               sysctl_max_syn_backlog = 1024;
-       } else if (order < 3) {
-               tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
-               sysctl_tcp_max_orphans >>= (3 - order);
-               sysctl_max_syn_backlog = 128;
-       }
+
+       cnt = tcp_hashinfo.ehash_mask + 1;
+
+       tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
+       sysctl_tcp_max_orphans = cnt / 2;
+       sysctl_max_syn_backlog = max(128, cnt / 256);
 
        /* Set the pressure threshold to be a fraction of global memory that
         * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
index 0ec9bd0ae94f2ef37024ac11c5e411f0179c816a..850c737e08e2a4a9185c64c8776711d83b8c7b08 100644 (file)
@@ -196,10 +196,10 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen)
 int tcp_set_allowed_congestion_control(char *val)
 {
        struct tcp_congestion_ops *ca;
-       char *clone, *name;
+       char *saved_clone, *clone, *name;
        int ret = 0;
 
-       clone = kstrdup(val, GFP_USER);
+       saved_clone = clone = kstrdup(val, GFP_USER);
        if (!clone)
                return -ENOMEM;
 
@@ -226,6 +226,7 @@ int tcp_set_allowed_congestion_control(char *val)
        }
 out:
        spin_unlock(&tcp_cong_list_lock);
+       kfree(saved_clone);
 
        return ret;
 }
index e663b78a2ef6b6286b549aa65b418fe385f32184..b55f60f6fcbe934c1364ee3aece309dff4d1be4b 100644 (file)
@@ -2545,7 +2545,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets)
                        cnt += tcp_skb_pcount(skb);
 
                if (cnt > packets) {
-                       if (tcp_is_sack(tp) || (oldcnt >= packets))
+                       if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) ||
+                           (oldcnt >= packets))
                                break;
 
                        mss = skb_shinfo(skb)->gso_size;
@@ -4048,6 +4049,8 @@ static void tcp_reset(struct sock *sk)
        default:
                sk->sk_err = ECONNRESET;
        }
+       /* This barrier is coupled with smp_rmb() in tcp_poll() */
+       smp_wmb();
 
        if (!sock_flag(sk, SOCK_DEAD))
                sk->sk_error_report(sk);
index f8efada580e8fed87b33ea52f27f415034a4d62e..6211e211417396f9c17dedf805998db731b4a27c 100644 (file)
@@ -214,6 +214,7 @@ static const struct file_operations tcpprobe_fops = {
        .owner   = THIS_MODULE,
        .open    = tcpprobe_open,
        .read    = tcpprobe_read,
+       .llseek  = noop_llseek,
 };
 
 static __init int tcpprobe_init(void)
index 808bb920c9f5e67249f6747c90cdeb7dddd9ddea..74c54b30600f618522e07581c43130eea031f2db 100644 (file)
@@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk)
 static int tcp_out_of_resources(struct sock *sk, int do_reset)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       int orphans = percpu_counter_read_positive(&tcp_orphan_count);
+       int shift = 0;
 
        /* If peer does not open window for long time, or did not transmit
         * anything for long time, penalize it. */
        if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
-               orphans <<= 1;
+               shift++;
 
        /* If some dubious ICMP arrived, penalize even more. */
        if (sk->sk_err_soft)
-               orphans <<= 1;
+               shift++;
 
-       if (tcp_too_many_orphans(sk, orphans)) {
+       if (tcp_too_many_orphans(sk, shift)) {
                if (net_ratelimit())
                        printk(KERN_INFO "Out of socket memory\n");
 
@@ -135,13 +135,16 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk)
 
 /* This function calculates a "timeout" which is equivalent to the timeout of a
  * TCP connection after "boundary" unsuccessful, exponentially backed-off
- * retransmissions with an initial RTO of TCP_RTO_MIN.
+ * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if
+ * syn_set flag is set.
  */
 static bool retransmits_timed_out(struct sock *sk,
-                                 unsigned int boundary)
+                                 unsigned int boundary,
+                                 bool syn_set)
 {
        unsigned int timeout, linear_backoff_thresh;
        unsigned int start_ts;
+       unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN;
 
        if (!inet_csk(sk)->icsk_retransmits)
                return false;
@@ -151,12 +154,12 @@ static bool retransmits_timed_out(struct sock *sk,
        else
                start_ts = tcp_sk(sk)->retrans_stamp;
 
-       linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN);
+       linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base);
 
        if (boundary <= linear_backoff_thresh)
-               timeout = ((2 << boundary) - 1) * TCP_RTO_MIN;
+               timeout = ((2 << boundary) - 1) * rto_base;
        else
-               timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN +
+               timeout = ((2 << linear_backoff_thresh) - 1) * rto_base +
                          (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
 
        return (tcp_time_stamp - start_ts) >= timeout;
@@ -167,14 +170,15 @@ static int tcp_write_timeout(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        int retry_until;
-       bool do_reset;
+       bool do_reset, syn_set = 0;
 
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                if (icsk->icsk_retransmits)
                        dst_negative_advice(sk);
                retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
+               syn_set = 1;
        } else {
-               if (retransmits_timed_out(sk, sysctl_tcp_retries1)) {
+               if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) {
                        /* Black hole detection */
                        tcp_mtu_probing(icsk, sk);
 
@@ -187,14 +191,14 @@ static int tcp_write_timeout(struct sock *sk)
 
                        retry_until = tcp_orphan_retries(sk, alive);
                        do_reset = alive ||
-                                  !retransmits_timed_out(sk, retry_until);
+                                  !retransmits_timed_out(sk, retry_until, 0);
 
                        if (tcp_out_of_resources(sk, do_reset))
                                return 1;
                }
        }
 
-       if (retransmits_timed_out(sk, retry_until)) {
+       if (retransmits_timed_out(sk, retry_until, syn_set)) {
                /* Has it gone just too far? */
                tcp_write_err(sk);
                return 1;
@@ -436,7 +440,7 @@ out_reset_timer:
                icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
        }
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX);
-       if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1))
+       if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0))
                __sk_dst_reset(sk);
 
 out:;
index 32e0bef60d0afdbedd3d4cbdd3c57a9f9beafcdc..fb23c2e63b5281a7ca505af3ac94f411e10c4ee6 100644 (file)
@@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk)
 }
 EXPORT_SYMBOL(udp_lib_unhash);
 
+/*
+ * inet_rcv_saddr was changed, we must rehash secondary hash
+ */
+void udp_lib_rehash(struct sock *sk, u16 newhash)
+{
+       if (sk_hashed(sk)) {
+               struct udp_table *udptable = sk->sk_prot->h.udp_table;
+               struct udp_hslot *hslot, *hslot2, *nhslot2;
+
+               hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
+               nhslot2 = udp_hashslot2(udptable, newhash);
+               udp_sk(sk)->udp_portaddr_hash = newhash;
+               if (hslot2 != nhslot2) {
+                       hslot = udp_hashslot(udptable, sock_net(sk),
+                                            udp_sk(sk)->udp_port_hash);
+                       /* we must lock primary chain too */
+                       spin_lock_bh(&hslot->lock);
+
+                       spin_lock(&hslot2->lock);
+                       hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
+                       hslot2->count--;
+                       spin_unlock(&hslot2->lock);
+
+                       spin_lock(&nhslot2->lock);
+                       hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
+                                                &nhslot2->head);
+                       nhslot2->count++;
+                       spin_unlock(&nhslot2->lock);
+
+                       spin_unlock_bh(&hslot->lock);
+               }
+       }
+}
+EXPORT_SYMBOL(udp_lib_rehash);
+
+static void udp_v4_rehash(struct sock *sk)
+{
+       u16 new_hash = udp4_portaddr_hash(sock_net(sk),
+                                         inet_sk(sk)->inet_rcv_saddr,
+                                         inet_sk(sk)->inet_num);
+       udp_lib_rehash(sk, new_hash);
+}
+
 static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
@@ -1843,6 +1886,7 @@ struct proto udp_prot = {
        .backlog_rcv       = __udp_queue_rcv_skb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v4_rehash,
        .get_port          = udp_v4_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 869078d4eeb957a4982ab62e5d408e8fbf42117c..a580349f0b8ab53c77b04b00d504de0bf1f83e09 100644 (file)
@@ -61,7 +61,7 @@ static int xfrm4_get_saddr(struct net *net,
 
 static int xfrm4_get_tos(struct flowi *fl)
 {
-       return fl->fl4_tos;
+       return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */
 }
 
 static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
index 1ef1366a0a03775eed25ab5ef0b083aed593726e..47947624eccc58fe7fcfcdbff19fb655a07ddedc 100644 (file)
@@ -21,21 +21,25 @@ static int xfrm4_init_flags(struct xfrm_state *x)
 }
 
 static void
-__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-                    struct xfrm_tmpl *tmpl,
-                    xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm4_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
+{
+       sel->daddr.a4 = fl->fl4_dst;
+       sel->saddr.a4 = fl->fl4_src;
+       sel->dport = xfrm_flowi_dport(fl);
+       sel->dport_mask = htons(0xffff);
+       sel->sport = xfrm_flowi_sport(fl);
+       sel->sport_mask = htons(0xffff);
+       sel->family = AF_INET;
+       sel->prefixlen_d = 32;
+       sel->prefixlen_s = 32;
+       sel->proto = fl->proto;
+       sel->ifindex = fl->oif;
+}
+
+static void
+xfrm4_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
+                  xfrm_address_t *daddr, xfrm_address_t *saddr)
 {
-       x->sel.daddr.a4 = fl->fl4_dst;
-       x->sel.saddr.a4 = fl->fl4_src;
-       x->sel.dport = xfrm_flowi_dport(fl);
-       x->sel.dport_mask = htons(0xffff);
-       x->sel.sport = xfrm_flowi_sport(fl);
-       x->sel.sport_mask = htons(0xffff);
-       x->sel.family = AF_INET;
-       x->sel.prefixlen_d = 32;
-       x->sel.prefixlen_s = 32;
-       x->sel.proto = fl->proto;
-       x->sel.ifindex = fl->oif;
        x->id = tmpl->id;
        if (x->id.daddr.a4 == 0)
                x->id.daddr.a4 = daddr->a4;
@@ -70,6 +74,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .owner                  = THIS_MODULE,
        .init_flags             = xfrm4_init_flags,
        .init_tempsel           = __xfrm4_init_tempsel,
+       .init_temprop           = xfrm4_init_temprop,
        .output                 = xfrm4_output,
        .extract_input          = xfrm4_extract_input,
        .extract_output         = xfrm4_extract_output,
index ab70a3fbcafafee9a080ea0f8c6eab2ce04fc37e..324fac3b6c16db0238d1139649038bcaa9aaced2 100644 (file)
@@ -4637,10 +4637,12 @@ int __init addrconf_init(void)
        if (err < 0) {
                printk(KERN_CRIT "IPv6 Addrconf:"
                       " cannot initialize default policy table: %d.\n", err);
-               return err;
+               goto out;
        }
 
-       register_pernet_subsys(&addrconf_ops);
+       err = register_pernet_subsys(&addrconf_ops);
+       if (err < 0)
+               goto out_addrlabel;
 
        /* The addrconf netdev notifier requires that loopback_dev
         * has it's ipv6 private information allocated and setup
@@ -4692,7 +4694,9 @@ errout:
        unregister_netdevice_notifier(&ipv6_dev_notf);
 errlo:
        unregister_pernet_subsys(&addrconf_ops);
-
+out_addrlabel:
+       ipv6_addr_label_cleanup();
+out:
        return err;
 }
 
@@ -4703,6 +4707,7 @@ void addrconf_cleanup(void)
 
        unregister_netdevice_notifier(&ipv6_dev_notf);
        unregister_pernet_subsys(&addrconf_ops);
+       ipv6_addr_label_cleanup();
 
        rtnl_lock();
 
index f0e774cea386696a72560d9306f441a46817a96d..8175f802651bec4481080823a73f60a21d3a2f36 100644 (file)
@@ -393,6 +393,11 @@ int __init ipv6_addr_label_init(void)
        return register_pernet_subsys(&ipv6_addr_label_ops);
 }
 
+void ipv6_addr_label_cleanup(void)
+{
+       unregister_pernet_subsys(&ipv6_addr_label_ops);
+}
+
 static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
        [IFAL_ADDRESS]          = { .len = sizeof(struct in6_addr), },
        [IFAL_LABEL]            = { .len = sizeof(u32), },
index 7d929a22cbc2f505aca94ba5a6fd9cae412824dc..ef371aa01ac50724f9dff9cbf7d084e062d844c9 100644 (file)
@@ -105,9 +105,12 @@ ipv4_connected:
                if (ipv6_addr_any(&np->saddr))
                        ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
 
-               if (ipv6_addr_any(&np->rcv_saddr))
+               if (ipv6_addr_any(&np->rcv_saddr)) {
                        ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
                                               &np->rcv_saddr);
+                       if (sk->sk_prot->rehash)
+                               sk->sk_prot->rehash(sk);
+               }
 
                goto out;
        }
@@ -181,6 +184,8 @@ ipv4_connected:
        if (ipv6_addr_any(&np->rcv_saddr)) {
                ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
                inet->inet_rcv_saddr = LOOPBACK4_IPV6;
+               if (sk->sk_prot->rehash)
+                       sk->sk_prot->rehash(sk);
        }
 
        ip6_dst_store(sk, dst,
index d40b330c0ee698af62f51f90caf86b2e6cf04c9f..980912ed7a388bd2404b8cb934b2b61e67e12a6c 100644 (file)
@@ -639,7 +639,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
        if (skb_has_frags(skb)) {
                int first_len = skb_pagelen(skb);
-               int truesizes = 0;
+               struct sk_buff *frag2;
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
@@ -651,18 +651,18 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                        if (frag->len > mtu ||
                            ((frag->len & 7) && frag->next) ||
                            skb_headroom(frag) < hlen)
-                           goto slow_path;
+                               goto slow_path_clean;
 
                        /* Partially cloned skb? */
                        if (skb_shared(frag))
-                               goto slow_path;
+                               goto slow_path_clean;
 
                        BUG_ON(frag->sk);
                        if (skb->sk) {
                                frag->sk = skb->sk;
                                frag->destructor = sock_wfree;
-                               truesizes += frag->truesize;
                        }
+                       skb->truesize -= frag->truesize;
                }
 
                err = 0;
@@ -693,7 +693,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
                first_len = skb_pagelen(skb);
                skb->data_len = first_len - skb_headlen(skb);
-               skb->truesize -= truesizes;
                skb->len = first_len;
                ipv6_hdr(skb)->payload_len = htons(first_len -
                                                   sizeof(struct ipv6hdr));
@@ -756,6 +755,15 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                              IPSTATS_MIB_FRAGFAILS);
                dst_release(&rt->dst);
                return err;
+
+slow_path_clean:
+               skb_walk_frags(skb, frag2) {
+                       if (frag2 == frag)
+                               break;
+                       frag2->sk = NULL;
+                       frag2->destructor = NULL;
+                       skb->truesize += frag2->truesize;
+               }
        }
 
 slow_path:
index 29a7bca29e3fddec24a55ea2e6ca228bc7a452ba..8e754be92c2450e7142a958466b493dc077f5772 100644 (file)
@@ -1766,6 +1766,9 @@ translate_compat_table(struct net *net,
                if (ret != 0)
                        break;
                ++i;
+               if (strcmp(ip6t_get_target(iter1)->u.user.name,
+                   XT_ERROR_TARGET) == 0)
+                       ++newinfo->stacksize;
        }
        if (ret) {
                /*
index 13ef5bc05cf5220a3e2aa62543c4a12b79e5a98a..578f3c1a16db614614f986947cbae5a7960fcdb5 100644 (file)
@@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb)
                kfree_skb(NFCT_FRAG6_CB(skb)->orig);
 }
 
-/* Memory Tracking Functions. */
-static void frag_kfree_skb(struct sk_buff *skb)
-{
-       atomic_sub(skb->truesize, &nf_init_frags.mem);
-       nf_skb_free(skb);
-       kfree_skb(skb);
-}
-
 /* Destruction primitives. */
 
 static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
@@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
        }
 
 found:
-       /* We found where to put this one.  Check for overlap with
-        * preceding fragment, and, if needed, align things so that
-        * any overlaps are eliminated.
-        */
-       if (prev) {
-               int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset;
-
-               if (i > 0) {
-                       offset += i;
-                       if (end <= offset) {
-                               pr_debug("overlap\n");
-                               goto err;
-                       }
-                       if (!pskb_pull(skb, i)) {
-                               pr_debug("Can't pull\n");
-                               goto err;
-                       }
-                       if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-                               skb->ip_summed = CHECKSUM_NONE;
-               }
-       }
-
-       /* Look for overlap with succeeding segments.
-        * If we can merge fragments, do it.
+       /* RFC5722, Section 4:
+        *                                  When reassembling an IPv6 datagram, if
+        *   one or more its constituent fragments is determined to be an
+        *   overlapping fragment, the entire datagram (and any constituent
+        *   fragments, including those not yet received) MUST be silently
+        *   discarded.
         */
-       while (next && NFCT_FRAG6_CB(next)->offset < end) {
-               /* overlap is 'i' bytes */
-               int i = end - NFCT_FRAG6_CB(next)->offset;
-
-               if (i < next->len) {
-                       /* Eat head of the next overlapped fragment
-                        * and leave the loop. The next ones cannot overlap.
-                        */
-                       pr_debug("Eat head of the overlapped parts.: %d", i);
-                       if (!pskb_pull(next, i))
-                               goto err;
 
-                       /* next fragment */
-                       NFCT_FRAG6_CB(next)->offset += i;
-                       fq->q.meat -= i;
-                       if (next->ip_summed != CHECKSUM_UNNECESSARY)
-                               next->ip_summed = CHECKSUM_NONE;
-                       break;
-               } else {
-                       struct sk_buff *free_it = next;
-
-                       /* Old fragmnet is completely overridden with
-                        * new one drop it.
-                        */
-                       next = next->next;
+       /* Check for overlap with preceding fragment. */
+       if (prev &&
+           (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0)
+               goto discard_fq;
 
-                       if (prev)
-                               prev->next = next;
-                       else
-                               fq->q.fragments = next;
-
-                       fq->q.meat -= free_it->len;
-                       frag_kfree_skb(free_it);
-               }
-       }
+       /* Look for overlap with succeeding segment. */
+       if (next && NFCT_FRAG6_CB(next)->offset < end)
+               goto discard_fq;
 
        NFCT_FRAG6_CB(skb)->offset = offset;
 
@@ -371,6 +319,8 @@ found:
        write_unlock(&nf_frags.lock);
        return 0;
 
+discard_fq:
+       fq_kill(fq);
 err:
        return -1;
 }
index 545c4141b755ee91277c6bd2912de4f42813bb05..64cfef1b0a4c556ccf63c2f912c86ec3a1599b82 100644 (file)
@@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a)
 }
 EXPORT_SYMBOL(ip6_frag_match);
 
-/* Memory Tracking Functions. */
-static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
-{
-       atomic_sub(skb->truesize, &nf->mem);
-       kfree_skb(skb);
-}
-
 void ip6_frag_init(struct inet_frag_queue *q, void *a)
 {
        struct frag_queue *fq = container_of(q, struct frag_queue, q);
@@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
        }
 
 found:
-       /* We found where to put this one.  Check for overlap with
-        * preceding fragment, and, if needed, align things so that
-        * any overlaps are eliminated.
+       /* RFC5722, Section 4:
+        *                                  When reassembling an IPv6 datagram, if
+        *   one or more its constituent fragments is determined to be an
+        *   overlapping fragment, the entire datagram (and any constituent
+        *   fragments, including those not yet received) MUST be silently
+        *   discarded.
         */
-       if (prev) {
-               int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
 
-               if (i > 0) {
-                       offset += i;
-                       if (end <= offset)
-                               goto err;
-                       if (!pskb_pull(skb, i))
-                               goto err;
-                       if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-                               skb->ip_summed = CHECKSUM_NONE;
-               }
-       }
+       /* Check for overlap with preceding fragment. */
+       if (prev &&
+           (FRAG6_CB(prev)->offset + prev->len) - offset > 0)
+               goto discard_fq;
 
-       /* Look for overlap with succeeding segments.
-        * If we can merge fragments, do it.
-        */
-       while (next && FRAG6_CB(next)->offset < end) {
-               int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
-
-               if (i < next->len) {
-                       /* Eat head of the next overlapped fragment
-                        * and leave the loop. The next ones cannot overlap.
-                        */
-                       if (!pskb_pull(next, i))
-                               goto err;
-                       FRAG6_CB(next)->offset += i;    /* next fragment */
-                       fq->q.meat -= i;
-                       if (next->ip_summed != CHECKSUM_UNNECESSARY)
-                               next->ip_summed = CHECKSUM_NONE;
-                       break;
-               } else {
-                       struct sk_buff *free_it = next;
-
-                       /* Old fragment is completely overridden with
-                        * new one drop it.
-                        */
-                       next = next->next;
-
-                       if (prev)
-                               prev->next = next;
-                       else
-                               fq->q.fragments = next;
-
-                       fq->q.meat -= free_it->len;
-                       frag_kfree_skb(fq->q.net, free_it);
-               }
-       }
+       /* Look for overlap with succeeding segment. */
+       if (next && FRAG6_CB(next)->offset < end)
+               goto discard_fq;
 
        FRAG6_CB(skb)->offset = offset;
 
@@ -436,6 +393,8 @@ found:
        write_unlock(&ip6_frags.lock);
        return -1;
 
+discard_fq:
+       fq_kill(fq);
 err:
        IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
                      IPSTATS_MIB_REASMFAILS);
index d126365ac0463bc075d62446562a8d9f07d548a2..a275c6e1e25c23884d7d1859e46a2ee82c00acef 100644 (file)
@@ -670,7 +670,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
 
                        if (net_ratelimit())
                                printk(KERN_WARNING
-                                      "Neighbour table overflow.\n");
+                                      "ipv6: Neighbour table overflow.\n");
                        dst_free(&rt->dst);
                        return NULL;
                }
@@ -1556,14 +1556,13 @@ out:
  *     i.e. Path MTU discovery
  */
 
-void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
-                       struct net_device *dev, u32 pmtu)
+static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
+                            struct net *net, u32 pmtu, int ifindex)
 {
        struct rt6_info *rt, *nrt;
-       struct net *net = dev_net(dev);
        int allfrag = 0;
 
-       rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
+       rt = rt6_lookup(net, daddr, saddr, ifindex, 0);
        if (rt == NULL)
                return;
 
@@ -1631,6 +1630,27 @@ out:
        dst_release(&rt->dst);
 }
 
+void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+                       struct net_device *dev, u32 pmtu)
+{
+       struct net *net = dev_net(dev);
+
+       /*
+        * RFC 1981 states that a node "MUST reduce the size of the packets it
+        * is sending along the path" that caused the Packet Too Big message.
+        * Since it's not possible in the general case to determine which
+        * interface was used to send the original packet, we update the MTU
+        * on the interface that will be used to send future packets. We also
+        * update the MTU on the interface that received the Packet Too Big in
+        * case the original packet was forced out that interface with
+        * SO_BINDTODEVICE or similar. This is the next best thing to the
+        * correct behaviour, which would be to update the MTU on all
+        * interfaces.
+        */
+       rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0);
+       rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex);
+}
+
 /*
  *     Misc support functions
  */
index 1dd1affdead2d418a3d98a0f34e5d027cab88371..5acb3560ff15267021266f59c7b2102f633f3d6a 100644 (file)
@@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
        return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr);
 }
 
+static void udp_v6_rehash(struct sock *sk)
+{
+       u16 new_hash = udp6_portaddr_hash(sock_net(sk),
+                                         &inet6_sk(sk)->rcv_saddr,
+                                         inet_sk(sk)->inet_num);
+
+       udp_lib_rehash(sk, new_hash);
+}
+
 static inline int compute_score(struct sock *sk, struct net *net,
                                unsigned short hnum,
                                struct in6_addr *saddr, __be16 sport,
@@ -1447,6 +1456,7 @@ struct proto udpv6_prot = {
        .backlog_rcv       = udpv6_queue_rcv_skb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v6_rehash,
        .get_port          = udp_v6_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index f417b77fa0e15762715a9498974fbd8f5071401d..a67575d472a320f306002a88959f0d0f9a73af09 100644 (file)
 #include <net/addrconf.h>
 
 static void
-__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-                    struct xfrm_tmpl *tmpl,
-                    xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
 {
        /* Initialize temporary selector matching only
         * to current session. */
-       ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
-       ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
-       x->sel.dport = xfrm_flowi_dport(fl);
-       x->sel.dport_mask = htons(0xffff);
-       x->sel.sport = xfrm_flowi_sport(fl);
-       x->sel.sport_mask = htons(0xffff);
-       x->sel.family = AF_INET6;
-       x->sel.prefixlen_d = 128;
-       x->sel.prefixlen_s = 128;
-       x->sel.proto = fl->proto;
-       x->sel.ifindex = fl->oif;
+       ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst);
+       ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src);
+       sel->dport = xfrm_flowi_dport(fl);
+       sel->dport_mask = htons(0xffff);
+       sel->sport = xfrm_flowi_sport(fl);
+       sel->sport_mask = htons(0xffff);
+       sel->family = AF_INET6;
+       sel->prefixlen_d = 128;
+       sel->prefixlen_s = 128;
+       sel->proto = fl->proto;
+       sel->ifindex = fl->oif;
+}
+
+static void
+xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
+                  xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
        x->id = tmpl->id;
        if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
                memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
@@ -168,6 +172,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
        .eth_proto              = htons(ETH_P_IPV6),
        .owner                  = THIS_MODULE,
        .init_tempsel           = __xfrm6_init_tempsel,
+       .init_temprop           = xfrm6_init_temprop,
        .tmpl_sort              = __xfrm6_tmpl_sort,
        .state_sort             = __xfrm6_state_sort,
        .output                 = xfrm6_output,
index e9ad0062fbb6a8df3e13182597176016657695b6..02549cb2c3282f5a04ad70214a5cf3f95d1538bf 100644 (file)
@@ -3,6 +3,7 @@
 #
 config IPX
        tristate "The IPX protocol"
+       depends on BKL # should be fixable
        select LLC
        ---help---
          This is support for the Novell networking protocol, IPX, commonly
index 79986a674f6ea23329fb5a3960f1d3ece82b9a9d..fd55b5135de5aad91f547281a9c7a07c44f676b0 100644 (file)
@@ -824,8 +824,8 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
        if (err < 0) {
-               kfree(self->ias_obj->name);
-               kfree(self->ias_obj);
+               irias_delete_object(self->ias_obj);
+               self->ias_obj = NULL;
                goto out;
        }
 
index a788f9e9427d2c1c127d411adc8b06eb9d19ba87..6130f9d9dbe138edffaaafed0528b1d2110db0c4 100644 (file)
@@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
        memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
        le16_to_cpus(&val_len); n+=2;
 
-       if (val_len > 1016) {
+       if (val_len >= 1016) {
                IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
                return -RSP_INVALID_COMMAND_FORMAT;
        }
index 9616c32d1076dda982fff4c6da5c6e1057cf39d1..5bb8353105cca7c761647b94c346cc1da82c42e9 100644 (file)
@@ -169,6 +169,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
 {
        struct irlan_cb *self = netdev_priv(dev);
        int ret;
+       unsigned int len;
 
        /* skb headroom large enough to contain all IrDA-headers? */
        if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
@@ -188,6 +189,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
 
        dev->trans_start = jiffies;
 
+       len = skb->len;
        /* Now queue the packet in the transport layer */
        if (self->use_udata)
                ret = irttp_udata_request(self->tsap_data, skb);
@@ -209,7 +211,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
                self->stats.tx_dropped++;
        } else {
                self->stats.tx_packets++;
-               self->stats.tx_bytes += skb->len;
+               self->stats.tx_bytes += len;
        }
 
        return NETDEV_TX_OK;
index 58c6c4cda73b576cd65d3121a9abdf67bc6f7668..1ae697681bc735f3f4ed8cf98f9f63745157be36 100644 (file)
@@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
                printk("\n");
        }
 
-       if (data_len < ETH_HLEN)
+       if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
                goto error;
 
        secpath_reset(skb);
index 023ba820236f391a01595418873b7c5e0df3ece8..582612998211d24aa8d4aea919eed1ba1e994db3 100644 (file)
@@ -1024,7 +1024,8 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
 {
        struct sock *sk = sock->sk;
        struct llc_sock *llc = llc_sk(sk);
-       int rc = -EINVAL, opt;
+       unsigned int opt;
+       int rc = -EINVAL;
 
        lock_sock(sk);
        if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
index e4dae0244d76b677ee89ef0b35dd51ccf7807e06..cf4aea3ba30f3c822be7a2c19a8fef87cdb8aadf 100644 (file)
@@ -689,7 +689,7 @@ static void llc_station_rcv(struct sk_buff *skb)
 
 int __init llc_station_init(void)
 {
-       u16 rc = -ENOBUFS;
+       int rc = -ENOBUFS;
        struct sk_buff *skb;
        struct llc_station_state_ev *ev;
 
index c893f236acea771076b5572b42c82162c3684913..8f23401832b7729d28c9e0791a78ce8acd797728 100644 (file)
@@ -175,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 
        set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
 
+       del_timer_sync(&tid_tx->addba_resp_timer);
+
        /*
         * After this packets are no longer handed right through
         * to the driver but are put onto tid_tx->pending instead,
index a694c593ff6ac1e17479ae07d26ad1fd02f258ba..b8b0ae79a74390568707a29b5a98747f5573e1fa 100644 (file)
@@ -36,6 +36,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_ADD(name)                                              \
@@ -101,7 +102,8 @@ static ssize_t tsf_write(struct file *file,
 static const struct file_operations tsf_ops = {
        .read = tsf_read,
        .write = tsf_write,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t reset_write(struct file *file, const char __user *user_buf,
@@ -120,6 +122,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,
 static const struct file_operations reset_ops = {
        .write = reset_write,
        .open = mac80211_open_file_generic,
+       .llseek = noop_llseek,
 };
 
 static ssize_t noack_read(struct file *file, char __user *user_buf,
@@ -155,7 +158,8 @@ static ssize_t noack_write(struct file *file,
 static const struct file_operations noack_ops = {
        .read = noack_read,
        .write = noack_write,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
@@ -201,7 +205,8 @@ static ssize_t uapsd_queues_write(struct file *file,
 static const struct file_operations uapsd_queues_ops = {
        .read = uapsd_queues_read,
        .write = uapsd_queues_write,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
@@ -247,7 +252,8 @@ static ssize_t uapsd_max_sp_len_write(struct file *file,
 static const struct file_operations uapsd_max_sp_len_ops = {
        .read = uapsd_max_sp_len_read,
        .write = uapsd_max_sp_len_write,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t channel_type_read(struct file *file, char __user *user_buf,
@@ -279,7 +285,8 @@ static ssize_t channel_type_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations channel_type_ops = {
        .read = channel_type_read,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 static ssize_t queues_read(struct file *file, char __user *user_buf,
@@ -302,7 +309,8 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations queues_ops = {
        .read = queues_read,
-       .open = mac80211_open_file_generic
+       .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 /* statistics stuff */
@@ -346,6 +354,7 @@ static ssize_t stats_ ##name## _read(struct file *file,                     \
 static const struct file_operations stats_ ##name## _ops = {           \
        .read = stats_ ##name## _read,                                  \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 };
 
 #define DEBUGFS_STATS_ADD(name, field)                                 \
index fa5e76e658ef058b5fb87c4d4647c5025a3e4d71..7cd8dd9fc240ee027795a550d89ede7f0d66f3b4 100644 (file)
@@ -32,6 +32,7 @@ static ssize_t key_##name##_read(struct file *file,                   \
 static const struct file_operations key_ ##name## _ops = {             \
        .read = key_##name##_read,                                      \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 }
 
 #define KEY_FILE(name, format)                                         \
@@ -46,6 +47,7 @@ static const struct file_operations key_ ##name## _ops = {            \
 static const struct file_operations key_ ##name## _ops = {             \
        .read = key_conf_##name##_read,                                 \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 }
 
 #define KEY_CONF_FILE(name, format)                                    \
index 20b2998fa0ed07b68b410f77a82d0f159603d79e..8ad33eef7dda460155901f611f082af4060c34ca 100644 (file)
@@ -121,6 +121,7 @@ static const struct file_operations name##_ops = {                  \
        .read = ieee80211_if_read_##name,                               \
        .write = (_write),                                              \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 }
 
 #define __IEEE80211_IF_FILE_W(name)                                    \
index 76839d4dfaacabe15c30f886478367ad2b524585..6a8fdc372c43e2ff236da5423a58ab5f74dd8e8a 100644 (file)
@@ -36,6 +36,7 @@ static ssize_t sta_ ##name## _read(struct file *file,                 \
 static const struct file_operations sta_ ##name## _ops = {             \
        .read = sta_##name##_read,                                      \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 }
 
 #define STA_OPS_RW(name)                                               \
@@ -43,6 +44,7 @@ static const struct file_operations sta_ ##name## _ops = {            \
        .read = sta_##name##_read,                                      \
        .write = sta_##name##_write,                                    \
        .open = mac80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 }
 
 #define STA_FILE(name, field, format)                                  \
index 798a91b100cc277d154bde089eb6f4745f47b6b6..ded5c3843e061a13e1d82be4666b746c829c467c 100644 (file)
@@ -732,6 +732,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        rtnl_unlock();
 
+       /*
+        * Now all work items will be gone, but the
+        * timer might still be armed, so delete it
+        */
+       del_timer_sync(&local->work_timer);
+
        cancel_work_sync(&local->reconfig_filter);
 
        ieee80211_clear_tx_pending(local);
index be04d46110fe8cdccc5e07eb810b67ee39c5c20f..334cbd3d2aae9ceffb708f6c2c4b361b6e6359d4 100644 (file)
@@ -145,6 +145,7 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf,
 static const struct file_operations rcname_ops = {
        .read = rcname_read,
        .open = mac80211_open_file_generic,
+       .llseek = default_llseek,
 };
 #endif
 
index 241e76f3fdf2974a3a476c31d267eaa0d7c77db5..a290ad231d772b23ca6cf7d2c1377736ae77f4ad 100644 (file)
@@ -122,6 +122,7 @@ static const struct file_operations minstrel_stat_fops = {
        .open = minstrel_stats_open,
        .read = minstrel_stats_read,
        .release = minstrel_stats_release,
+       .llseek = default_llseek,
 };
 
 void
index 4a5a4b3e7799f1845421843e22fee503ef62ffb4..cefcb5d2dae6e40888af8d712ed564a00cebc42c 100644 (file)
@@ -90,7 +90,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
                MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
        ms->len = p - ms->buf;
 
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static const struct file_operations minstrel_ht_stat_fops = {
@@ -98,6 +98,7 @@ static const struct file_operations minstrel_ht_stat_fops = {
        .open = minstrel_ht_stats_open,
        .read = minstrel_stats_read,
        .release = minstrel_stats_release,
+       .llseek = no_llseek,
 };
 
 void
index 47438b4a9af52d33589e9cc1a695f77a8461d987..7905f79cc2e43197e644a5e44931de4cd735e6a0 100644 (file)
@@ -206,6 +206,7 @@ static const struct file_operations rc_pid_fop_events = {
        .poll = rate_control_pid_events_poll,
        .open = rate_control_pid_events_open,
        .release = rate_control_pid_events_release,
+       .llseek = noop_llseek,
 };
 
 void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
index fa0f37e4afe4901226b0ccd668ae6a88c136eeb2..28624282c5f36ad5bed8f74c0e8bf7df42ee2d6c 100644 (file)
@@ -2199,9 +2199,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
        struct net_device *prev_dev = NULL;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-       if (status->flag & RX_FLAG_INTERNAL_CMTR)
-               goto out_free_skb;
-
        if (skb_headroom(skb) < sizeof(*rthdr) &&
            pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
                goto out_free_skb;
@@ -2260,7 +2257,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
        } else
                goto out_free_skb;
 
-       status->flag |= RX_FLAG_INTERNAL_CMTR;
        return;
 
  out_free_skb:
index 10caec5ea8fa7740d9617605adf1590eefa2a730..34da67995d94ae91c8982776fd3e9104c161079f 100644 (file)
@@ -377,7 +377,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                                skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2) {
                                        skb2->dev = prev_dev;
-                                       netif_receive_skb(skb2);
+                                       netif_rx(skb2);
                                }
                        }
 
@@ -386,7 +386,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        }
        if (prev_dev) {
                skb->dev = prev_dev;
-               netif_receive_skb(skb);
+               netif_rx(skb);
                skb = NULL;
        }
        rcu_read_unlock();
index 78b505d33bfb42cdf1033be323c2fdb1a359a833..fdaec7daff1d539038ef6ee6c0d0acfeae6e7cf6 100644 (file)
@@ -27,7 +27,7 @@
 
 static DEFINE_MUTEX(afinfo_mutex);
 
-const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
+const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
 EXPORT_SYMBOL(nf_afinfo);
 
 int nf_register_afinfo(const struct nf_afinfo *afinfo)
index 4f8ddba480110167674fa36f6854e53f673e8d68..4c2f89df5ccecc40f1dc9200772a4e8bb3e85b95 100644 (file)
@@ -924,6 +924,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 
        ip_vs_out_stats(cp, skb);
        ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
+       ip_vs_update_conntrack(skb, cp, 0);
        ip_vs_conn_put(cp);
 
        skb->ipvs_property = 1;
index f228a17ec6499b1440cae8a9dd9a1d8e312c4a00..7e9af5b76d9eb280cc7d197538e5ce6161c42e66 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_helper.h>
 #include <linux/gfp.h>
 #include <net/protocol.h>
@@ -359,7 +360,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
                buf_len = strlen(buf);
 
                ct = nf_ct_get(skb, &ctinfo);
-               if (ct && !nf_ct_is_untracked(ct)) {
+               if (ct && !nf_ct_is_untracked(ct) && nfct_nat(ct)) {
                        /* If mangling fails this function will return 0
                         * which will cause the packet to be dropped.
                         * Mangling can only fail under memory pressure,
@@ -409,7 +410,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
        union nf_inet_addr to;
        __be16 port;
        struct ip_vs_conn *n_cp;
-       struct nf_conn *ct;
 
 #ifdef CONFIG_IP_VS_IPV6
        /* This application helper doesn't work with IPv6 yet,
@@ -496,11 +496,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
                ip_vs_control_add(n_cp, cp);
        }
 
-       ct = (struct nf_conn *)skb->nfct;
-       if (ct && ct != &nf_conntrack_untracked)
-               ip_vs_expect_related(skb, ct, n_cp,
-                                    IPPROTO_TCP, &n_cp->dport, 1);
-
        /*
         *      Move tunnel to listen state
         */
index 21e1a5e9b9d3cd354d74808e44094ffc67f671da..49df6bea6a2ddaec391ce077cf9f72a72efc4a7f 100644 (file)
@@ -349,8 +349,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 }
 #endif
 
-static void
-ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
+void
+ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
 {
        struct nf_conn *ct = (struct nf_conn *)skb->nfct;
        struct nf_conntrack_tuple new_tuple;
@@ -365,11 +365,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
         * real-server we will see RIP->DIP.
         */
        new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-       new_tuple.src.u3 = cp->daddr;
+       if (outin)
+               new_tuple.src.u3 = cp->daddr;
+       else
+               new_tuple.dst.u3 = cp->vaddr;
        /*
         * This will also take care of UDP and other protocols.
         */
-       new_tuple.src.u.tcp.port = cp->dport;
+       if (outin)
+               new_tuple.src.u.tcp.port = cp->dport;
+       else
+               new_tuple.dst.u.tcp.port = cp->vport;
        nf_conntrack_alter_reply(ct, &new_tuple);
 }
 
@@ -428,7 +434,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
        IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
 
-       ip_vs_update_conntrack(skb, cp);
+       ip_vs_update_conntrack(skb, cp, 1);
 
        /* FIXME: when application helper enlarges the packet and the length
           is larger than the MTU of outgoing device, there will be still
@@ -506,7 +512,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
        IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
 
-       ip_vs_update_conntrack(skb, cp);
+       ip_vs_update_conntrack(skb, cp, 1);
 
        /* FIXME: when application helper enlarges the packet and the length
           is larger than the MTU of outgoing device, there will be still
index cdcc7649476b60e0e8584a7c2b2d31e7509a4bd4..5702de35e2bb327ea0e9bd346f57bf8ebf36c951 100644 (file)
 
 static DEFINE_MUTEX(nf_ct_ecache_mutex);
 
-struct nf_ct_event_notifier *nf_conntrack_event_cb __read_mostly;
+struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_event_cb);
 
-struct nf_exp_event_notifier *nf_expect_event_cb __read_mostly;
+struct nf_exp_event_notifier __rcu *nf_expect_event_cb __read_mostly;
 EXPORT_SYMBOL_GPL(nf_expect_event_cb);
 
 /* deliver cached events and clear cache entry - must be called with locally
index 7dcf7a404190e6aa3fa06e642f54279e2f30fba9..bd82450c193f5dbb4895f4fc7565040686fa740d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/skbuff.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 
-static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
+static struct nf_ct_ext_type __rcu *nf_ct_ext_types[NF_CT_EXT_NUM];
 static DEFINE_MUTEX(nf_ct_ext_type_mutex);
 
 void __nf_ct_ext_destroy(struct nf_conn *ct)
@@ -48,15 +48,17 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
 {
        unsigned int off, len;
        struct nf_ct_ext_type *t;
+       size_t alloc_size;
 
        rcu_read_lock();
        t = rcu_dereference(nf_ct_ext_types[id]);
        BUG_ON(t == NULL);
        off = ALIGN(sizeof(struct nf_ct_ext), t->align);
        len = off + t->len;
+       alloc_size = t->alloc_size;
        rcu_read_unlock();
 
-       *ext = kzalloc(t->alloc_size, gfp);
+       *ext = kzalloc(alloc_size, gfp);
        if (!*ext)
                return NULL;
 
index 5bae1cd15eea93ee3f74cb51dab972c10c96d33c..146476c6441a9ea8894d78bc5a00c558c84a0874 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/rculist_nulls.h>
 #include <linux/types.h>
 #include <linux/timer.h>
+#include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
 #include <linux/netlink.h>
@@ -245,16 +246,31 @@ nla_put_failure:
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 static inline int
-ctnetlink_dump_secmark(struct sk_buff *skb, const struct nf_conn *ct)
+ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 {
-       NLA_PUT_BE32(skb, CTA_SECMARK, htonl(ct->secmark));
-       return 0;
+       struct nlattr *nest_secctx;
+       int len, ret;
+       char *secctx;
+
+       ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+       if (ret)
+               return ret;
+
+       ret = -1;
+       nest_secctx = nla_nest_start(skb, CTA_SECCTX | NLA_F_NESTED);
+       if (!nest_secctx)
+               goto nla_put_failure;
+
+       NLA_PUT_STRING(skb, CTA_SECCTX_NAME, secctx);
+       nla_nest_end(skb, nest_secctx);
 
+       ret = 0;
 nla_put_failure:
-       return -1;
+       security_release_secctx(secctx, len);
+       return ret;
 }
 #else
-#define ctnetlink_dump_secmark(a, b) (0)
+#define ctnetlink_dump_secctx(a, b) (0)
 #endif
 
 #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
@@ -391,7 +407,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
            ctnetlink_dump_protoinfo(skb, ct) < 0 ||
            ctnetlink_dump_helpinfo(skb, ct) < 0 ||
            ctnetlink_dump_mark(skb, ct) < 0 ||
-           ctnetlink_dump_secmark(skb, ct) < 0 ||
+           ctnetlink_dump_secctx(skb, ct) < 0 ||
            ctnetlink_dump_id(skb, ct) < 0 ||
            ctnetlink_dump_use(skb, ct) < 0 ||
            ctnetlink_dump_master(skb, ct) < 0 ||
@@ -437,6 +453,17 @@ ctnetlink_counters_size(const struct nf_conn *ct)
               ;
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ctnetlink_nlmsg_secctx_size(const struct nf_conn *ct)
+{
+       int len;
+
+       security_secid_to_secctx(ct->secmark, NULL, &len);
+
+       return sizeof(char) * len;
+}
+#endif
+
 static inline size_t
 ctnetlink_nlmsg_size(const struct nf_conn *ct)
 {
@@ -453,7 +480,8 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct)
               + nla_total_size(0) /* CTA_HELP */
               + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
-              + nla_total_size(sizeof(u_int32_t)) /* CTA_SECMARK */
+              + nla_total_size(0) /* CTA_SECCTX */
+              + nla_total_size(ctnetlink_nlmsg_secctx_size(ct)) /* CTA_SECCTX_NAME */
 #endif
 #ifdef CONFIG_NF_NAT_NEEDED
               + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
@@ -556,7 +584,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
                if ((events & (1 << IPCT_SECMARK) || ct->secmark)
-                   && ctnetlink_dump_secmark(skb, ct) < 0)
+                   && ctnetlink_dump_secctx(skb, ct) < 0)
                        goto nla_put_failure;
 #endif
 
index 5886ba1d52a0c353a2538313c717328cacfdcac3..ed6d929580236c1b4aa77a42db959c9e522f2fc5 100644 (file)
@@ -28,8 +28,8 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-static struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
-struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
+static struct nf_conntrack_l4proto __rcu **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX] __read_mostly;
 EXPORT_SYMBOL_GPL(nf_ct_l3protos);
 
 static DEFINE_MUTEX(nf_ct_proto_mutex);
index 53d892210a049363fa3ab04f6e17b04fa9969bbe..f64de95448669242cf23ac5d8a38987c2f8cd344 100644 (file)
@@ -1376,7 +1376,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
        unsigned int msglen, origlen;
        const char *dptr, *end;
        s16 diff, tdiff = 0;
-       int ret;
+       int ret = NF_ACCEPT;
        typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;
 
        if (ctinfo != IP_CT_ESTABLISHED &&
index eb973fcd67ab4273a3cdee566a5f4a4fb44a24f2..0fb65705b44b522e3ba4de6c02d06f119f43f2d9 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
 #include <linux/netdevice.h>
+#include <linux/security.h>
 #include <net/net_namespace.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
@@ -108,6 +109,29 @@ static void ct_seq_stop(struct seq_file *s, void *v)
        rcu_read_unlock();
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+       int ret;
+       u32 len;
+       char *secctx;
+
+       ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+       if (ret)
+               return ret;
+
+       ret = seq_printf(s, "secctx=%s ", secctx);
+
+       security_release_secctx(secctx, len);
+       return ret;
+}
+#else
+static inline int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+       return 0;
+}
+#endif
+
 /* return 0 on success, 1 in case of error */
 static int ct_seq_show(struct seq_file *s, void *v)
 {
@@ -168,10 +192,8 @@ static int ct_seq_show(struct seq_file *s, void *v)
                goto release;
 #endif
 
-#ifdef CONFIG_NF_CONNTRACK_SECMARK
-       if (seq_printf(s, "secmark=%u ", ct->secmark))
+       if (ct_show_secctx(s, ct))
                goto release;
-#endif
 
 #ifdef CONFIG_NF_CONNTRACK_ZONES
        if (seq_printf(s, "zone=%u ", nf_ct_zone(ct)))
index 7df37fd786bc19406a5ed8a8558df95cd26d93be..b07393eab88e2fb86a21d7556f7ce532c807a172 100644 (file)
@@ -16,7 +16,7 @@
 #define NF_LOG_PREFIXLEN               128
 #define NFLOGGER_NAME_LEN              64
 
-static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
+static const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
 static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly;
 static DEFINE_MUTEX(nf_log_mutex);
 
index 78b3cf9c519ca86e66b0ba4ae88c6797a7518c3f..74aebed5bd28bb5c0c924cec7d908615b82ffdd6 100644 (file)
@@ -18,7 +18,7 @@
  * long term mutex.  The handler must provide an an outfn() to accept packets
  * for queueing and must reinject all packets it receives, no matter what.
  */
-static const struct nf_queue_handler *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
+static const struct nf_queue_handler __rcu *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
 
 static DEFINE_MUTEX(queue_handler_mutex);
 
index 5490fc37c92dfa5363a2992fd67fd4f145f65360..daab8c4a903ca20103c1c5d6ebe997fdb657f581 100644 (file)
@@ -70,7 +70,11 @@ nf_tproxy_destructor(struct sk_buff *skb)
 int
 nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
 {
-       if (inet_sk(sk)->transparent) {
+       bool transparent = (sk->sk_state == TCP_TIME_WAIT) ?
+                               inet_twsk(sk)->tw_transparent :
+                               inet_sk(sk)->transparent;
+
+       if (transparent) {
                skb_orphan(skb);
                skb->sk = sk;
                skb->destructor = nf_tproxy_destructor;
index 0cb6053f02fdf04723254bfe90d8ca9bff29edfc..782e51986a6f670ce6c033c1a1d99e5a26d46885 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/skbuff.h>
-#include <linux/selinux.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/x_tables.h>
index 23b2d6c486b573927dcefd00b575546b35376bfa..9faf5e050b796186b3204a02ece181726a26cb1a 100644 (file)
@@ -14,8 +14,8 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
+#include <linux/security.h>
 #include <linux/skbuff.h>
-#include <linux/selinux.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_SECMARK.h>
 
@@ -39,9 +39,8 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 
        switch (mode) {
        case SECMARK_MODE_SEL:
-               secmark = info->u.sel.selsid;
+               secmark = info->secid;
                break;
-
        default:
                BUG();
        }
@@ -50,33 +49,33 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
        return XT_CONTINUE;
 }
 
-static int checkentry_selinux(struct xt_secmark_target_info *info)
+static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
        int err;
-       struct xt_secmark_target_selinux_info *sel = &info->u.sel;
 
-       sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
+       info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
+       info->secid = 0;
 
-       err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+       err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
+                                      &info->secid);
        if (err) {
                if (err == -EINVAL)
-                       pr_info("invalid SELinux context \'%s\'\n",
-                               sel->selctx);
+                       pr_info("invalid security context \'%s\'\n", info->secctx);
                return err;
        }
 
-       if (!sel->selsid) {
-               pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
+       if (!info->secid) {
+               pr_info("unable to map security context \'%s\'\n", info->secctx);
                return -ENOENT;
        }
 
-       err = selinux_secmark_relabel_packet_permission(sel->selsid);
+       err = security_secmark_relabel_packet(info->secid);
        if (err) {
                pr_info("unable to obtain relabeling permission\n");
                return err;
        }
 
-       selinux_secmark_refcount_inc();
+       security_secmark_refcount_inc();
        return 0;
 }
 
@@ -100,16 +99,16 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)
 
        switch (info->mode) {
        case SECMARK_MODE_SEL:
-               err = checkentry_selinux(info);
-               if (err <= 0)
-                       return err;
                break;
-
        default:
                pr_info("invalid mode: %hu\n", info->mode);
                return -EINVAL;
        }
 
+       err = checkentry_lsm(info);
+       if (err)
+               return err;
+
        if (!mode)
                mode = info->mode;
        return 0;
@@ -119,7 +118,7 @@ static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
 {
        switch (mode) {
        case SECMARK_MODE_SEL:
-               selinux_secmark_refcount_dec();
+               security_secmark_refcount_dec();
        }
 }
 
index 76aec6a44762df7de9a371ea61bab9925c933be8..d2ff15a2412b3335b016e2598d10cb9e2d31eabe 100644 (file)
@@ -567,6 +567,7 @@ static const struct file_operations recent_mt_fops = {
        .write   = recent_mt_proc_write,
        .release = seq_release_private,
        .owner   = THIS_MODULE,
+       .llseek = seq_lseek,
 };
 
 static int __net_init recent_proc_net_init(struct net *net)
index 8648a9922aabace0231de8eec18b88e30239fd5f..cd96ed3ccee4602a9fee20464e4a54d3fb0783b2 100644 (file)
@@ -1406,7 +1406,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
        struct netlink_sock *nlk = nlk_sk(sk);
        int noblock = flags&MSG_DONTWAIT;
        size_t copied;
-       struct sk_buff *skb, *frag __maybe_unused = NULL;
+       struct sk_buff *skb, *data_skb;
        int err;
 
        if (flags&MSG_OOB)
@@ -1418,45 +1418,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
        if (skb == NULL)
                goto out;
 
+       data_skb = skb;
+
 #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
        if (unlikely(skb_shinfo(skb)->frag_list)) {
-               bool need_compat = !!(flags & MSG_CMSG_COMPAT);
-
                /*
-                * If this skb has a frag_list, then here that means that
-                * we will have to use the frag_list skb for compat tasks
-                * and the regular skb for non-compat tasks.
+                * If this skb has a frag_list, then here that means that we
+                * will have to use the frag_list skb's data for compat tasks
+                * and the regular skb's data for normal (non-compat) tasks.
                 *
-                * The skb might (and likely will) be cloned, so we can't
-                * just reset frag_list and go on with things -- we need to
-                * keep that. For the compat case that's easy -- simply get
-                * a reference to the compat skb and free the regular one
-                * including the frag. For the non-compat case, we need to
-                * avoid sending the frag to the user -- so assign NULL but
-                * restore it below before freeing the skb.
+                * If we need to send the compat skb, assign it to the
+                * 'data_skb' variable so that it will be used below for data
+                * copying. We keep 'skb' for everything else, including
+                * freeing both later.
                 */
-               if (need_compat) {
-                       struct sk_buff *compskb = skb_shinfo(skb)->frag_list;
-                       skb_get(compskb);
-                       kfree_skb(skb);
-                       skb = compskb;
-               } else {
-                       frag = skb_shinfo(skb)->frag_list;
-                       skb_shinfo(skb)->frag_list = NULL;
-               }
+               if (flags & MSG_CMSG_COMPAT)
+                       data_skb = skb_shinfo(skb)->frag_list;
        }
 #endif
 
        msg->msg_namelen = 0;
 
-       copied = skb->len;
+       copied = data_skb->len;
        if (len < copied) {
                msg->msg_flags |= MSG_TRUNC;
                copied = len;
        }
 
-       skb_reset_transport_header(skb);
-       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       skb_reset_transport_header(data_skb);
+       err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied);
 
        if (msg->msg_name) {
                struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name;
@@ -1476,11 +1466,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
        }
        siocb->scm->creds = *NETLINK_CREDS(skb);
        if (flags & MSG_TRUNC)
-               copied = skb->len;
-
-#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
-       skb_shinfo(skb)->frag_list = frag;
-#endif
+               copied = data_skb->len;
 
        skb_free_datagram(sk, skb);
 
@@ -2116,6 +2102,26 @@ static void __net_exit netlink_net_exit(struct net *net)
 #endif
 }
 
+static void __init netlink_add_usersock_entry(void)
+{
+       unsigned long *listeners;
+       int groups = 32;
+
+       listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head),
+                           GFP_KERNEL);
+       if (!listeners)
+               panic("netlink_add_usersock_entry: Cannot allocate listneres\n");
+
+       netlink_table_grab();
+
+       nl_table[NETLINK_USERSOCK].groups = groups;
+       nl_table[NETLINK_USERSOCK].listeners = listeners;
+       nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
+       nl_table[NETLINK_USERSOCK].registered = 1;
+
+       netlink_table_ungrab();
+}
+
 static struct pernet_operations __net_initdata netlink_net_ops = {
        .init = netlink_net_init,
        .exit = netlink_net_exit,
@@ -2164,6 +2170,8 @@ static int __init netlink_proto_init(void)
                hash->rehash_time = jiffies;
        }
 
+       netlink_add_usersock_entry();
+
        sock_register(&netlink_family_ops);
        register_pernet_subsys(&netlink_net_ops);
        /* The netlink device handler may be needed early. */
index 92e76640c7cd65146dd6aed382698174f7a0f2a2..b1a73fda9c12ed4225f13b3b9ce4051950510025 100644 (file)
@@ -22,4 +22,5 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
 const struct file_operations bad_sock_fops = {
        .owner = THIS_MODULE,
        .open = sock_no_open,
+       .llseek = noop_llseek,
 };
index b2a3ae6cad78e28324e23b857dc0a5773f569786..15003021f4f0a8706e540150425b4f995dc582a6 100644 (file)
@@ -225,12 +225,13 @@ static void pipe_grant_credits(struct sock *sk)
 static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
 {
        struct pep_sock *pn = pep_sk(sk);
-       struct pnpipehdr *hdr = pnp_hdr(skb);
+       struct pnpipehdr *hdr;
        int wake = 0;
 
        if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
                return -EINVAL;
 
+       hdr = pnp_hdr(skb);
        if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
                LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n",
                                (unsigned)hdr->data[0]);
index 595a952d4b17f069c60a457701d6e207f68e621b..1dfbfea12e9bc82ba8482277b4331289effa275b 100644 (file)
@@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset,
        unsigned long ret;
        void *addr;
 
-       if (to_user)
+       addr = kmap(page);
+       if (to_user) {
                rds_stats_add(s_copy_to_user, bytes);
-       else
+               ret = copy_to_user(ptr, addr + offset, bytes);
+       } else {
                rds_stats_add(s_copy_from_user, bytes);
-
-       addr = kmap_atomic(page, KM_USER0);
-       if (to_user)
-               ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
-       else
-               ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
-       kunmap_atomic(addr, KM_USER0);
-
-       if (ret) {
-               addr = kmap(page);
-               if (to_user)
-                       ret = copy_to_user(ptr, addr + offset, bytes);
-               else
-                       ret = copy_from_user(addr + offset, ptr, bytes);
-               kunmap(page);
-               if (ret)
-                       return -EFAULT;
+               ret = copy_from_user(addr + offset, ptr, bytes);
        }
+       kunmap(page);
 
-       return 0;
+       return ret ? -EFAULT : 0;
 }
 EXPORT_SYMBOL_GPL(rds_page_copy_user);
 
index 795a00b7f2cb7aa6a539adb3c86a2cad180575f1..c93588c2d553cf6b162ab500cf1fd72dbbc9c26c 100644 (file)
@@ -297,7 +297,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc,
 int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr)
 {
        struct rds_notifier *notifier;
-       struct rds_rdma_notify cmsg;
+       struct rds_rdma_notify cmsg = { 0 }; /* fill holes with zero */
        unsigned int count = 0, max_messages = ~0U;
        unsigned long flags;
        LIST_HEAD(copy);
index c397524c039cdb28140ff5f6c0fe2359cebfa3b5..c519939e8da98fd3ae8252355a0ebb9efac4acd5 100644 (file)
@@ -43,7 +43,7 @@ void rds_tcp_state_change(struct sock *sk)
        struct rds_connection *conn;
        struct rds_tcp_connection *tc;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        conn = sk->sk_user_data;
        if (conn == NULL) {
                state_change = sk->sk_state_change;
@@ -68,7 +68,7 @@ void rds_tcp_state_change(struct sock *sk)
                        break;
        }
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        state_change(sk);
 }
 
index 975183fe6950a34b242ef55db011e6f04c1c6772..27844f231d103a4e49e542d670eaca66d01e761d 100644 (file)
@@ -114,7 +114,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes)
 
        rdsdebug("listen data ready sk %p\n", sk);
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        ready = sk->sk_user_data;
        if (ready == NULL) { /* check for teardown race */
                ready = sk->sk_data_ready;
@@ -131,7 +131,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes)
                queue_work(rds_wq, &rds_tcp_listen_work);
 
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        ready(sk, bytes);
 }
 
index 1aba6878fa5dc42d4c54473350fde61d714a184c..e43797404102efcc2ed45117456e839b5425adb1 100644 (file)
@@ -324,7 +324,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes)
 
        rdsdebug("data ready sk %p bytes %d\n", sk, bytes);
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        conn = sk->sk_user_data;
        if (conn == NULL) { /* check for teardown race */
                ready = sk->sk_data_ready;
@@ -338,7 +338,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes)
        if (rds_tcp_read_sock(conn, GFP_ATOMIC, KM_SOFTIRQ0) == -ENOMEM)
                queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        ready(sk, bytes);
 }
 
index a28b895ff0d10194730463b218e3ccb526cdea50..2f012a07d94d16d3aa01d4c78d0894e939dfd751 100644 (file)
@@ -224,7 +224,7 @@ void rds_tcp_write_space(struct sock *sk)
        struct rds_connection *conn;
        struct rds_tcp_connection *tc;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        conn = sk->sk_user_data;
        if (conn == NULL) {
                write_space = sk->sk_write_space;
@@ -244,7 +244,7 @@ void rds_tcp_write_space(struct sock *sk)
                queue_delayed_work(rds_wq, &conn->c_send_w, 0);
 
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 
        /*
         * write_space is only called when data leaves tcp's send queue if
index 51875a0c5d48c489899e1bcb71c3fd2a2fd3c91c..04f599089e6d1bdc64d3625c288fc132b3cd621a 100644 (file)
@@ -1241,6 +1241,7 @@ static const struct file_operations rfkill_fops = {
        .unlocked_ioctl = rfkill_fop_ioctl,
        .compat_ioctl   = rfkill_fop_ioctl,
 #endif
+       .llseek         = no_llseek,
 };
 
 static struct miscdevice rfkill_miscdev = {
index 8e45e76a95f51cdca332263ee7e32108f0beb95c..d952e7eac18867501a0bf7d2034c621c2fd08df7 100644 (file)
@@ -679,7 +679,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
                return -EINVAL;
 
-       if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+       if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
                return -EINVAL;
 
        if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) {
@@ -739,7 +739,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
        if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
                return -EINVAL;
 
-       if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+       if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
                return -EINVAL;
 
        /* Source + Destination digis should not exceed ROSE_MAX_DIGIS */
index 537a48732e9e0b8513dd324801c342ec00cd3820..7ebf7439b478d24b4246527c7313fb8cb774496b 100644 (file)
@@ -350,22 +350,19 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
        struct tcf_police *police = a->priv;
-       struct tc_police opt;
-
-       opt.index = police->tcf_index;
-       opt.action = police->tcf_action;
-       opt.mtu = police->tcfp_mtu;
-       opt.burst = police->tcfp_burst;
-       opt.refcnt = police->tcf_refcnt - ref;
-       opt.bindcnt = police->tcf_bindcnt - bind;
+       struct tc_police opt = {
+               .index = police->tcf_index,
+               .action = police->tcf_action,
+               .mtu = police->tcfp_mtu,
+               .burst = police->tcfp_burst,
+               .refcnt = police->tcf_refcnt - ref,
+               .bindcnt = police->tcf_bindcnt - bind,
+       };
+
        if (police->tcfp_R_tab)
                opt.rate = police->tcfp_R_tab->rate;
-       else
-               memset(&opt.rate, 0, sizeof(opt.rate));
        if (police->tcfp_P_tab)
                opt.peakrate = police->tcfp_P_tab->rate;
-       else
-               memset(&opt.peakrate, 0, sizeof(opt.peakrate));
        NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
        if (police->tcfp_result)
                NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
index 78ef2c5e130ba9224512dd3872d86226b36306f3..37dff78e9cb17c6fcf35e5302d57b84dd5e9f5f9 100644 (file)
@@ -123,7 +123,7 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
         * calls by looking at the number of nested bh disable calls because
         * softirqs always disables bh.
         */
-       if (softirq_count() != SOFTIRQ_OFFSET) {
+       if (in_serving_softirq()) {
                /* If there is an sk_classid we'll use that. */
                if (!skb->sk)
                        return -1;
index 7416a5c73b2a993550991ac66eca7cc254c6f2e6..b0c2a82178afa032ce1d09b0e9f400afb2b578f5 100644 (file)
@@ -137,7 +137,7 @@ next_knode:
                        int toff = off + key->off + (off2 & key->offmask);
                        __be32 *data, _data;
 
-                       if (skb_headroom(skb) + toff < 0)
+                       if (skb_headroom(skb) + toff > INT_MAX)
                                goto out;
 
                        data = skb_header_pointer(skb, toff, 4, &_data);
index 3406627895298324fdd9d27186ad8c9c8d9a9964..6318e1136b83de86f1b73150a0a5199522293f4f 100644 (file)
@@ -255,10 +255,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
                        error = -EINVAL;
                        goto err_out;
                }
-               if (!list_empty(&flow->list)) {
-                       error = -EEXIST;
-                       goto err_out;
-               }
        } else {
                int i;
                unsigned long cl;
index abd904be428717462395d62adb682023e64e17a5..47496098d35c2876cd0b5a88e1365922cc369ce9 100644 (file)
@@ -761,8 +761,8 @@ init_vf(struct hfsc_class *cl, unsigned int len)
                if (f != cl->cl_f) {
                        cl->cl_f = f;
                        cftree_update(cl);
-                       update_cfmin(cl->cl_parent);
                }
+               update_cfmin(cl->cl_parent);
        }
 }
 
index 86366390038a1cae0b536874fd037464f2a1678f..ddbbf7c81fa1d62adf50600b6c788d6769ff5d32 100644 (file)
@@ -543,16 +543,20 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc)
                id = ntohs(hmacs->hmac_ids[i]);
 
                /* Check the id is in the supported range */
-               if (id > SCTP_AUTH_HMAC_ID_MAX)
+               if (id > SCTP_AUTH_HMAC_ID_MAX) {
+                       id = 0;
                        continue;
+               }
 
                /* See is we support the id.  Supported IDs have name and
                 * length fields set, so that we can allocated and use
                 * them.  We can safely just check for name, for without the
                 * name, we can't allocate the TFM.
                 */
-               if (!sctp_hmac_list[id].hmac_name)
+               if (!sctp_hmac_list[id].hmac_name) {
+                       id = 0;
                        continue;
+               }
 
                break;
        }
index a646681f5acdffe30cd7b5b2f06c3bbf413609a6..bcc4590ccaf21bb988a7827614f71a39ffa31318 100644 (file)
@@ -92,7 +92,6 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
        SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__,
                          packet, vtag);
 
-       sctp_packet_reset(packet);
        packet->vtag = vtag;
 
        if (ecn_capable && sctp_packet_empty(packet)) {
index db3a42b8b34962594b7c8fe3e38b45cb68b19f83..289b1ba62cac6623886f8bf47c50b74cc86cd66e 100644 (file)
@@ -117,6 +117,7 @@ static const struct file_operations sctpprobe_fops = {
        .owner  = THIS_MODULE,
        .open   = sctpprobe_open,
        .read   = sctpprobe_read,
+       .llseek = noop_llseek,
 };
 
 sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
index 24b2cd55563726e8cd24be5dfbfafe8eb2892886..d344dc481ccc7a22d517c13995e825a73bed21ce 100644 (file)
@@ -1232,6 +1232,18 @@ out:
        return 0;
 }
 
+static bool list_has_sctp_addr(const struct list_head *list,
+                              union sctp_addr *ipaddr)
+{
+       struct sctp_transport *addr;
+
+       list_for_each_entry(addr, list, transports) {
+               if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr))
+                       return true;
+       }
+
+       return false;
+}
 /* A restart is occurring, check to make sure no new addresses
  * are being added as we may be under a takeover attack.
  */
@@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
                                       struct sctp_chunk *init,
                                       sctp_cmd_seq_t *commands)
 {
-       struct sctp_transport *new_addr, *addr;
-       int found;
+       struct sctp_transport *new_addr;
+       int ret = 1;
 
-       /* Implementor's Guide - Sectin 5.2.2
+       /* Implementor's Guide - Section 5.2.2
         * ...
         * Before responding the endpoint MUST check to see if the
         * unexpected INIT adds new addresses to the association. If new
@@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
        /* Search through all current addresses and make sure
         * we aren't adding any new ones.
         */
-       new_addr = NULL;
-       found = 0;
-
        list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
-                       transports) {
-               found = 0;
-               list_for_each_entry(addr, &asoc->peer.transport_addr_list,
-                               transports) {
-                       if (sctp_cmp_addr_exact(&new_addr->ipaddr,
-                                               &addr->ipaddr)) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
+                           transports) {
+               if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
+                                       &new_addr->ipaddr)) {
+                       sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
+                                                  commands);
+                       ret = 0;
                        break;
-       }
-
-       /* If a new address was added, ABORT the sender. */
-       if (!found && new_addr) {
-               sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands);
+               }
        }
 
        /* Return success if all addresses were found. */
-       return found;
+       return ret;
 }
 
 /* Populate the verification/tie tags based on overlapping INIT
index ca44917872d2553b98f4e2f3601f95fe0f2c414f..fbb70770ad05d05807d25b5527e5616a621f58e8 100644 (file)
@@ -916,6 +916,11 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        /* Walk through the addrs buffer and count the number of addresses. */
        addr_buf = kaddrs;
        while (walk_size < addrs_size) {
+               if (walk_size + sizeof(sa_family_t) > addrs_size) {
+                       kfree(kaddrs);
+                       return -EINVAL;
+               }
+
                sa_addr = (struct sockaddr *)addr_buf;
                af = sctp_get_af_specific(sa_addr->sa_family);
 
@@ -1002,9 +1007,13 @@ static int __sctp_connect(struct sock* sk,
        /* Walk through the addrs buffer and count the number of addresses. */
        addr_buf = kaddrs;
        while (walk_size < addrs_size) {
+               if (walk_size + sizeof(sa_family_t) > addrs_size) {
+                       err = -EINVAL;
+                       goto out_free;
+               }
+
                sa_addr = (union sctp_addr *)addr_buf;
                af = sctp_get_af_specific(sa_addr->sa.sa_family);
-               port = ntohs(sa_addr->v4.sin_port);
 
                /* If the address family is not supported or if this address
                 * causes the address buffer to overflow return EINVAL.
@@ -1014,6 +1023,8 @@ static int __sctp_connect(struct sock* sk,
                        goto out_free;
                }
 
+               port = ntohs(sa_addr->v4.sin_port);
+
                /* Save current address so we can work with it */
                memcpy(&to, sa_addr, af->sockaddr_len);
 
index 2270b941bcc76ec0e52cc0d1321d8572164299e1..9eac5c3941340c60343233402886780117aa93d3 100644 (file)
@@ -502,6 +502,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
 const struct file_operations bad_sock_fops = {
        .owner = THIS_MODULE,
        .open = sock_no_open,
+       .llseek = noop_llseek,
 };
 
 /**
index 36cb66022a279e96869de77c3c9cebbbe9824ff4..e9eaaf7d43c18104167692f801794bdacf89b97e 100644 (file)
@@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
 static LIST_HEAD(cred_unused);
 static unsigned long number_cred_unused;
 
-#define MAX_HASHTABLE_BITS (10) 
+#define MAX_HASHTABLE_BITS (14)
 static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp)
 {
        unsigned long num;
index dcfc66bab2bb16f9872aca4adc6b258b55afe05a..12c4859828146cbdff7a0e9c38a039eaa3395426 100644 (file)
@@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode)
        struct rpc_inode *rpci = RPC_I(inode);
        struct gss_upcall_msg *gss_msg;
 
+restart:
        spin_lock(&inode->i_lock);
-       while (!list_empty(&rpci->in_downcall)) {
+       list_for_each_entry(gss_msg, &rpci->in_downcall, list) {
 
-               gss_msg = list_entry(rpci->in_downcall.next,
-                               struct gss_upcall_msg, list);
+               if (!list_empty(&gss_msg->msg.list))
+                       continue;
                gss_msg->msg.errno = -EPIPE;
                atomic_inc(&gss_msg->count);
                __gss_unhash_msg(gss_msg);
                spin_unlock(&inode->i_lock);
                gss_release_msg(gss_msg);
-               spin_lock(&inode->i_lock);
+               goto restart;
        }
        spin_unlock(&inode->i_lock);
 
index 032644610524306ea0e01383b3c4ea54888b10ab..778e5dfc5144910f83609b8bf48ca2a35011110d 100644 (file)
@@ -237,6 +237,7 @@ get_key(const void *p, const void *end,
        if (!supported_gss_krb5_enctype(alg)) {
                printk(KERN_WARNING "gss_kerberos_mech: unsupported "
                        "encryption key algorithm %d\n", alg);
+               p = ERR_PTR(-EINVAL);
                goto out_err;
        }
        p = simple_get_netobj(p, end, &key);
@@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
        ctx->enctype = ENCTYPE_DES_CBC_RAW;
 
        ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
-       if (ctx->gk5e == NULL)
+       if (ctx->gk5e == NULL) {
+               p = ERR_PTR(-EINVAL);
                goto out_err;
+       }
 
        /* The downcall format was designed before we completely understood
         * the uses of the context fields; so it includes some stuff we
         * just give some minimal sanity-checking, and some we ignore
         * completely (like the next twenty bytes): */
-       if (unlikely(p + 20 > end || p + 20 < p))
+       if (unlikely(p + 20 > end || p + 20 < p)) {
+               p = ERR_PTR(-EFAULT);
                goto out_err;
+       }
        p += 20;
        p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
        if (IS_ERR(p))
@@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
        if (ctx->seq_send64 != ctx->seq_send) {
                dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,
                        (long unsigned)ctx->seq_send64, ctx->seq_send);
+               p = ERR_PTR(-EINVAL);
                goto out_err;
        }
        p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
index dc3f1f5ed8654da469bd477803eb3530ea9659b7..adade3d313f279bde98674e2e7ed21496267f9e7 100644 (file)
@@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len,
        if (version != 1) {
                dprintk("RPC:       unknown spkm3 token format: "
                                "obsolete nfs-utils?\n");
+               p = ERR_PTR(-EINVAL);
                goto out_err_free_ctx;
        }
 
@@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len,
        if (IS_ERR(p))
                goto out_err_free_intg_alg;
 
-       if (p != end)
+       if (p != end) {
+               p = ERR_PTR(-EFAULT);
                goto out_err_free_intg_key;
+       }
 
        ctx_id->internal_ctx_id = ctx;
 
index 2b06410e584e10d3f557b3b4bb58d0c660f56283..7dce81a926c5e000b1444d2909fad940b93d0cf4 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <asm/ioctls.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
@@ -1348,15 +1347,10 @@ static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)
 static long cache_ioctl_procfs(struct file *filp,
                               unsigned int cmd, unsigned long arg)
 {
-       long ret;
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct cache_detail *cd = PDE(inode)->data;
 
-       lock_kernel();
-       ret = cache_ioctl(inode, filp, cmd, arg, cd);
-       unlock_kernel();
-
-       return ret;
+       return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_procfs(struct inode *inode, struct file *filp)
@@ -1441,6 +1435,7 @@ static const struct file_operations cache_flush_operations_procfs = {
        .read           = read_flush_procfs,
        .write          = write_flush_procfs,
        .release        = release_flush_procfs,
+       .llseek         = no_llseek,
 };
 
 static void remove_cache_proc_entries(struct cache_detail *cd)
@@ -1555,13 +1550,8 @@ static long cache_ioctl_pipefs(struct file *filp,
 {
        struct inode *inode = filp->f_dentry->d_inode;
        struct cache_detail *cd = RPC_I(inode)->private;
-       long ret;
 
-       lock_kernel();
-       ret = cache_ioctl(inode, filp, cmd, arg, cd);
-       unlock_kernel();
-
-       return ret;
+       return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_pipefs(struct inode *inode, struct file *filp)
@@ -1646,6 +1636,7 @@ const struct file_operations cache_flush_operations_pipefs = {
        .read           = read_flush_pipefs,
        .write          = write_flush_pipefs,
        .release        = release_flush_pipefs,
+       .llseek         = no_llseek,
 };
 
 int sunrpc_cache_register_pipefs(struct dentry *parent,
index 2388d83b68ff75dc4644d1b5808ef19224cd469b..fa5549079d79ca7709d3a68bc686b77f10b08243 100644 (file)
@@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
                        goto out_no_principal;
        }
 
-       kref_init(&clnt->cl_kref);
+       atomic_set(&clnt->cl_count, 1);
 
        err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
        if (err < 0)
@@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt)
                if (new->cl_principal == NULL)
                        goto out_no_principal;
        }
-       kref_init(&new->cl_kref);
+       atomic_set(&new->cl_count, 1);
        err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
        if (err != 0)
                goto out_no_path;
        if (new->cl_auth)
                atomic_inc(&new->cl_auth->au_count);
        xprt_get(clnt->cl_xprt);
-       kref_get(&clnt->cl_kref);
+       atomic_inc(&clnt->cl_count);
        rpc_register_client(new);
        rpciod_up();
        return new;
@@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client);
  * Free an RPC client
  */
 static void
-rpc_free_client(struct kref *kref)
+rpc_free_client(struct rpc_clnt *clnt)
 {
-       struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
-
        dprintk("RPC:       destroying %s client for %s\n",
                        clnt->cl_protname, clnt->cl_server);
        if (!IS_ERR(clnt->cl_path.dentry)) {
@@ -495,12 +493,10 @@ out_free:
  * Free an RPC client
  */
 static void
-rpc_free_auth(struct kref *kref)
+rpc_free_auth(struct rpc_clnt *clnt)
 {
-       struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
-
        if (clnt->cl_auth == NULL) {
-               rpc_free_client(kref);
+               rpc_free_client(clnt);
                return;
        }
 
@@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref)
         *       release remaining GSS contexts. This mechanism ensures
         *       that it can do so safely.
         */
-       kref_init(kref);
+       atomic_inc(&clnt->cl_count);
        rpcauth_release(clnt->cl_auth);
        clnt->cl_auth = NULL;
-       kref_put(kref, rpc_free_client);
+       if (atomic_dec_and_test(&clnt->cl_count))
+               rpc_free_client(clnt);
 }
 
 /*
@@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt)
 
        if (list_empty(&clnt->cl_tasks))
                wake_up(&destroy_wait);
-       kref_put(&clnt->cl_kref, rpc_free_auth);
+       if (atomic_dec_and_test(&clnt->cl_count))
+               rpc_free_auth(clnt);
 }
 
 /**
@@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
        if (clnt != NULL) {
                rpc_task_release_client(task);
                task->tk_client = clnt;
-               kref_get(&clnt->cl_kref);
+               atomic_inc(&clnt->cl_count);
                if (clnt->cl_softrtry)
                        task->tk_flags |= RPC_TASK_SOFT;
                /* Add to the client's list of all tasks */
@@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task)
        task->tk_status = 0;
        if (status >= 0) {
                if (task->tk_rqstp) {
-                       task->tk_action = call_allocate;
+                       task->tk_action = call_refresh;
                        return;
                }
 
@@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task)
 }
 
 /*
- * 2.  Allocate the buffer. For details, see sched.c:rpc_malloc.
+ * 2.  Bind and/or refresh the credentials
+ */
+static void
+call_refresh(struct rpc_task *task)
+{
+       dprint_status(task);
+
+       task->tk_action = call_refreshresult;
+       task->tk_status = 0;
+       task->tk_client->cl_stats->rpcauthrefresh++;
+       rpcauth_refreshcred(task);
+}
+
+/*
+ * 2a. Process the results of a credential refresh
+ */
+static void
+call_refreshresult(struct rpc_task *task)
+{
+       int status = task->tk_status;
+
+       dprint_status(task);
+
+       task->tk_status = 0;
+       task->tk_action = call_allocate;
+       if (status >= 0 && rpcauth_uptodatecred(task))
+               return;
+       switch (status) {
+       case -EACCES:
+               rpc_exit(task, -EACCES);
+               return;
+       case -ENOMEM:
+               rpc_exit(task, -ENOMEM);
+               return;
+       case -ETIMEDOUT:
+               rpc_delay(task, 3*HZ);
+       }
+       task->tk_action = call_refresh;
+}
+
+/*
+ * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc.
  *     (Note: buffer memory is freed in xprt_release).
  */
 static void
 call_allocate(struct rpc_task *task)
 {
-       unsigned int slack = task->tk_client->cl_auth->au_cslack;
+       unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack;
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task)
        dprint_status(task);
 
        task->tk_status = 0;
-       task->tk_action = call_refresh;
+       task->tk_action = call_bind;
 
        if (req->rq_buffer)
                return;
@@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task)
        rpc_exit(task, -ERESTARTSYS);
 }
 
-/*
- * 2a. Bind and/or refresh the credentials
- */
-static void
-call_refresh(struct rpc_task *task)
-{
-       dprint_status(task);
-
-       task->tk_action = call_refreshresult;
-       task->tk_status = 0;
-       task->tk_client->cl_stats->rpcauthrefresh++;
-       rpcauth_refreshcred(task);
-}
-
-/*
- * 2b. Process the results of a credential refresh
- */
-static void
-call_refreshresult(struct rpc_task *task)
-{
-       int status = task->tk_status;
-
-       dprint_status(task);
-
-       task->tk_status = 0;
-       task->tk_action = call_bind;
-       if (status >= 0 && rpcauth_uptodatecred(task))
-               return;
-       switch (status) {
-       case -EACCES:
-               rpc_exit(task, -EACCES);
-               return;
-       case -ENOMEM:
-               rpc_exit(task, -ENOMEM);
-               return;
-       case -ETIMEDOUT:
-               rpc_delay(task, 3*HZ);
-       }
-       task->tk_action = call_refresh;
-}
-
 static inline int
 rpc_task_need_encode(struct rpc_task *task)
 {
index 95ccbcf45d3eb64c6ee84c4767c85e7c5a9ee694..28bcd52e3ce97428c296989cdb637d71f31a6693 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/cache.h>
-#include <linux/smp_lock.h>
 
 static struct vfsmount *rpc_mount __read_mostly;
 static int rpc_mount_count;
@@ -48,7 +47,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head,
                return;
        do {
                msg = list_entry(head->next, struct rpc_pipe_msg, list);
-               list_del(&msg->list);
+               list_del_init(&msg->list);
                msg->errno = err;
                destroy_msg(msg);
        } while (!list_empty(head));
@@ -208,7 +207,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
        if (msg != NULL) {
                spin_lock(&inode->i_lock);
                msg->errno = -EAGAIN;
-               list_del(&msg->list);
+               list_del_init(&msg->list);
                spin_unlock(&inode->i_lock);
                rpci->ops->destroy_msg(msg);
        }
@@ -268,7 +267,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
        if (res < 0 || msg->len == msg->copied) {
                filp->private_data = NULL;
                spin_lock(&inode->i_lock);
-               list_del(&msg->list);
+               list_del_init(&msg->list);
                spin_unlock(&inode->i_lock);
                rpci->ops->destroy_msg(msg);
        }
@@ -309,40 +308,33 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
        return mask;
 }
 
-static int
-rpc_pipe_ioctl_unlocked(struct file *filp, unsigned int cmd, unsigned long arg)
+static long
+rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-       struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       struct rpc_inode *rpci = RPC_I(inode);
        int len;
 
        switch (cmd) {
        case FIONREAD:
-               if (rpci->ops == NULL)
+               spin_lock(&inode->i_lock);
+               if (rpci->ops == NULL) {
+                       spin_unlock(&inode->i_lock);
                        return -EPIPE;
+               }
                len = rpci->pipelen;
                if (filp->private_data) {
                        struct rpc_pipe_msg *msg;
                        msg = (struct rpc_pipe_msg *)filp->private_data;
                        len += msg->len - msg->copied;
                }
+               spin_unlock(&inode->i_lock);
                return put_user(len, (int __user *)arg);
        default:
                return -EINVAL;
        }
 }
 
-static long
-rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       long ret;
-
-       lock_kernel();
-       ret = rpc_pipe_ioctl_unlocked(filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
-
 static const struct file_operations rpc_pipe_fops = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
@@ -371,21 +363,23 @@ rpc_show_info(struct seq_file *m, void *v)
 static int
 rpc_info_open(struct inode *inode, struct file *file)
 {
-       struct rpc_clnt *clnt;
+       struct rpc_clnt *clnt = NULL;
        int ret = single_open(file, rpc_show_info, NULL);
 
        if (!ret) {
                struct seq_file *m = file->private_data;
-               mutex_lock(&inode->i_mutex);
-               clnt = RPC_I(inode)->private;
-               if (clnt) {
-                       kref_get(&clnt->cl_kref);
+
+               spin_lock(&file->f_path.dentry->d_lock);
+               if (!d_unhashed(file->f_path.dentry))
+                       clnt = RPC_I(inode)->private;
+               if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) {
+                       spin_unlock(&file->f_path.dentry->d_lock);
                        m->private = clnt;
                } else {
+                       spin_unlock(&file->f_path.dentry->d_lock);
                        single_release(inode, file);
                        ret = -EINVAL;
                }
-               mutex_unlock(&inode->i_mutex);
        }
        return ret;
 }
index b6309db5622689deaf1c76a6acb1f6a09a02602c..fe9306bf10cc7f3bba4590ddf853c2ac39eadae9 100644 (file)
@@ -800,7 +800,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        u32 _xid;
        __be32 *xp;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        dprintk("RPC:       xs_udp_data_ready...\n");
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
@@ -852,7 +852,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
  dropit:
        skb_free_datagram(sk, skb);
  out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
@@ -1229,7 +1229,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
 
        dprintk("RPC:       xs_tcp_data_ready...\n");
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        if (xprt->shutdown)
@@ -1248,7 +1248,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
                read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
        } while (read > 0);
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /*
@@ -1301,7 +1301,7 @@ static void xs_tcp_state_change(struct sock *sk)
 {
        struct rpc_xprt *xprt;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
@@ -1313,7 +1313,7 @@ static void xs_tcp_state_change(struct sock *sk)
 
        switch (sk->sk_state) {
        case TCP_ESTABLISHED:
-               spin_lock_bh(&xprt->transport_lock);
+               spin_lock(&xprt->transport_lock);
                if (!xprt_test_and_set_connected(xprt)) {
                        struct sock_xprt *transport = container_of(xprt,
                                        struct sock_xprt, xprt);
@@ -1327,7 +1327,7 @@ static void xs_tcp_state_change(struct sock *sk)
 
                        xprt_wake_pending_tasks(xprt, -EAGAIN);
                }
-               spin_unlock_bh(&xprt->transport_lock);
+               spin_unlock(&xprt->transport_lock);
                break;
        case TCP_FIN_WAIT1:
                /* The client initiated a shutdown of the socket */
@@ -1365,7 +1365,7 @@ static void xs_tcp_state_change(struct sock *sk)
                xs_sock_mark_closed(xprt);
        }
  out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1376,7 +1376,7 @@ static void xs_error_report(struct sock *sk)
 {
        struct rpc_xprt *xprt;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        dprintk("RPC:       %s client %p...\n"
@@ -1384,7 +1384,7 @@ static void xs_error_report(struct sock *sk)
                        __func__, xprt, sk->sk_err);
        xprt_wake_pending_tasks(xprt, -EAGAIN);
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_write_space(struct sock *sk)
@@ -1416,13 +1416,13 @@ static void xs_write_space(struct sock *sk)
  */
 static void xs_udp_write_space(struct sock *sk)
 {
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
 
        /* from net/core/sock.c:sock_def_write_space */
        if (sock_writeable(sk))
                xs_write_space(sk);
 
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1437,13 +1437,13 @@ static void xs_udp_write_space(struct sock *sk)
  */
 static void xs_tcp_write_space(struct sock *sk)
 {
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
 
        /* from net/core/stream.c:sk_stream_write_space */
        if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
                xs_write_space(sk);
 
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
index 4414a18c63b49601357789fb5d6df78326819ba7..0b39b2451ea59958c0819c51faf337d000cbb88d 100644 (file)
@@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock)
        static u32 ordernum = 1;
        struct unix_address *addr;
        int err;
+       unsigned int retries = 0;
 
        mutex_lock(&u->readlock);
 
@@ -717,9 +718,17 @@ retry:
        if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
                                      addr->hash)) {
                spin_unlock(&unix_table_lock);
-               /* Sanity yield. It is unusual case, but yet... */
-               if (!(ordernum&0xFF))
-                       yield();
+               /*
+                * __unix_find_socket_byname() may take long time if many names
+                * are already in use.
+                */
+               cond_resched();
+               /* Give up if all names seems to be in use. */
+               if (retries++ == 0xFFFFF) {
+                       err = -ENOSPC;
+                       kfree(addr);
+                       goto out;
+               }
                goto retry;
        }
        addr->hash ^= sk->sk_type;
index 541e2fff5e9c5a0fab346fa55ac9f078630dcf43..d6d046b9f6f2d7d85f8a10680cf662519838e877 100644 (file)
@@ -475,12 +475,10 @@ int wiphy_register(struct wiphy *wiphy)
        mutex_lock(&cfg80211_mutex);
 
        res = device_add(&rdev->wiphy.dev);
-       if (res)
-               goto out_unlock;
-
-       res = rfkill_register(rdev->rfkill);
-       if (res)
-               goto out_rm_dev;
+       if (res) {
+               mutex_unlock(&cfg80211_mutex);
+               return res;
+       }
 
        /* set up regulatory info */
        wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
@@ -509,13 +507,18 @@ int wiphy_register(struct wiphy *wiphy)
        cfg80211_debugfs_rdev_add(rdev);
        mutex_unlock(&cfg80211_mutex);
 
+       /*
+        * due to a locking dependency this has to be outside of the
+        * cfg80211_mutex lock
+        */
+       res = rfkill_register(rdev->rfkill);
+       if (res)
+               goto out_rm_dev;
+
        return 0;
 
 out_rm_dev:
        device_del(&rdev->wiphy.dev);
-
-out_unlock:
-       mutex_unlock(&cfg80211_mutex);
        return res;
 }
 EXPORT_SYMBOL(wiphy_register);
index a4991a3efec0249ac5dea20424628388652072fa..39765bcfb472c7299d0bb45dd0c6dc1627fc283c 100644 (file)
@@ -34,6 +34,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
        .open = cfg80211_open_file_generic,                             \
+       .llseek = generic_file_llseek,                                  \
 };
 
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
@@ -102,6 +103,7 @@ static ssize_t ht40allow_map_read(struct file *file,
 static const struct file_operations ht40allow_map_ops = {
        .read = ht40allow_map_read,
        .open = cfg80211_open_file_generic,
+       .llseek = default_llseek,
 };
 
 #define DEBUGFS_ADD(name)                                              \
index bb5e0a5ecfa1c2f999034bf4ceb34e69fbec855d..7e5c3a45f811d1a951ebee2486cfd8ffa70e5482 100644 (file)
@@ -1420,6 +1420,9 @@ int cfg80211_wext_giwessid(struct net_device *dev,
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
 
+       data->flags = 0;
+       data->length = 0;
+
        switch (wdev->iftype) {
        case NL80211_IFTYPE_ADHOC:
                return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
index 0ef17bc42bac05996eab6e2dada02fc67953c3dc..8f5116f5af19988555316eb5b97c7465a0890677 100644 (file)
@@ -782,6 +782,22 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
                }
        }
 
+       if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
+               /*
+                * If this is a GET, but not NOMAX, it means that the extra
+                * data is not bounded by userspace, but by max_tokens. Thus
+                * set the length to max_tokens. This matches the extra data
+                * allocation.
+                * The driver should fill it with the number of tokens it
+                * provided, and it may check iwp->length rather than having
+                * knowledge of max_tokens. If the driver doesn't change the
+                * iwp->length, this ioctl just copies back max_token tokens
+                * filled with zeroes. Hopefully the driver isn't claiming
+                * them to be valid data.
+                */
+               iwp->length = descr->max_tokens;
+       }
+
        err = handler(dev, info, (union iwreq_data *) iwp, extra);
 
        iwp->length += essid_compat;
index 3feb28e41c5347b85175f57daf223918620723b2..674d426a9d24f9aab7657d1e8ecf342e3be87438 100644 (file)
@@ -152,7 +152,7 @@ static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd,
        } else if (!iwp->pointer)
                return -EFAULT;
 
-       extra = kmalloc(extra_size, GFP_KERNEL);
+       extra = kzalloc(extra_size, GFP_KERNEL);
        if (!extra)
                return -ENOMEM;
 
index e6759c9660bb2507b0c3f8d40d2630e16f773980..2196e55e4f6147021f1b5a6a70123ed4effad881 100644 (file)
@@ -5,6 +5,7 @@
 config X25
        tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
        depends on EXPERIMENTAL
+       depends on BKL # should be fixable
        ---help---
          X.25 is a set of standardized network protocols, similar in scope to
          frame relay; the one physical line from your box to the X.25 network
index a3cca0a94346319dec462ef7ef2fb7df2265945e..64f2ae1fdc15e2a63a28fc7073fc0e1f957cee44 100644 (file)
@@ -101,7 +101,7 @@ resume:
                        err = -EHOSTUNREACH;
                        goto error_nolock;
                }
-               skb_dst_set_noref(skb, dst);
+               skb_dst_set(skb, dst_clone(dst));
                x = dst->xfrm;
        } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
index 2b3ed7ad49338f3ec2d64caf1dd589c2aefc4264..cbab6e1a8c9c4043fcfdba5bdc17c5e9d5dea45c 100644 (file)
@@ -1175,9 +1175,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
                    tmpl->mode == XFRM_MODE_BEET) {
                        remote = &tmpl->id.daddr;
                        local = &tmpl->saddr;
-                       family = tmpl->encap_family;
-                       if (xfrm_addr_any(local, family)) {
-                               error = xfrm_get_saddr(net, &tmp, remote, family);
+                       if (xfrm_addr_any(local, tmpl->encap_family)) {
+                               error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family);
                                if (error)
                                        goto fail;
                                local = &tmp;
index 5208b12fbfb4942d4142f79ddb41ccb1420a4c93..eb96ce52f1789dd881116e76a08169189b50f02c 100644 (file)
@@ -656,15 +656,23 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
 EXPORT_SYMBOL(xfrm_sad_getinfo);
 
 static int
-xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-                 struct xfrm_tmpl *tmpl,
-                 xfrm_address_t *daddr, xfrm_address_t *saddr,
-                 unsigned short family)
+xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl,
+                   struct xfrm_tmpl *tmpl,
+                   xfrm_address_t *daddr, xfrm_address_t *saddr,
+                   unsigned short family)
 {
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
        if (!afinfo)
                return -1;
-       afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
+       afinfo->init_tempsel(&x->sel, fl);
+
+       if (family != tmpl->encap_family) {
+               xfrm_state_put_afinfo(afinfo);
+               afinfo = xfrm_state_get_afinfo(tmpl->encap_family);
+               if (!afinfo)
+                       return -1;
+       }
+       afinfo->init_temprop(x, tmpl, daddr, saddr);
        xfrm_state_put_afinfo(afinfo);
        return 0;
 }
@@ -790,37 +798,38 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
        int error = 0;
        struct xfrm_state *best = NULL;
        u32 mark = pol->mark.v & pol->mark.m;
+       unsigned short encap_family = tmpl->encap_family;
 
        to_put = NULL;
 
        spin_lock_bh(&xfrm_state_lock);
-       h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family);
+       h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
        hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
-               if (x->props.family == family &&
+               if (x->props.family == encap_family &&
                    x->props.reqid == tmpl->reqid &&
                    (mark & x->mark.m) == x->mark.v &&
                    !(x->props.flags & XFRM_STATE_WILDRECV) &&
-                   xfrm_state_addr_check(x, daddr, saddr, family) &&
+                   xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
                    tmpl->mode == x->props.mode &&
                    tmpl->id.proto == x->id.proto &&
                    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-                       xfrm_state_look_at(pol, x, fl, family, daddr, saddr,
+                       xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
                                           &best, &acquire_in_progress, &error);
        }
        if (best)
                goto found;
 
-       h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family);
+       h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
        hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
-               if (x->props.family == family &&
+               if (x->props.family == encap_family &&
                    x->props.reqid == tmpl->reqid &&
                    (mark & x->mark.m) == x->mark.v &&
                    !(x->props.flags & XFRM_STATE_WILDRECV) &&
-                   xfrm_state_addr_check(x, daddr, saddr, family) &&
+                   xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
                    tmpl->mode == x->props.mode &&
                    tmpl->id.proto == x->id.proto &&
                    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-                       xfrm_state_look_at(pol, x, fl, family, daddr, saddr,
+                       xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
                                           &best, &acquire_in_progress, &error);
        }
 
@@ -829,7 +838,7 @@ found:
        if (!x && !error && !acquire_in_progress) {
                if (tmpl->id.spi &&
                    (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
-                                             tmpl->id.proto, family)) != NULL) {
+                                             tmpl->id.proto, encap_family)) != NULL) {
                        to_put = x0;
                        error = -EEXIST;
                        goto out;
@@ -839,9 +848,9 @@ found:
                        error = -ENOMEM;
                        goto out;
                }
-               /* Initialize temporary selector matching only
+               /* Initialize temporary state matching only
                 * to current session. */
-               xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
+               xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
                memcpy(&x->mark, &pol->mark, sizeof(x->mark));
 
                error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
@@ -856,10 +865,10 @@ found:
                        x->km.state = XFRM_STATE_ACQ;
                        list_add(&x->km.all, &net->xfrm.state_all);
                        hlist_add_head(&x->bydst, net->xfrm.state_bydst+h);
-                       h = xfrm_src_hash(net, daddr, saddr, family);
+                       h = xfrm_src_hash(net, daddr, saddr, encap_family);
                        hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h);
                        if (x->id.spi) {
-                               h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family);
+                               h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family);
                                hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
                        }
                        x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
index b14ed4b1f27c3bd70f5837c2f032baf11a88e9a1..8bae6b22c8461c7a03fd15f86bd672a662b0b437 100644 (file)
@@ -1801,7 +1801,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_user_expire *ue = nlmsg_data(nlh);
        struct xfrm_usersa_info *p = &ue->state;
        struct xfrm_mark m;
-       u32 mark = xfrm_mark_get(attrs, &m);;
+       u32 mark = xfrm_mark_get(attrs, &m);
 
        x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
 
index 178061e87ffe47d39ac97a247071d896ff080e8a..cfe40addda764f9a1353cb29eb6a11b551a1eec9 100644 (file)
@@ -148,6 +148,7 @@ static const struct file_operations fifo_fops = {
        .owner          = THIS_MODULE,
        .read           = fifo_read,
        .write          = fifo_write,
+       .llseek         = noop_llseek,
 };
 
 static int __init example_init(void)
index ee03a4f0b64f4361af8c850b3123b8d457bec0bf..06473791c08adb7c5b0a7080ea9600d927c09d94 100644 (file)
@@ -24,6 +24,7 @@ static int __init example_init(void)
 {
        int                     i;
        unsigned int            ret;
+       unsigned int            nents;
        struct scatterlist      sg[10];
 
        printk(KERN_INFO "DMA fifo test start\n");
@@ -61,9 +62,9 @@ static int __init example_init(void)
         * byte at the beginning, after the kfifo_skip().
         */
        sg_init_table(sg, ARRAY_SIZE(sg));
-       ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
-       printk(KERN_INFO "DMA sgl entries: %d\n", ret);
-       if (!ret) {
+       nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
+       printk(KERN_INFO "DMA sgl entries: %d\n", nents);
+       if (!nents) {
                /* fifo is full and no sgl was created */
                printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
                return -EIO;
@@ -71,7 +72,7 @@ static int __init example_init(void)
 
        /* receive data */
        printk(KERN_INFO "scatterlist for receive:\n");
-       for (i = 0; i < ARRAY_SIZE(sg); i++) {
+       for (i = 0; i < nents; i++) {
                printk(KERN_INFO
                "sg[%d] -> "
                "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
@@ -91,16 +92,16 @@ static int __init example_init(void)
        kfifo_dma_in_finish(&fifo, ret);
 
        /* Prepare to transmit data, example: 8 bytes */
-       ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
-       printk(KERN_INFO "DMA sgl entries: %d\n", ret);
-       if (!ret) {
+       nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
+       printk(KERN_INFO "DMA sgl entries: %d\n", nents);
+       if (!nents) {
                /* no data was available and no sgl was created */
                printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
                return -EIO;
        }
 
        printk(KERN_INFO "scatterlist for transmit:\n");
-       for (i = 0; i < ARRAY_SIZE(sg); i++) {
+       for (i = 0; i < nents; i++) {
                printk(KERN_INFO
                "sg[%d] -> "
                "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
index 71b2aabca96aa4d41af62d391a5b6f620fbd6d51..6f8e79e76c9e43aa6d181698c281e5b83b80a529 100644 (file)
@@ -141,6 +141,7 @@ static const struct file_operations fifo_fops = {
        .owner          = THIS_MODULE,
        .read           = fifo_read,
        .write          = fifo_write,
+       .llseek         = noop_llseek,
 };
 
 static int __init example_init(void)
index e68bd16a5da43d010f315264931c40132e84632a..2d7529eeb2940a8d6f92cc2104e0f8379dcb74ca 100644 (file)
@@ -155,6 +155,7 @@ static const struct file_operations fifo_fops = {
        .owner          = THIS_MODULE,
        .read           = fifo_read,
        .write          = fifo_write,
+       .llseek         = noop_llseek,
 };
 
 static int __init example_init(void)
index 26fab33ffa8cccc13a02e9d3b4573c974f71e86e..f4d89e008c32adeb7ff02baf572a6edb36707205 100644 (file)
@@ -30,6 +30,7 @@ static int my_open(struct inode *inode, struct file *file)
 
 static const struct file_operations mark_ops = {
        .open = my_open,
+       .llseek = noop_llseek,
 };
 
 static int __init sample_init(void)
index 842dbc2d5aeda0af27ce18af9914deea370dc329..2e088109fbd5238f3e4f6d293848606d0ac95a58 100644 (file)
@@ -11,6 +11,7 @@ hostprogs-$(CONFIG_KALLSYMS)     += kallsyms
 hostprogs-$(CONFIG_LOGO)         += pnmtologo
 hostprogs-$(CONFIG_VT)           += conmakehash
 hostprogs-$(CONFIG_IKCONFIG)     += bin2c
+hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
 
 always         := $(hostprogs-y) $(hostprogs-m)
 
index a1a5cf95a68d73bd5179474e07b274f77eb5efaf..5ad25e17b6cb2782a2101b59ad7cfd442a8af2ea 100644 (file)
@@ -209,12 +209,23 @@ cmd_modversions =                                                         \
 endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ifdef BUILD_C_RECORDMCOUNT
+# Due to recursion, we must skip empty.o.
+# The empty.o file is created in the make process in order to determine
+#  the target endianness and word size. It is made before all other C
+#  files, including recordmcount.
+cmd_record_mcount = if [ $(@) != "scripts/mod/empty.o" ]; then                 \
+                       $(objtree)/scripts/recordmcount "$(@)";                 \
+                   fi;
+else
 cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
        "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
        "$(if $(CONFIG_64BIT),64,32)" \
-       "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+       "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+       "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
        "$(if $(part-of-module),1,0)" "$(@)";
 endif
+endif
 
 define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
index 54fd1b700131e1e1fcb0ddd13d89ee3a06983ecb..7bfcf1a09ac599be43a125ddb5cabf17d3a37e65 100644 (file)
@@ -101,14 +101,6 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
-#hash values
-ifdef CONFIG_DYNAMIC_DEBUG
-debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
-              -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
-else
-debug_flags =
-endif
-
 orig_c_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
                  $(ccflags-y) $(CFLAGS_$(basetarget).o)
 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
@@ -152,8 +144,7 @@ endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
                 $(__c_flags) $(modkern_cflags)                           \
-                -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
-                 $(debug_flags)
+                -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
 
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
                 $(__a_flags) $(modkern_aflags)
index 09559951df1208e00f5a51efa1208145a87efe14..4c324a1f1e0efb8668b4d64e05b56e8e0f64f25b 100644 (file)
@@ -9,7 +9,7 @@
 # fixdep:       Used to generate dependency information during build process
 # docproc:      Used in Documentation/DocBook
 
-hostprogs-y    := fixdep docproc hash
+hostprogs-y    := fixdep docproc
 always         := $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
index 79ab973fb43a42715d61092ce58d7408109e6eff..fc3b18d844af848a415c0e1a98024f5b097b9ead 100644 (file)
  *
  */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <limits.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -54,6 +56,7 @@ typedef void FILEONLY(char * file);
 FILEONLY *internalfunctions;
 FILEONLY *externalfunctions;
 FILEONLY *symbolsonly;
+FILEONLY *findall;
 
 typedef void FILELINE(char * file, char * line);
 FILELINE * singlefunctions;
@@ -65,12 +68,30 @@ FILELINE * docsection;
 #define KERNELDOCPATH "scripts/"
 #define KERNELDOC     "kernel-doc"
 #define DOCBOOK       "-docbook"
+#define LIST          "-list"
 #define FUNCTION      "-function"
 #define NOFUNCTION    "-nofunction"
 #define NODOCSECTIONS "-no-doc-sections"
 
 static char *srctree, *kernsrctree;
 
+static char **all_list = NULL;
+static int all_list_len = 0;
+
+static void consume_symbol(const char *sym)
+{
+       int i;
+
+       for (i = 0; i < all_list_len; i++) {
+               if (!all_list[i])
+                       continue;
+               if (strcmp(sym, all_list[i]))
+                       continue;
+               all_list[i] = NULL;
+               break;
+       }
+}
+
 static void usage (void)
 {
        fprintf(stderr, "Usage: docproc {doc|depend} file\n");
@@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type)
                struct symfile * sym = &symfilelist[i];
                for (j=0; j < sym->symbolcnt; j++) {
                        vec[idx++]     = type;
+                       consume_symbol(sym->symbollist[j].name);
                        vec[idx++] = sym->symbollist[j].name;
                }
        }
@@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line)
                         vec[idx++] = &line[i];
                 }
         }
+       for (i = 0; i < idx; i++) {
+               if (strcmp(vec[i], FUNCTION))
+                       continue;
+               consume_symbol(vec[i + 1]);
+       }
        vec[idx++] = filename;
        vec[idx] = NULL;
        exec_kernel_doc(vec);
@@ -306,6 +333,10 @@ static void docsect(char *filename, char *line)
                if (*s == '\n')
                        *s = '\0';
 
+       asprintf(&s, "DOC: %s", line);
+       consume_symbol(s);
+       free(s);
+
        vec[0] = KERNELDOC;
        vec[1] = DOCBOOK;
        vec[2] = FUNCTION;
@@ -315,6 +346,84 @@ static void docsect(char *filename, char *line)
        exec_kernel_doc(vec);
 }
 
+static void find_all_symbols(char *filename)
+{
+       char *vec[4]; /* kerneldoc -list file NULL */
+       pid_t pid;
+       int ret, i, count, start;
+       char real_filename[PATH_MAX + 1];
+       int pipefd[2];
+       char *data, *str;
+       size_t data_len = 0;
+
+       vec[0] = KERNELDOC;
+       vec[1] = LIST;
+       vec[2] = filename;
+       vec[3] = NULL;
+
+       if (pipe(pipefd)) {
+               perror("pipe");
+               exit(1);
+       }
+
+       switch (pid=fork()) {
+               case -1:
+                       perror("fork");
+                       exit(1);
+               case  0:
+                       close(pipefd[0]);
+                       dup2(pipefd[1], 1);
+                       memset(real_filename, 0, sizeof(real_filename));
+                       strncat(real_filename, kernsrctree, PATH_MAX);
+                       strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
+                                       PATH_MAX - strlen(real_filename));
+                       execvp(real_filename, vec);
+                       fprintf(stderr, "exec ");
+                       perror(real_filename);
+                       exit(1);
+               default:
+                       close(pipefd[1]);
+                       data = malloc(4096);
+                       do {
+                               while ((ret = read(pipefd[0],
+                                                  data + data_len,
+                                                  4096)) > 0) {
+                                       data_len += ret;
+                                       data = realloc(data, data_len + 4096);
+                               }
+                       } while (ret == -EAGAIN);
+                       if (ret != 0) {
+                               perror("read");
+                               exit(1);
+                       }
+                       waitpid(pid, &ret ,0);
+       }
+       if (WIFEXITED(ret))
+               exitstatus |= WEXITSTATUS(ret);
+       else
+               exitstatus = 0xff;
+
+       count = 0;
+       /* poor man's strtok, but with counting */
+       for (i = 0; i < data_len; i++) {
+               if (data[i] == '\n') {
+                       count++;
+                       data[i] = '\0';
+               }
+       }
+       start = all_list_len;
+       all_list_len += count;
+       all_list = realloc(all_list, sizeof(char *) * all_list_len);
+       str = data;
+       for (i = 0; i < data_len && start != all_list_len; i++) {
+               if (data[i] == '\0') {
+                       all_list[start] = str;
+                       str = data + i + 1;
+                       start++;
+               }
+       }
+}
+
 /*
  * Parse file, calling action specific functions for:
  * 1) Lines containing !E
@@ -322,7 +431,8 @@ static void docsect(char *filename, char *line)
  * 3) Lines containing !D
  * 4) Lines containing !F
  * 5) Lines containing !P
- * 6) Default lines - lines not matching the above
+ * 6) Lines containing !C
+ * 7) Default lines - lines not matching the above
  */
 static void parse_file(FILE *infile)
 {
@@ -365,6 +475,12 @@ static void parse_file(FILE *infile)
                                                s++;
                                        docsection(line + 2, s);
                                        break;
+                               case 'C':
+                                       while (*s && !isspace(*s)) s++;
+                                       *s = '\0';
+                                       if (findall)
+                                               findall(line+2);
+                                       break;
                                default:
                                        defaultline(line);
                        }
@@ -380,6 +496,7 @@ static void parse_file(FILE *infile)
 int main(int argc, char *argv[])
 {
        FILE * infile;
+       int i;
 
        srctree = getenv("SRCTREE");
        if (!srctree)
@@ -415,6 +532,7 @@ int main(int argc, char *argv[])
                symbolsonly       = find_export_symbols;
                singlefunctions   = noaction2;
                docsection        = noaction2;
+               findall           = find_all_symbols;
                parse_file(infile);
 
                /* Rewind to start from beginning of file again */
@@ -425,8 +543,16 @@ int main(int argc, char *argv[])
                symbolsonly       = printline;
                singlefunctions   = singfunc;
                docsection        = docsect;
+               findall           = NULL;
 
                parse_file(infile);
+
+               for (i = 0; i < all_list_len; i++) {
+                       if (!all_list[i])
+                               continue;
+                       fprintf(stderr, "Warning: didn't use docs for %s\n",
+                               all_list[i]);
+               }
        }
        else if (strcmp("depend", argv[1]) == 0)
        {
@@ -439,6 +565,7 @@ int main(int argc, char *argv[])
                symbolsonly       = adddep;
                singlefunctions   = adddep2;
                docsection        = adddep2;
+               findall           = adddep;
                parse_file(infile);
                printf("\n");
        }
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
deleted file mode 100644 (file)
index 2ef5d3f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DYNAMIC_DEBUG_HASH_BITS 6
-
-static const char *program;
-
-static void usage(void)
-{
-       printf("Usage: %s <djb2|r5> <modname>\n", program);
-       exit(1);
-}
-
-/* djb2 hashing algorithm by Dan Bernstein. From:
- * http://www.cse.yorku.ca/~oz/hash.html
- */
-
-static unsigned int djb2_hash(char *str)
-{
-       unsigned long hash = 5381;
-       int c;
-
-       c = *str;
-       while (c) {
-               hash = ((hash << 5) + hash) + c;
-               c = *++str;
-       }
-       return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-static unsigned int r5_hash(char *str)
-{
-       unsigned long hash = 0;
-       int c;
-
-       c = *str;
-       while (c) {
-               hash = (hash + (c << 4) + (c >> 4)) * 11;
-               c = *++str;
-       }
-       return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-int main(int argc, char *argv[])
-{
-       program = argv[0];
-
-       if (argc != 3)
-               usage();
-       if (!strcmp(argv[1], "djb2"))
-               printf("%d\n", djb2_hash(argv[2]));
-       else if (!strcmp(argv[1], "r5"))
-               printf("%d\n", r5_hash(argv[2]));
-       else
-               usage();
-       exit(0);
-}
-
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
new file mode 100644 (file)
index 0000000..520d16b
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Test for gcc 'asm goto' suport
+# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
+
+echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
index 5b7c86ea43a1e3f27484ccfc83f8d2992ad548a4..7ef429cd5cb38f9bd07889aad8f5ab8f3983e27b 100644 (file)
@@ -427,7 +427,7 @@ static void check_conf(struct menu *menu)
                                if (sym->name && !sym_is_choice_value(sym)) {
                                        printf("CONFIG_%s\n", sym->name);
                                }
-                       } else {
+                       } else if (input_mode != oldnoconfig) {
                                if (!conf_cnt++)
                                        printf(_("*\n* Restart config...\n*\n"));
                                rootEntry = menu_get_parent_menu(menu);
index c39327e60ea499919937fae08a8d5bc5dc9c4fd9..515253fe46cfdb3d034f983090abfeff7c8c0aa2 100644 (file)
@@ -497,7 +497,9 @@ int conf_write_defconfig(const char *filename)
                        /*
                         * If symbol is a choice value and equals to the
                         * default for a choice - skip.
-                        * But only if value is bool and equal to "y" .
+                        * But only if value is bool and equal to "y" and
+                        * choice is not "optional".
+                        * (If choice is "optional" then all values can be "n")
                         */
                        if (sym_is_choice_value(sym)) {
                                struct symbol *cs;
@@ -505,7 +507,7 @@ int conf_write_defconfig(const char *filename)
 
                                cs = prop_get_symbol(sym_get_choice_prop(sym));
                                ds = sym_choice_default(cs);
-                               if (sym == ds) {
+                               if (!sym_is_optional(cs) && sym == ds) {
                                        if ((sym->type == S_BOOLEAN) &&
                                            sym_get_tristate_value(sym) == yes)
                                                goto next_menu;
index 6ee2e4fb148146ace18b2e5a7414e6a89d5d3e2f..170459c224a13d94be08b00b72b63c1503303ed1 100644 (file)
@@ -165,7 +165,6 @@ struct menu {
        struct symbol *sym;
        struct property *prompt;
        struct expr *dep;
-       struct expr *dir_dep;
        unsigned int flags;
        char *help;
        struct file *file;
index 4fb590247f330bb75215fe88eb749d42da8b489e..edda8b49619d9e66ff70e16dd8ef68caf4a86bc6 100644 (file)
@@ -107,7 +107,6 @@ static struct expr *menu_check_dep(struct expr *e)
 void menu_add_dep(struct expr *dep)
 {
        current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
-       current_entry->dir_dep = current_entry->dep;
 }
 
 void menu_set_type(int type)
@@ -291,10 +290,6 @@ void menu_finalize(struct menu *parent)
                for (menu = parent->list; menu; menu = menu->next)
                        menu_finalize(menu);
        } else if (sym) {
-               /* ignore inherited dependencies for dir_dep */
-               sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep));
-               sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);
-
                basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
                basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
                basedep = expr_eliminate_dups(expr_transform(basedep));
@@ -325,6 +320,8 @@ void menu_finalize(struct menu *parent)
                        parent->next = last_menu->next;
                        last_menu->next = NULL;
                }
+
+               sym->dir_dep.expr = parent->dep;
        }
        for (menu = parent->list; menu; menu = menu->next) {
                if (sym && sym_is_choice(sym) &&
index e95718fea3555de1b8db125b16add3cf9a350719..1f8b305449db354b103c6eb7ced09095c801dc1b 100644 (file)
@@ -350,6 +350,7 @@ void sym_calc_value(struct symbol *sym)
                                }
                        }
                calc_newval:
+#if 0
                        if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
                                fprintf(stderr, "warning: (");
                                expr_fprint(sym->rev_dep.expr, stderr);
@@ -358,6 +359,7 @@ void sym_calc_value(struct symbol *sym)
                                expr_fprint(sym->dir_dep.expr, stderr);
                                fprintf(stderr, ")\n");
                        }
+#endif
                        newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
                }
                if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
@@ -937,6 +939,8 @@ static void sym_check_print_recursive(struct symbol *last_sym)
                sym = stack->sym;
                next_sym = stack->next ? stack->next->sym : last_sym;
                prop = stack->prop;
+               if (prop == NULL)
+                       prop = stack->sym->prop;
 
                /* for choice values find the menu entry (used below) */
                if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
index 102e1235fd5ced3f83f18a9a5ecd2306b31e087b..cdb6dc1f6458ba4634c0f8584ae3da615ce10696 100755 (executable)
@@ -44,12 +44,13 @@ use strict;
 # Note: This only supports 'c'.
 
 # usage:
-# kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ]
+# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
 #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
 # or
 #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
 #
 #  Set output format using one of -docbook -html -text or -man.  Default is man.
+#  The -list format is for internal use by docproc.
 #
 #  -no-doc-sections
 #      Do not output DOC: sections
@@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1",
                        $type_param, "\$1" );
 my $blankline_text = "";
 
+# list mode
+my %highlights_list = ( $type_constant, "\$1",
+                       $type_func, "\$1",
+                       $type_struct, "\$1",
+                       $type_param, "\$1" );
+my $blankline_list = "";
 
 sub usage {
-    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n";
+    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
+    print "         [ -no-doc-sections ]\n";
     print "         [ -function funcname [ -function funcname ...] ]\n";
     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
     print "         c source file(s) > outputfile\n";
@@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        $output_mode = "xml";
        %highlights = %highlights_xml;
        $blankline = $blankline_xml;
+    } elsif ($cmd eq "-list") {
+       $output_mode = "list";
+       %highlights = %highlights_list;
+       $blankline = $blankline_list;
     } elsif ($cmd eq "-gnome") {
        $output_mode = "gnome";
        %highlights = %highlights_gnome;
@@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) {
     }
 }
 
+## list mode output functions
+
+sub output_function_list(%) {
+    my %args = %{$_[0]};
+
+    print $args{'function'} . "\n";
+}
+
+# output enum in list
+sub output_enum_list(%) {
+    my %args = %{$_[0]};
+    print $args{'enum'} . "\n";
+}
+
+# output typedef in list
+sub output_typedef_list(%) {
+    my %args = %{$_[0]};
+    print $args{'typedef'} . "\n";
+}
+
+# output struct as list
+sub output_struct_list(%) {
+    my %args = %{$_[0]};
+
+    print $args{'struct'} . "\n";
+}
+
+sub output_blockhead_list(%) {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       print "DOC: $section\n";
+    }
+}
+
 ##
 # generic output function for all types (function, struct/union, typedef, enum);
 # calls the generated, variable output_ function name based on
@@ -1679,7 +1727,7 @@ sub check_sections($$$$$$) {
                foreach $px (0 .. $#prms) {
                        $prm_clean = $prms[$px];
                        $prm_clean =~ s/\[.*\]//;
-                       $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
+                       $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
                        # ignore array size in a parameter string;
                        # however, the original param string may contain
                        # spaces, e.g.:  addr[6 + 2]
index 67d59c7a18dc57b1580a833ed37e832eff227c85..5325423ceab483833c8f09efb37a336aaa8f9588 100644 (file)
@@ -44,7 +44,9 @@ all:
 
 Makefile:;
 
-\$(all) %/: all
+\$(all): all
        @:
 
+%/: all
+       @:
 EOF
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
new file mode 100644 (file)
index 0000000..26e1271
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * recordmcount.c: construct a table of the locations of calls to 'mcount'
+ * so that ftrace can find them quickly.
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ *
+ * Restructured to fit Linux format, as well as other updates:
+ *  Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ */
+
+/*
+ * Strategy: alter the .o file in-place.
+ *
+ * Append a new STRTAB that has the new section names, followed by a new array
+ * ElfXX_Shdr[] that has the new section headers, followed by the section
+ * contents for __mcount_loc and its relocations.  The old shstrtab strings,
+ * and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
+ * kilobytes.)  Subsequent processing by /bin/ld (or the kernel module loader)
+ * will ignore the garbage regions, because they are not designated by the
+ * new .e_shoff nor the new ElfXX_Shdr[].  [In order to remove the garbage,
+ * then use "ld -r" to create a new file that omits the garbage.]
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int fd_map;     /* File descriptor for file being modified. */
+static int mmap_failed; /* Boolean flag. */
+static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
+static char gpfx;      /* prefix for global symbol name (sometimes '_') */
+static struct stat sb; /* Remember .st_size, etc. */
+static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
+
+/* setjmp() return values */
+enum {
+       SJ_SETJMP = 0,  /* hardwired first return */
+       SJ_FAIL,
+       SJ_SUCCEED
+};
+
+/* Per-file resource cleanup when multiple files. */
+static void
+cleanup(void)
+{
+       if (!mmap_failed)
+               munmap(ehdr_curr, sb.st_size);
+       else
+               free(ehdr_curr);
+       close(fd_map);
+}
+
+static void __attribute__((noreturn))
+fail_file(void)
+{
+       cleanup();
+       longjmp(jmpenv, SJ_FAIL);
+}
+
+static void __attribute__((noreturn))
+succeed_file(void)
+{
+       cleanup();
+       longjmp(jmpenv, SJ_SUCCEED);
+}
+
+/* ulseek, uread, ...:  Check return value for errors. */
+
+static off_t
+ulseek(int const fd, off_t const offset, int const whence)
+{
+       off_t const w = lseek(fd, offset, whence);
+       if ((off_t)-1 == w) {
+               perror("lseek");
+               fail_file();
+       }
+       return w;
+}
+
+static size_t
+uread(int const fd, void *const buf, size_t const count)
+{
+       size_t const n = read(fd, buf, count);
+       if (n != count) {
+               perror("read");
+               fail_file();
+       }
+       return n;
+}
+
+static size_t
+uwrite(int const fd, void const *const buf, size_t const count)
+{
+       size_t const n = write(fd, buf, count);
+       if (n != count) {
+               perror("write");
+               fail_file();
+       }
+       return n;
+}
+
+static void *
+umalloc(size_t size)
+{
+       void *const addr = malloc(size);
+       if (0 == addr) {
+               fprintf(stderr, "malloc failed: %zu bytes\n", size);
+               fail_file();
+       }
+       return addr;
+}
+
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces.  If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write; new info will be appended to the file.
+ * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
+ * do not propagate to the file until an explicit overwrite at the last.
+ * This preserves most aspects of consistency (all except .st_size)
+ * for simultaneous readers of the file while we are appending to it.
+ * However, multiple writers still are bad.  We choose not to use
+ * locking because it is expensive and the use case of kernel build
+ * makes multiple writers unlikely.
+ */
+static void *mmap_file(char const *fname)
+{
+       void *addr;
+
+       fd_map = open(fname, O_RDWR);
+       if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
+               perror(fname);
+               fail_file();
+       }
+       if (!S_ISREG(sb.st_mode)) {
+               fprintf(stderr, "not a regular file: %s\n", fname);
+               fail_file();
+       }
+       addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                   fd_map, 0);
+       mmap_failed = 0;
+       if (MAP_FAILED == addr) {
+               mmap_failed = 1;
+               addr = umalloc(sb.st_size);
+               uread(fd_map, addr, sb.st_size);
+       }
+       return addr;
+}
+
+/* w8rev, w8nat, ...: Handle endianness. */
+
+static uint64_t w8rev(uint64_t const x)
+{
+       return   ((0xff & (x >> (0 * 8))) << (7 * 8))
+              | ((0xff & (x >> (1 * 8))) << (6 * 8))
+              | ((0xff & (x >> (2 * 8))) << (5 * 8))
+              | ((0xff & (x >> (3 * 8))) << (4 * 8))
+              | ((0xff & (x >> (4 * 8))) << (3 * 8))
+              | ((0xff & (x >> (5 * 8))) << (2 * 8))
+              | ((0xff & (x >> (6 * 8))) << (1 * 8))
+              | ((0xff & (x >> (7 * 8))) << (0 * 8));
+}
+
+static uint32_t w4rev(uint32_t const x)
+{
+       return   ((0xff & (x >> (0 * 8))) << (3 * 8))
+              | ((0xff & (x >> (1 * 8))) << (2 * 8))
+              | ((0xff & (x >> (2 * 8))) << (1 * 8))
+              | ((0xff & (x >> (3 * 8))) << (0 * 8));
+}
+
+static uint32_t w2rev(uint16_t const x)
+{
+       return   ((0xff & (x >> (0 * 8))) << (1 * 8))
+              | ((0xff & (x >> (1 * 8))) << (0 * 8));
+}
+
+static uint64_t w8nat(uint64_t const x)
+{
+       return x;
+}
+
+static uint32_t w4nat(uint32_t const x)
+{
+       return x;
+}
+
+static uint32_t w2nat(uint16_t const x)
+{
+       return x;
+}
+
+static uint64_t (*w8)(uint64_t);
+static uint32_t (*w)(uint32_t);
+static uint32_t (*w2)(uint16_t);
+
+/* Names of the sections that could contain calls to mcount. */
+static int
+is_mcounted_section_name(char const *const txtname)
+{
+       return 0 == strcmp(".text",          txtname) ||
+               0 == strcmp(".sched.text",    txtname) ||
+               0 == strcmp(".spinlock.text", txtname) ||
+               0 == strcmp(".irqentry.text", txtname) ||
+               0 == strcmp(".text.unlikely", txtname);
+}
+
+/* 32 bit and 64 bit are very similar */
+#include "recordmcount.h"
+#define RECORD_MCOUNT_64
+#include "recordmcount.h"
+
+static void
+do_file(char const *const fname)
+{
+       Elf32_Ehdr *const ehdr = mmap_file(fname);
+       unsigned int reltype = 0;
+
+       ehdr_curr = ehdr;
+       w = w4nat;
+       w2 = w2nat;
+       w8 = w8nat;
+       switch (ehdr->e_ident[EI_DATA]) {
+               static unsigned int const endian = 1;
+       default: {
+               fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+                       ehdr->e_ident[EI_DATA], fname);
+               fail_file();
+       } break;
+       case ELFDATA2LSB: {
+               if (1 != *(unsigned char const *)&endian) {
+                       /* main() is big endian, file.o is little endian. */
+                       w = w4rev;
+                       w2 = w2rev;
+                       w8 = w8rev;
+               }
+       } break;
+       case ELFDATA2MSB: {
+               if (0 != *(unsigned char const *)&endian) {
+                       /* main() is little endian, file.o is big endian. */
+                       w = w4rev;
+                       w2 = w2rev;
+                       w8 = w8rev;
+               }
+       } break;
+       }  /* end switch */
+       if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
+       ||  ET_REL != w2(ehdr->e_type)
+       ||  EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
+               fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
+               fail_file();
+       }
+
+       gpfx = 0;
+       switch (w2(ehdr->e_machine)) {
+       default: {
+               fprintf(stderr, "unrecognized e_machine %d %s\n",
+                       w2(ehdr->e_machine), fname);
+               fail_file();
+       } break;
+       case EM_386:     reltype = R_386_32;                   break;
+       case EM_ARM:     reltype = R_ARM_ABS32;                break;
+       case EM_IA_64:   reltype = R_IA64_IMM64;   gpfx = '_'; break;
+       case EM_PPC:     reltype = R_PPC_ADDR32;   gpfx = '_'; break;
+       case EM_PPC64:   reltype = R_PPC64_ADDR64; gpfx = '_'; break;
+       case EM_S390:    /* reltype: e_class    */ gpfx = '_'; break;
+       case EM_SH:      reltype = R_SH_DIR32;                 break;
+       case EM_SPARCV9: reltype = R_SPARC_64;     gpfx = '_'; break;
+       case EM_X86_64:  reltype = R_X86_64_64;                break;
+       }  /* end switch */
+
+       switch (ehdr->e_ident[EI_CLASS]) {
+       default: {
+               fprintf(stderr, "unrecognized ELF class %d %s\n",
+                       ehdr->e_ident[EI_CLASS], fname);
+               fail_file();
+       } break;
+       case ELFCLASS32: {
+               if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
+               ||  sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
+                       fprintf(stderr,
+                               "unrecognized ET_REL file: %s\n", fname);
+                       fail_file();
+               }
+               if (EM_S390 == w2(ehdr->e_machine))
+                       reltype = R_390_32;
+               do32(ehdr, fname, reltype);
+       } break;
+       case ELFCLASS64: {
+               Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
+               if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
+               ||  sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
+                       fprintf(stderr,
+                               "unrecognized ET_REL file: %s\n", fname);
+                       fail_file();
+               }
+               if (EM_S390 == w2(ghdr->e_machine))
+                       reltype = R_390_64;
+               do64(ghdr, fname, reltype);
+       } break;
+       }  /* end switch */
+
+       cleanup();
+}
+
+int
+main(int argc, char const *argv[])
+{
+       const char ftrace[] = "kernel/trace/ftrace.o";
+       int ftrace_size = sizeof(ftrace) - 1;
+       int n_error = 0;  /* gcc-4.3.0 false positive complaint */
+
+       if (argc <= 1) {
+               fprintf(stderr, "usage: recordmcount file.o...\n");
+               return 0;
+       }
+
+       /* Process each file in turn, allowing deep failure. */
+       for (--argc, ++argv; 0 < argc; --argc, ++argv) {
+               int const sjval = setjmp(jmpenv);
+               int len;
+
+               /*
+                * The file kernel/trace/ftrace.o references the mcount
+                * function but does not call it. Since ftrace.o should
+                * not be traced anyway, we just skip it.
+                */
+               len = strlen(argv[0]);
+               if (len >= ftrace_size &&
+                   strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
+                       continue;
+
+               switch (sjval) {
+               default: {
+                       fprintf(stderr, "internal error: %s\n", argv[0]);
+                       exit(1);
+               } break;
+               case SJ_SETJMP: {  /* normal sequence */
+                       /* Avoid problems if early cleanup() */
+                       fd_map = -1;
+                       ehdr_curr = NULL;
+                       mmap_failed = 1;
+                       do_file(argv[0]);
+               } break;
+               case SJ_FAIL: {  /* error in do_file or below */
+                       ++n_error;
+               } break;
+               case SJ_SUCCEED: {  /* premature success */
+                       /* do nothing */
+               } break;
+               }  /* end switch */
+       }
+       return !!n_error;
+}
+
+
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
new file mode 100644 (file)
index 0000000..7f39d09
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * recordmcount.h
+ *
+ * This code was taken out of recordmcount.c written by
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
+ *
+ * The original code had the same algorithms for both 32bit
+ * and 64bit ELF files, but the code was duplicated to support
+ * the difference in structures that were used. This
+ * file creates a macro of everything that is different between
+ * the 64 and 32 bit code, such that by including this header
+ * twice we can create both sets of functions by including this
+ * header once with RECORD_MCOUNT_64 undefined, and again with
+ * it defined.
+ *
+ * This conversion to macros was done by:
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ *
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ */
+#undef append_func
+#undef sift_rel_mcount
+#undef find_secsym_ndx
+#undef __has_rel_mcount
+#undef has_rel_mcount
+#undef tot_relsize
+#undef do_func
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Sym
+#undef ELF_R_SYM
+#undef ELF_R_INFO
+#undef ELF_ST_BIND
+#undef uint_t
+#undef _w
+#undef _align
+#undef _size
+
+#ifdef RECORD_MCOUNT_64
+# define append_func           append64
+# define sift_rel_mcount       sift64_rel_mcount
+# define find_secsym_ndx       find64_secsym_ndx
+# define __has_rel_mcount      __has64_rel_mcount
+# define has_rel_mcount                has64_rel_mcount
+# define tot_relsize           tot64_relsize
+# define do_func               do64
+# define Elf_Ehdr              Elf64_Ehdr
+# define Elf_Shdr              Elf64_Shdr
+# define Elf_Rel               Elf64_Rel
+# define Elf_Rela              Elf64_Rela
+# define Elf_Sym               Elf64_Sym
+# define ELF_R_SYM             ELF64_R_SYM
+# define ELF_R_INFO            ELF64_R_INFO
+# define ELF_ST_BIND           ELF64_ST_BIND
+# define uint_t                        uint64_t
+# define _w                    w8
+# define _align                        7u
+# define _size                 8
+#else
+# define append_func           append32
+# define sift_rel_mcount       sift32_rel_mcount
+# define find_secsym_ndx       find32_secsym_ndx
+# define __has_rel_mcount      __has32_rel_mcount
+# define has_rel_mcount                has32_rel_mcount
+# define tot_relsize           tot32_relsize
+# define do_func               do32
+# define Elf_Ehdr              Elf32_Ehdr
+# define Elf_Shdr              Elf32_Shdr
+# define Elf_Rel               Elf32_Rel
+# define Elf_Rela              Elf32_Rela
+# define Elf_Sym               Elf32_Sym
+# define ELF_R_SYM             ELF32_R_SYM
+# define ELF_R_INFO            ELF32_R_INFO
+# define ELF_ST_BIND           ELF32_ST_BIND
+# define uint_t                        uint32_t
+# define _w                    w
+# define _align                        3u
+# define _size                 4
+#endif
+
+/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
+static void append_func(Elf_Ehdr *const ehdr,
+                       Elf_Shdr *const shstr,
+                       uint_t const *const mloc0,
+                       uint_t const *const mlocp,
+                       Elf_Rel const *const mrel0,
+                       Elf_Rel const *const mrelp,
+                       unsigned int const rel_entsize,
+                       unsigned int const symsec_sh_link)
+{
+       /* Begin constructing output file */
+       Elf_Shdr mcsec;
+       char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
+               ? ".rela__mcount_loc"
+               :  ".rel__mcount_loc";
+       unsigned const old_shnum = w2(ehdr->e_shnum);
+       uint_t const old_shoff = _w(ehdr->e_shoff);
+       uint_t const old_shstr_sh_size   = _w(shstr->sh_size);
+       uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
+       uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
+       uint_t new_e_shoff;
+
+       shstr->sh_size = _w(t);
+       shstr->sh_offset = _w(sb.st_size);
+       t += sb.st_size;
+       t += (_align & -t);  /* word-byte align */
+       new_e_shoff = t;
+
+       /* body for new shstrtab */
+       ulseek(fd_map, sb.st_size, SEEK_SET);
+       uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
+       uwrite(fd_map, mc_name, 1 + strlen(mc_name));
+
+       /* old(modified) Elf_Shdr table, word-byte aligned */
+       ulseek(fd_map, t, SEEK_SET);
+       t += sizeof(Elf_Shdr) * old_shnum;
+       uwrite(fd_map, old_shoff + (void *)ehdr,
+              sizeof(Elf_Shdr) * old_shnum);
+
+       /* new sections __mcount_loc and .rel__mcount_loc */
+       t += 2*sizeof(mcsec);
+       mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
+               + old_shstr_sh_size);
+       mcsec.sh_type = w(SHT_PROGBITS);
+       mcsec.sh_flags = _w(SHF_ALLOC);
+       mcsec.sh_addr = 0;
+       mcsec.sh_offset = _w(t);
+       mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
+       mcsec.sh_link = 0;
+       mcsec.sh_info = 0;
+       mcsec.sh_addralign = _w(_size);
+       mcsec.sh_entsize = _w(_size);
+       uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+       mcsec.sh_name = w(old_shstr_sh_size);
+       mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
+               ? w(SHT_RELA)
+               : w(SHT_REL);
+       mcsec.sh_flags = 0;
+       mcsec.sh_addr = 0;
+       mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
+       mcsec.sh_size   = _w((void *)mrelp - (void *)mrel0);
+       mcsec.sh_link = w(symsec_sh_link);
+       mcsec.sh_info = w(old_shnum);
+       mcsec.sh_addralign = _w(_size);
+       mcsec.sh_entsize = _w(rel_entsize);
+       uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+       uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
+       uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
+
+       ehdr->e_shoff = _w(new_e_shoff);
+       ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum));  /* {.rel,}__mcount_loc */
+       ulseek(fd_map, 0, SEEK_SET);
+       uwrite(fd_map, ehdr, sizeof(*ehdr));
+}
+
+
+/*
+ * Look at the relocations in order to find the calls to mcount.
+ * Accumulate the section offsets that are found, and their relocation info,
+ * onto the end of the existing arrays.
+ */
+static uint_t *sift_rel_mcount(uint_t *mlocp,
+                              unsigned const offbase,
+                              Elf_Rel **const mrelpp,
+                              Elf_Shdr const *const relhdr,
+                              Elf_Ehdr const *const ehdr,
+                              unsigned const recsym,
+                              uint_t const recval,
+                              unsigned const reltype)
+{
+       uint_t *const mloc0 = mlocp;
+       Elf_Rel *mrelp = *mrelpp;
+       Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+               + (void *)ehdr);
+       unsigned const symsec_sh_link = w(relhdr->sh_link);
+       Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
+       Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
+               + (void *)ehdr);
+
+       Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
+       char const *const str0 = (char const *)(_w(strsec->sh_offset)
+               + (void *)ehdr);
+
+       Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
+               + (void *)ehdr);
+       unsigned rel_entsize = _w(relhdr->sh_entsize);
+       unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+       Elf_Rel const *relp = rel0;
+
+       unsigned mcountsym = 0;
+       unsigned t;
+
+       for (t = nrel; t; --t) {
+               if (!mcountsym) {
+                       Elf_Sym const *const symp =
+                               &sym0[ELF_R_SYM(_w(relp->r_info))];
+                       char const *symname = &str0[w(symp->st_name)];
+
+                       if ('.' == symname[0])
+                               ++symname;  /* ppc64 hack */
+                       if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
+                                       symname))
+                               mcountsym = ELF_R_SYM(_w(relp->r_info));
+               }
+
+               if (mcountsym == ELF_R_SYM(_w(relp->r_info))) {
+                       uint_t const addend = _w(_w(relp->r_offset) - recval);
+
+                       mrelp->r_offset = _w(offbase
+                               + ((void *)mlocp - (void *)mloc0));
+                       mrelp->r_info = _w(ELF_R_INFO(recsym, reltype));
+                       if (sizeof(Elf_Rela) == rel_entsize) {
+                               ((Elf_Rela *)mrelp)->r_addend = addend;
+                               *mlocp++ = 0;
+                       } else
+                               *mlocp++ = addend;
+
+                       mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
+               }
+               relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
+       }
+       *mrelpp = mrelp;
+       return mlocp;
+}
+
+
+/*
+ * Find a symbol in the given section, to be used as the base for relocating
+ * the table of offsets of calls to mcount.  A local or global symbol suffices,
+ * but avoid a Weak symbol because it may be overridden; the change in value
+ * would invalidate the relocations of the offsets of the calls to mcount.
+ * Often the found symbol will be the unnamed local symbol generated by
+ * GNU 'as' for the start of each section.  For example:
+ *    Num:    Value  Size Type    Bind   Vis      Ndx Name
+ *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
+ */
+static unsigned find_secsym_ndx(unsigned const txtndx,
+                               char const *const txtname,
+                               uint_t *const recvalp,
+                               Elf_Shdr const *const symhdr,
+                               Elf_Ehdr const *const ehdr)
+{
+       Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
+               + (void *)ehdr);
+       unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
+       Elf_Sym const *symp;
+       unsigned t;
+
+       for (symp = sym0, t = nsym; t; --t, ++symp) {
+               unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
+
+               if (txtndx == w2(symp->st_shndx)
+                       /* avoid STB_WEAK */
+                   && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
+                       *recvalp = _w(symp->st_value);
+                       return symp - sym0;
+               }
+       }
+       fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
+               txtndx, txtname);
+       fail_file();
+}
+
+
+/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
+static char const *
+__has_rel_mcount(Elf_Shdr const *const relhdr,  /* is SHT_REL or SHT_RELA */
+                Elf_Shdr const *const shdr0,
+                char const *const shstrtab,
+                char const *const fname)
+{
+       /* .sh_info depends on .sh_type == SHT_REL[,A] */
+       Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
+       char const *const txtname = &shstrtab[w(txthdr->sh_name)];
+
+       if (0 == strcmp("__mcount_loc", txtname)) {
+               fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
+                       fname);
+               succeed_file();
+       }
+       if (SHT_PROGBITS != w(txthdr->sh_type) ||
+           !is_mcounted_section_name(txtname))
+               return NULL;
+       return txtname;
+}
+
+static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
+                                 Elf_Shdr const *const shdr0,
+                                 char const *const shstrtab,
+                                 char const *const fname)
+{
+       if (SHT_REL  != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
+               return NULL;
+       return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
+}
+
+
+static unsigned tot_relsize(Elf_Shdr const *const shdr0,
+                           unsigned nhdr,
+                           const char *const shstrtab,
+                           const char *const fname)
+{
+       unsigned totrelsz = 0;
+       Elf_Shdr const *shdrp = shdr0;
+
+       for (; nhdr; --nhdr, ++shdrp) {
+               if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
+                       totrelsz += _w(shdrp->sh_size);
+       }
+       return totrelsz;
+}
+
+
+/* Overall supervision for Elf32 ET_REL file. */
+static void
+do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
+{
+       Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+               + (void *)ehdr);
+       unsigned const nhdr = w2(ehdr->e_shnum);
+       Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
+       char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
+               + (void *)ehdr);
+
+       Elf_Shdr const *relhdr;
+       unsigned k;
+
+       /* Upper bound on space: assume all relevant relocs are for mcount. */
+       unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+       Elf_Rel *const mrel0 = umalloc(totrelsz);
+       Elf_Rel *      mrelp = mrel0;
+
+       /* 2*sizeof(address) <= sizeof(Elf_Rel) */
+       uint_t *const mloc0 = umalloc(totrelsz>>1);
+       uint_t *      mlocp = mloc0;
+
+       unsigned rel_entsize = 0;
+       unsigned symsec_sh_link = 0;
+
+       for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
+               char const *const txtname = has_rel_mcount(relhdr, shdr0,
+                       shstrtab, fname);
+               if (txtname) {
+                       uint_t recval = 0;
+                       unsigned const recsym = find_secsym_ndx(
+                               w(relhdr->sh_info), txtname, &recval,
+                               &shdr0[symsec_sh_link = w(relhdr->sh_link)],
+                               ehdr);
+
+                       rel_entsize = _w(relhdr->sh_entsize);
+                       mlocp = sift_rel_mcount(mlocp,
+                               (void *)mlocp - (void *)mloc0, &mrelp,
+                               relhdr, ehdr, recsym, recval, reltype);
+               }
+       }
+       if (mloc0 != mlocp) {
+               append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+                           rel_entsize, symsec_sh_link);
+       }
+       free(mrel0);
+       free(mloc0);
+}
index e67f054860877d676fc4359ef2f670b5d7531479..1d7963f4ee79b853055337f3eed7ca80731dc667 100755 (executable)
@@ -270,6 +270,8 @@ if ($arch eq "x86_64") {
 } elsif ($arch eq "arm") {
     $alignment = 2;
     $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
+                       "\\s+(__gnu_mcount_nc|mcount)\$";
 
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
index e90a91cc5185709d31a9a128b4790b676a35599e..057b6b3c5dfb4cf0677add9a7c6f04c5029d2e15 100755 (executable)
@@ -43,7 +43,7 @@ scm_version()
        fi
 
        # Check for git and a git repo.
-       if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+       if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
 
                # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
                # it, because this version is defined in the top level Makefile.
@@ -85,7 +85,7 @@ scm_version()
        fi
 
        # Check for mercurial and a mercurial repo.
-       if hgid=`hg id 2>/dev/null`; then
+       if test -d .hg && hgid=`hg id 2>/dev/null`; then
                tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
 
                # Do we have an untagged version?
index 0a0a99f3b08331f78f7499c5e964929af20e96c9..4d995aeaebc0ad0a3232faebead627da4ebb40b9 100644 (file)
@@ -3,3 +3,4 @@
 #
 af_names.h
 capability_names.h
+rlim_names.h
index 7320331b44aba5bd52eac6b2a97302ad21a4ca5f..0848292982a2315f9e491728afe2714ad767bca0 100644 (file)
@@ -29,7 +29,7 @@
  * aa_simple_write_to_buffer - common routine for getting policy from user
  * @op: operation doing the user buffer copy
  * @userbuf: user buffer to copy data from  (NOT NULL)
- * @alloc_size: size of user buffer
+ * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size)
  * @copy_size: size of data to copy from user buffer
  * @pos: position write is at in the file (NOT NULL)
  *
@@ -42,6 +42,8 @@ static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
 {
        char *data;
 
+       BUG_ON(copy_size > alloc_size);
+
        if (*pos != 0)
                /* only writes from pos 0, that is complete writes */
                return ERR_PTR(-ESPIPE);
@@ -86,7 +88,8 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
 }
 
 static const struct file_operations aa_fs_profile_load = {
-       .write = profile_load
+       .write = profile_load,
+       .llseek = default_llseek,
 };
 
 /* .replace file hook fn to load and/or replace policy */
@@ -107,7 +110,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf,
 }
 
 static const struct file_operations aa_fs_profile_replace = {
-       .write = profile_replace
+       .write = profile_replace,
+       .llseek = default_llseek,
 };
 
 /* .remove file hook fn to remove loaded policy */
@@ -134,7 +138,8 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
 }
 
 static const struct file_operations aa_fs_profile_remove = {
-       .write = profile_remove
+       .write = profile_remove,
+       .llseek = default_llseek,
 };
 
 /** Base file system setup **/
index 3c88be94649408b412c0193f0bf4186273c6a972..02baec732bb512c77fed7d5ede247b72d788a147 100644 (file)
@@ -33,8 +33,8 @@ struct aa_rlimit {
 };
 
 int aa_map_resource(int resource);
-int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-                     struct rlimit *new_rlim);
+int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
+                     unsigned int resource, struct rlimit *new_rlim);
 
 void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
 
index 6e85cdb4303f69fc1911c94aefd5f1c5b695239c..506d2baf614797624fc4b9450c0d12c9f56e8ae4 100644 (file)
@@ -40,6 +40,7 @@ char *aa_split_fqname(char *fqname, char **ns_name)
        *ns_name = NULL;
        if (name[0] == ':') {
                char *split = strchr(&name[1], ':');
+               *ns_name = skip_spaces(&name[1]);
                if (split) {
                        /* overwrite ':' with \0 */
                        *split = 0;
@@ -47,7 +48,6 @@ char *aa_split_fqname(char *fqname, char **ns_name)
                } else
                        /* a ns name without a following profile is allowed */
                        name = NULL;
-               *ns_name = &name[1];
        }
        if (name && *name == 0)
                name = NULL;
index f73e2c2042185fff2d079dbdb3f4b8b828371e72..cf1de4462ccd3fb297f48bf351dd3494804f22c1 100644 (file)
@@ -614,7 +614,7 @@ static int apparmor_task_setrlimit(struct task_struct *task,
        int error = 0;
 
        if (!unconfined(profile))
-               error = aa_task_setrlimit(profile, resource, new_rlim);
+               error = aa_task_setrlimit(profile, task, resource, new_rlim);
 
        return error;
 }
index 19358dc14605bae1422ae00226291751695ba44c..82396050f18646ac0519352321637e930c05e367 100644 (file)
@@ -59,8 +59,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
 {
        struct path root, tmp;
        char *res;
-       int deleted, connected;
-       int error = 0;
+       int connected, error = 0;
 
        /* Get the root we want to resolve too, released below */
        if (flags & PATH_CHROOT_REL) {
@@ -74,19 +73,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
        }
 
        spin_lock(&dcache_lock);
-       /* There is a race window between path lookup here and the
-        * need to strip the " (deleted) string that __d_path applies
-        * Detect the race and relookup the path
-        *
-        * The stripping of (deleted) is a hack that could be removed
-        * with an updated __d_path
-        */
-       do {
-               tmp = root;
-               deleted = d_unlinked(path->dentry);
-               res = __d_path(path, &tmp, buf, buflen);
-
-       } while (deleted != d_unlinked(path->dentry));
+       tmp = root;
+       res = __d_path(path, &tmp, buf, buflen);
        spin_unlock(&dcache_lock);
 
        *name = res;
@@ -98,21 +86,17 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
                *name = buf;
                goto out;
        }
-       if (deleted) {
-               /* On some filesystems, newly allocated dentries appear to the
-                * security_path hooks as a deleted dentry except without an
-                * inode allocated.
-                *
-                * Remove the appended deleted text and return as string for
-                * normal mediation, or auditing.  The (deleted) string is
-                * guaranteed to be added in this case, so just strip it.
-                */
-               buf[buflen - 11] = 0;   /* - (len(" (deleted)") +\0) */
 
-               if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
+       /* Handle two cases:
+        * 1. A deleted dentry && profile is not allowing mediation of deleted
+        * 2. On some filesystems, newly allocated dentries appear to the
+        *    security_path hooks as a deleted dentry except without an inode
+        *    allocated.
+        */
+       if (d_unlinked(path->dentry) && path->dentry->d_inode &&
+           !(flags & PATH_MEDIATE_DELETED)) {
                        error = -ENOENT;
                        goto out;
-               }
        }
 
        /* Determine if the path is connected to the expected root */
index 3cdc1ad0787ec9c4769455f8aeb004a417d246bf..52cc865f1464574e696fd28eca6a6e0eed326d68 100644 (file)
@@ -1151,12 +1151,14 @@ ssize_t aa_remove_profiles(char *fqname, size_t size)
                /* released below */
                ns = aa_get_namespace(root);
 
-       write_lock(&ns->lock);
        if (!name) {
                /* remove namespace - can only happen if fqname[0] == ':' */
+               write_lock(&ns->parent->lock);
                __remove_namespace(ns);
+               write_unlock(&ns->parent->lock);
        } else {
                /* remove profile */
+               write_lock(&ns->lock);
                profile = aa_get_profile(__lookup_profile(&ns->base, name));
                if (!profile) {
                        error = -ENOENT;
@@ -1165,8 +1167,8 @@ ssize_t aa_remove_profiles(char *fqname, size_t size)
                }
                name = profile->base.hname;
                __remove_profile(profile);
+               write_unlock(&ns->lock);
        }
-       write_unlock(&ns->lock);
 
        /* don't fail removal if audit fails */
        (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
index 4a368f1fd36ddf02af7204d30ee1b136f1d57bf7..a4136c10b1c6292edbdadae7285803583fb74241 100644 (file)
@@ -72,6 +72,7 @@ int aa_map_resource(int resource)
 /**
  * aa_task_setrlimit - test permission to set an rlimit
  * @profile - profile confining the task  (NOT NULL)
+ * @task - task the resource is being set on
  * @resource - the resource being set
  * @new_rlim - the new resource limit  (NOT NULL)
  *
@@ -79,18 +80,21 @@ int aa_map_resource(int resource)
  *
  * Returns: 0 or error code if setting resource failed
  */
-int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-                     struct rlimit *new_rlim)
+int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task,
+                     unsigned int resource, struct rlimit *new_rlim)
 {
        int error = 0;
 
-       if (profile->rlimits.mask & (1 << resource) &&
-           new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)
-
-               error = audit_resource(profile, resource, new_rlim->rlim_max,
-                       -EACCES);
+       /* TODO: extend resource control to handle other (non current)
+        * processes.  AppArmor rules currently have the implicit assumption
+        * that the task is setting the resource of the current process
+        */
+       if ((task != current->group_leader) ||
+           (profile->rlimits.mask & (1 << resource) &&
+            new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max))
+               error = -EACCES;
 
-       return error;
+       return audit_resource(profile, resource, new_rlim->rlim_max, error);
 }
 
 /**
index 95a6599a37bb3ae0737779d16d9a0d811d5bfc82..30ae00fbecd591591acb55c1431d62a1bbbac427 100644 (file)
@@ -677,7 +677,18 @@ static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
 {
 }
 
+static int cap_secmark_relabel_packet(u32 secid)
+{
+       return 0;
+}
 
+static void cap_secmark_refcount_inc(void)
+{
+}
+
+static void cap_secmark_refcount_dec(void)
+{
+}
 
 static void cap_req_classify_flow(const struct request_sock *req,
                                  struct flowi *fl)
@@ -777,7 +788,8 @@ static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 
 static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
-       return -EOPNOTSUPP;
+       *secid = 0;
+       return 0;
 }
 
 static void cap_release_secctx(char *secdata, u32 seclen)
@@ -1018,6 +1030,9 @@ void __init security_fixup_ops(struct security_operations *ops)
        set_to_cap_if_null(ops, inet_conn_request);
        set_to_cap_if_null(ops, inet_csk_clone);
        set_to_cap_if_null(ops, inet_conn_established);
+       set_to_cap_if_null(ops, secmark_relabel_packet);
+       set_to_cap_if_null(ops, secmark_refcount_inc);
+       set_to_cap_if_null(ops, secmark_refcount_dec);
        set_to_cap_if_null(ops, req_classify_flow);
        set_to_cap_if_null(ops, tun_dev_create);
        set_to_cap_if_null(ops, tun_dev_post_create);
index 9d172e6e330c9fd7906a8a2e5754713f80dfb433..5e632b4857e443d8031eaa17c0e2bd7e877b3d14 100644 (file)
@@ -719,14 +719,11 @@ static int cap_safe_nice(struct task_struct *p)
 /**
  * cap_task_setscheduler - Detemine if scheduler policy change is permitted
  * @p: The task to affect
- * @policy: The policy to effect
- * @lp: The parameters to the scheduling policy
  *
  * Detemine if the requested scheduler policy change is permitted for the
  * specified task, returning 0 if permission is granted, -ve if denied.
  */
-int cap_task_setscheduler(struct task_struct *p, int policy,
-                          struct sched_param *lp)
+int cap_task_setscheduler(struct task_struct *p)
 {
        return cap_safe_nice(p);
 }
index 8c777f022ad132eca07eed38503ea1af716f8dfd..88839866cbcd029a52422b51cf163ec8167a4034 100644 (file)
@@ -53,6 +53,7 @@ static const struct file_operations default_file_ops = {
        .read =         default_read_file,
        .write =        default_write_file,
        .open =         default_open,
+       .llseek =       noop_llseek,
 };
 
 static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
index 16d100d3fc38de931de8e1a2679bc025359f3d31..3fbcd1dda0ef6e06da4a5b4b9c23a240a6378a35 100644 (file)
@@ -35,6 +35,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
 
 /* set during initialization */
+extern int iint_initialized;
 extern int ima_initialized;
 extern int ima_used_chip;
 extern char *ima_hash;
index 7625b85c2274f457fc0d260a21e2d9039758d12c..afba4aef812f699134f7c7bc66c32251d2f12c69 100644 (file)
 
 RADIX_TREE(ima_iint_store, GFP_ATOMIC);
 DEFINE_SPINLOCK(ima_iint_lock);
-
 static struct kmem_cache *iint_cache __read_mostly;
 
+int iint_initialized = 0;
+
 /* ima_iint_find_get - return the iint associated with an inode
  *
  * ima_iint_find_get gets a reference to the iint. Caller must
@@ -141,6 +142,7 @@ static int __init ima_iintcache_init(void)
        iint_cache =
            kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
                              SLAB_PANIC, init_once);
+       iint_initialized = 1;
        return 0;
 }
 security_initcall(ima_iintcache_init);
index f93641382e9f9483576578a3ba5f41286f4cc3ab..e662b89d407944103dc121b9ccb37f7e68ac62e1 100644 (file)
@@ -148,12 +148,14 @@ void ima_counts_get(struct file *file)
        struct ima_iint_cache *iint;
        int rc;
 
-       if (!ima_initialized || !S_ISREG(inode->i_mode))
+       if (!iint_initialized || !S_ISREG(inode->i_mode))
                return;
        iint = ima_iint_find_get(inode);
        if (!iint)
                return;
        mutex_lock(&iint->mutex);
+       if (!ima_initialized)
+               goto out;
        rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
        if (rc < 0)
                goto out;
@@ -213,7 +215,7 @@ void ima_file_free(struct file *file)
        struct inode *inode = file->f_dentry->d_inode;
        struct ima_iint_cache *iint;
 
-       if (!ima_initialized || !S_ISREG(inode->i_mode))
+       if (!iint_initialized || !S_ISREG(inode->i_mode))
                return;
        iint = ima_iint_find_get(inode);
        if (!iint)
@@ -230,7 +232,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ima_iint_cache *iint;
-       int rc;
+       int rc = 0;
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return 0;
index b2b0998d6abda7759433d7032d255eb0a317c126..60924f6a52db2bbff40ddc953a50bb9d708febb5 100644 (file)
@@ -1272,6 +1272,7 @@ long keyctl_session_to_parent(void)
        keyring_r = NULL;
 
        me = current;
+       rcu_read_lock();
        write_lock_irq(&tasklist_lock);
 
        parent = me->real_parent;
@@ -1304,7 +1305,8 @@ long keyctl_session_to_parent(void)
                goto not_permitted;
 
        /* the keyrings must have the same UID */
-       if (pcred->tgcred->session_keyring->uid != mycred->euid ||
+       if ((pcred->tgcred->session_keyring &&
+            pcred->tgcred->session_keyring->uid != mycred->euid) ||
            mycred->tgcred->session_keyring->uid != mycred->euid)
                goto not_permitted;
 
@@ -1319,6 +1321,7 @@ long keyctl_session_to_parent(void)
        set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
 
        write_unlock_irq(&tasklist_lock);
+       rcu_read_unlock();
        if (oldcred)
                put_cred(oldcred);
        return 0;
@@ -1327,6 +1330,7 @@ already_same:
        ret = 0;
 not_permitted:
        write_unlock_irq(&tasklist_lock);
+       rcu_read_unlock();
        put_cred(cred);
        return ret;
 
index c53949f17d9e0dddc0601032576ef2922fb88f86..b50f472061a43c6ec7fb53781c084fb2cb487dcb 100644 (file)
@@ -89,20 +89,12 @@ __setup("security=", choose_lsm);
  * Return true if:
  *     -The passed LSM is the one chosen by user at boot time,
  *     -or the passed LSM is configured as the default and the user did not
- *      choose an alternate LSM at boot time,
- *     -or there is no default LSM set and the user didn't specify a
- *      specific LSM and we're the first to ask for registration permission,
- *     -or the passed LSM is currently loaded.
+ *      choose an alternate LSM at boot time.
  * Otherwise, return false.
  */
 int __init security_module_enable(struct security_operations *ops)
 {
-       if (!*chosen_lsm)
-               strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
-       else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
-               return 0;
-
-       return 1;
+       return !strcmp(ops->name, chosen_lsm);
 }
 
 /**
@@ -786,10 +778,9 @@ int security_task_setrlimit(struct task_struct *p, unsigned int resource,
        return security_ops->task_setrlimit(p, resource, new_rlim);
 }
 
-int security_task_setscheduler(struct task_struct *p,
-                               int policy, struct sched_param *lp)
+int security_task_setscheduler(struct task_struct *p)
 {
-       return security_ops->task_setscheduler(p, policy, lp);
+       return security_ops->task_setscheduler(p);
 }
 
 int security_task_getscheduler(struct task_struct *p)
@@ -1145,6 +1136,24 @@ void security_inet_conn_established(struct sock *sk,
        security_ops->inet_conn_established(sk, skb);
 }
 
+int security_secmark_relabel_packet(u32 secid)
+{
+       return security_ops->secmark_relabel_packet(secid);
+}
+EXPORT_SYMBOL(security_secmark_relabel_packet);
+
+void security_secmark_refcount_inc(void)
+{
+       security_ops->secmark_refcount_inc();
+}
+EXPORT_SYMBOL(security_secmark_refcount_inc);
+
+void security_secmark_refcount_dec(void)
+{
+       security_ops->secmark_refcount_dec();
+}
+EXPORT_SYMBOL(security_secmark_refcount_dec);
+
 int security_tun_dev_create(void)
 {
        return security_ops->tun_dev_create();
index 58d80f3bd6f681f6d366f5b67becd7ff433ce2c7..ad5cd76ec231cd14f02b2fb15f07a3d8a069972f 100644 (file)
@@ -2,25 +2,20 @@
 # Makefile for building the SELinux module as part of the kernel tree.
 #
 
-obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
-
-selinux-y := avc.o \
-            hooks.o \
-            selinuxfs.o \
-            netlink.o \
-            nlmsgtab.o \
-            netif.o \
-            netnode.o \
-            netport.o \
-            exports.o
+obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
+
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
+            netnode.o netport.o exports.o \
+            ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
+            ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o
 
 selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
 selinux-$(CONFIG_NETLABEL) += netlabel.o
 
-EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
+ccflags-y := -Isecurity/selinux -Isecurity/selinux/include
 
-$(obj)/avc.o: $(obj)/flask.h
+$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
 
 quiet_cmd_flask = GEN     $(obj)/flask.h $(obj)/av_permissions.h
       cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
index c0a454aee1e03cb0e3825a2c5f965c941636c4d9..90664385dead0df01f6eec2b7479c83f4f021160 100644 (file)
  * it under the terms of the GNU General Public License version 2,
  * as published by the Free Software Foundation.
  */
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/selinux.h>
-#include <linux/fs.h>
-#include <linux/ipc.h>
-#include <asm/atomic.h>
 
 #include "security.h"
-#include "objsec.h"
-
-/* SECMARK reference count */
-extern atomic_t selinux_secmark_refcount;
-
-int selinux_string_to_sid(char *str, u32 *sid)
-{
-       if (selinux_enabled)
-               return security_context_to_sid(str, strlen(str), sid);
-       else {
-               *sid = 0;
-               return 0;
-       }
-}
-EXPORT_SYMBOL_GPL(selinux_string_to_sid);
-
-int selinux_secmark_relabel_packet_permission(u32 sid)
-{
-       if (selinux_enabled) {
-               const struct task_security_struct *__tsec;
-               u32 tsid;
-
-               __tsec = current_security();
-               tsid = __tsec->sid;
-
-               return avc_has_perm(tsid, sid, SECCLASS_PACKET,
-                                   PACKET__RELABELTO, NULL);
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission);
-
-void selinux_secmark_refcount_inc(void)
-{
-       atomic_inc(&selinux_secmark_refcount);
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc);
-
-void selinux_secmark_refcount_dec(void)
-{
-       atomic_dec(&selinux_secmark_refcount);
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
 
 bool selinux_is_enabled(void)
 {
index 4796ddd4e721ae454a02563d713aa235870ece02..d9154cf90ae19cd4eb5f40d65882abb60781da3d 100644 (file)
@@ -3354,11 +3354,11 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
        return 0;
 }
 
-static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
+static int selinux_task_setscheduler(struct task_struct *p)
 {
        int rc;
 
-       rc = cap_task_setscheduler(p, policy, lp);
+       rc = cap_task_setscheduler(p);
        if (rc)
                return rc;
 
@@ -4279,6 +4279,27 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
        selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
 }
 
+static int selinux_secmark_relabel_packet(u32 sid)
+{
+       const struct task_security_struct *__tsec;
+       u32 tsid;
+
+       __tsec = current_security();
+       tsid = __tsec->sid;
+
+       return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
+}
+
+static void selinux_secmark_refcount_inc(void)
+{
+       atomic_inc(&selinux_secmark_refcount);
+}
+
+static void selinux_secmark_refcount_dec(void)
+{
+       atomic_dec(&selinux_secmark_refcount);
+}
+
 static void selinux_req_classify_flow(const struct request_sock *req,
                                      struct flowi *fl)
 {
@@ -5533,6 +5554,9 @@ static struct security_operations selinux_ops = {
        .inet_conn_request =            selinux_inet_conn_request,
        .inet_csk_clone =               selinux_inet_csk_clone,
        .inet_conn_established =        selinux_inet_conn_established,
+       .secmark_relabel_packet =       selinux_secmark_relabel_packet,
+       .secmark_refcount_inc =         selinux_secmark_refcount_inc,
+       .secmark_refcount_dec =         selinux_secmark_refcount_dec,
        .req_classify_flow =            selinux_req_classify_flow,
        .tun_dev_create =               selinux_tun_dev_create,
        .tun_dev_post_create =          selinux_tun_dev_post_create,
index b4c9eb4bd6f9127a506e2a4483c592362c8fcafa..8858d2b2d4b6ad1dd1b005b20a06afa4a3505d03 100644 (file)
@@ -17,7 +17,7 @@ struct security_class_mapping secclass_map[] = {
          { "compute_av", "compute_create", "compute_member",
            "check_context", "load_policy", "compute_relabel",
            "compute_user", "setenforce", "setbool", "setsecparam",
-           "setcheckreqprot", NULL } },
+           "setcheckreqprot", "read_policy", NULL } },
        { "process",
          { "fork", "transition", "sigchld", "sigkill",
            "sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
index 1f7c2491d3dccbc54769a6ccaf509d50255cfe3f..671273eb1115c4e7f05983af071069aea7535650 100644 (file)
@@ -9,6 +9,7 @@
 #define _SELINUX_SECURITY_H_
 
 #include <linux/magic.h>
+#include <linux/types.h>
 #include "flask.h"
 
 #define SECSID_NULL                    0x00000000 /* unspecified SID */
@@ -82,6 +83,8 @@ extern int selinux_policycap_openperm;
 int security_mls_enabled(void);
 
 int security_load_policy(void *data, size_t len);
+int security_read_policy(void **data, ssize_t *len);
+size_t security_policydb_len(void);
 
 int security_policycap_supported(unsigned int req_cap);
 
@@ -191,5 +194,25 @@ static inline int security_netlbl_sid_to_secattr(u32 sid,
 
 const char *security_get_initial_sid_context(u32 sid);
 
+/*
+ * status notifier using mmap interface
+ */
+extern struct page *selinux_kernel_status_page(void);
+
+#define SELINUX_KERNEL_STATUS_VERSION  1
+struct selinux_kernel_status {
+       u32     version;        /* version number of thie structure */
+       u32     sequence;       /* sequence number of seqlock logic */
+       u32     enforcing;      /* current setting of enforcing mode */
+       u32     policyload;     /* times of policy reloaded */
+       u32     deny_unknown;   /* current setting of deny_unknown */
+       /*
+        * The version > 0 supports above members.
+        */
+} __attribute__((packed));
+
+extern void selinux_status_update_setenforce(int enforcing);
+extern void selinux_status_update_policyload(int seqno);
+
 #endif /* _SELINUX_SECURITY_H_ */
 
index 79a1bb635662fbc7f65a306e10b5b67e534fcf1c..87e0556bae70ff977ea290b3cdfcc2c308d8edf5 100644 (file)
@@ -68,6 +68,8 @@ static int *bool_pending_values;
 static struct dentry *class_dir;
 static unsigned long last_class_ino;
 
+static char policy_opened;
+
 /* global data for policy capabilities */
 static struct dentry *policycap_dir;
 
@@ -110,6 +112,8 @@ enum sel_inos {
        SEL_COMPAT_NET, /* whether to use old compat network packet controls */
        SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
        SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
+       SEL_STATUS,     /* export current status using mmap() */
+       SEL_POLICY,     /* allow userspace to read the in kernel policy */
        SEL_INO_NEXT,   /* The next inode number to use */
 };
 
@@ -171,6 +175,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                if (selinux_enforcing)
                        avc_ss_reset(0);
                selnl_notify_setenforce(selinux_enforcing);
+               selinux_status_update_setenforce(selinux_enforcing);
        }
        length = count;
 out:
@@ -205,6 +210,59 @@ static const struct file_operations sel_handle_unknown_ops = {
        .llseek         = generic_file_llseek,
 };
 
+static int sel_open_handle_status(struct inode *inode, struct file *filp)
+{
+       struct page    *status = selinux_kernel_status_page();
+
+       if (!status)
+               return -ENOMEM;
+
+       filp->private_data = status;
+
+       return 0;
+}
+
+static ssize_t sel_read_handle_status(struct file *filp, char __user *buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct page    *status = filp->private_data;
+
+       BUG_ON(!status);
+
+       return simple_read_from_buffer(buf, count, ppos,
+                                      page_address(status),
+                                      sizeof(struct selinux_kernel_status));
+}
+
+static int sel_mmap_handle_status(struct file *filp,
+                                 struct vm_area_struct *vma)
+{
+       struct page    *status = filp->private_data;
+       unsigned long   size = vma->vm_end - vma->vm_start;
+
+       BUG_ON(!status);
+
+       /* only allows one page from the head */
+       if (vma->vm_pgoff > 0 || size != PAGE_SIZE)
+               return -EIO;
+       /* disallow writable mapping */
+       if (vma->vm_flags & VM_WRITE)
+               return -EPERM;
+       /* disallow mprotect() turns it into writable */
+       vma->vm_flags &= ~VM_MAYWRITE;
+
+       return remap_pfn_range(vma, vma->vm_start,
+                              page_to_pfn(status),
+                              size, vma->vm_page_prot);
+}
+
+static const struct file_operations sel_handle_status_ops = {
+       .open           = sel_open_handle_status,
+       .read           = sel_read_handle_status,
+       .mmap           = sel_mmap_handle_status,
+       .llseek         = generic_file_llseek,
+};
+
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static ssize_t sel_write_disable(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
@@ -296,6 +354,141 @@ static const struct file_operations sel_mls_ops = {
        .llseek         = generic_file_llseek,
 };
 
+struct policy_load_memory {
+       size_t len;
+       void *data;
+};
+
+static int sel_open_policy(struct inode *inode, struct file *filp)
+{
+       struct policy_load_memory *plm = NULL;
+       int rc;
+
+       BUG_ON(filp->private_data);
+
+       mutex_lock(&sel_mutex);
+
+       rc = task_has_security(current, SECURITY__READ_POLICY);
+       if (rc)
+               goto err;
+
+       rc = -EBUSY;
+       if (policy_opened)
+               goto err;
+
+       rc = -ENOMEM;
+       plm = kzalloc(sizeof(*plm), GFP_KERNEL);
+       if (!plm)
+               goto err;
+
+       if (i_size_read(inode) != security_policydb_len()) {
+               mutex_lock(&inode->i_mutex);
+               i_size_write(inode, security_policydb_len());
+               mutex_unlock(&inode->i_mutex);
+       }
+
+       rc = security_read_policy(&plm->data, &plm->len);
+       if (rc)
+               goto err;
+
+       policy_opened = 1;
+
+       filp->private_data = plm;
+
+       mutex_unlock(&sel_mutex);
+
+       return 0;
+err:
+       mutex_unlock(&sel_mutex);
+
+       if (plm)
+               vfree(plm->data);
+       kfree(plm);
+       return rc;
+}
+
+static int sel_release_policy(struct inode *inode, struct file *filp)
+{
+       struct policy_load_memory *plm = filp->private_data;
+
+       BUG_ON(!plm);
+
+       policy_opened = 0;
+
+       vfree(plm->data);
+       kfree(plm);
+
+       return 0;
+}
+
+static ssize_t sel_read_policy(struct file *filp, char __user *buf,
+                              size_t count, loff_t *ppos)
+{
+       struct policy_load_memory *plm = filp->private_data;
+       int ret;
+
+       mutex_lock(&sel_mutex);
+
+       ret = task_has_security(current, SECURITY__READ_POLICY);
+       if (ret)
+               goto out;
+
+       ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
+out:
+       mutex_unlock(&sel_mutex);
+       return ret;
+}
+
+static int sel_mmap_policy_fault(struct vm_area_struct *vma,
+                                struct vm_fault *vmf)
+{
+       struct policy_load_memory *plm = vma->vm_file->private_data;
+       unsigned long offset;
+       struct page *page;
+
+       if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE))
+               return VM_FAULT_SIGBUS;
+
+       offset = vmf->pgoff << PAGE_SHIFT;
+       if (offset >= roundup(plm->len, PAGE_SIZE))
+               return VM_FAULT_SIGBUS;
+
+       page = vmalloc_to_page(plm->data + offset);
+       get_page(page);
+
+       vmf->page = page;
+
+       return 0;
+}
+
+static struct vm_operations_struct sel_mmap_policy_ops = {
+       .fault = sel_mmap_policy_fault,
+       .page_mkwrite = sel_mmap_policy_fault,
+};
+
+int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & VM_SHARED) {
+               /* do not allow mprotect to make mapping writable */
+               vma->vm_flags &= ~VM_MAYWRITE;
+
+               if (vma->vm_flags & VM_WRITE)
+                       return -EACCES;
+       }
+
+       vma->vm_flags |= VM_RESERVED;
+       vma->vm_ops = &sel_mmap_policy_ops;
+
+       return 0;
+}
+
+static const struct file_operations sel_policy_ops = {
+       .open           = sel_open_policy,
+       .read           = sel_read_policy,
+       .mmap           = sel_mmap_policy,
+       .release        = sel_release_policy,
+};
+
 static ssize_t sel_write_load(struct file *file, const char __user *buf,
                              size_t count, loff_t *ppos)
 
@@ -1612,6 +1805,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
                [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
                [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
                [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
+               [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
+               [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
                /* last one */ {""}
        };
        ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
deleted file mode 100644 (file)
index 15d4e62..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for building the SELinux security server as part of the kernel tree.
-#
-
-EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
-obj-y := ss.o
-
-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
-
index 929480c6c4306e874eff82db107045b944cdd33b..a3dd9faa19c01eda269b13f7cfcd7ab6da6aa098 100644 (file)
@@ -266,8 +266,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
        if (shift > 2)
                shift = shift - 2;
        nslot = 1 << shift;
-       if (nslot > MAX_AVTAB_SIZE)
-               nslot = MAX_AVTAB_SIZE;
+       if (nslot > MAX_AVTAB_HASH_BUCKETS)
+               nslot = MAX_AVTAB_HASH_BUCKETS;
        mask = nslot - 1;
 
        h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
@@ -501,6 +501,48 @@ bad:
        goto out;
 }
 
+int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
+{
+       __le16 buf16[4];
+       __le32 buf32[1];
+       int rc;
+
+       buf16[0] = cpu_to_le16(cur->key.source_type);
+       buf16[1] = cpu_to_le16(cur->key.target_type);
+       buf16[2] = cpu_to_le16(cur->key.target_class);
+       buf16[3] = cpu_to_le16(cur->key.specified);
+       rc = put_entry(buf16, sizeof(u16), 4, fp);
+       if (rc)
+               return rc;
+       buf32[0] = cpu_to_le32(cur->datum.data);
+       rc = put_entry(buf32, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+       return 0;
+}
+
+int avtab_write(struct policydb *p, struct avtab *a, void *fp)
+{
+       unsigned int i;
+       int rc = 0;
+       struct avtab_node *cur;
+       __le32 buf[1];
+
+       buf[0] = cpu_to_le32(a->nel);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < a->nslot; i++) {
+               for (cur = a->htable[i]; cur; cur = cur->next) {
+                       rc = avtab_write_item(p, cur, fp);
+                       if (rc)
+                               return rc;
+               }
+       }
+
+       return rc;
+}
 void avtab_cache_init(void)
 {
        avtab_node_cachep = kmem_cache_create("avtab_node",
index cd4f734e27499cf2f9e203f0edb2557cf02bc24c..dff0c75345c1642fd2b3181a6677035947834951 100644 (file)
@@ -71,6 +71,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                    void *p);
 
 int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
+int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp);
+int avtab_write(struct policydb *p, struct avtab *a, void *fp);
 
 struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
                                          struct avtab_datum *datum);
@@ -85,7 +87,6 @@ void avtab_cache_destroy(void);
 #define MAX_AVTAB_HASH_BITS 11
 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
 #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
-#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
 
 #endif /* _SS_AVTAB_H_ */
 
index c91e150c3087d78127eb8ca6cc6faccf04e9cd32..655fe1c6cc69dccd862b3142a37e41b6fb4010a7 100644 (file)
@@ -490,6 +490,129 @@ err:
        return rc;
 }
 
+int cond_write_bool(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct cond_bool_datum *booldatum = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       __le32 buf[3];
+       u32 len;
+       int rc;
+
+       len = strlen(key);
+       buf[0] = cpu_to_le32(booldatum->value);
+       buf[1] = cpu_to_le32(booldatum->state);
+       buf[2] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (rc)
+               return rc;
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+       return 0;
+}
+
+/*
+ * cond_write_cond_av_list doesn't write out the av_list nodes.
+ * Instead it writes out the key/value pairs from the avtab. This
+ * is necessary because there is no way to uniquely identifying rules
+ * in the avtab so it is not possible to associate individual rules
+ * in the avtab with a conditional without saving them as part of
+ * the conditional. This means that the avtab with the conditional
+ * rules will not be saved but will be rebuilt on policy load.
+ */
+static int cond_write_av_list(struct policydb *p,
+                             struct cond_av_list *list, struct policy_file *fp)
+{
+       __le32 buf[1];
+       struct cond_av_list *cur_list;
+       u32 len;
+       int rc;
+
+       len = 0;
+       for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
+               len++;
+
+       buf[0] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       if (len == 0)
+               return 0;
+
+       for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
+               rc = avtab_write_item(p, cur_list->node, fp);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+int cond_write_node(struct policydb *p, struct cond_node *node,
+                   struct policy_file *fp)
+{
+       struct cond_expr *cur_expr;
+       __le32 buf[2];
+       int rc;
+       u32 len = 0;
+
+       buf[0] = cpu_to_le32(node->cur_state);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
+               len++;
+
+       buf[0] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
+               buf[0] = cpu_to_le32(cur_expr->expr_type);
+               buf[1] = cpu_to_le32(cur_expr->bool);
+               rc = put_entry(buf, sizeof(u32), 2, fp);
+               if (rc)
+                       return rc;
+       }
+
+       rc = cond_write_av_list(p, node->true_list, fp);
+       if (rc)
+               return rc;
+       rc = cond_write_av_list(p, node->false_list, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
+{
+       struct cond_node *cur;
+       u32 len;
+       __le32 buf[1];
+       int rc;
+
+       len = 0;
+       for (cur = list; cur != NULL; cur = cur->next)
+               len++;
+       buf[0] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       for (cur = list; cur != NULL; cur = cur->next) {
+               rc = cond_write_node(p, cur, fp);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
 /* Determine whether additional permissions are granted by the conditional
  * av table, and if so, add them to the result
  */
index 53ddb013ae573f8bb053da9fa9416fbcf5ee9701..3f209c635295681f026874e332573577e743dea4 100644 (file)
@@ -69,6 +69,8 @@ int cond_index_bool(void *key, void *datum, void *datap);
 
 int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
 int cond_read_list(struct policydb *p, void *fp);
+int cond_write_bool(void *key, void *datum, void *ptr);
+int cond_write_list(struct policydb *p, struct cond_node *list, void *fp);
 
 void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
 
index 04b6145d767f96093423d5f733e6fe1b6a4e5687..d42951fcbe877355b08c16d5a63526c729f4355c 100644 (file)
@@ -22,6 +22,8 @@
 #include "ebitmap.h"
 #include "policydb.h"
 
+#define BITS_PER_U64   (sizeof(u64) * 8)
+
 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
 {
        struct ebitmap_node *n1, *n2;
@@ -363,10 +365,10 @@ int ebitmap_read(struct ebitmap *e, void *fp)
        e->highbit = le32_to_cpu(buf[1]);
        count = le32_to_cpu(buf[2]);
 
-       if (mapunit != sizeof(u64) * 8) {
+       if (mapunit != BITS_PER_U64) {
                printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
                       "match my size %Zd (high bit was %d)\n",
-                      mapunit, sizeof(u64) * 8, e->highbit);
+                      mapunit, BITS_PER_U64, e->highbit);
                goto bad;
        }
 
@@ -446,3 +448,78 @@ bad:
        ebitmap_destroy(e);
        goto out;
 }
+
+int ebitmap_write(struct ebitmap *e, void *fp)
+{
+       struct ebitmap_node *n;
+       u32 count;
+       __le32 buf[3];
+       u64 map;
+       int bit, last_bit, last_startbit, rc;
+
+       buf[0] = cpu_to_le32(BITS_PER_U64);
+
+       count = 0;
+       last_bit = 0;
+       last_startbit = -1;
+       ebitmap_for_each_positive_bit(e, n, bit) {
+               if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
+                       count++;
+                       last_startbit = rounddown(bit, BITS_PER_U64);
+               }
+               last_bit = roundup(bit + 1, BITS_PER_U64);
+       }
+       buf[1] = cpu_to_le32(last_bit);
+       buf[2] = cpu_to_le32(count);
+
+       rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (rc)
+               return rc;
+
+       map = 0;
+       last_startbit = INT_MIN;
+       ebitmap_for_each_positive_bit(e, n, bit) {
+               if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
+                       __le64 buf64[1];
+
+                       /* this is the very first bit */
+                       if (!map) {
+                               last_startbit = rounddown(bit, BITS_PER_U64);
+                               map = (u64)1 << (bit - last_startbit);
+                               continue;
+                       }
+
+                       /* write the last node */
+                       buf[0] = cpu_to_le32(last_startbit);
+                       rc = put_entry(buf, sizeof(u32), 1, fp);
+                       if (rc)
+                               return rc;
+
+                       buf64[0] = cpu_to_le64(map);
+                       rc = put_entry(buf64, sizeof(u64), 1, fp);
+                       if (rc)
+                               return rc;
+
+                       /* set up for the next node */
+                       map = 0;
+                       last_startbit = rounddown(bit, BITS_PER_U64);
+               }
+               map |= (u64)1 << (bit - last_startbit);
+       }
+       /* write the last node */
+       if (map) {
+               __le64 buf64[1];
+
+               /* write the last node */
+               buf[0] = cpu_to_le32(last_startbit);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+
+               buf64[0] = cpu_to_le64(map);
+               rc = put_entry(buf64, sizeof(u64), 1, fp);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
index f283b4367f54d640e6a3b6fedb8f3180786883c3..1f4e93c2ae8695430c4a9ff33cfd31e7d36cec36 100644 (file)
@@ -123,6 +123,7 @@ int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
 void ebitmap_destroy(struct ebitmap *e);
 int ebitmap_read(struct ebitmap *e, void *fp);
+int ebitmap_write(struct ebitmap *e, void *fp);
 
 #ifdef CONFIG_NETLABEL
 int ebitmap_netlbl_export(struct ebitmap *ebmap,
index 3a29704be8ce10f4409dd0a3d4f0bea8bb0d1086..94f630d93a5c5d0964a51e030646d26652619ee6 100644 (file)
@@ -37,6 +37,7 @@
 #include "policydb.h"
 #include "conditional.h"
 #include "mls.h"
+#include "services.h"
 
 #define _DEBUG_HASHES
 
@@ -185,9 +186,19 @@ static u32 rangetr_hash(struct hashtab *h, const void *k)
 static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
 {
        const struct range_trans *key1 = k1, *key2 = k2;
-       return (key1->source_type != key2->source_type ||
-               key1->target_type != key2->target_type ||
-               key1->target_class != key2->target_class);
+       int v;
+
+       v = key1->source_type - key2->source_type;
+       if (v)
+               return v;
+
+       v = key1->target_type - key2->target_type;
+       if (v)
+               return v;
+
+       v = key1->target_class - key2->target_class;
+
+       return v;
 }
 
 /*
@@ -1624,11 +1635,11 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap)
 
 static int type_bounds_sanity_check(void *key, void *datum, void *datap)
 {
-       struct type_datum *upper, *type;
+       struct type_datum *upper;
        struct policydb *p = datap;
        int depth = 0;
 
-       upper = type = datum;
+       upper = datum;
        while (upper->bounds) {
                if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
                        printk(KERN_ERR "SELinux: type %s: "
@@ -2306,3 +2317,843 @@ bad:
        policydb_destroy(p);
        goto out;
 }
+
+/*
+ * Write a MLS level structure to a policydb binary
+ * representation file.
+ */
+static int mls_write_level(struct mls_level *l, void *fp)
+{
+       __le32 buf[1];
+       int rc;
+
+       buf[0] = cpu_to_le32(l->sens);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       rc = ebitmap_write(&l->cat, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * Write a MLS range structure to a policydb binary
+ * representation file.
+ */
+static int mls_write_range_helper(struct mls_range *r, void *fp)
+{
+       __le32 buf[3];
+       size_t items;
+       int rc, eq;
+
+       eq = mls_level_eq(&r->level[1], &r->level[0]);
+
+       if (eq)
+               items = 2;
+       else
+               items = 3;
+       buf[0] = cpu_to_le32(items-1);
+       buf[1] = cpu_to_le32(r->level[0].sens);
+       if (!eq)
+               buf[2] = cpu_to_le32(r->level[1].sens);
+
+       BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+
+       rc = put_entry(buf, sizeof(u32), items, fp);
+       if (rc)
+               return rc;
+
+       rc = ebitmap_write(&r->level[0].cat, fp);
+       if (rc)
+               return rc;
+       if (!eq) {
+               rc = ebitmap_write(&r->level[1].cat, fp);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static int sens_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct level_datum *levdatum = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       __le32 buf[2];
+       size_t len;
+       int rc;
+
+       len = strlen(key);
+       buf[0] = cpu_to_le32(len);
+       buf[1] = cpu_to_le32(levdatum->isalias);
+       rc = put_entry(buf, sizeof(u32), 2, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       rc = mls_write_level(levdatum->level, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int cat_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct cat_datum *catdatum = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       __le32 buf[3];
+       size_t len;
+       int rc;
+
+       len = strlen(key);
+       buf[0] = cpu_to_le32(len);
+       buf[1] = cpu_to_le32(catdatum->value);
+       buf[2] = cpu_to_le32(catdatum->isalias);
+       rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int role_trans_write(struct role_trans *r, void *fp)
+{
+       struct role_trans *tr;
+       u32 buf[3];
+       size_t nel;
+       int rc;
+
+       nel = 0;
+       for (tr = r; tr; tr = tr->next)
+               nel++;
+       buf[0] = cpu_to_le32(nel);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+       for (tr = r; tr; tr = tr->next) {
+               buf[0] = cpu_to_le32(tr->role);
+               buf[1] = cpu_to_le32(tr->type);
+               buf[2] = cpu_to_le32(tr->new_role);
+               rc = put_entry(buf, sizeof(u32), 3, fp);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static int role_allow_write(struct role_allow *r, void *fp)
+{
+       struct role_allow *ra;
+       u32 buf[2];
+       size_t nel;
+       int rc;
+
+       nel = 0;
+       for (ra = r; ra; ra = ra->next)
+               nel++;
+       buf[0] = cpu_to_le32(nel);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+       for (ra = r; ra; ra = ra->next) {
+               buf[0] = cpu_to_le32(ra->role);
+               buf[1] = cpu_to_le32(ra->new_role);
+               rc = put_entry(buf, sizeof(u32), 2, fp);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
+/*
+ * Write a security context structure
+ * to a policydb binary representation file.
+ */
+static int context_write(struct policydb *p, struct context *c,
+                        void *fp)
+{
+       int rc;
+       __le32 buf[3];
+
+       buf[0] = cpu_to_le32(c->user);
+       buf[1] = cpu_to_le32(c->role);
+       buf[2] = cpu_to_le32(c->type);
+
+       rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (rc)
+               return rc;
+
+       rc = mls_write_range_helper(&c->range, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * The following *_write functions are used to
+ * write the symbol data to a policy database
+ * binary representation file.
+ */
+
+static int perm_write(void *vkey, void *datum, void *fp)
+{
+       char *key = vkey;
+       struct perm_datum *perdatum = datum;
+       __le32 buf[2];
+       size_t len;
+       int rc;
+
+       len = strlen(key);
+       buf[0] = cpu_to_le32(len);
+       buf[1] = cpu_to_le32(perdatum->value);
+       rc = put_entry(buf, sizeof(u32), 2, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int common_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct common_datum *comdatum = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       __le32 buf[4];
+       size_t len;
+       int rc;
+
+       len = strlen(key);
+       buf[0] = cpu_to_le32(len);
+       buf[1] = cpu_to_le32(comdatum->value);
+       buf[2] = cpu_to_le32(comdatum->permissions.nprim);
+       buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
+       rc = put_entry(buf, sizeof(u32), 4, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int write_cons_helper(struct policydb *p, struct constraint_node *node,
+                            void *fp)
+{
+       struct constraint_node *c;
+       struct constraint_expr *e;
+       __le32 buf[3];
+       u32 nel;
+       int rc;
+
+       for (c = node; c; c = c->next) {
+               nel = 0;
+               for (e = c->expr; e; e = e->next)
+                       nel++;
+               buf[0] = cpu_to_le32(c->permissions);
+               buf[1] = cpu_to_le32(nel);
+               rc = put_entry(buf, sizeof(u32), 2, fp);
+               if (rc)
+                       return rc;
+               for (e = c->expr; e; e = e->next) {
+                       buf[0] = cpu_to_le32(e->expr_type);
+                       buf[1] = cpu_to_le32(e->attr);
+                       buf[2] = cpu_to_le32(e->op);
+                       rc = put_entry(buf, sizeof(u32), 3, fp);
+                       if (rc)
+                               return rc;
+
+                       switch (e->expr_type) {
+                       case CEXPR_NAMES:
+                               rc = ebitmap_write(&e->names, fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int class_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct class_datum *cladatum = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       struct policydb *p = pd->p;
+       struct constraint_node *c;
+       __le32 buf[6];
+       u32 ncons;
+       size_t len, len2;
+       int rc;
+
+       len = strlen(key);
+       if (cladatum->comkey)
+               len2 = strlen(cladatum->comkey);
+       else
+               len2 = 0;
+
+       ncons = 0;
+       for (c = cladatum->constraints; c; c = c->next)
+               ncons++;
+
+       buf[0] = cpu_to_le32(len);
+       buf[1] = cpu_to_le32(len2);
+       buf[2] = cpu_to_le32(cladatum->value);
+       buf[3] = cpu_to_le32(cladatum->permissions.nprim);
+       if (cladatum->permissions.table)
+               buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
+       else
+               buf[4] = 0;
+       buf[5] = cpu_to_le32(ncons);
+       rc = put_entry(buf, sizeof(u32), 6, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       if (cladatum->comkey) {
+               rc = put_entry(cladatum->comkey, 1, len2, fp);
+               if (rc)
+                       return rc;
+       }
+
+       rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
+       if (rc)
+               return rc;
+
+       rc = write_cons_helper(p, cladatum->constraints, fp);
+       if (rc)
+               return rc;
+
+       /* write out the validatetrans rule */
+       ncons = 0;
+       for (c = cladatum->validatetrans; c; c = c->next)
+               ncons++;
+
+       buf[0] = cpu_to_le32(ncons);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       rc = write_cons_helper(p, cladatum->validatetrans, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int role_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct role_datum *role = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       struct policydb *p = pd->p;
+       __le32 buf[3];
+       size_t items, len;
+       int rc;
+
+       len = strlen(key);
+       items = 0;
+       buf[items++] = cpu_to_le32(len);
+       buf[items++] = cpu_to_le32(role->value);
+       if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
+               buf[items++] = cpu_to_le32(role->bounds);
+
+       BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+
+       rc = put_entry(buf, sizeof(u32), items, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       rc = ebitmap_write(&role->dominates, fp);
+       if (rc)
+               return rc;
+
+       rc = ebitmap_write(&role->types, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int type_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct type_datum *typdatum = datum;
+       struct policy_data *pd = ptr;
+       struct policydb *p = pd->p;
+       void *fp = pd->fp;
+       __le32 buf[4];
+       int rc;
+       size_t items, len;
+
+       len = strlen(key);
+       items = 0;
+       buf[items++] = cpu_to_le32(len);
+       buf[items++] = cpu_to_le32(typdatum->value);
+       if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
+               u32 properties = 0;
+
+               if (typdatum->primary)
+                       properties |= TYPEDATUM_PROPERTY_PRIMARY;
+
+               if (typdatum->attribute)
+                       properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
+
+               buf[items++] = cpu_to_le32(properties);
+               buf[items++] = cpu_to_le32(typdatum->bounds);
+       } else {
+               buf[items++] = cpu_to_le32(typdatum->primary);
+       }
+       BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+       rc = put_entry(buf, sizeof(u32), items, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int user_write(void *vkey, void *datum, void *ptr)
+{
+       char *key = vkey;
+       struct user_datum *usrdatum = datum;
+       struct policy_data *pd = ptr;
+       struct policydb *p = pd->p;
+       void *fp = pd->fp;
+       __le32 buf[3];
+       size_t items, len;
+       int rc;
+
+       len = strlen(key);
+       items = 0;
+       buf[items++] = cpu_to_le32(len);
+       buf[items++] = cpu_to_le32(usrdatum->value);
+       if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
+               buf[items++] = cpu_to_le32(usrdatum->bounds);
+       BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+       rc = put_entry(buf, sizeof(u32), items, fp);
+       if (rc)
+               return rc;
+
+       rc = put_entry(key, 1, len, fp);
+       if (rc)
+               return rc;
+
+       rc = ebitmap_write(&usrdatum->roles, fp);
+       if (rc)
+               return rc;
+
+       rc = mls_write_range_helper(&usrdatum->range, fp);
+       if (rc)
+               return rc;
+
+       rc = mls_write_level(&usrdatum->dfltlevel, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int (*write_f[SYM_NUM]) (void *key, void *datum,
+                               void *datap) =
+{
+       common_write,
+       class_write,
+       role_write,
+       type_write,
+       user_write,
+       cond_write_bool,
+       sens_write,
+       cat_write,
+};
+
+static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
+                         void *fp)
+{
+       unsigned int i, j, rc;
+       size_t nel, len;
+       __le32 buf[3];
+       u32 nodebuf[8];
+       struct ocontext *c;
+       for (i = 0; i < info->ocon_num; i++) {
+               nel = 0;
+               for (c = p->ocontexts[i]; c; c = c->next)
+                       nel++;
+               buf[0] = cpu_to_le32(nel);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               for (c = p->ocontexts[i]; c; c = c->next) {
+                       switch (i) {
+                       case OCON_ISID:
+                               buf[0] = cpu_to_le32(c->sid[0]);
+                               rc = put_entry(buf, sizeof(u32), 1, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       case OCON_FS:
+                       case OCON_NETIF:
+                               len = strlen(c->u.name);
+                               buf[0] = cpu_to_le32(len);
+                               rc = put_entry(buf, sizeof(u32), 1, fp);
+                               if (rc)
+                                       return rc;
+                               rc = put_entry(c->u.name, 1, len, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[1], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       case OCON_PORT:
+                               buf[0] = cpu_to_le32(c->u.port.protocol);
+                               buf[1] = cpu_to_le32(c->u.port.low_port);
+                               buf[2] = cpu_to_le32(c->u.port.high_port);
+                               rc = put_entry(buf, sizeof(u32), 3, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       case OCON_NODE:
+                               nodebuf[0] = c->u.node.addr; /* network order */
+                               nodebuf[1] = c->u.node.mask; /* network order */
+                               rc = put_entry(nodebuf, sizeof(u32), 2, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       case OCON_FSUSE:
+                               buf[0] = cpu_to_le32(c->v.behavior);
+                               len = strlen(c->u.name);
+                               buf[1] = cpu_to_le32(len);
+                               rc = put_entry(buf, sizeof(u32), 2, fp);
+                               if (rc)
+                                       return rc;
+                               rc = put_entry(c->u.name, 1, len, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       case OCON_NODE6:
+                               for (j = 0; j < 4; j++)
+                                       nodebuf[j] = c->u.node6.addr[j]; /* network order */
+                               for (j = 0; j < 4; j++)
+                                       nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
+                               rc = put_entry(nodebuf, sizeof(u32), 8, fp);
+                               if (rc)
+                                       return rc;
+                               rc = context_write(p, &c->context[0], fp);
+                               if (rc)
+                                       return rc;
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int genfs_write(struct policydb *p, void *fp)
+{
+       struct genfs *genfs;
+       struct ocontext *c;
+       size_t len;
+       __le32 buf[1];
+       int rc;
+
+       len = 0;
+       for (genfs = p->genfs; genfs; genfs = genfs->next)
+               len++;
+       buf[0] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+       for (genfs = p->genfs; genfs; genfs = genfs->next) {
+               len = strlen(genfs->fstype);
+               buf[0] = cpu_to_le32(len);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               rc = put_entry(genfs->fstype, 1, len, fp);
+               if (rc)
+                       return rc;
+               len = 0;
+               for (c = genfs->head; c; c = c->next)
+                       len++;
+               buf[0] = cpu_to_le32(len);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               for (c = genfs->head; c; c = c->next) {
+                       len = strlen(c->u.name);
+                       buf[0] = cpu_to_le32(len);
+                       rc = put_entry(buf, sizeof(u32), 1, fp);
+                       if (rc)
+                               return rc;
+                       rc = put_entry(c->u.name, 1, len, fp);
+                       if (rc)
+                               return rc;
+                       buf[0] = cpu_to_le32(c->v.sclass);
+                       rc = put_entry(buf, sizeof(u32), 1, fp);
+                       if (rc)
+                               return rc;
+                       rc = context_write(p, &c->context[0], fp);
+                       if (rc)
+                               return rc;
+               }
+       }
+       return 0;
+}
+
+static int range_count(void *key, void *data, void *ptr)
+{
+       int *cnt = ptr;
+       *cnt = *cnt + 1;
+
+       return 0;
+}
+
+static int range_write_helper(void *key, void *data, void *ptr)
+{
+       __le32 buf[2];
+       struct range_trans *rt = key;
+       struct mls_range *r = data;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       struct policydb *p = pd->p;
+       int rc;
+
+       buf[0] = cpu_to_le32(rt->source_type);
+       buf[1] = cpu_to_le32(rt->target_type);
+       rc = put_entry(buf, sizeof(u32), 2, fp);
+       if (rc)
+               return rc;
+       if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
+               buf[0] = cpu_to_le32(rt->target_class);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+       }
+       rc = mls_write_range_helper(r, fp);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int range_write(struct policydb *p, void *fp)
+{
+       size_t nel;
+       __le32 buf[1];
+       int rc;
+       struct policy_data pd;
+
+       pd.p = p;
+       pd.fp = fp;
+
+       /* count the number of entries in the hashtab */
+       nel = 0;
+       rc = hashtab_map(p->range_tr, range_count, &nel);
+       if (rc)
+               return rc;
+
+       buf[0] = cpu_to_le32(nel);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+
+       /* actually write all of the entries */
+       rc = hashtab_map(p->range_tr, range_write_helper, &pd);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * Write the configuration data in a policy database
+ * structure to a policy database binary representation
+ * file.
+ */
+int policydb_write(struct policydb *p, void *fp)
+{
+       unsigned int i, num_syms;
+       int rc;
+       __le32 buf[4];
+       u32 config;
+       size_t len;
+       struct policydb_compat_info *info;
+
+       /*
+        * refuse to write policy older than compressed avtab
+        * to simplify the writer.  There are other tests dropped
+        * since we assume this throughout the writer code.  Be
+        * careful if you ever try to remove this restriction
+        */
+       if (p->policyvers < POLICYDB_VERSION_AVTAB) {
+               printk(KERN_ERR "SELinux: refusing to write policy version %d."
+                      "  Because it is less than version %d\n", p->policyvers,
+                      POLICYDB_VERSION_AVTAB);
+               return -EINVAL;
+       }
+
+       config = 0;
+       if (p->mls_enabled)
+               config |= POLICYDB_CONFIG_MLS;
+
+       if (p->reject_unknown)
+               config |= REJECT_UNKNOWN;
+       if (p->allow_unknown)
+               config |= ALLOW_UNKNOWN;
+
+       /* Write the magic number and string identifiers. */
+       buf[0] = cpu_to_le32(POLICYDB_MAGIC);
+       len = strlen(POLICYDB_STRING);
+       buf[1] = cpu_to_le32(len);
+       rc = put_entry(buf, sizeof(u32), 2, fp);
+       if (rc)
+               return rc;
+       rc = put_entry(POLICYDB_STRING, 1, len, fp);
+       if (rc)
+               return rc;
+
+       /* Write the version, config, and table sizes. */
+       info = policydb_lookup_compat(p->policyvers);
+       if (!info) {
+               printk(KERN_ERR "SELinux: compatibility lookup failed for policy "
+                   "version %d", p->policyvers);
+               return rc;
+       }
+
+       buf[0] = cpu_to_le32(p->policyvers);
+       buf[1] = cpu_to_le32(config);
+       buf[2] = cpu_to_le32(info->sym_num);
+       buf[3] = cpu_to_le32(info->ocon_num);
+
+       rc = put_entry(buf, sizeof(u32), 4, fp);
+       if (rc)
+               return rc;
+
+       if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
+               rc = ebitmap_write(&p->policycaps, fp);
+               if (rc)
+                       return rc;
+       }
+
+       if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
+               rc = ebitmap_write(&p->permissive_map, fp);
+               if (rc)
+                       return rc;
+       }
+
+       num_syms = info->sym_num;
+       for (i = 0; i < num_syms; i++) {
+               struct policy_data pd;
+
+               pd.fp = fp;
+               pd.p = p;
+
+               buf[0] = cpu_to_le32(p->symtab[i].nprim);
+               buf[1] = cpu_to_le32(p->symtab[i].table->nel);
+
+               rc = put_entry(buf, sizeof(u32), 2, fp);
+               if (rc)
+                       return rc;
+               rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
+               if (rc)
+                       return rc;
+       }
+
+       rc = avtab_write(p, &p->te_avtab, fp);
+       if (rc)
+               return rc;
+
+       rc = cond_write_list(p, p->cond_list, fp);
+       if (rc)
+               return rc;
+
+       rc = role_trans_write(p->role_tr, fp);
+       if (rc)
+               return rc;
+
+       rc = role_allow_write(p->role_allow, fp);
+       if (rc)
+               return rc;
+
+       rc = ocontext_write(p, info, fp);
+       if (rc)
+               return rc;
+
+       rc = genfs_write(p, fp);
+       if (rc)
+               return rc;
+
+       rc = range_write(p, fp);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < p->p_types.nprim; i++) {
+               struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
+
+               BUG_ON(!e);
+               rc = ebitmap_write(e, fp);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
index 310e94442cb8b3535a8774b952de45ba0180794e..95d3d7de361e628adcc53b974533cafb384ef851 100644 (file)
@@ -254,6 +254,9 @@ struct policydb {
 
        struct ebitmap permissive_map;
 
+       /* length of this policy when it was loaded */
+       size_t len;
+
        unsigned int policyvers;
 
        unsigned int reject_unknown : 1;
@@ -270,6 +273,7 @@ extern int policydb_class_isvalid(struct policydb *p, unsigned int class);
 extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
 extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
 extern int policydb_read(struct policydb *p, void *fp);
+extern int policydb_write(struct policydb *p, void *fp);
 
 #define PERM_SYMTAB_SIZE 32
 
@@ -290,6 +294,11 @@ struct policy_file {
        size_t len;
 };
 
+struct policy_data {
+       struct policydb *p;
+       void *fp;
+};
+
 static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
 {
        if (bytes > fp->len)
@@ -301,6 +310,17 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
        return 0;
 }
 
+static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp)
+{
+       size_t len = bytes * num;
+
+       memcpy(fp->data, buf, len);
+       fp->data += len;
+       fp->len -= len;
+
+       return 0;
+}
+
 extern u16 string_to_security_class(struct policydb *p, const char *name);
 extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
 
index 9ea2feca3cd4f7b572361543fdf1b265002cecfb..223c1ff6ef2324488eca915d2ba87bc4f6e27fa9 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/mutex.h>
 #include <linux/selinux.h>
 #include <linux/flex_array.h>
+#include <linux/vmalloc.h>
 #include <net/netlabel.h>
 
 #include "flask.h"
@@ -991,7 +992,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 {
        char *scontextp;
 
-       *scontext = NULL;
+       if (scontext)
+               *scontext = NULL;
        *scontext_len = 0;
 
        if (context->len) {
@@ -1008,6 +1010,9 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
        *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
        *scontext_len += mls_compute_context_len(context);
 
+       if (!scontext)
+               return 0;
+
        /* Allocate space for the context; caller must free this space. */
        scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
        if (!scontextp)
@@ -1047,7 +1052,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
        struct context *context;
        int rc = 0;
 
-       *scontext = NULL;
+       if (scontext)
+               *scontext = NULL;
        *scontext_len  = 0;
 
        if (!ss_initialized) {
@@ -1055,6 +1061,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
                        char *scontextp;
 
                        *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+                       if (!scontext)
+                               goto out;
                        scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
                        if (!scontextp) {
                                rc = -ENOMEM;
@@ -1769,6 +1777,7 @@ int security_load_policy(void *data, size_t len)
                        return rc;
                }
 
+               policydb.len = len;
                rc = selinux_set_mapping(&policydb, secclass_map,
                                         &current_mapping,
                                         &current_mapping_size);
@@ -1791,6 +1800,7 @@ int security_load_policy(void *data, size_t len)
                selinux_complete_init();
                avc_ss_reset(seqno);
                selnl_notify_policyload(seqno);
+               selinux_status_update_policyload(seqno);
                selinux_netlbl_cache_invalidate();
                selinux_xfrm_notify_policyload();
                return 0;
@@ -1804,6 +1814,7 @@ int security_load_policy(void *data, size_t len)
        if (rc)
                return rc;
 
+       newpolicydb.len = len;
        /* If switching between different policy types, log MLS status */
        if (policydb.mls_enabled && !newpolicydb.mls_enabled)
                printk(KERN_INFO "SELinux: Disabling MLS support...\n");
@@ -1870,6 +1881,7 @@ int security_load_policy(void *data, size_t len)
 
        avc_ss_reset(seqno);
        selnl_notify_policyload(seqno);
+       selinux_status_update_policyload(seqno);
        selinux_netlbl_cache_invalidate();
        selinux_xfrm_notify_policyload();
 
@@ -1883,6 +1895,17 @@ err:
 
 }
 
+size_t security_policydb_len(void)
+{
+       size_t len;
+
+       read_lock(&policy_rwlock);
+       len = policydb.len;
+       read_unlock(&policy_rwlock);
+
+       return len;
+}
+
 /**
  * security_port_sid - Obtain the SID for a port.
  * @protocol: protocol number
@@ -2374,6 +2397,7 @@ out:
        if (!rc) {
                avc_ss_reset(seqno);
                selnl_notify_policyload(seqno);
+               selinux_status_update_policyload(seqno);
                selinux_xfrm_notify_policyload();
        }
        return rc;
@@ -3129,3 +3153,38 @@ netlbl_sid_to_secattr_failure:
        return rc;
 }
 #endif /* CONFIG_NETLABEL */
+
+/**
+ * security_read_policy - read the policy.
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ */
+int security_read_policy(void **data, ssize_t *len)
+{
+       int rc;
+       struct policy_file fp;
+
+       if (!ss_initialized)
+               return -EINVAL;
+
+       *len = security_policydb_len();
+
+       *data = vmalloc_user(*len);
+       if (!*data)
+               return -ENOMEM;
+
+       fp.data = *data;
+       fp.len = *len;
+
+       read_lock(&policy_rwlock);
+       rc = policydb_write(&policydb, &fp);
+       read_unlock(&policy_rwlock);
+
+       if (rc)
+               return rc;
+
+       *len = (unsigned long)fp.data - (unsigned long)*data;
+       return 0;
+
+}
diff --git a/security/selinux/ss/status.c b/security/selinux/ss/status.c
new file mode 100644 (file)
index 0000000..d982365
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * mmap based event notifications for SELinux
+ *
+ * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * Copyright (C) 2010 NEC corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include "avc.h"
+#include "services.h"
+
+/*
+ * The selinux_status_page shall be exposed to userspace applications
+ * using mmap interface on /selinux/status.
+ * It enables to notify applications a few events that will cause reset
+ * of userspace access vector without context switching.
+ *
+ * The selinux_kernel_status structure on the head of status page is
+ * protected from concurrent accesses using seqlock logic, so userspace
+ * application should reference the status page according to the seqlock
+ * logic.
+ *
+ * Typically, application checks status->sequence at the head of access
+ * control routine. If it is odd-number, kernel is updating the status,
+ * so please wait for a moment. If it is changed from the last sequence
+ * number, it means something happen, so application will reset userspace
+ * avc, if needed.
+ * In most cases, application shall confirm the kernel status is not
+ * changed without any system call invocations.
+ */
+static struct page *selinux_status_page;
+static DEFINE_MUTEX(selinux_status_lock);
+
+/*
+ * selinux_kernel_status_page
+ *
+ * It returns a reference to selinux_status_page. If the status page is
+ * not allocated yet, it also tries to allocate it at the first time.
+ */
+struct page *selinux_kernel_status_page(void)
+{
+       struct selinux_kernel_status   *status;
+       struct page                    *result = NULL;
+
+       mutex_lock(&selinux_status_lock);
+       if (!selinux_status_page) {
+               selinux_status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+
+               if (selinux_status_page) {
+                       status = page_address(selinux_status_page);
+
+                       status->version = SELINUX_KERNEL_STATUS_VERSION;
+                       status->sequence = 0;
+                       status->enforcing = selinux_enforcing;
+                       /*
+                        * NOTE: the next policyload event shall set
+                        * a positive value on the status->policyload,
+                        * although it may not be 1, but never zero.
+                        * So, application can know it was updated.
+                        */
+                       status->policyload = 0;
+                       status->deny_unknown = !security_get_allow_unknown();
+               }
+       }
+       result = selinux_status_page;
+       mutex_unlock(&selinux_status_lock);
+
+       return result;
+}
+
+/*
+ * selinux_status_update_setenforce
+ *
+ * It updates status of the current enforcing/permissive mode.
+ */
+void selinux_status_update_setenforce(int enforcing)
+{
+       struct selinux_kernel_status   *status;
+
+       mutex_lock(&selinux_status_lock);
+       if (selinux_status_page) {
+               status = page_address(selinux_status_page);
+
+               status->sequence++;
+               smp_wmb();
+
+               status->enforcing = enforcing;
+
+               smp_wmb();
+               status->sequence++;
+       }
+       mutex_unlock(&selinux_status_lock);
+}
+
+/*
+ * selinux_status_update_policyload
+ *
+ * It updates status of the times of policy reloaded, and current
+ * setting of deny_unknown.
+ */
+void selinux_status_update_policyload(int seqno)
+{
+       struct selinux_kernel_status   *status;
+
+       mutex_lock(&selinux_status_lock);
+       if (selinux_status_page) {
+               status = page_address(selinux_status_page);
+
+               status->sequence++;
+               smp_wmb();
+
+               status->policyload = seqno;
+               status->deny_unknown = !security_get_allow_unknown();
+
+               smp_wmb();
+               status->sequence++;
+       }
+       mutex_unlock(&selinux_status_lock);
+}
index c448d57ae2b7721f72f17c5cf42e88f3f1bcba5e..bc39f4067af668874312af4187ad6f21dbdbb113 100644 (file)
@@ -1281,12 +1281,11 @@ static int smack_task_getioprio(struct task_struct *p)
  *
  * Return 0 if read access is permitted
  */
-static int smack_task_setscheduler(struct task_struct *p, int policy,
-                                  struct sched_param *lp)
+static int smack_task_setscheduler(struct task_struct *p)
 {
        int rc;
 
-       rc = cap_task_setscheduler(p, policy, lp);
+       rc = cap_task_setscheduler(p);
        if (rc == 0)
                rc = smk_curacc_on_task(p, MAY_WRITE);
        return rc;
@@ -3005,7 +3004,8 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
        char *sp = smack_from_secid(secid);
 
-       *secdata = sp;
+       if (secdata)
+               *secdata = sp;
        *seclen = strlen(sp);
        return 0;
 }
index a2b72d77f9265f7553c4bffb225644baf4bd44d0..7512502d0162b6be0afc54f874e88f407b8470c6 100644 (file)
@@ -968,6 +968,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
 static const struct file_operations smk_doi_ops = {
        .read           = smk_read_doi,
        .write          = smk_write_doi,
+       .llseek         = default_llseek,
 };
 
 /**
@@ -1031,6 +1032,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
 static const struct file_operations smk_direct_ops = {
        .read           = smk_read_direct,
        .write          = smk_write_direct,
+       .llseek         = default_llseek,
 };
 
 /**
@@ -1112,6 +1114,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
 static const struct file_operations smk_ambient_ops = {
        .read           = smk_read_ambient,
        .write          = smk_write_ambient,
+       .llseek         = default_llseek,
 };
 
 /**
@@ -1191,6 +1194,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
 static const struct file_operations smk_onlycap_ops = {
        .read           = smk_read_onlycap,
        .write          = smk_write_onlycap,
+       .llseek         = default_llseek,
 };
 
 /**
@@ -1255,6 +1259,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf,
 static const struct file_operations smk_logging_ops = {
        .read           = smk_read_logging,
        .write          = smk_write_logging,
+       .llseek         = default_llseek,
 };
 /**
  * smk_fill_super - fill the /smackfs superblock
index ef43995119a453401dd768adfa5ae41a2602dd3a..7556315c197823e0baedcf15d0f0930c74345429 100644 (file)
@@ -768,8 +768,10 @@ static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
                return true; /* Do nothing if open(O_WRONLY). */
        memset(&head->r, 0, sizeof(head->r));
        head->r.print_this_domain_only = true;
-       head->r.eof = !domain;
-       head->r.domain = &domain->list;
+       if (domain)
+               head->r.domain = &domain->list;
+       else
+               head->r.eof = 1;
        tomoyo_io_printf(head, "# select %s\n", data);
        if (domain && domain->is_deleted)
                tomoyo_io_printf(head, "# This is a deleted domain.\n");
@@ -1416,15 +1418,19 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
        const pid_t gpid = task_pid_nr(current);
        static const int tomoyo_buffer_len = 4096;
        char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
+       pid_t ppid;
        if (!buffer)
                return NULL;
        do_gettimeofday(&tv);
+       rcu_read_lock();
+       ppid = task_tgid_vnr(current->real_parent);
+       rcu_read_unlock();
        snprintf(buffer, tomoyo_buffer_len - 1,
                 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
                 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
                 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
                 tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid,
-                (pid_t) sys_getpid(), (pid_t) sys_getppid(),
+                task_tgid_vnr(current), ppid,
                 current_uid(), current_gid(), current_euid(),
                 current_egid(), current_suid(), current_sgid(),
                 current_fsuid(), current_fsgid());
@@ -2047,13 +2053,22 @@ void tomoyo_check_profile(void)
                const u8 profile = domain->profile;
                if (tomoyo_profile_ptr[profile])
                        continue;
+               printk(KERN_ERR "You need to define profile %u before using it.\n",
+                      profile);
+               printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
+                      "for more information.\n");
                panic("Profile %u (used by '%s') not defined.\n",
                      profile, domain->domainname->name);
        }
        tomoyo_read_unlock(idx);
-       if (tomoyo_profile_version != 20090903)
+       if (tomoyo_profile_version != 20090903) {
+               printk(KERN_ERR "You need to install userland programs for "
+                      "TOMOYO 2.3 and initialize policy configuration.\n");
+               printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
+                      "for more information.\n");
                panic("Profile version %u is not supported.\n",
                      tomoyo_profile_version);
+       }
        printk(KERN_INFO "TOMOYO: 2.3.0\n");
        printk(KERN_INFO "Mandatory Access Control activated.\n");
 }
index 04454cb7b24a534e84c8873a8babeb9614a8da60..7c66bd898782ce0c6fa8ea037cd19dfd78fc8bfe 100644 (file)
@@ -689,9 +689,6 @@ struct tomoyo_profile {
 
 /********** Function prototypes. **********/
 
-extern asmlinkage long sys_getpid(void);
-extern asmlinkage long sys_getppid(void);
-
 /* Check whether the given string starts with the given keyword. */
 bool tomoyo_str_starts(char **src, const char *find);
 /* Get tomoyo_realpath() of current process. */
index 070aab4901914870a0af43faef27e82e761acc32..45a818002d990f664cffadd066488a21c76fedd7 100644 (file)
@@ -31,6 +31,7 @@
 
 /* max number of user-defined controls */
 #define MAX_USER_CONTROLS      32
+#define MAX_CONTROL_COUNT      1028
 
 struct snd_kctl_ioctl {
        struct list_head list;          /* list of all ioctls */
@@ -195,6 +196,10 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
        
        if (snd_BUG_ON(!control || !control->count))
                return NULL;
+
+       if (control->count > MAX_CONTROL_COUNT)
+               return NULL;
+
        kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
        if (kctl == NULL) {
                snd_printk(KERN_ERR "Cannot allocate control instance\n");
index cbe815dfbdc8c3bd3f417ba960e7aee37cf5a0e9..ac242a377aea8068f859bce49aae6825aae5d001 100644 (file)
@@ -203,10 +203,16 @@ static char *snd_pcm_format_names[] = {
        FORMAT(S18_3BE),
        FORMAT(U18_3LE),
        FORMAT(U18_3BE),
+       FORMAT(G723_24),
+       FORMAT(G723_24_1B),
+       FORMAT(G723_40),
+       FORMAT(G723_40_1B),
 };
 
 const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
+       if (format >= ARRAY_SIZE(snd_pcm_format_names))
+               return "Unknown";
        return snd_pcm_format_names[format];
 }
 EXPORT_SYMBOL_GPL(snd_pcm_format_name);
@@ -366,14 +372,17 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
                                                  struct snd_info_buffer *buffer)
 {
        struct snd_pcm_substream *substream = entry->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime;
+
+       mutex_lock(&substream->pcm->open_mutex);
+       runtime = substream->runtime;
        if (!runtime) {
                snd_iprintf(buffer, "closed\n");
-               return;
+               goto unlock;
        }
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                snd_iprintf(buffer, "no setup\n");
-               return;
+               goto unlock;
        }
        snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
        snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
@@ -392,20 +401,25 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
        }
 #endif
+ unlock:
+       mutex_unlock(&substream->pcm->open_mutex);
 }
 
 static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
                                                  struct snd_info_buffer *buffer)
 {
        struct snd_pcm_substream *substream = entry->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime;
+
+       mutex_lock(&substream->pcm->open_mutex);
+       runtime = substream->runtime;
        if (!runtime) {
                snd_iprintf(buffer, "closed\n");
-               return;
+               goto unlock;
        }
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                snd_iprintf(buffer, "no setup\n");
-               return;
+               goto unlock;
        }
        snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
        snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
@@ -415,24 +429,29 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
        snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
        snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
+ unlock:
+       mutex_unlock(&substream->pcm->open_mutex);
 }
 
 static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
                                               struct snd_info_buffer *buffer)
 {
        struct snd_pcm_substream *substream = entry->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime;
        struct snd_pcm_status status;
        int err;
+
+       mutex_lock(&substream->pcm->open_mutex);
+       runtime = substream->runtime;
        if (!runtime) {
                snd_iprintf(buffer, "closed\n");
-               return;
+               goto unlock;
        }
        memset(&status, 0, sizeof(status));
        err = snd_pcm_status(substream, &status);
        if (err < 0) {
                snd_iprintf(buffer, "error %d\n", err);
-               return;
+               goto unlock;
        }
        snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
        snd_iprintf(buffer, "owner_pid   : %d\n", pid_vnr(substream->pid));
@@ -446,6 +465,8 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "-----\n");
        snd_iprintf(buffer, "hw_ptr      : %ld\n", runtime->status->hw_ptr);
        snd_iprintf(buffer, "appl_ptr    : %ld\n", runtime->control->appl_ptr);
+ unlock:
+       mutex_unlock(&substream->pcm->open_mutex);
 }
 
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
index 134fc6c2e08dc01eeda84a730545b0532f0588fe..d4eb2ef8078416cc8d06e5d80f3ec3bb467a4f1b 100644 (file)
@@ -1992,6 +1992,8 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
                substream->ops->close(substream);
                substream->hw_opened = 0;
        }
+       if (pm_qos_request_active(&substream->latency_pm_qos_req))
+               pm_qos_remove_request(&substream->latency_pm_qos_req);
        if (substream->pcm_release) {
                substream->pcm_release(substream);
                substream->pcm_release = NULL;
index eb68326c37d47626b53d7970fe6e88027edc0e13..cbbed0db9e560315ae0559c7e5e97786387a5371 100644 (file)
@@ -535,13 +535,15 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
 {
        struct snd_rawmidi_file *rfile;
        struct snd_rawmidi *rmidi;
+       struct module *module;
 
        rfile = file->private_data;
        rmidi = rfile->rmidi;
        rawmidi_release_priv(rfile);
        kfree(rfile);
+       module = rmidi->card->module;
        snd_card_file_remove(rmidi->card, file);
-       module_put(rmidi->card->module);
+       module_put(module);
        return 0;
 }
 
@@ -829,6 +831,8 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
                
                if (get_user(device, (int __user *)argp))
                        return -EFAULT;
+               if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */
+                       device = SNDRV_RAWMIDI_DEVICES - 1;
                mutex_lock(&register_mutex);
                device = device < 0 ? 0 : device + 1;
                while (device < SNDRV_RAWMIDI_DEVICES) {
index f25e3cc7ddfa53b4aa9244abe3fdf776146d7958..a1f1a2f00ccb6f1398a17bcab473908420b82a24 100644 (file)
@@ -220,6 +220,7 @@ static const struct file_operations seq_oss_f_ops =
        .poll =         odev_poll,
        .unlocked_ioctl =       odev_ioctl,
        .compat_ioctl = odev_ioctl_compat,
+       .llseek =       noop_llseek,
 };
 
 static int __init
index 685712276ac95ab0d57985489b86f4f840bcf9b1..69cd7b3c362d19f4b0ac989b8bc107e49e59ff1b 100644 (file)
@@ -281,13 +281,10 @@ snd_seq_oss_open(struct file *file, int level)
        return 0;
 
  _error:
-       snd_seq_oss_writeq_delete(dp->writeq);
-       snd_seq_oss_readq_delete(dp->readq);
        snd_seq_oss_synth_cleanup(dp);
        snd_seq_oss_midi_cleanup(dp);
-       delete_port(dp);
        delete_seq_queue(dp->queue);
-       kfree(dp);
+       delete_port(dp);
 
        return rc;
 }
@@ -350,8 +347,10 @@ create_port(struct seq_oss_devinfo *dp)
 static int
 delete_port(struct seq_oss_devinfo *dp)
 {
-       if (dp->port < 0)
+       if (dp->port < 0) {
+               kfree(dp);
                return 0;
+       }
 
        debug_printk(("delete_port %i\n", dp->port));
        return snd_seq_event_port_detach(dp->cseq, dp->port);
index ac42af42b78709d367713e49626440c116ba3ca2..62a093efb453cc5d9657e4a3ce822ce42ca07748 100644 (file)
@@ -184,7 +184,8 @@ static int snd_open(struct inode *inode, struct file *file)
 static const struct file_operations snd_fops =
 {
        .owner =        THIS_MODULE,
-       .open =         snd_open
+       .open =         snd_open,
+       .llseek =       noop_llseek,
 };
 
 #ifdef CONFIG_SND_DYNAMIC_MINORS
index 1adb8a3c2b62db229f9ba0b580d930d288e74c14..42d7844ecd0bfa66ddf3db96527ccc18c79f7485 100644 (file)
@@ -900,7 +900,7 @@ static int proc_init(struct snd_akm4xxx *ak)
        return 0;
 }
 #else /* !CONFIG_PROC_FS */
-static int proc_init(struct snd_akm4xxx *ak) {}
+static int proc_init(struct snd_akm4xxx *ak) { return 0; }
 #endif
 
 int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
index 5f3e68401f905dbf2b8a03bc12fd657450b739d4..91d6023a63e57c6b14227e158c171b8edf4b8087 100644 (file)
@@ -764,9 +764,9 @@ static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 
+#ifndef MSND_CLASSIC
 static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 
-#ifndef MSND_CLASSIC
 /* Extra Peripheral Configuration (Default: Disable) */
 static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
@@ -894,7 +894,11 @@ static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
        struct snd_card *card;
        struct snd_msnd *chip;
 
-       if (has_isapnp(idx) || cfg[idx] == SNDRV_AUTO_PORT) {
+       if (has_isapnp(idx)
+#ifndef MSND_CLASSIC
+           || cfg[idx] == SNDRV_AUTO_PORT
+#endif
+           ) {
                printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
                return -ENODEV;
        }
index 2e48b17667d0f661671dfdfd0a3f30bd7b641b95..ca942f7cd2313c38c95d091f20c78658b36b36b7 100644 (file)
@@ -1117,6 +1117,7 @@ static const struct file_operations dev_fileops = {
        .unlocked_ioctl = dev_ioctl,
        .open           = dev_open,
        .release        = dev_release,
+       .llseek         = noop_llseek,
 };
 
 static int reset_dsp(void)
index f0f0c19fbff7a75c4e5ad561d18ce9f970775e97..48cda6c4c257b34d191d3512ff52658de4329669 100644 (file)
@@ -26,7 +26,7 @@ static unsigned long prev_event_time;
 static volatile unsigned long usecs_per_tmr;   /* Length of the current interval */
 
 static struct sound_lowlev_timer *tmr;
-static spinlock_t lock;
+static DEFINE_SPINLOCK(lock);
 
 static unsigned long tmr2ticks(int tmr_value)
 {
index 92aa762ffb7e97c998db3ca1da3a5cddc2968139..07f803e6d203a41615db0923cf073f7eadc283b6 100644 (file)
@@ -391,11 +391,11 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case SND_DEV_DSP:
        case SND_DEV_DSP16:
        case SND_DEV_AUDIO:
-               return audio_ioctl(dev, file, cmd, p);
+               ret = audio_ioctl(dev, file, cmd, p);
                break;
 
        case SND_DEV_MIDIN:
-               return MIDIbuf_ioctl(dev, file, cmd, p);
+               ret = MIDIbuf_ioctl(dev, file, cmd, p);
                break;
 
        }
index 3b44134482266ff5f17ddeb301b258846a34eb77..22c5fc6255335ac94aca5ac297432f16b0950c4e 100644 (file)
@@ -941,8 +941,7 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
 
 }
 
-static u32 outstream_get_space_available(struct hpi_hostbuffer_status
-       *status)
+static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)
 {
        return status->size_in_bytes - (status->host_index -
                status->dSP_index);
@@ -987,6 +986,10 @@ static void outstream_write(struct hpi_adapter_obj *pao,
                /* write it */
                phm->function = HPI_OSTREAM_WRITE;
                hw_message(pao, phm, phr);
+
+               if (phr->error)
+                       return;
+
                /* update status information that the DSP would typically
                 * update (and will update next time the DSP
                 * buffer update task reads data from the host BBM buffer)
index dd8fb86c842b85feef9a3018f2dcf42b2a06dba4..14829210ef0bf4b1bac018d4f5e31a1d1c4728b9 100644 (file)
@@ -589,6 +589,7 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
        bus->ops = temp->ops;
 
        mutex_init(&bus->cmd_mutex);
+       mutex_init(&bus->prepare_mutex);
        INIT_LIST_HEAD(&bus->codec_list);
 
        snprintf(bus->workq_name, sizeof(bus->workq_name),
@@ -1068,7 +1069,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
        codec->addr = codec_addr;
        mutex_init(&codec->spdif_mutex);
        mutex_init(&codec->control_mutex);
-       mutex_init(&codec->prepare_mutex);
        init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
        init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
        snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
@@ -1213,6 +1213,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                                u32 stream_tag,
                                int channel_id, int format)
 {
+       struct hda_codec *c;
        struct hda_cvt_setup *p;
        unsigned int oldval, newval;
        int i;
@@ -1253,10 +1254,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
        p->dirty = 0;
 
        /* make other inactive cvts with the same stream-tag dirty */
-       for (i = 0; i < codec->cvt_setups.used; i++) {
-               p = snd_array_elem(&codec->cvt_setups, i);
-               if (!p->active && p->stream_tag == stream_tag)
-                       p->dirty = 1;
+       list_for_each_entry(c, &codec->bus->codec_list, list) {
+               for (i = 0; i < c->cvt_setups.used; i++) {
+                       p = snd_array_elem(&c->cvt_setups, i);
+                       if (!p->active && p->stream_tag == stream_tag)
+                               p->dirty = 1;
+               }
        }
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
@@ -1306,12 +1309,16 @@ static void really_cleanup_stream(struct hda_codec *codec,
 /* clean up the all conflicting obsolete streams */
 static void purify_inactive_streams(struct hda_codec *codec)
 {
+       struct hda_codec *c;
        int i;
 
-       for (i = 0; i < codec->cvt_setups.used; i++) {
-               struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
-               if (p->dirty)
-                       really_cleanup_stream(codec, p);
+       list_for_each_entry(c, &codec->bus->codec_list, list) {
+               for (i = 0; i < c->cvt_setups.used; i++) {
+                       struct hda_cvt_setup *p;
+                       p = snd_array_elem(&c->cvt_setups, i);
+                       if (p->dirty)
+                               really_cleanup_stream(c, p);
+               }
        }
 }
 
@@ -3502,11 +3509,11 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
                          struct snd_pcm_substream *substream)
 {
        int ret;
-       mutex_lock(&codec->prepare_mutex);
+       mutex_lock(&codec->bus->prepare_mutex);
        ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream);
        if (ret >= 0)
                purify_inactive_streams(codec);
-       mutex_unlock(&codec->prepare_mutex);
+       mutex_unlock(&codec->bus->prepare_mutex);
        return ret;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);
@@ -3515,9 +3522,9 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
                           struct hda_pcm_stream *hinfo,
                           struct snd_pcm_substream *substream)
 {
-       mutex_lock(&codec->prepare_mutex);
+       mutex_lock(&codec->bus->prepare_mutex);
        hinfo->ops.cleanup(hinfo, codec, substream);
-       mutex_unlock(&codec->prepare_mutex);
+       mutex_unlock(&codec->bus->prepare_mutex);
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);
 
@@ -4529,7 +4536,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                        cfg->hp_outs--;
                        memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
                                sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
-                       memmove(sequences_hp + i - 1, sequences_hp + i,
+                       memmove(sequences_hp + i, sequences_hp + i + 1,
                                sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
                }
        }
index 4303353feda99af99b63b63ed0a9bb6a404f8fdc..62c70224010808dca1b7a8330e28dfa791bbe61e 100644 (file)
@@ -648,6 +648,7 @@ struct hda_bus {
        struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
 
        struct mutex cmd_mutex;
+       struct mutex prepare_mutex;
 
        /* unsolicited event queue */
        struct hda_bus_unsolicited *unsol;
@@ -826,7 +827,6 @@ struct hda_codec {
 
        struct mutex spdif_mutex;
        struct mutex control_mutex;
-       struct mutex prepare_mutex;
        unsigned int spdif_status;      /* IEC958 status bits */
        unsigned short spdif_ctls;      /* SPDIF control bits */
        unsigned int spdif_in_enable;   /* SPDIF input enable? */
index 803b298f741101065b5966f17a84cddf01028ef6..26c3ade735838624c9f6d2ca889b4ca724df96db 100644 (file)
@@ -596,6 +596,8 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
 }
 EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
 
+#endif /* CONFIG_PROC_FS */
+
 /* update PCM info based on ELD */
 void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
                              struct hda_pcm_stream *codec_pars)
@@ -644,5 +646,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
 EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info);
-
-#endif /* CONFIG_PROC_FS */
index 1053fff4bd0a7bc5b1dbe07de0c1a7a3d0df68db..34940a07905192590a056efe734e155d66f575f7 100644 (file)
@@ -126,6 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{Intel, ICH10},"
                         "{Intel, PCH},"
                         "{Intel, CPT},"
+                        "{Intel, PBG},"
                         "{Intel, SCH},"
                         "{ATI, SB450},"
                         "{ATI, SB600},"
@@ -2749,6 +2750,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
+       /* PBG */
+       { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
        /* ATI SB 450/600 */
index b697fd2a6f8b8cd19a84840fd8e05369226981db..10bbbaf6ebc3d2b0531ba2fb1ab7e3f2be1f8994 100644 (file)
@@ -3641,6 +3641,7 @@ static struct snd_pci_quirk ad1984_cfg_tbl[] = {
        /* Lenovo Thinkpad T61/X61 */
        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
        SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
+       SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
        {}
 };
 
index 4ef5efaaaef1a81d29290d5d9618097634957c10..488fd9ade1ba2bf7b306bf6e48ae106ef823294b 100644 (file)
@@ -972,6 +972,53 @@ static struct hda_verb cs_coef_init_verbs[] = {
        {} /* terminator */
 };
 
+/* Errata: CS4207 rev C0/C1/C2 Silicon
+ *
+ * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
+ *
+ * 6. At high temperature (TA > +85°C), the digital supply current (IVD)
+ * may be excessive (up to an additional 200 Î¼A), which is most easily
+ * observed while the part is being held in reset (RESET# active low).
+ *
+ * Root Cause: At initial powerup of the device, the logic that drives
+ * the clock and write enable to the S/PDIF SRC RAMs is not properly
+ * initialized.
+ * Certain random patterns will cause a steady leakage current in those
+ * RAM cells. The issue will resolve once the SRCs are used (turned on).
+ *
+ * Workaround: The following verb sequence briefly turns on the S/PDIF SRC
+ * blocks, which will alleviate the issue.
+ */
+
+static struct hda_verb cs_errata_init_verbs[] = {
+       {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
+       {0x11, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
+
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x9999},
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
+       {0x11, AC_VERB_SET_PROC_COEF, 0xa412},
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x0009},
+
+       {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */
+       {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */
+
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x2412},
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x0000},
+       {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x0008},
+       {0x11, AC_VERB_SET_PROC_STATE, 0x00},
+
+       {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */
+       {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */
+       /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */
+
+       {} /* terminator */
+};
+
 /* SPDIF setup */
 static void init_digital(struct hda_codec *codec)
 {
@@ -991,6 +1038,9 @@ static int cs_init(struct hda_codec *codec)
 {
        struct cs_spec *spec = codec->spec;
 
+       /* init_verb sequence for C0/C1/C2 errata*/
+       snd_hda_sequence_write(codec, cs_errata_init_verbs);
+
        snd_hda_sequence_write(codec, cs_coef_init_verbs);
 
        if (spec->gpio_mask) {
index c424952a734e0e48546518fe6b47ccbf959e9aee..972e7c453b3d6c8320d58b6aebe6ef41fc259920 100644 (file)
@@ -116,6 +116,7 @@ struct conexant_spec {
        unsigned int dell_vostro:1;
        unsigned int ideapad:1;
        unsigned int thinkpad:1;
+       unsigned int hp_laptop:1;
 
        unsigned int ext_mic_present;
        unsigned int recording;
@@ -2299,6 +2300,18 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
        }
 }
 
+/* toggle input of built-in digital mic and mic jack appropriately */
+static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_jack_detect(codec, 0x1b);
+       snd_printdd("CXT5066: external microphone present=%d\n", present);
+       snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
+                           present ? 1 : 3);
+}
+
+
 /* toggle input of built-in digital mic and mic jack appropriately
    order is: external mic -> dock mic -> interal mic */
 static void cxt5066_thinkpad_automic(struct hda_codec *codec)
@@ -2407,6 +2420,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res)
        }
 }
 
+/* unsolicited event for jack sensing */
+static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res)
+{
+       snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26);
+       switch (res >> 26) {
+       case CONEXANT_HP_EVENT:
+               cxt5066_hp_automute(codec);
+               break;
+       case CONEXANT_MIC_EVENT:
+               cxt5066_hp_laptop_automic(codec);
+               break;
+       }
+}
+
 /* unsolicited event for jack sensing */
 static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res)
 {
@@ -2989,6 +3016,14 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
        { } /* end */
 };
 
+
+static struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
+       {0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+       {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+       { } /* end */
+};
+
 /* initialize jack-sensing, too */
 static int cxt5066_init(struct hda_codec *codec)
 {
@@ -3004,6 +3039,8 @@ static int cxt5066_init(struct hda_codec *codec)
                        cxt5066_ideapad_automic(codec);
                else if (spec->thinkpad)
                        cxt5066_thinkpad_automic(codec);
+               else if (spec->hp_laptop)
+                       cxt5066_hp_laptop_automic(codec);
        }
        cxt5066_set_mic_boost(codec);
        return 0;
@@ -3031,6 +3068,7 @@ enum {
        CXT5066_DELL_VOSTO,     /* Dell Vostro 1015i */
        CXT5066_IDEAPAD,        /* Lenovo IdeaPad U150 */
        CXT5066_THINKPAD,       /* Lenovo ThinkPad T410s, others? */
+       CXT5066_HP_LAPTOP,      /* HP Laptop */
        CXT5066_MODELS
 };
 
@@ -3041,6 +3079,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
        [CXT5066_DELL_VOSTO]    = "dell-vostro",
        [CXT5066_IDEAPAD]       = "ideapad",
        [CXT5066_THINKPAD]      = "thinkpad",
+       [CXT5066_HP_LAPTOP]     = "hp-laptop",
 };
 
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -3052,13 +3091,17 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
+       SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
+       SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
        {}
@@ -3115,6 +3158,23 @@ static int patch_cxt5066(struct hda_codec *codec)
                spec->num_init_verbs++;
                spec->dell_automute = 1;
                break;
+       case CXT5066_HP_LAPTOP:
+               codec->patch_ops.init = cxt5066_init;
+               codec->patch_ops.unsol_event = cxt5066_hp_laptop_event;
+               spec->init_verbs[spec->num_init_verbs] =
+                       cxt5066_init_verbs_hp_laptop;
+               spec->num_init_verbs++;
+               spec->hp_laptop = 1;
+               spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
+               spec->mixers[spec->num_mixers++] = cxt5066_mixers;
+               /* no S/PDIF out */
+               spec->multiout.dig_out_nid = 0;
+               /* input source automatically selected */
+               spec->input_mux = NULL;
+               spec->port_d_mode = 0;
+               spec->mic_boost = 3; /* default 30dB gain */
+               break;
+
        case CXT5066_OLPC_XO_1_5:
                codec->patch_ops.init = cxt5066_olpc_init;
                codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event;
index 2bc0f07cf33fe4f67720fc3c9487a817b3e77823..afd6022a96a75bda3b24b652973dccbe591c625f 100644 (file)
@@ -707,8 +707,6 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                              u32 stream_tag, int format)
 {
        struct hdmi_spec *spec = codec->spec;
-       int tag;
-       int fmt;
        int pinctl;
        int new_pinctl = 0;
        int i;
@@ -745,24 +743,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                return -EINVAL;
        }
 
-       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-       snd_printdd("hdmi_setup_stream: "
-                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-                   nid,
-                   tag == stream_tag ? "" : "new-",
-                   stream_tag,
-                   fmt == format ? "" : "new-",
-                   format);
-
-       if (tag != stream_tag)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CHANNEL_STREAMID,
-                                   stream_tag << 4);
-       if (fmt != format)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_STREAM_FORMAT, format);
+       snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
        return 0;
 }
 
index d382d3c81c0fc5bb0f320fcad17b96d67f6ef473..36a9b83a6174d93f703bf76795e7ba140901c739 100644 (file)
@@ -69,20 +69,12 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
        return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
 }
 
-static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-                                          struct hda_codec *codec,
-                                          struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
 static struct hda_pcm_stream intel_hdmi_pcm_playback = {
        .substreams = 1,
        .channels_min = 2,
        .ops = {
                .open = hdmi_pcm_open,
                .prepare = intel_hdmi_playback_pcm_prepare,
-               .cleanup = intel_hdmi_playback_pcm_cleanup,
        },
 };
 
index f636870dc718d4445ed400924f3075b11b186159..baa108b9d6aacaf88be2999aa35515d2400bb9fd 100644 (file)
@@ -84,7 +84,7 @@ static struct hda_verb nvhdmi_basic_init_7x[] = {
 #else
 /* support all rates and formats */
 #define SUPPORTED_RATES \
-       (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
+       (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
        SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
         SNDRV_PCM_RATE_192000)
 #define SUPPORTED_MAXBPS       24
@@ -326,13 +326,6 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
        return 0;
 }
 
-static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-                                          struct hda_codec *codec,
-                                          struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
                                        struct hda_codec *codec,
                                        unsigned int stream_tag,
@@ -350,7 +343,6 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
        .ops = {
                .open = hdmi_pcm_open,
                .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
-               .cleanup = nvhdmi_playback_pcm_cleanup,
        },
 };
 
index a4dd04524e4391ce7d47f76196b6eeca5e6e9f85..a432e6efd19bbe7bbce3ad9b6607c44661f912cf 100644 (file)
@@ -1594,12 +1594,22 @@ static void alc_auto_parse_digital(struct hda_codec *codec)
        }
 
        if (spec->autocfg.dig_in_pin) {
-               hda_nid_t dig_nid;
-               err = snd_hda_get_connections(codec,
-                                             spec->autocfg.dig_in_pin,
-                                             &dig_nid, 1);
-               if (err > 0)
-                       spec->dig_in_nid = dig_nid;
+               dig_nid = codec->start_nid;
+               for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
+                       unsigned int wcaps = get_wcaps(codec, dig_nid);
+                       if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
+                               continue;
+                       if (!(wcaps & AC_WCAP_DIGITAL))
+                               continue;
+                       if (!(wcaps & AC_WCAP_CONN_LIST))
+                               continue;
+                       err = get_connection_index(codec, dig_nid,
+                                                  spec->autocfg.dig_in_pin);
+                       if (err >= 0) {
+                               spec->dig_in_nid = dig_nid;
+                               break;
+                       }
+               }
        }
 }
 
@@ -5334,6 +5344,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
 
 static struct snd_pci_quirk beep_white_list[] = {
        SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
        SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
        {}
 };
@@ -14452,6 +14463,7 @@ static void alc269_auto_init(struct hda_codec *codec)
 
 enum {
        ALC269_FIXUP_SONY_VAIO,
+       ALC269_FIXUP_DELL_M101Z,
 };
 
 static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = {
@@ -14463,10 +14475,20 @@ static const struct alc_fixup alc269_fixups[] = {
        [ALC269_FIXUP_SONY_VAIO] = {
                .verbs = alc269_sony_vaio_fixup_verbs
        },
+       [ALC269_FIXUP_DELL_M101Z] = {
+               .verbs = (const struct hda_verb[]) {
+                       /* Enables internal speaker */
+                       {0x20, AC_VERB_SET_COEF_INDEX, 13},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
+                       {}
+               }
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+       SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+       SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        {}
 };
 
index f3f861bd1bf880f650d4361df30092f2b034d09c..c16c5ba0fda0fe61387d6924a6b84307b0dedcbb 100644 (file)
@@ -1747,6 +1747,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
                      "HP dv6", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
                      "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e,
+                     "HP DV6", STAC_HP_DV5),
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
                      "HP", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
@@ -6303,6 +6305,21 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx },
        { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
        { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
+       { .id = 0x111d76c0, .name = "92HD89C3", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c1, .name = "92HD89C2", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c2, .name = "92HD89C1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c3, .name = "92HD89B3", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c4, .name = "92HD89B2", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c5, .name = "92HD89B1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c6, .name = "92HD89E3", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c7, .name = "92HD89E2", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c8, .name = "92HD89E1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76c9, .name = "92HD89D3", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76ca, .name = "92HD89D2", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76cb, .name = "92HD89D1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
        {} /* terminator */
 };
 
index 6433e65c9507d20a65be6c0b14af1275c30e0c40..46774924957643874171c1c4e0dfd9a20672d2f3 100644 (file)
@@ -1774,6 +1774,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .name = "HP/Compaq nx7010",
                .type = AC97_TUNE_MUTE_LED
         },
+       {
+               .subvendor = 0x1014,
+               .subdevice = 0x0534,
+               .name = "ThinkPad X31",
+               .type = AC97_TUNE_INV_EAPD
+       },
        {
                .subvendor = 0x1014,
                .subdevice = 0x1f00,
index 289cb4dacfc79ec012b6efb174054efaa0afe855..6c0a11adb2a84511b83b23b69d5efce9fb2085c6 100644 (file)
@@ -543,6 +543,10 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
                chip->model.suspend = claro_suspend;
                chip->model.resume = claro_resume;
                chip->model.set_adc_params = set_ak5385_params;
+               chip->model.device_config = PLAYBACK_0_TO_I2S |
+                                           PLAYBACK_1_TO_SPDIF |
+                                           CAPTURE_0_FROM_I2S_2 |
+                                           CAPTURE_1_FROM_SPDIF;
                break;
        }
        if (id->driver_data == MODEL_MERIDIAN ||
index 6147216af74412f5ff47af36b04ce9fd51013f6b..a3409edcfb5094791c33563f8ad3911826ce3e26 100644 (file)
@@ -155,6 +155,7 @@ void oxygen_pci_remove(struct pci_dev *pci);
 int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
 int oxygen_pci_resume(struct pci_dev *pci);
 #endif
+void oxygen_pci_shutdown(struct pci_dev *pci);
 
 /* oxygen_mixer.c */
 
index fad03d64e3ad0c936aca79a257f6c484b067f657..7e93cf884437d0b5844c9515250c49994390e54c 100644 (file)
@@ -519,16 +519,21 @@ static void oxygen_init(struct oxygen *chip)
        }
 }
 
-static void oxygen_card_free(struct snd_card *card)
+static void oxygen_shutdown(struct oxygen *chip)
 {
-       struct oxygen *chip = card->private_data;
-
        spin_lock_irq(&chip->reg_lock);
        chip->interrupt_mask = 0;
        chip->pcm_running = 0;
        oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
        oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
        spin_unlock_irq(&chip->reg_lock);
+}
+
+static void oxygen_card_free(struct snd_card *card)
+{
+       struct oxygen *chip = card->private_data;
+
+       oxygen_shutdown(chip);
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
        flush_scheduled_work();
@@ -778,3 +783,13 @@ int oxygen_pci_resume(struct pci_dev *pci)
 }
 EXPORT_SYMBOL(oxygen_pci_resume);
 #endif /* CONFIG_PM */
+
+void oxygen_pci_shutdown(struct pci_dev *pci)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct oxygen *chip = card->private_data;
+
+       oxygen_shutdown(chip);
+       chip->model.cleanup(chip);
+}
+EXPORT_SYMBOL(oxygen_pci_shutdown);
index f03a2f2cffee88911e9c11db08c5dd7dd8087b55..06c863e86e3d3d24a5dfd0f7b43f56a47b120719 100644 (file)
@@ -95,6 +95,7 @@ static struct pci_driver xonar_driver = {
        .suspend = oxygen_pci_suspend,
        .resume = oxygen_pci_resume,
 #endif
+       .shutdown = oxygen_pci_shutdown,
 };
 
 static int __init alsa_card_xonar_init(void)
index dbc4b89d74e43ffa3311af7c9386fb5aae38d9a9..b82c1cfa96f5334554435a6eeebc6e82fa63857d 100644 (file)
@@ -53,6 +53,8 @@ struct xonar_wm87x6 {
        struct xonar_generic generic;
        u16 wm8776_regs[0x17];
        u16 wm8766_regs[0x10];
+       struct snd_kcontrol *line_adcmux_control;
+       struct snd_kcontrol *mic_adcmux_control;
        struct snd_kcontrol *lc_controls[13];
 };
 
@@ -193,6 +195,7 @@ static void xonar_ds_init(struct oxygen *chip)
 static void xonar_ds_cleanup(struct oxygen *chip)
 {
        xonar_disable_output(chip);
+       wm8776_write(chip, WM8776_RESET, 0);
 }
 
 static void xonar_ds_suspend(struct oxygen *chip)
@@ -603,6 +606,7 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
 {
        struct oxygen *chip = ctl->private_data;
        struct xonar_wm87x6 *data = chip->model_data;
+       struct snd_kcontrol *other_ctl;
        unsigned int mux_bit = ctl->private_value;
        u16 reg;
        int changed;
@@ -610,8 +614,18 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
        mutex_lock(&chip->mutex);
        reg = data->wm8776_regs[WM8776_ADCMUX];
        if (value->value.integer.value[0]) {
-               reg &= ~0x003;
                reg |= mux_bit;
+               /* line-in and mic-in are exclusive */
+               mux_bit ^= 3;
+               if (reg & mux_bit) {
+                       reg &= ~mux_bit;
+                       if (mux_bit == 1)
+                               other_ctl = data->line_adcmux_control;
+                       else
+                               other_ctl = data->mic_adcmux_control;
+                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                      &other_ctl->id);
+               }
        } else
                reg &= ~mux_bit;
        changed = reg != data->wm8776_regs[WM8776_ADCMUX];
@@ -963,7 +977,13 @@ static int xonar_ds_mixer_init(struct oxygen *chip)
                err = snd_ctl_add(chip->card, ctl);
                if (err < 0)
                        return err;
+               if (!strcmp(ctl->id.name, "Line Capture Switch"))
+                       data->line_adcmux_control = ctl;
+               else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
+                       data->mic_adcmux_control = ctl;
        }
+       if (!data->line_adcmux_control || !data->mic_adcmux_control)
+               return -ENXIO;
        BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
        for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
                ctl = snd_ctl_new1(&lc_controls[i], chip);
index b92adef8e81e7ae61eef5681925610b87f03a502..d6fa7bfd9aa123d7f8bb8142a8def39888129434 100644 (file)
@@ -4609,6 +4609,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
                if (err < 0)
                        return err;
 
+               memset(&info, 0, sizeof(info));
                spin_lock_irqsave(&hdsp->lock, flags);
                info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
                info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
index 547b713d720449a7bdd746ca04fbf5a6cbe84931..0c98ef9156d8fd919f81711fe7b798be7c0ca7d8 100644 (file)
@@ -4127,6 +4127,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
 
        case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
 
+               memset(&info, 0, sizeof(info));
                spin_lock_irq(&hdspm->lock);
                info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
                info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
index 7ab9174a8a841b4a924474deb3c238a003180188..8cc4733698a0f02d7de84de2cf4aec3b8c683584 100644 (file)
@@ -142,10 +142,9 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
        link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
        link->resource[0]->end = 16;
 
-       link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->conf.ConfigIndex = 1;
-       link->conf.Present = PRESENT_OPTION;
+       link->config_flags = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+       link->config_index = 1;
+       link->config_regs = PRESENT_OPTION;
 
        return pdacf_config(link);
 }
@@ -217,7 +216,8 @@ static int pdacf_config(struct pcmcia_device *link)
        int ret;
 
        snd_printdd(KERN_DEBUG "pdacf_config called\n");
-       link->conf.ConfigIndex = 0x5;
+       link->config_index = 0x5;
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 
        ret = pcmcia_request_io(link);
        if (ret)
@@ -227,7 +227,7 @@ static int pdacf_config(struct pcmcia_device *link)
        if (ret)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -287,9 +287,7 @@ MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids);
 
 static struct pcmcia_driver pdacf_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "snd-pdaudiocf",
-       },
+       .name           = "snd-pdaudiocf",
        .probe          = snd_pdacf_probe,
        .remove         = snd_pdacf_detach,
        .id_table       = snd_pdacf_ids,
index 5cc3e45730747fc62e505e965b3bfe7d4d2054eb..bd26e092aead47c7f1385017973145b326cf6ffd 100644 (file)
@@ -24,7 +24,6 @@
 #include <sound/pcm.h>
 #include <asm/io.h>
 #include <linux/interrupt.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
index a6edfc3be29a59b018d6b268f9a01255b08451db..80000d631f88366deeeaae70588dec5d3c960830 100644 (file)
@@ -2,7 +2,7 @@
  * Driver for Digigram VXpocket V2/440 soundcards
  *
  * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
- *
+
  *   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
@@ -162,10 +162,9 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
        link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
        link->resource[0]->end = 16;
 
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->conf.ConfigIndex = 1;
-       link->conf.Present = PRESENT_OPTION;
+       link->config_flags |= CONF_ENABLE_IRQ;
+       link->config_index = 1;
+       link->config_regs = PRESENT_OPTION;
 
        *chip_ret = vxp;
        return 0;
@@ -234,7 +233,7 @@ static int vxpocket_config(struct pcmcia_device *link)
        if (ret)
                goto failed;
 
-       ret = pcmcia_request_configuration(link, &link->conf);
+       ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
 
@@ -359,9 +358,7 @@ MODULE_DEVICE_TABLE(pcmcia, vxp_ids);
 
 static struct pcmcia_driver vxp_cs_driver = {
        .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "snd-vxpocket",
-       },
+       .name           = "snd-vxpocket",
        .probe          = vxpocket_probe,
        .remove         = vxpocket_detach,
        .id_table       = vxp_ids,
index d9110669d0425cd6f4bc652073335bacac6ab8b1..13d658c1a2167b9b62f3ebedf1249f2f7405a2f8 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sound/vx_core.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
index 2f12da4da561f6eeec98a028d7163c68e112b5dd..581a670e826192ee7267859144cc70e89f9a7a8e 100644 (file)
@@ -579,7 +579,7 @@ static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream,
                                  rate * delay_ms / 1000)
                * substream->runtime->channels;
 
-       pr_debug(KERN_ERR "%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n",
+       pr_debug("%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n",
                 __func__,
                 delay_ms,
                 rate,
index a11daa1e905b3552ed2c1a8dc178e29e5491cca6..c81da05a4f11ee0ada1ad170dea17aea207eb969 100644 (file)
@@ -254,6 +254,9 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
                dma_data = &ssi->dma_params_rx;
        }
 
+       if (ssi->flags & IMX_SSI_SYN)
+               reg = SSI_STCCR;
+
        snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
index 1b61c23ff300be0ef2c593cf5e813e20aeb2cb5d..f1b1bc4bacfb7134d588469cbcd0b5032747f0ae 100644 (file)
@@ -94,8 +94,7 @@ static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
 
                if ((pos + len) > prtd->dma_end) {
                        len  = prtd->dma_end - pos;
-                       pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n",
-                              __func__, len);
+                       pr_debug("%s: corrected dma len %ld\n", __func__, len);
                }
 
                ret = s3c2410_dma_enqueue(prtd->params->channel,
index b823a5c9b9bc81d81b8f64f4847483eae3f253bc..87e2b7fcbf176d9f429506b285dcc2f6ac05d7bc 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 
+#include <asm/clkdev.h>
 #include <asm/clock.h>
 
 #include <cpu/sh7722.h>
@@ -40,12 +41,12 @@ static struct clk_ops siumckb_clk_ops = {
 };
 
 static struct clk siumckb_clk = {
-       .name           = "siumckb_clk",
-       .id             = -1,
        .ops            = &siumckb_clk_ops,
        .rate           = 0, /* initialised at run-time */
 };
 
+static struct clk_lookup *siumckb_lookup;
+
 static int migor_hw_params(struct snd_pcm_substream *substream,
                           struct snd_pcm_hw_params *params)
 {
@@ -180,6 +181,13 @@ static int __init migor_init(void)
        if (ret < 0)
                return ret;
 
+       siumckb_lookup = clkdev_alloc(&siumckb_clk, "siumckb_clk", NULL);
+       if (!siumckb_lookup) {
+               ret = -ENOMEM;
+               goto eclkdevalloc;
+       }
+       clkdev_add(siumckb_lookup);
+
        /* Port number used on this machine: port B */
        migor_snd_device = platform_device_alloc("soc-audio", 1);
        if (!migor_snd_device) {
@@ -200,12 +208,15 @@ static int __init migor_init(void)
 epdevadd:
        platform_device_put(migor_snd_device);
 epdevalloc:
+       clkdev_drop(siumckb_lookup);
+eclkdevalloc:
        clk_unregister(&siumckb_clk);
        return ret;
 }
 
 static void __exit migor_exit(void)
 {
+       clkdev_drop(siumckb_lookup);
        clk_unregister(&siumckb_clk);
        platform_device_unregister(migor_snd_device);
 }
index adbc68ce90508221cc919121fc19e062fd309f44..f6b0d2829ea96d438d1e84550272c6a7bda80b4c 100644 (file)
@@ -203,8 +203,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
        data[1] = (value >> 8) & 0xff;
        data[2] = value & 0xff;
 
-       if (!snd_soc_codec_volatile_register(codec, reg))
-               reg_cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg)
+               && reg < codec->reg_cache_size)
+                       reg_cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
index 844ae8221a3af65be95dcd848f925b26651a0640..4057d35343bbbbd434e6a2f99bf0398aeac2a75e 100644 (file)
@@ -223,6 +223,7 @@ static const struct file_operations codec_reg_fops = {
        .open = codec_reg_open_file,
        .read = codec_reg_read_file,
        .write = codec_reg_write_file,
+       .llseek = default_llseek,
 };
 
 static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
@@ -251,7 +252,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
                printk(KERN_WARNING
                       "ASoC: Failed to create codec register debugfs file\n");
 
-       codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
+       codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644,
                                                     codec->debugfs_codec_root,
                                                     &codec->pop_time);
        if (!codec->debugfs_pop_time)
index 03cb7c05ebec2f26800fd7dc35e4798a811fcea1..72a53d0a41e934972120efe156902d4d42290533 100644 (file)
@@ -1089,6 +1089,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 static const struct file_operations dapm_widget_power_fops = {
        .open = dapm_widget_power_open_file,
        .read = dapm_widget_power_read_file,
+       .llseek = default_llseek,
 };
 
 void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
index cb61317df509690fd597cb0385647af63d5a0e06..c03bbaefdbc36c623e3f5b76cea86f6ad59e46cc 100644 (file)
@@ -165,6 +165,7 @@ static const struct file_operations soundcore_fops =
        /* We must have an owner or the module locking fails */
        .owner  = THIS_MODULE,
        .open   = soundcore_open,
+       .llseek = noop_llseek,
 };
 
 /*
index 9feb00c831a02b791227b75294e6dc8e15975f1f..4eabafa5b037db66b250db64cc0ce05aa783f595 100644 (file)
@@ -126,7 +126,7 @@ static void snd_usb_stream_disconnect(struct list_head *head)
        for (idx = 0; idx < 2; idx++) {
                subs = &as->substream[idx];
                if (!subs->num_formats)
-                       return;
+                       continue;
                snd_usb_release_substream_urbs(subs, 1);
                subs->interface = -1;
        }
@@ -216,6 +216,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
        }
 
        switch (protocol) {
+       default:
+               snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n",
+                           protocol);
+               /* fall through */
+
        case UAC_VERSION_1: {
                struct uac1_ac_header_descriptor *h1 = control_header;
 
@@ -253,10 +258,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
 
                break;
        }
-
-       default:
-               snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol);
-               return -EINVAL;
        }
 
        return 0;
@@ -465,7 +466,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                        goto __error;
        }
 
-       chip->ctrl_intf = alts;
+       /*
+        * For devices with more than one control interface, we assume the
+        * first contains the audio controls. We might need a more specific
+        * check here in the future.
+        */
+       if (!chip->ctrl_intf)
+               chip->ctrl_intf = alts;
 
        if (err > 0) {
                /* create normal USB audio interfaces */
index b853f8df794f6a35ceb8e39576abf3d1cb91e36c..7754a10345451109a9ff9bd03d271148160861b9 100644 (file)
@@ -295,12 +295,11 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 
        switch (altsd->bInterfaceProtocol) {
        case UAC_VERSION_1:
+       default:
                return set_sample_rate_v1(chip, iface, alts, fmt, rate);
 
        case UAC_VERSION_2:
                return set_sample_rate_v2(chip, iface, alts, fmt, rate);
        }
-
-       return -EINVAL;
 }
 
index 1a701f1e8f501b358029f84bedcbe1268e9f543f..ef0a07e34844ae4d53ffd12e54b16a203da02a19 100644 (file)
@@ -275,6 +275,12 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 
                /* get audio formats */
                switch (protocol) {
+               default:
+                       snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
+                                   dev->devnum, iface_no, altno, protocol);
+                       protocol = UAC_VERSION_1;
+                       /* fall through */
+
                case UAC_VERSION_1: {
                        struct uac1_as_header_descriptor *as =
                                snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
@@ -336,11 +342,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                                   dev->devnum, iface_no, altno, as->bTerminalLink);
                        continue;
                }
-
-               default:
-                       snd_printk(KERN_ERR "%d:%u:%d : unknown interface protocol %04x\n",
-                                  dev->devnum, iface_no, altno, protocol);
-                       continue;
                }
 
                /* get format type */
index 3a1375459c06a49d0d48a309460af30a0fcfd8c0..69148212aa70e66f9e1193040bfb41aad5548b6b 100644 (file)
@@ -49,7 +49,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
        u64 pcm_formats;
 
        switch (protocol) {
-       case UAC_VERSION_1: {
+       case UAC_VERSION_1:
+       default: {
                struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
                sample_width = fmt->bBitResolution;
                sample_bytes = fmt->bSubframeSize;
@@ -64,9 +65,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
                format <<= 1;
                break;
        }
-
-       default:
-               return -EINVAL;
        }
 
        pcm_formats = 0;
@@ -384,6 +382,10 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
         * audio class v2 uses class specific EP0 range requests for that.
         */
        switch (protocol) {
+       default:
+               snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
+                          chip->dev->devnum, fp->iface, fp->altsetting, protocol);
+               /* fall through */
        case UAC_VERSION_1:
                fp->channels = fmt->bNrChannels;
                ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
@@ -392,10 +394,6 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
                /* fp->channels is already set in this case */
                ret = parse_audio_format_rates_v2(chip, fp);
                break;
-       default:
-               snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n",
-                          chip->dev->devnum, fp->iface, fp->altsetting, protocol);
-               return -EINVAL;
        }
 
        if (fp->channels < 1) {
@@ -438,6 +436,10 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
        fp->channels = 1;
 
        switch (protocol) {
+       default:
+               snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
+                          chip->dev->devnum, fp->iface, fp->altsetting, protocol);
+               /* fall through */
        case UAC_VERSION_1: {
                struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;
                brate = le16_to_cpu(fmt->wMaxBitRate);
@@ -456,10 +458,6 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
                ret = parse_audio_format_rates_v2(chip, fp);
                break;
        }
-       default:
-               snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n",
-                          chip->dev->devnum, fp->iface, fp->altsetting, protocol);
-               return -EINVAL;
        }
 
        return ret;
index c166db0057d3e0e613954b21f8ca5274f0242741..3ed3901369ce1a9ca58473ecef450623cf95a7b2 100644 (file)
@@ -2175,7 +2175,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        }
 
        host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-       mixer->protocol = get_iface_desc(host_iface)->bInterfaceProtocol;
+       switch (get_iface_desc(host_iface)->bInterfaceProtocol) {
+       case UAC_VERSION_1:
+       default:
+               mixer->protocol = UAC_VERSION_1;
+               break;
+       case UAC_VERSION_2:
+               mixer->protocol = UAC_VERSION_2;
+               break;
+       }
 
        if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
            (err = snd_usb_mixer_status_create(mixer)) < 0)
index 3634cedf93061629619125690fb19dc7d0beae64..3b5135c930628fc092cad54e67ce2a7645c59c02 100644 (file)
@@ -173,13 +173,12 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
 
        switch (altsd->bInterfaceProtocol) {
        case UAC_VERSION_1:
+       default:
                return init_pitch_v1(chip, iface, alts, fmt);
 
        case UAC_VERSION_2:
                return init_pitch_v2(chip, iface, alts, fmt);
        }
-
-       return -EINVAL;
 }
 
 /*
index 5164a655c39f60b578c8642f2caabe8af66fa016..b2c63309a65165b471822e99268c828bbdb07777 100644 (file)
@@ -8,7 +8,7 @@ perf-annotate - Read perf.data (created by perf record) and display annotated co
 SYNOPSIS
 --------
 [verse]
-'perf annotate' [-i <file> | --input=file] symbol_name
+'perf annotate' [-i <file> | --input=file] [symbol_name]
 
 DESCRIPTION
 -----------
@@ -24,6 +24,13 @@ OPTIONS
 --input=::
         Input file name. (default: perf.data)
 
+--stdio:: Use the stdio interface.
+
+--tui:: Use the TUI interface Use of --tui requires a tty, if one is not
+       present, as when piping to other commands, the stdio interface is
+       used. This interfaces starts by centering on the line with more
+       samples, TAB/UNTAB cycles thru the lines with more samples.
+
 SEE ALSO
 --------
-linkperf:perf-record[1]
+linkperf:perf-record[1], linkperf:perf-report[1]
index abfabe9147a4f2a48b6fd47bfdb758de2a3f3eea..12052c9ed0babfc3a1c93cc01758ec3b7747ee10 100644 (file)
@@ -65,6 +65,13 @@ OPTIONS
                 the tree is considered as a new profiled object. +
        Default: fractal,0.5.
 
+--stdio:: Use the stdio interface.
+
+--tui:: Use the TUI interface, that is integrated with annotate and allows
+        zooming into DSOs or threads, among other features. Use of --tui
+       requires a tty, if one is not present, as when piping to other
+       commands, the stdio interface is used.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1]
index 4f1fa77c1feb0b7a854ab8a85bd21682cbc66377..d1db0f676a4bf14850fa0264e78fe3d482d376dc 100644 (file)
@@ -313,6 +313,9 @@ TEST_PROGRAMS =
 
 SCRIPT_SH += perf-archive.sh
 
+grep-libs = $(filter -l%,$(1))
+strip-libs = $(filter-out -l%,$(1))
+
 #
 # No Perl scripts right now:
 #
@@ -588,14 +591,17 @@ endif
 ifdef NO_LIBPERL
        BASIC_CFLAGS += -DNO_LIBPERL
 else
-       PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null`
+       PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
+       PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
+       PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
        PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
        FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
        ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y)
                BASIC_CFLAGS += -DNO_LIBPERL
        else
-               ALL_LDFLAGS += $(PERL_EMBED_LDOPTS)
+               ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS)
+               EXTLIBS += $(PERL_EMBED_LIBADD)
                LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
                LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
        endif
@@ -604,13 +610,16 @@ endif
 ifdef NO_LIBPYTHON
        BASIC_CFLAGS += -DNO_LIBPYTHON
 else
-       PYTHON_EMBED_LDOPTS = `python-config --ldflags 2>/dev/null`
+       PYTHON_EMBED_LDOPTS = $(shell python-config --ldflags 2>/dev/null)
+       PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
+       PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
        PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null`
        FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
        ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
                BASIC_CFLAGS += -DNO_LIBPYTHON
        else
-               ALL_LDFLAGS += $(PYTHON_EMBED_LDOPTS)
+               ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
+               EXTLIBS += $(PYTHON_EMBED_LIBADD)
                LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
                LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
        endif
@@ -653,6 +662,15 @@ else
        endif
 endif
 
+
+ifdef NO_STRLCPY
+       BASIC_CFLAGS += -DNO_STRLCPY
+else
+       ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
+               BASIC_CFLAGS += -DNO_STRLCPY
+       endif
+endif
+
 ifndef CC_LD_DYNPATH
        ifdef NO_R_TO_GCC_LINKER
                # Some gcc does not accept and pass -R to the linker to specify
@@ -910,8 +928,8 @@ $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
                $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
 
 $(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
-       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(OUTPUT)perf.o \
-               $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
+               $(BUILTIN_OBJS) $(LIBS) -o $@
 
 $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
@@ -1017,7 +1035,7 @@ builtin-revert.o wt-status.o: wt-status.h
 # we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
 # we depend the various files onto their directories.
 DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
-$(DIRECTORY_DEPS): $(sort $(dir $(DIRECTORY_DEPS)))
+$(DIRECTORY_DEPS): $(sort $(dir $(DIRECTORY_DEPS)))
 # In the second step, we make a rule to actually create these directories
 $(sort $(dir $(DIRECTORY_DEPS))):
        $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
index 1478dc64bf157fc0f226cba51eef80ec8646c15f..6d5604d8df9599acb55d87017f5d58e19d906395 100644 (file)
@@ -28,7 +28,7 @@
 
 static char            const *input_name = "perf.data";
 
-static bool            force;
+static bool            force, use_tui, use_stdio;
 
 static bool            full_paths;
 
@@ -321,7 +321,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he)
 
 static void hists__find_annotations(struct hists *self)
 {
-       struct rb_node *first = rb_first(&self->entries), *nd = first;
+       struct rb_node *nd = rb_first(&self->entries), *next;
        int key = KEY_RIGHT;
 
        while (nd) {
@@ -343,20 +343,19 @@ find_next:
 
                if (use_browser > 0) {
                        key = hist_entry__tui_annotate(he);
-                       if (is_exit_key(key))
-                               break;
                        switch (key) {
                        case KEY_RIGHT:
-                       case '\t':
-                               nd = rb_next(nd);
+                               next = rb_next(nd);
                                break;
                        case KEY_LEFT:
-                               if (nd == first)
-                                       continue;
-                               nd = rb_prev(nd);
-                       default:
+                               next = rb_prev(nd);
                                break;
+                       default:
+                               return;
                        }
+
+                       if (next != NULL)
+                               nd = next;
                } else {
                        hist_entry__tty_annotate(he);
                        nd = rb_next(nd);
@@ -428,6 +427,8 @@ static const struct option options[] = {
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
+       OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
+       OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
        OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -443,6 +444,11 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 {
        argc = parse_options(argc, argv, options, annotate_usage, 0);
 
+       if (use_stdio)
+               use_browser = 0;
+       else if (use_tui)
+               use_browser = 1;
+
        setup_browser();
 
        symbol_conf.priv_size = sizeof(struct sym_priv);
index 55fc1f46892a6a920411db7dc91226bcbe6a7f82..5de405d452300318541338293563d8ebc41ccb87 100644 (file)
@@ -32,7 +32,7 @@
 
 static char            const *input_name = "perf.data";
 
-static bool            force;
+static bool            force, use_tui, use_stdio;
 static bool            hide_unresolved;
 static bool            dont_use_callchains;
 
@@ -107,7 +107,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
                goto out_free_syms;
        err = 0;
        if (symbol_conf.use_callchain) {
-               err = append_chain(he->callchain, data->callchain, syms, data->period);
+               err = callchain_append(he->callchain, data->callchain, syms,
+                                      data->period);
                if (err)
                        goto out_free_syms;
        }
@@ -450,6 +451,8 @@ static const struct option options[] = {
                    "Show per-thread event counters"),
        OPT_STRING(0, "pretty", &pretty_printing_style, "key",
                   "pretty printing style key: normal raw"),
+       OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
+       OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
                   "sort by key(s): pid, comm, dso, symbol, parent"),
        OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -482,8 +485,15 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 {
        argc = parse_options(argc, argv, options, report_usage, 0);
 
+       if (use_stdio)
+               use_browser = 0;
+       else if (use_tui)
+               use_browser = 1;
+
        if (strcmp(input_name, "-") != 0)
                setup_browser();
+       else
+               use_browser = 0;
        /*
         * Only in the newt browser we are doing integrated annotation,
         * so don't allocate extra space that won't be used in the stdio
index 7a7b6085905382c791834b0c0f35ed5f39658e26..b253db634f04b7e8ddfddd1cc33bb3ce8343a49a 100644 (file)
@@ -110,6 +110,17 @@ int main(void)
 }
 endef
 
+define SOURCE_STRLCPY
+#include <stdlib.h>
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+int main(void)
+{
+       strlcpy(NULL, NULL, 0);
+       return 0;
+}
+endef
+
 # try-cc
 # Usage: option = $(call try-cc, source-to-build, cc-options)
 try-cc = $(shell sh -c                                           \
index ef7aa0a0c5265191e8120e76f9f134b5e241fa53..95aaf565c704fb6ea67cee78d49e177f0ba8f595 100644 (file)
@@ -73,6 +73,18 @@ void get_term_dimensions(struct winsize *ws);
 #define cpu_relax()    asm volatile("":::"memory")
 #endif
 
+#ifdef __mips__
+#include "../../arch/mips/include/asm/unistd.h"
+#define rmb()          asm volatile(                                   \
+                               ".set   mips2\n\t"                      \
+                               "sync\n\t"                              \
+                               ".set   mips0"                          \
+                               : /* no output */                       \
+                               : /* no input */                        \
+                               : "memory")
+#define cpu_relax()    asm volatile("" ::: "memory")
+#endif
+
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
new file mode 100644 (file)
index 0000000..d931a82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+perf record -a -e net:net_dev_xmit -e net:net_dev_queue                \
+               -e net:netif_receive_skb -e net:netif_rx                \
+               -e skb:consume_skb -e skb:kfree_skb                     \
+               -e skb:skb_copy_datagram_iovec -e napi:napi_poll        \
+               -e irq:irq_handler_entry -e irq:irq_handler_exit        \
+               -e irq:softirq_entry -e irq:softirq_exit                \
+               -e irq:softirq_raise $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
new file mode 100644 (file)
index 0000000..c3d0a63
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+# description: display a process of packet and processing time
+# args: [tx] [rx] [dev=] [debug]
+
+perf trace -s ~/libexec/perf-core/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
new file mode 100644 (file)
index 0000000..9aa0a32
--- /dev/null
@@ -0,0 +1,464 @@
+# Display a process of packets and processed time.
+# It helps us to investigate networking or network device.
+#
+# options
+# tx: show only tx chart
+# rx: show only rx chart
+# dev=: show only thing related to specified device
+# debug: work with debug mode. It shows buffer status.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+       '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+from Util import *
+
+all_event_list = []; # insert all tracepoint event related with this script
+irq_dic = {}; # key is cpu and value is a list which stacks irqs
+              # which raise NET_RX softirq
+net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry
+                # and a list which stacks receive
+receive_hunk_list = []; # a list which include a sequence of receive events
+rx_skb_list = []; # received packet list for matching
+                      # skb_copy_datagram_iovec
+
+buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and
+                      # tx_xmit_list
+of_count_rx_skb_list = 0; # overflow count
+
+tx_queue_list = []; # list of packets which pass through dev_queue_xmit
+of_count_tx_queue_list = 0; # overflow count
+
+tx_xmit_list = [];  # list of packets which pass through dev_hard_start_xmit
+of_count_tx_xmit_list = 0; # overflow count
+
+tx_free_list = [];  # list of packets which is freed
+
+# options
+show_tx = 0;
+show_rx = 0;
+dev = 0; # store a name of device specified by option "dev="
+debug = 0;
+
+# indices of event_info tuple
+EINFO_IDX_NAME=   0
+EINFO_IDX_CONTEXT=1
+EINFO_IDX_CPU=    2
+EINFO_IDX_TIME=   3
+EINFO_IDX_PID=    4
+EINFO_IDX_COMM=   5
+
+# Calculate a time interval(msec) from src(nsec) to dst(nsec)
+def diff_msec(src, dst):
+       return (dst - src) / 1000000.0
+
+# Display a process of transmitting a packet
+def print_transmit(hunk):
+       if dev != 0 and hunk['dev'].find(dev) < 0:
+               return
+       print "%7s %5d %6d.%06dsec %12.3fmsec      %12.3fmsec" % \
+               (hunk['dev'], hunk['len'],
+               nsecs_secs(hunk['queue_t']),
+               nsecs_nsecs(hunk['queue_t'])/1000,
+               diff_msec(hunk['queue_t'], hunk['xmit_t']),
+               diff_msec(hunk['xmit_t'], hunk['free_t']))
+
+# Format for displaying rx packet processing
+PF_IRQ_ENTRY= "  irq_entry(+%.3fmsec irq=%d:%s)"
+PF_SOFT_ENTRY="  softirq_entry(+%.3fmsec)"
+PF_NAPI_POLL= "  napi_poll_exit(+%.3fmsec %s)"
+PF_JOINT=     "         |"
+PF_WJOINT=    "         |            |"
+PF_NET_RECV=  "         |---netif_receive_skb(+%.3fmsec skb=%x len=%d)"
+PF_NET_RX=    "         |---netif_rx(+%.3fmsec skb=%x)"
+PF_CPY_DGRAM= "         |      skb_copy_datagram_iovec(+%.3fmsec %d:%s)"
+PF_KFREE_SKB= "         |      kfree_skb(+%.3fmsec location=%x)"
+PF_CONS_SKB=  "         |      consume_skb(+%.3fmsec)"
+
+# Display a process of received packets and interrputs associated with
+# a NET_RX softirq
+def print_receive(hunk):
+       show_hunk = 0
+       irq_list = hunk['irq_list']
+       cpu = irq_list[0]['cpu']
+       base_t = irq_list[0]['irq_ent_t']
+       # check if this hunk should be showed
+       if dev != 0:
+               for i in range(len(irq_list)):
+                       if irq_list[i]['name'].find(dev) >= 0:
+                               show_hunk = 1
+                               break
+       else:
+               show_hunk = 1
+       if show_hunk == 0:
+               return
+
+       print "%d.%06dsec cpu=%d" % \
+               (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu)
+       for i in range(len(irq_list)):
+               print PF_IRQ_ENTRY % \
+                       (diff_msec(base_t, irq_list[i]['irq_ent_t']),
+                       irq_list[i]['irq'], irq_list[i]['name'])
+               print PF_JOINT
+               irq_event_list = irq_list[i]['event_list']
+               for j in range(len(irq_event_list)):
+                       irq_event = irq_event_list[j]
+                       if irq_event['event'] == 'netif_rx':
+                               print PF_NET_RX % \
+                                       (diff_msec(base_t, irq_event['time']),
+                                       irq_event['skbaddr'])
+                               print PF_JOINT
+       print PF_SOFT_ENTRY % \
+               diff_msec(base_t, hunk['sirq_ent_t'])
+       print PF_JOINT
+       event_list = hunk['event_list']
+       for i in range(len(event_list)):
+               event = event_list[i]
+               if event['event_name'] == 'napi_poll':
+                       print PF_NAPI_POLL % \
+                           (diff_msec(base_t, event['event_t']), event['dev'])
+                       if i == len(event_list) - 1:
+                               print ""
+                       else:
+                               print PF_JOINT
+               else:
+                       print PF_NET_RECV % \
+                           (diff_msec(base_t, event['event_t']), event['skbaddr'],
+                               event['len'])
+                       if 'comm' in event.keys():
+                               print PF_WJOINT
+                               print PF_CPY_DGRAM % \
+                                       (diff_msec(base_t, event['comm_t']),
+                                       event['pid'], event['comm'])
+                       elif 'handle' in event.keys():
+                               print PF_WJOINT
+                               if event['handle'] == "kfree_skb":
+                                       print PF_KFREE_SKB % \
+                                               (diff_msec(base_t,
+                                               event['comm_t']),
+                                               event['location'])
+                               elif event['handle'] == "consume_skb":
+                                       print PF_CONS_SKB % \
+                                               diff_msec(base_t,
+                                                       event['comm_t'])
+                       print PF_JOINT
+
+def trace_begin():
+       global show_tx
+       global show_rx
+       global dev
+       global debug
+
+       for i in range(len(sys.argv)):
+               if i == 0:
+                       continue
+               arg = sys.argv[i]
+               if arg == 'tx':
+                       show_tx = 1
+               elif arg =='rx':
+                       show_rx = 1
+               elif arg.find('dev=',0, 4) >= 0:
+                       dev = arg[4:]
+               elif arg == 'debug':
+                       debug = 1
+       if show_tx == 0  and show_rx == 0:
+               show_tx = 1
+               show_rx = 1
+
+def trace_end():
+       # order all events in time
+       all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME],
+                                           b[EINFO_IDX_TIME]))
+       # process all events
+       for i in range(len(all_event_list)):
+               event_info = all_event_list[i]
+               name = event_info[EINFO_IDX_NAME]
+               if name == 'irq__softirq_exit':
+                       handle_irq_softirq_exit(event_info)
+               elif name == 'irq__softirq_entry':
+                       handle_irq_softirq_entry(event_info)
+               elif name == 'irq__softirq_raise':
+                       handle_irq_softirq_raise(event_info)
+               elif name == 'irq__irq_handler_entry':
+                       handle_irq_handler_entry(event_info)
+               elif name == 'irq__irq_handler_exit':
+                       handle_irq_handler_exit(event_info)
+               elif name == 'napi__napi_poll':
+                       handle_napi_poll(event_info)
+               elif name == 'net__netif_receive_skb':
+                       handle_netif_receive_skb(event_info)
+               elif name == 'net__netif_rx':
+                       handle_netif_rx(event_info)
+               elif name == 'skb__skb_copy_datagram_iovec':
+                       handle_skb_copy_datagram_iovec(event_info)
+               elif name == 'net__net_dev_queue':
+                       handle_net_dev_queue(event_info)
+               elif name == 'net__net_dev_xmit':
+                       handle_net_dev_xmit(event_info)
+               elif name == 'skb__kfree_skb':
+                       handle_kfree_skb(event_info)
+               elif name == 'skb__consume_skb':
+                       handle_consume_skb(event_info)
+       # display receive hunks
+       if show_rx:
+               for i in range(len(receive_hunk_list)):
+                       print_receive(receive_hunk_list[i])
+       # display transmit hunks
+       if show_tx:
+               print "   dev    len      Qdisc        " \
+                       "       netdevice             free"
+               for i in range(len(tx_free_list)):
+                       print_transmit(tx_free_list[i])
+       if debug:
+               print "debug buffer status"
+               print "----------------------------"
+               print "xmit Qdisc:remain:%d overflow:%d" % \
+                       (len(tx_queue_list), of_count_tx_queue_list)
+               print "xmit netdevice:remain:%d overflow:%d" % \
+                       (len(tx_xmit_list), of_count_tx_xmit_list)
+               print "receive:remain:%d overflow:%d" % \
+                       (len(rx_skb_list), of_count_rx_skb_list)
+
+# called from perf, when it finds a correspoinding event
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+       if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+               return
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+       all_event_list.append(event_info)
+
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+       if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+               return
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+       all_event_list.append(event_info)
+
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+       if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+               return
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+       all_event_list.append(event_info)
+
+def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
+                       irq, irq_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       irq, irq_name)
+       all_event_list.append(event_info)
+
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
+       all_event_list.append(event_info)
+
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       napi, dev_name)
+       all_event_list.append(event_info)
+
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+                       skblen, dev_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, skblen, dev_name)
+       all_event_list.append(event_info)
+
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+                       skblen, dev_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, skblen, dev_name)
+       all_event_list.append(event_info)
+
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+                       skbaddr, skblen, dev_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, skblen, dev_name)
+       all_event_list.append(event_info)
+
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+                       skbaddr, skblen, rc, dev_name):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, skblen, rc ,dev_name)
+       all_event_list.append(event_info)
+
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+                       skbaddr, protocol, location):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, protocol, location)
+       all_event_list.append(event_info)
+
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr)
+       all_event_list.append(event_info)
+
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+       skbaddr, skblen):
+       event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+                       skbaddr, skblen)
+       all_event_list.append(event_info)
+
+def handle_irq_handler_entry(event_info):
+       (name, context, cpu, time, pid, comm, irq, irq_name) = event_info
+       if cpu not in irq_dic.keys():
+               irq_dic[cpu] = []
+       irq_record = {'irq':irq, 'name':irq_name, 'cpu':cpu, 'irq_ent_t':time}
+       irq_dic[cpu].append(irq_record)
+
+def handle_irq_handler_exit(event_info):
+       (name, context, cpu, time, pid, comm, irq, ret) = event_info
+       if cpu not in irq_dic.keys():
+               return
+       irq_record = irq_dic[cpu].pop()
+       if irq != irq_record['irq']:
+               return
+       irq_record.update({'irq_ext_t':time})
+       # if an irq doesn't include NET_RX softirq, drop.
+       if 'event_list' in irq_record.keys():
+               irq_dic[cpu].append(irq_record)
+
+def handle_irq_softirq_raise(event_info):
+       (name, context, cpu, time, pid, comm, vec) = event_info
+       if cpu not in irq_dic.keys() \
+       or len(irq_dic[cpu]) == 0:
+               return
+       irq_record = irq_dic[cpu].pop()
+       if 'event_list' in irq_record.keys():
+               irq_event_list = irq_record['event_list']
+       else:
+               irq_event_list = []
+       irq_event_list.append({'time':time, 'event':'sirq_raise'})
+       irq_record.update({'event_list':irq_event_list})
+       irq_dic[cpu].append(irq_record)
+
+def handle_irq_softirq_entry(event_info):
+       (name, context, cpu, time, pid, comm, vec) = event_info
+       net_rx_dic[cpu] = {'sirq_ent_t':time, 'event_list':[]}
+
+def handle_irq_softirq_exit(event_info):
+       (name, context, cpu, time, pid, comm, vec) = event_info
+       irq_list = []
+       event_list = 0
+       if cpu in irq_dic.keys():
+               irq_list = irq_dic[cpu]
+               del irq_dic[cpu]
+       if cpu in net_rx_dic.keys():
+               sirq_ent_t = net_rx_dic[cpu]['sirq_ent_t']
+               event_list = net_rx_dic[cpu]['event_list']
+               del net_rx_dic[cpu]
+       if irq_list == [] or event_list == 0:
+               return
+       rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
+                   'irq_list':irq_list, 'event_list':event_list}
+       # merge information realted to a NET_RX softirq
+       receive_hunk_list.append(rec_data)
+
+def handle_napi_poll(event_info):
+       (name, context, cpu, time, pid, comm, napi, dev_name) = event_info
+       if cpu in net_rx_dic.keys():
+               event_list = net_rx_dic[cpu]['event_list']
+               rec_data = {'event_name':'napi_poll',
+                               'dev':dev_name, 'event_t':time}
+               event_list.append(rec_data)
+
+def handle_netif_rx(event_info):
+       (name, context, cpu, time, pid, comm,
+               skbaddr, skblen, dev_name) = event_info
+       if cpu not in irq_dic.keys() \
+       or len(irq_dic[cpu]) == 0:
+               return
+       irq_record = irq_dic[cpu].pop()
+       if 'event_list' in irq_record.keys():
+               irq_event_list = irq_record['event_list']
+       else:
+               irq_event_list = []
+       irq_event_list.append({'time':time, 'event':'netif_rx',
+               'skbaddr':skbaddr, 'skblen':skblen, 'dev_name':dev_name})
+       irq_record.update({'event_list':irq_event_list})
+       irq_dic[cpu].append(irq_record)
+
+def handle_netif_receive_skb(event_info):
+       global of_count_rx_skb_list
+
+       (name, context, cpu, time, pid, comm,
+               skbaddr, skblen, dev_name) = event_info
+       if cpu in net_rx_dic.keys():
+               rec_data = {'event_name':'netif_receive_skb',
+                           'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
+               event_list = net_rx_dic[cpu]['event_list']
+               event_list.append(rec_data)
+               rx_skb_list.insert(0, rec_data)
+               if len(rx_skb_list) > buffer_budget:
+                       rx_skb_list.pop()
+                       of_count_rx_skb_list += 1
+
+def handle_net_dev_queue(event_info):
+       global of_count_tx_queue_list
+
+       (name, context, cpu, time, pid, comm,
+               skbaddr, skblen, dev_name) = event_info
+       skb = {'dev':dev_name, 'skbaddr':skbaddr, 'len':skblen, 'queue_t':time}
+       tx_queue_list.insert(0, skb)
+       if len(tx_queue_list) > buffer_budget:
+               tx_queue_list.pop()
+               of_count_tx_queue_list += 1
+
+def handle_net_dev_xmit(event_info):
+       global of_count_tx_xmit_list
+
+       (name, context, cpu, time, pid, comm,
+               skbaddr, skblen, rc, dev_name) = event_info
+       if rc == 0: # NETDEV_TX_OK
+               for i in range(len(tx_queue_list)):
+                       skb = tx_queue_list[i]
+                       if skb['skbaddr'] == skbaddr:
+                               skb['xmit_t'] = time
+                               tx_xmit_list.insert(0, skb)
+                               del tx_queue_list[i]
+                               if len(tx_xmit_list) > buffer_budget:
+                                       tx_xmit_list.pop()
+                                       of_count_tx_xmit_list += 1
+                               return
+
+def handle_kfree_skb(event_info):
+       (name, context, cpu, time, pid, comm,
+               skbaddr, protocol, location) = event_info
+       for i in range(len(tx_queue_list)):
+               skb = tx_queue_list[i]
+               if skb['skbaddr'] == skbaddr:
+                       del tx_queue_list[i]
+                       return
+       for i in range(len(tx_xmit_list)):
+               skb = tx_xmit_list[i]
+               if skb['skbaddr'] == skbaddr:
+                       skb['free_t'] = time
+                       tx_free_list.append(skb)
+                       del tx_xmit_list[i]
+                       return
+       for i in range(len(rx_skb_list)):
+               rec_data = rx_skb_list[i]
+               if rec_data['skbaddr'] == skbaddr:
+                       rec_data.update({'handle':"kfree_skb",
+                                       'comm':comm, 'pid':pid, 'comm_t':time})
+                       del rx_skb_list[i]
+                       return
+
+def handle_consume_skb(event_info):
+       (name, context, cpu, time, pid, comm, skbaddr) = event_info
+       for i in range(len(tx_xmit_list)):
+               skb = tx_xmit_list[i]
+               if skb['skbaddr'] == skbaddr:
+                       skb['free_t'] = time
+                       tx_free_list.append(skb)
+                       del tx_xmit_list[i]
+                       return
+
+def handle_skb_copy_datagram_iovec(event_info):
+       (name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info
+       for i in range(len(rx_skb_list)):
+               rec_data = rx_skb_list[i]
+               if skbaddr == rec_data['skbaddr']:
+                       rec_data.update({'handle':"skb_copy_datagram_iovec",
+                                       'comm':comm, 'pid':pid, 'comm_t':time})
+                       del rx_skb_list[i]
+                       return
index 27e9ebe4076e0efbf4117a46f2dbbcc74a1dcc3e..a7729797fd96254bc35326077337a71f919c19b5 100644 (file)
@@ -82,6 +82,8 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
 extern char *perf_pathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
+#ifdef NO_STRLCPY
 extern size_t strlcpy(char *dest, const char *src, size_t size);
+#endif
 
 #endif /* __PERF_CACHE_H */
index f231f43424d27930a286cb52902c21cb4534a068..e12d539417b2cc4644e2d5a919cfb8a23e8ae163 100644 (file)
@@ -28,6 +28,9 @@ bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event)
 #define chain_for_each_child(child, parent)    \
        list_for_each_entry(child, &parent->children, brothers)
 
+#define chain_for_each_child_safe(child, next, parent) \
+       list_for_each_entry_safe(child, next, &parent->children, brothers)
+
 static void
 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
                    enum chain_mode mode)
@@ -86,10 +89,10 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
  * sort them by hit
  */
 static void
-sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
+sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
                u64 min_hit, struct callchain_param *param __used)
 {
-       __sort_chain_flat(rb_root, node, min_hit);
+       __sort_chain_flat(rb_root, &root->node, min_hit);
 }
 
 static void __sort_chain_graph_abs(struct callchain_node *node,
@@ -108,11 +111,11 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
 }
 
 static void
-sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root,
+sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
                     u64 min_hit, struct callchain_param *param __used)
 {
-       __sort_chain_graph_abs(chain_root, min_hit);
-       rb_root->rb_node = chain_root->rb_root.rb_node;
+       __sort_chain_graph_abs(&chain_root->node, min_hit);
+       rb_root->rb_node = chain_root->node.rb_root.rb_node;
 }
 
 static void __sort_chain_graph_rel(struct callchain_node *node,
@@ -133,11 +136,11 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
 }
 
 static void
-sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root,
+sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
                     u64 min_hit __used, struct callchain_param *param)
 {
-       __sort_chain_graph_rel(chain_root, param->min_percent / 100.0);
-       rb_root->rb_node = chain_root->rb_root.rb_node;
+       __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
+       rb_root->rb_node = chain_root->node.rb_root.rb_node;
 }
 
 int register_callchain_param(struct callchain_param *param)
@@ -284,19 +287,18 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
 }
 
 static int
-__append_chain(struct callchain_node *root, struct resolved_chain *chain,
-              unsigned int start, u64 period);
+append_chain(struct callchain_node *root, struct resolved_chain *chain,
+            unsigned int start, u64 period);
 
 static void
-__append_chain_children(struct callchain_node *root,
-                       struct resolved_chain *chain,
-                       unsigned int start, u64 period)
+append_chain_children(struct callchain_node *root, struct resolved_chain *chain,
+                     unsigned int start, u64 period)
 {
        struct callchain_node *rnode;
 
        /* lookup in childrens */
        chain_for_each_child(rnode, root) {
-               unsigned int ret = __append_chain(rnode, chain, start, period);
+               unsigned int ret = append_chain(rnode, chain, start, period);
 
                if (!ret)
                        goto inc_children_hit;
@@ -309,8 +311,8 @@ inc_children_hit:
 }
 
 static int
-__append_chain(struct callchain_node *root, struct resolved_chain *chain,
-              unsigned int start, u64 period)
+append_chain(struct callchain_node *root, struct resolved_chain *chain,
+            unsigned int start, u64 period)
 {
        struct callchain_list *cnode;
        unsigned int i = start;
@@ -357,7 +359,7 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
        }
 
        /* We match the node and still have a part remaining */
-       __append_chain_children(root, chain, i, period);
+       append_chain_children(root, chain, i, period);
 
        return 0;
 }
@@ -380,8 +382,8 @@ static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
 }
 
 
-int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-                struct map_symbol *syms, u64 period)
+int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
+                    struct map_symbol *syms, u64 period)
 {
        struct resolved_chain *filtered;
 
@@ -398,9 +400,65 @@ int append_chain(struct callchain_node *root, struct ip_callchain *chain,
        if (!filtered->nr)
                goto end;
 
-       __append_chain_children(root, filtered, 0, period);
+       append_chain_children(&root->node, filtered, 0, period);
+
+       if (filtered->nr > root->max_depth)
+               root->max_depth = filtered->nr;
 end:
        free(filtered);
 
        return 0;
 }
+
+static int
+merge_chain_branch(struct callchain_node *dst, struct callchain_node *src,
+                  struct resolved_chain *chain)
+{
+       struct callchain_node *child, *next_child;
+       struct callchain_list *list, *next_list;
+       int old_pos = chain->nr;
+       int err = 0;
+
+       list_for_each_entry_safe(list, next_list, &src->val, list) {
+               chain->ips[chain->nr].ip = list->ip;
+               chain->ips[chain->nr].ms = list->ms;
+               chain->nr++;
+               list_del(&list->list);
+               free(list);
+       }
+
+       if (src->hit)
+               append_chain_children(dst, chain, 0, src->hit);
+
+       chain_for_each_child_safe(child, next_child, src) {
+               err = merge_chain_branch(dst, child, chain);
+               if (err)
+                       break;
+
+               list_del(&child->brothers);
+               free(child);
+       }
+
+       chain->nr = old_pos;
+
+       return err;
+}
+
+int callchain_merge(struct callchain_root *dst, struct callchain_root *src)
+{
+       struct resolved_chain *chain;
+       int err;
+
+       chain = malloc(sizeof(*chain) +
+                      src->max_depth * sizeof(struct resolved_ip));
+       if (!chain)
+               return -ENOMEM;
+
+       chain->nr = 0;
+
+       err = merge_chain_branch(&dst->node, &src->node, chain);
+
+       free(chain);
+
+       return err;
+}
index 624a96c636fdbc36a472ecaadf5fcb72c226bf38..c15fb8c24ad2b87388e97cd6346cfdebaac11dd5 100644 (file)
@@ -26,9 +26,14 @@ struct callchain_node {
        u64                     children_hit;
 };
 
+struct callchain_root {
+       u64                     max_depth;
+       struct callchain_node   node;
+};
+
 struct callchain_param;
 
-typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
+typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
                                 u64, struct callchain_param *);
 
 struct callchain_param {
@@ -44,14 +49,16 @@ struct callchain_list {
        struct list_head        list;
 };
 
-static inline void callchain_init(struct callchain_node *node)
+static inline void callchain_init(struct callchain_root *root)
 {
-       INIT_LIST_HEAD(&node->brothers);
-       INIT_LIST_HEAD(&node->children);
-       INIT_LIST_HEAD(&node->val);
+       INIT_LIST_HEAD(&root->node.brothers);
+       INIT_LIST_HEAD(&root->node.children);
+       INIT_LIST_HEAD(&root->node.val);
 
-       node->parent = NULL;
-       node->hit = 0;
+       root->node.parent = NULL;
+       root->node.hit = 0;
+       root->node.children_hit = 0;
+       root->max_depth = 0;
 }
 
 static inline u64 cumul_hits(struct callchain_node *node)
@@ -60,8 +67,9 @@ static inline u64 cumul_hits(struct callchain_node *node)
 }
 
 int register_callchain_param(struct callchain_param *param);
-int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-                struct map_symbol *syms, u64 period);
+int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
+                    struct map_symbol *syms, u64 period);
+int callchain_merge(struct callchain_root *dst, struct callchain_root *src);
 
 bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event);
 #endif /* __PERF_CALLCHAIN_H */
index be22ae6ef0558009c0a1faaa4f55bcf2c5d828ca..2022e87409942ca4b0d133c3f889e41178a663d1 100644 (file)
@@ -87,7 +87,7 @@ static void hist_entry__add_cpumode_period(struct hist_entry *self,
 
 static struct hist_entry *hist_entry__new(struct hist_entry *template)
 {
-       size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0;
+       size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
        struct hist_entry *self = malloc(sizeof(*self) + callchain_size);
 
        if (self != NULL) {
@@ -226,6 +226,8 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
 
                if (!cmp) {
                        iter->period += he->period;
+                       if (symbol_conf.use_callchain)
+                               callchain_merge(iter->callchain, he->callchain);
                        hist_entry__free(he);
                        return false;
                }
index 58a470d036dd0917c16eda49fb8b1987703ca7b5..bd74977114242ff465af39a291d30aa7d463f3b2 100644 (file)
@@ -22,6 +22,7 @@ static const char *get_perf_dir(void)
        return ".";
 }
 
+#ifdef NO_STRLCPY
 size_t strlcpy(char *dest, const char *src, size_t size)
 {
        size_t ret = strlen(src);
@@ -33,7 +34,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
        }
        return ret;
 }
-
+#endif
 
 static char *get_pathname(void)
 {
index e72f05c3bef09258311f7192afb179a10657c450..fcc16e4349df9f3353ac03f975d9c1be9938863a 100644 (file)
@@ -1539,6 +1539,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
                goto error;
        }
        tev->point.offset = pev->point.offset;
+       tev->point.retprobe = pev->point.retprobe;
        tev->nargs = pev->nargs;
        if (tev->nargs) {
                tev->args = zalloc(sizeof(struct probe_trace_arg)
index 525136684d4ec170201b4d07c7b080b73851edf9..32b81f707ff5eb5d950a2d233d6c00c6b90fedb2 100644 (file)
@@ -686,6 +686,25 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
        char buf[32], *ptr;
        int ret, nscopes;
 
+       if (!is_c_varname(pf->pvar->var)) {
+               /* Copy raw parameters */
+               pf->tvar->value = strdup(pf->pvar->var);
+               if (pf->tvar->value == NULL)
+                       return -ENOMEM;
+               if (pf->pvar->type) {
+                       pf->tvar->type = strdup(pf->pvar->type);
+                       if (pf->tvar->type == NULL)
+                               return -ENOMEM;
+               }
+               if (pf->pvar->name) {
+                       pf->tvar->name = strdup(pf->pvar->name);
+                       if (pf->tvar->name == NULL)
+                               return -ENOMEM;
+               } else
+                       pf->tvar->name = NULL;
+               return 0;
+       }
+
        if (pf->pvar->name)
                pf->tvar->name = strdup(pf->pvar->name);
        else {
@@ -700,19 +719,6 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
        if (pf->tvar->name == NULL)
                return -ENOMEM;
 
-       if (!is_c_varname(pf->pvar->var)) {
-               /* Copy raw parameters */
-               pf->tvar->value = strdup(pf->pvar->var);
-               if (pf->tvar->value == NULL)
-                       return -ENOMEM;
-               if (pf->pvar->type) {
-                       pf->tvar->type = strdup(pf->pvar->type);
-                       if (pf->tvar->type == NULL)
-                               return -ENOMEM;
-               }
-               return 0;
-       }
-
        pr_debug("Searching '%s' variable in context.\n",
                 pf->pvar->var);
        /* Search child die for local variables and parameters. */
@@ -783,6 +789,16 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
                /* This function has no name. */
                tev->point.offset = (unsigned long)pf->addr;
 
+       /* Return probe must be on the head of a subprogram */
+       if (pf->pev->point.retprobe) {
+               if (tev->point.offset != 0) {
+                       pr_warning("Return probe must be on the head of"
+                                  " a real function\n");
+                       return -EINVAL;
+               }
+               tev->point.retprobe = true;
+       }
+
        pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
                 tev->point.offset);
 
index 46e531d09e8bfcbe1064a4307ce5a75ef72a6405..0b91053a7d11af888eea81a4c8de24fdd60ce6f8 100644 (file)
@@ -70,7 +70,7 @@ struct hist_entry {
                struct hist_entry *pair;
                struct rb_root    sorted_chain;
        };
-       struct callchain_node   callchain[0];
+       struct callchain_root   callchain[0];
 };
 
 enum sort_type {
index 1a367734e01693c8a93f79bb3846af4a89f9cffe..b39f499e575a604198bf1bb11d11d6280a091548 100644 (file)
@@ -388,6 +388,20 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
        return fprintf(fp, "%s", sbuild_id);
 }
 
+size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp)
+{
+       size_t ret = 0;
+       struct rb_node *nd;
+       struct symbol_name_rb_node *pos;
+
+       for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
+               pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
+               fprintf(fp, "%s\n", pos->sym.name);
+       }
+
+       return ret;
+}
+
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
 {
        struct rb_node *nd;
@@ -2268,6 +2282,9 @@ static int setup_list(struct strlist **list, const char *list_str,
 
 int symbol__init(void)
 {
+       if (symbol_conf.initialized)
+               return 0;
+
        elf_version(EV_CURRENT);
        if (symbol_conf.sort_by_name)
                symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
@@ -2293,6 +2310,7 @@ int symbol__init(void)
                       symbol_conf.sym_list_str, "symbol") < 0)
                goto out_free_comm_list;
 
+       symbol_conf.initialized = true;
        return 0;
 
 out_free_dso_list:
@@ -2304,11 +2322,14 @@ out_free_comm_list:
 
 void symbol__exit(void)
 {
+       if (!symbol_conf.initialized)
+               return;
        strlist__delete(symbol_conf.sym_list);
        strlist__delete(symbol_conf.dso_list);
        strlist__delete(symbol_conf.comm_list);
        vmlinux_path__exit();
        symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
+       symbol_conf.initialized = false;
 }
 
 int machines__create_kernel_maps(struct rb_root *self, pid_t pid)
index b7a8da4af5a0a98e84e1616e55cdaceec18fcdbf..038f2201ee09579ca3f460d9f59576770ea477d2 100644 (file)
@@ -69,7 +69,8 @@ struct symbol_conf {
                        show_nr_samples,
                        use_callchain,
                        exclude_other,
-                       show_cpu_utilization;
+                       show_cpu_utilization,
+                       initialized;
        const char      *vmlinux_name,
                        *source_prefix,
                        *field_sep;
@@ -181,6 +182,7 @@ size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp);
 size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
 
 size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
+size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp);
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
 
 enum dso_origin {
index 7ea983acfaea521a425f7eb33250e319b0a3a960..f7af2fca965d5c206973f73ccd25b8b3607e02e5 100644 (file)
@@ -97,7 +97,7 @@ void setup_python_scripting(void)
        register_python_scripting(&python_scripting_unsupported_ops);
 }
 #else
-struct scripting_ops python_scripting_ops;
+extern struct scripting_ops python_scripting_ops;
 
 void setup_python_scripting(void)
 {
@@ -158,7 +158,7 @@ void setup_perl_scripting(void)
        register_perl_scripting(&perl_scripting_unsupported_ops);
 }
 #else
-struct scripting_ops perl_scripting_ops;
+extern struct scripting_ops perl_scripting_ops;
 
 void setup_perl_scripting(void)
 {
index 66f2d583d8c4326971dc9d37cd47df57eeb82306..6d0df809a2edab24f28af4bea093d1cda3c2614d 100644 (file)
@@ -1,16 +1,6 @@
-#define _GNU_SOURCE
-#include <stdio.h>
-#undef _GNU_SOURCE
-/*
- * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
- * the build if it isn't defined. Use the equivalent one that glibc
- * has on features.h.
- */
-#include <features.h>
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
-#endif
 #include <slang.h>
+#include "libslang.h"
+#include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <stdlib.h>
@@ -19,17 +9,9 @@
 #include "helpline.h"
 #include "../color.h"
 #include "../util.h"
+#include <stdio.h>
 
-#if SLANG_VERSION < 20104
-#define sltt_set_color(obj, name, fg, bg) \
-       SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
-#else
-#define sltt_set_color SLtt_set_color
-#endif
-
-newtComponent newt_form__new(void);
-
-int ui_browser__percent_color(double percent, bool current)
+static int ui_browser__percent_color(double percent, bool current)
 {
        if (current)
                return HE_COLORSET_SELECTED;
@@ -40,6 +22,23 @@ int ui_browser__percent_color(double percent, bool current)
        return HE_COLORSET_NORMAL;
 }
 
+void ui_browser__set_color(struct ui_browser *self __used, int color)
+{
+       SLsmg_set_color(color);
+}
+
+void ui_browser__set_percent_color(struct ui_browser *self,
+                                  double percent, bool current)
+{
+        int color = ui_browser__percent_color(percent, current);
+        ui_browser__set_color(self, color);
+}
+
+void ui_browser__gotorc(struct ui_browser *self, int y, int x)
+{
+       SLsmg_gotorc(self->y + y, self->x + x);
+}
+
 void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
 {
        struct list_head *head = self->entries;
@@ -111,7 +110,7 @@ unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
        nd = self->top;
 
        while (nd != NULL) {
-               SLsmg_gotorc(self->y + row, self->x);
+               ui_browser__gotorc(self, row, 0);
                self->write(self, nd, row);
                if (++row == self->height)
                        break;
@@ -131,13 +130,10 @@ void ui_browser__refresh_dimensions(struct ui_browser *self)
        int cols, rows;
        newtGetScreenSize(&cols, &rows);
 
-       if (self->width > cols - 4)
-               self->width = cols - 4;
-       self->height = rows - 5;
-       if (self->height > self->nr_entries)
-               self->height = self->nr_entries;
-       self->y  = (rows - self->height) / 2;
-       self->x = (cols - self->width) / 2;
+       self->width = cols - 1;
+       self->height = rows - 2;
+       self->y = 1;
+       self->x = 0;
 }
 
 void ui_browser__reset_index(struct ui_browser *self)
@@ -146,34 +142,48 @@ void ui_browser__reset_index(struct ui_browser *self)
        self->seek(self, 0, SEEK_SET);
 }
 
+void ui_browser__add_exit_key(struct ui_browser *self, int key)
+{
+       newtFormAddHotKey(self->form, key);
+}
+
+void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
+{
+       int i = 0;
+
+       while (keys[i] && i < 64) {
+               ui_browser__add_exit_key(self, keys[i]);
+               ++i;
+       }
+}
+
 int ui_browser__show(struct ui_browser *self, const char *title,
                     const char *helpline, ...)
 {
        va_list ap;
+       int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
+                      NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
+                      NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
 
-       if (self->form != NULL) {
+       if (self->form != NULL)
                newtFormDestroy(self->form);
-               newtPopWindow();
-       }
+
        ui_browser__refresh_dimensions(self);
-       newtCenteredWindow(self->width, self->height, title);
-       self->form = newt_form__new();
+       self->form = newtForm(NULL, NULL, 0);
        if (self->form == NULL)
                return -1;
 
-       self->sb = newtVerticalScrollbar(self->width, 0, self->height,
+       self->sb = newtVerticalScrollbar(self->width, 1, self->height,
                                         HE_COLORSET_NORMAL,
                                         HE_COLORSET_SELECTED);
        if (self->sb == NULL)
                return -1;
 
-       newtFormAddHotKey(self->form, NEWT_KEY_UP);
-       newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
-       newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
-       newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
-       newtFormAddHotKey(self->form, NEWT_KEY_HOME);
-       newtFormAddHotKey(self->form, NEWT_KEY_END);
-       newtFormAddHotKey(self->form, ' ');
+       SLsmg_gotorc(0, 0);
+       ui_browser__set_color(self, NEWT_COLORSET_ROOT);
+       slsmg_write_nstring(title, self->width);
+
+       ui_browser__add_exit_keys(self, keys);
        newtFormAddComponent(self->form, self->sb);
 
        va_start(ap, helpline);
@@ -185,7 +195,6 @@ int ui_browser__show(struct ui_browser *self, const char *title,
 void ui_browser__hide(struct ui_browser *self)
 {
        newtFormDestroy(self->form);
-       newtPopWindow();
        self->form = NULL;
        ui_helpline__pop();
 }
@@ -196,28 +205,28 @@ int ui_browser__refresh(struct ui_browser *self)
 
        newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
        row = self->refresh(self);
-       SLsmg_set_color(HE_COLORSET_NORMAL);
+       ui_browser__set_color(self, HE_COLORSET_NORMAL);
        SLsmg_fill_region(self->y + row, self->x,
                          self->height - row, self->width, ' ');
 
        return 0;
 }
 
-int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
+int ui_browser__run(struct ui_browser *self)
 {
+       struct newtExitStruct es;
+
        if (ui_browser__refresh(self) < 0)
                return -1;
 
        while (1) {
                off_t offset;
 
-               newtFormRun(self->form, es);
+               newtFormRun(self->form, &es);
 
-               if (es->reason != NEWT_EXIT_HOTKEY)
+               if (es.reason != NEWT_EXIT_HOTKEY)
                        break;
-               if (is_exit_key(es->u.key))
-                       return es->u.key;
-               switch (es->u.key) {
+               switch (es.u.key) {
                case NEWT_KEY_DOWN:
                        if (self->index == self->nr_entries - 1)
                                break;
@@ -274,12 +283,12 @@ int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
                        self->seek(self, -offset, SEEK_END);
                        break;
                default:
-                       return es->u.key;
+                       return es.u.key;
                }
                if (ui_browser__refresh(self) < 0)
                        return -1;
        }
-       return 0;
+       return -1;
 }
 
 unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
@@ -294,7 +303,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
        pos = self->top;
 
        list_for_each_from(pos, head) {
-               SLsmg_gotorc(self->y + row, self->x);
+               ui_browser__gotorc(self, row, 0);
                self->write(self, pos, row);
                if (++row == self->height)
                        break;
index 0b9f829214f756ec16227745835cfea55d7ee503..0dc7e4da36f52c42ef3574dc89dce7102ae8438d 100644 (file)
@@ -25,16 +25,21 @@ struct ui_browser {
 };
 
 
-int ui_browser__percent_color(double percent, bool current);
+void ui_browser__set_color(struct ui_browser *self, int color);
+void ui_browser__set_percent_color(struct ui_browser *self,
+                                  double percent, bool current);
 bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
 void ui_browser__refresh_dimensions(struct ui_browser *self);
 void ui_browser__reset_index(struct ui_browser *self);
 
+void ui_browser__gotorc(struct ui_browser *self, int y, int x);
+void ui_browser__add_exit_key(struct ui_browser *self, int key);
+void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]);
 int ui_browser__show(struct ui_browser *self, const char *title,
                     const char *helpline, ...);
 void ui_browser__hide(struct ui_browser *self);
 int ui_browser__refresh(struct ui_browser *self);
-int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es);
+int ui_browser__run(struct ui_browser *self);
 
 void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
 unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
index a90273e63f4fb6939ea64e074513e1afabb1f289..82b78f99251bb2b764165cf8066a85f1e6e4b97d 100644 (file)
@@ -40,14 +40,12 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
 
        if (ol->offset != -1) {
                struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
-               int color = ui_browser__percent_color(olrb->percent, current_entry);
-               SLsmg_set_color(color);
+               ui_browser__set_percent_color(self, olrb->percent, current_entry);
                slsmg_printf(" %7.2f ", olrb->percent);
                if (!current_entry)
-                       SLsmg_set_color(HE_COLORSET_CODE);
+                       ui_browser__set_color(self, HE_COLORSET_CODE);
        } else {
-               int color = ui_browser__percent_color(0, current_entry);
-               SLsmg_set_color(color);
+               ui_browser__set_percent_color(self, 0, current_entry);
                slsmg_write_nstring(" ", 9);
        }
 
@@ -135,32 +133,31 @@ static void annotate_browser__set_top(struct annotate_browser *self,
        self->curr_hot = nd;
 }
 
-static int annotate_browser__run(struct annotate_browser *self,
-                                struct newtExitStruct *es)
+static int annotate_browser__run(struct annotate_browser *self)
 {
        struct rb_node *nd;
        struct hist_entry *he = self->b.priv;
+       int key;
 
        if (ui_browser__show(&self->b, he->ms.sym->name,
-                            "<- or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
+                            "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
                return -1;
-
-       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT);
+       /*
+        * To allow builtin-annotate to cycle thru multiple symbols by
+        * examining the exit key for this function.
+        */
+       ui_browser__add_exit_key(&self->b, NEWT_KEY_RIGHT);
 
        nd = self->curr_hot;
        if (nd) {
-               newtFormAddHotKey(self->b.form, NEWT_KEY_TAB);
-               newtFormAddHotKey(self->b.form, NEWT_KEY_UNTAB);
+               int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 };
+               ui_browser__add_exit_keys(&self->b, tabs);
        }
 
        while (1) {
-               ui_browser__run(&self->b, es);
-
-               if (es->reason != NEWT_EXIT_HOTKEY)
-                       break;
+               key = ui_browser__run(&self->b);
 
-               switch (es->u.key) {
+               switch (key) {
                case NEWT_KEY_TAB:
                        nd = rb_prev(nd);
                        if (nd == NULL)
@@ -179,12 +176,11 @@ static int annotate_browser__run(struct annotate_browser *self,
        }
 out:
        ui_browser__hide(&self->b);
-       return es->u.key;
+       return key;
 }
 
 int hist_entry__tui_annotate(struct hist_entry *self)
 {
-       struct newtExitStruct es;
        struct objdump_line *pos, *n;
        struct objdump_line_rb_node *rbpos;
        LIST_HEAD(head);
@@ -232,7 +228,7 @@ int hist_entry__tui_annotate(struct hist_entry *self)
                annotate_browser__set_top(&browser, browser.curr_hot);
 
        browser.b.width += 18; /* Percentage */
-       ret = annotate_browser__run(&browser, &es);
+       ret = annotate_browser__run(&browser);
        list_for_each_entry_safe(pos, n, &head, node) {
                list_del(&pos->node);
                objdump_line__free(pos);
index dafdf6775d77f44d69abf1980b1a9cfe4ab053dc..ebda8c3fde9e6468ddbd84fc2df7e324ba862854 100644 (file)
@@ -58,6 +58,11 @@ static char callchain_list__folded(const struct callchain_list *self)
        return map_symbol__folded(&self->ms);
 }
 
+static void map_symbol__set_folding(struct map_symbol *self, bool unfold)
+{
+       self->unfolded = unfold ? self->has_children : false;
+}
+
 static int callchain_node__count_rows_rb_tree(struct callchain_node *self)
 {
        int n = 0;
@@ -129,16 +134,16 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *se
        for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
                struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
                struct callchain_list *chain;
-               int first = true;
+               bool first = true;
 
                list_for_each_entry(chain, &child->val, list) {
                        if (first) {
                                first = false;
                                chain->ms.has_children = chain->list.next != &child->val ||
-                                                        rb_first(&child->rb_root) != NULL;
+                                                        !RB_EMPTY_ROOT(&child->rb_root);
                        } else
                                chain->ms.has_children = chain->list.next == &child->val &&
-                                                        rb_first(&child->rb_root) != NULL;
+                                                        !RB_EMPTY_ROOT(&child->rb_root);
                }
 
                callchain_node__init_have_children_rb_tree(child);
@@ -150,7 +155,7 @@ static void callchain_node__init_have_children(struct callchain_node *self)
        struct callchain_list *chain;
 
        list_for_each_entry(chain, &self->val, list)
-               chain->ms.has_children = rb_first(&self->rb_root) != NULL;
+               chain->ms.has_children = !RB_EMPTY_ROOT(&self->rb_root);
 
        callchain_node__init_have_children_rb_tree(self);
 }
@@ -168,6 +173,7 @@ static void callchain__init_have_children(struct rb_root *self)
 static void hist_entry__init_have_children(struct hist_entry *self)
 {
        if (!self->init_have_children) {
+               self->ms.has_children = !RB_EMPTY_ROOT(&self->sorted_chain);
                callchain__init_have_children(&self->sorted_chain);
                self->init_have_children = true;
        }
@@ -195,43 +201,114 @@ static bool hist_browser__toggle_fold(struct hist_browser *self)
        return false;
 }
 
-static int hist_browser__run(struct hist_browser *self, const char *title,
-                            struct newtExitStruct *es)
+static int callchain_node__set_folding_rb_tree(struct callchain_node *self, bool unfold)
+{
+       int n = 0;
+       struct rb_node *nd;
+
+       for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
+               struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
+               struct callchain_list *chain;
+               bool has_children = false;
+
+               list_for_each_entry(chain, &child->val, list) {
+                       ++n;
+                       map_symbol__set_folding(&chain->ms, unfold);
+                       has_children = chain->ms.has_children;
+               }
+
+               if (has_children)
+                       n += callchain_node__set_folding_rb_tree(child, unfold);
+       }
+
+       return n;
+}
+
+static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
+{
+       struct callchain_list *chain;
+       bool has_children = false;
+       int n = 0;
+
+       list_for_each_entry(chain, &node->val, list) {
+               ++n;
+               map_symbol__set_folding(&chain->ms, unfold);
+               has_children = chain->ms.has_children;
+       }
+
+       if (has_children)
+               n += callchain_node__set_folding_rb_tree(node, unfold);
+
+       return n;
+}
+
+static int callchain__set_folding(struct rb_root *chain, bool unfold)
+{
+       struct rb_node *nd;
+       int n = 0;
+
+       for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
+               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+               n += callchain_node__set_folding(node, unfold);
+       }
+
+       return n;
+}
+
+static void hist_entry__set_folding(struct hist_entry *self, bool unfold)
+{
+       hist_entry__init_have_children(self);
+       map_symbol__set_folding(&self->ms, unfold);
+
+       if (self->ms.has_children) {
+               int n = callchain__set_folding(&self->sorted_chain, unfold);
+               self->nr_rows = unfold ? n : 0;
+       } else
+               self->nr_rows = 0;
+}
+
+static void hists__set_folding(struct hists *self, bool unfold)
+{
+       struct rb_node *nd;
+
+       self->nr_entries = 0;
+
+       for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
+               struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
+               hist_entry__set_folding(he, unfold);
+               self->nr_entries += 1 + he->nr_rows;
+       }
+}
+
+static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
+{
+       hists__set_folding(self->hists, unfold);
+       self->b.nr_entries = self->hists->nr_entries;
+       /* Go to the start, we may be way after valid entries after a collapse */
+       ui_browser__reset_index(&self->b);
+}
+
+static int hist_browser__run(struct hist_browser *self, const char *title)
 {
-       char str[256], unit;
-       unsigned long nr_events = self->hists->stats.nr_events[PERF_RECORD_SAMPLE];
+       int key;
+       int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't',
+                           NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT, 0, };
 
        self->b.entries = &self->hists->entries;
        self->b.nr_entries = self->hists->nr_entries;
 
        hist_browser__refresh_dimensions(self);
 
-       nr_events = convert_unit(nr_events, &unit);
-       snprintf(str, sizeof(str), "Events: %lu%c                            ",
-                nr_events, unit);
-       newtDrawRootText(0, 0, str);
-
        if (ui_browser__show(&self->b, title,
                             "Press '?' for help on key bindings") < 0)
                return -1;
 
-       newtFormAddHotKey(self->b.form, 'a');
-       newtFormAddHotKey(self->b.form, '?');
-       newtFormAddHotKey(self->b.form, 'h');
-       newtFormAddHotKey(self->b.form, 'd');
-       newtFormAddHotKey(self->b.form, 'D');
-       newtFormAddHotKey(self->b.form, 't');
-
-       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
+       ui_browser__add_exit_keys(&self->b, exit_keys);
 
        while (1) {
-               ui_browser__run(&self->b, es);
+               key = ui_browser__run(&self->b);
 
-               if (es->reason != NEWT_EXIT_HOTKEY)
-                       break;
-               switch (es->u.key) {
+               switch (key) {
                case 'D': { /* Debug */
                        static int seq;
                        struct hist_entry *h = rb_entry(self->b.top,
@@ -245,18 +322,26 @@ static int hist_browser__run(struct hist_browser *self, const char *title,
                                           self->b.top_idx,
                                           h->row_offset, h->nr_rows);
                }
-                       continue;
+                       break;
+               case 'C':
+                       /* Collapse the whole world. */
+                       hist_browser__set_folding(self, false);
+                       break;
+               case 'E':
+                       /* Expand the whole world. */
+                       hist_browser__set_folding(self, true);
+                       break;
                case NEWT_KEY_ENTER:
                        if (hist_browser__toggle_fold(self))
                                break;
                        /* fall thru */
                default:
-                       return 0;
+                       goto out;
                }
        }
-
+out:
        ui_browser__hide(&self->b);
-       return 0;
+       return key;
 }
 
 static char *callchain_list__sym_name(struct callchain_list *self,
@@ -306,15 +391,10 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
                        int color;
                        bool was_first = first;
 
-                       if (first) {
+                       if (first)
                                first = false;
-                               chain->ms.has_children = chain->list.next != &child->val ||
-                                                        rb_first(&child->rb_root) != NULL;
-                       } else {
+                       else
                                extra_offset = LEVEL_OFFSET_STEP;
-                               chain->ms.has_children = chain->list.next == &child->val &&
-                                                        rb_first(&child->rb_root) != NULL;
-                       }
 
                        folded_sign = callchain_list__folded(chain);
                        if (*row_offset != 0) {
@@ -341,8 +421,8 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
                                *is_current_entry = true;
                        }
 
-                       SLsmg_set_color(color);
-                       SLsmg_gotorc(self->b.y + row, self->b.x);
+                       ui_browser__set_color(&self->b, color);
+                       ui_browser__gotorc(&self->b, row, 0);
                        slsmg_write_nstring(" ", offset + extra_offset);
                        slsmg_printf("%c ", folded_sign);
                        slsmg_write_nstring(str, width);
@@ -384,12 +464,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *self,
        list_for_each_entry(chain, &node->val, list) {
                char ipstr[BITS_PER_LONG / 4 + 1], *s;
                int color;
-               /*
-                * FIXME: This should be moved to somewhere else,
-                * probably when the callchain is created, so as not to
-                * traverse it all over again
-                */
-               chain->ms.has_children = rb_first(&node->rb_root) != NULL;
+
                folded_sign = callchain_list__folded(chain);
 
                if (*row_offset != 0) {
@@ -405,8 +480,8 @@ static int hist_browser__show_callchain_node(struct hist_browser *self,
                }
 
                s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
-               SLsmg_gotorc(self->b.y + row, self->b.x);
-               SLsmg_set_color(color);
+               ui_browser__gotorc(&self->b, row, 0);
+               ui_browser__set_color(&self->b, color);
                slsmg_write_nstring(" ", offset);
                slsmg_printf("%c ", folded_sign);
                slsmg_write_nstring(s, width - 2);
@@ -465,7 +540,7 @@ static int hist_browser__show_entry(struct hist_browser *self,
        }
 
        if (symbol_conf.use_callchain) {
-               entry->ms.has_children = !RB_EMPTY_ROOT(&entry->sorted_chain);
+               hist_entry__init_have_children(entry);
                folded_sign = hist_entry__folded(entry);
        }
 
@@ -484,8 +559,8 @@ static int hist_browser__show_entry(struct hist_browser *self,
                                color = HE_COLORSET_NORMAL;
                }
 
-               SLsmg_set_color(color);
-               SLsmg_gotorc(self->b.y + row, self->b.x);
+               ui_browser__set_color(&self->b, color);
+               ui_browser__gotorc(&self->b, row, 0);
                if (symbol_conf.use_callchain) {
                        slsmg_printf("%c ", folded_sign);
                        width -= 2;
@@ -687,8 +762,6 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
 
 static void hist_browser__delete(struct hist_browser *self)
 {
-       newtFormDestroy(self->b.form);
-       newtPopWindow();
        free(self);
 }
 
@@ -702,21 +775,26 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
        return self->he_selection->thread;
 }
 
-static int hist_browser__title(char *bf, size_t size, const char *ev_name,
-                              const struct dso *dso, const struct thread *thread)
+static int hists__browser_title(struct hists *self, char *bf, size_t size,
+                               const char *ev_name, const struct dso *dso,
+                               const struct thread *thread)
 {
-       int printed = 0;
+       char unit;
+       int printed;
+       unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
+
+       nr_events = convert_unit(nr_events, &unit);
+       printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
 
        if (thread)
                printed += snprintf(bf + printed, size - printed,
-                                   "Thread: %s(%d)",
-                                   (thread->comm_set ?  thread->comm : ""),
+                                   "Thread: %s(%d)",
+                                   (thread->comm_set ? thread->comm : ""),
                                    thread->pid);
        if (dso)
                printed += snprintf(bf + printed, size - printed,
-                                   "%sDSO: %s", thread ? " " : "",
-                                   dso->short_name);
-       return printed ?: snprintf(bf, size, "Event: %s", ev_name);
+                                   ", DSO: %s", dso->short_name);
+       return printed;
 }
 
 int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
@@ -725,7 +803,6 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
        struct pstack *fstack;
        const struct thread *thread_filter = NULL;
        const struct dso *dso_filter = NULL;
-       struct newtExitStruct es;
        char msg[160];
        int key = -1;
 
@@ -738,9 +815,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 
        ui_helpline__push(helpline);
 
-       hist_browser__title(msg, sizeof(msg), ev_name,
-                           dso_filter, thread_filter);
-
+       hists__browser_title(self, msg, sizeof(msg), ev_name,
+                            dso_filter, thread_filter);
        while (1) {
                const struct thread *thread;
                const struct dso *dso;
@@ -749,70 +825,63 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
                    annotate = -2, zoom_dso = -2, zoom_thread = -2,
                    browse_map = -2;
 
-               if (hist_browser__run(browser, msg, &es))
-                       break;
+               key = hist_browser__run(browser, msg);
 
                thread = hist_browser__selected_thread(browser);
                dso = browser->selection->map ? browser->selection->map->dso : NULL;
 
-               if (es.reason == NEWT_EXIT_HOTKEY) {
-                       key = es.u.key;
-
-                       switch (key) {
-                       case NEWT_KEY_F1:
-                               goto do_help;
-                       case NEWT_KEY_TAB:
-                       case NEWT_KEY_UNTAB:
-                               /*
-                                * Exit the browser, let hists__browser_tree
-                                * go to the next or previous
-                                */
-                               goto out_free_stack;
-                       default:;
-                       }
-
-                       switch (key) {
-                       case 'a':
-                               if (browser->selection->map == NULL &&
-                                   browser->selection->map->dso->annotate_warned)
-                                       continue;
-                               goto do_annotate;
-                       case 'd':
-                               goto zoom_dso;
-                       case 't':
-                               goto zoom_thread;
-                       case 'h':
-                       case '?':
-do_help:
-                               ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
-                                               "<-        Zoom out\n"
-                                               "a         Annotate current symbol\n"
-                                               "h/?/F1    Show this window\n"
-                                               "d         Zoom into current DSO\n"
-                                               "t         Zoom into current Thread\n"
-                                               "q/CTRL+C  Exit browser");
+               switch (key) {
+               case NEWT_KEY_TAB:
+               case NEWT_KEY_UNTAB:
+                       /*
+                        * Exit the browser, let hists__browser_tree
+                        * go to the next or previous
+                        */
+                       goto out_free_stack;
+               case 'a':
+                       if (browser->selection->map == NULL &&
+                           browser->selection->map->dso->annotate_warned)
                                continue;
-                       default:;
-                       }
-                       if (is_exit_key(key)) {
-                               if (key == NEWT_KEY_ESCAPE &&
-                                   !ui__dialog_yesno("Do you really want to exit?"))
-                                       continue;
-                               break;
-                       }
-
-                       if (es.u.key == NEWT_KEY_LEFT) {
-                               const void *top;
+                       goto do_annotate;
+               case 'd':
+                       goto zoom_dso;
+               case 't':
+                       goto zoom_thread;
+               case NEWT_KEY_F1:
+               case 'h':
+               case '?':
+                       ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
+                                       "<-        Zoom out\n"
+                                       "a         Annotate current symbol\n"
+                                       "h/?/F1    Show this window\n"
+                                       "C         Collapse all callchains\n"
+                                       "E         Expand all callchains\n"
+                                       "d         Zoom into current DSO\n"
+                                       "t         Zoom into current Thread\n"
+                                       "q/CTRL+C  Exit browser");
+                       continue;
+               case NEWT_KEY_ENTER:
+               case NEWT_KEY_RIGHT:
+                       /* menu */
+                       break;
+               case NEWT_KEY_LEFT: {
+                       const void *top;
 
-                               if (pstack__empty(fstack))
-                                       continue;
-                               top = pstack__pop(fstack);
-                               if (top == &dso_filter)
-                                       goto zoom_out_dso;
-                               if (top == &thread_filter)
-                                       goto zoom_out_thread;
+                       if (pstack__empty(fstack))
                                continue;
-                       }
+                       top = pstack__pop(fstack);
+                       if (top == &dso_filter)
+                               goto zoom_out_dso;
+                       if (top == &thread_filter)
+                               goto zoom_out_thread;
+                       continue;
+               }
+               case NEWT_KEY_ESCAPE:
+                       if (!ui__dialog_yesno("Do you really want to exit?"))
+                               continue;
+                       /* Fall thru */
+               default:
+                       goto out_free_stack;
                }
 
                if (browser->selection->sym != NULL &&
@@ -885,8 +954,8 @@ zoom_out_dso:
                                pstack__push(fstack, &dso_filter);
                        }
                        hists__filter_by_dso(self, dso_filter);
-                       hist_browser__title(msg, sizeof(msg), ev_name,
-                                           dso_filter, thread_filter);
+                       hists__browser_title(self, msg, sizeof(msg), ev_name,
+                                            dso_filter, thread_filter);
                        hist_browser__reset(browser);
                } else if (choice == zoom_thread) {
 zoom_thread:
@@ -903,8 +972,8 @@ zoom_out_thread:
                                pstack__push(fstack, &thread_filter);
                        }
                        hists__filter_by_thread(self, thread_filter);
-                       hist_browser__title(msg, sizeof(msg), ev_name,
-                                           dso_filter, thread_filter);
+                       hists__browser_title(self, msg, sizeof(msg), ev_name,
+                                            dso_filter, thread_filter);
                        hist_browser__reset(browser);
                }
        }
@@ -925,10 +994,6 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help)
                const char *ev_name = __event_name(hists->type, hists->config);
 
                key = hists__browse(hists, help, ev_name);
-
-               if (is_exit_key(key))
-                       break;
-
                switch (key) {
                case NEWT_KEY_TAB:
                        next = rb_next(nd);
@@ -940,7 +1005,7 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help)
                                continue;
                        nd = rb_prev(nd);
                default:
-                       break;
+                       return key;
                }
        }
 
index 142b825b42bf41d90ee013f51aaac5e79df44f5e..e35437dfa5b48aea8a0fb0237b2bf7ed7aaf90cd 100644 (file)
@@ -1,6 +1,5 @@
 #include "../libslang.h"
 #include <elf.h>
-#include <newt.h>
 #include <sys/ttydefaults.h>
 #include <ctype.h>
 #include <string.h>
@@ -47,7 +46,6 @@ out_free_form:
 struct map_browser {
        struct ui_browser b;
        struct map        *map;
-       u16               namelen;
        u8                addrlen;
 };
 
@@ -56,14 +54,16 @@ static void map_browser__write(struct ui_browser *self, void *nd, int row)
        struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
        struct map_browser *mb = container_of(self, struct map_browser, b);
        bool current_entry = ui_browser__is_current_entry(self, row);
-       int color = ui_browser__percent_color(0, current_entry);
+       int width;
 
-       SLsmg_set_color(color);
+       ui_browser__set_percent_color(self, 0, current_entry);
        slsmg_printf("%*llx %*llx %c ",
                     mb->addrlen, sym->start, mb->addrlen, sym->end,
                     sym->binding == STB_GLOBAL ? 'g' :
                     sym->binding == STB_LOCAL  ? 'l' : 'w');
-       slsmg_write_nstring(sym->name, mb->namelen);
+       width = self->width - ((mb->addrlen * 2) + 4);
+       if (width > 0)
+               slsmg_write_nstring(sym->name, width);
 }
 
 /* FIXME uber-kludgy, see comment on cmd_report... */
@@ -98,31 +98,29 @@ static int map_browser__search(struct map_browser *self)
        return 0;
 }
 
-static int map_browser__run(struct map_browser *self, struct newtExitStruct *es)
+static int map_browser__run(struct map_browser *self)
 {
+       int key;
+
        if (ui_browser__show(&self->b, self->map->dso->long_name,
                             "Press <- or ESC to exit, %s / to search",
                             verbose ? "" : "restart with -v to use") < 0)
                return -1;
 
-       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
        if (verbose)
-               newtFormAddHotKey(self->b.form, '/');
+               ui_browser__add_exit_key(&self->b, '/');
 
        while (1) {
-               ui_browser__run(&self->b, es);
+               key = ui_browser__run(&self->b);
 
-               if (es->reason != NEWT_EXIT_HOTKEY)
-                       break;
-               if (verbose && es->u.key == '/')
+               if (verbose && key == '/')
                        map_browser__search(self);
                else
                        break;
        }
 
        ui_browser__hide(&self->b);
-       return 0;
+       return key;
 }
 
 int map__browse(struct map *self)
@@ -136,7 +134,6 @@ int map__browse(struct map *self)
                },
                .map = self,
        };
-       struct newtExitStruct es;
        struct rb_node *nd;
        char tmp[BITS_PER_LONG / 4];
        u64 maxaddr = 0;
@@ -144,8 +141,6 @@ int map__browse(struct map *self)
        for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
                struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
 
-               if (mb.namelen < pos->namelen)
-                       mb.namelen = pos->namelen;
                if (maxaddr < pos->end)
                        maxaddr = pos->end;
                if (verbose) {
@@ -156,6 +151,5 @@ int map__browse(struct map *self)
        }
 
        mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr);
-       mb.b.width += mb.addrlen * 2 + 4 + mb.namelen;
-       return map_browser__run(&mb, &es);
+       return map_browser__run(&mb);
 }
index 04600e26ceea21d08b701570494c5e72210aaa9e..9706d9d40279859321412b270c8ac3053141f4f9 100644 (file)
@@ -11,8 +11,6 @@
 #include "helpline.h"
 #include "util.h"
 
-newtComponent newt_form__new(void);
-
 static void newt_form__set_exit_keys(newtComponent self)
 {
        newtFormAddHotKey(self, NEWT_KEY_LEFT);
@@ -22,7 +20,7 @@ static void newt_form__set_exit_keys(newtComponent self)
        newtFormAddHotKey(self, CTRL('c'));
 }
 
-newtComponent newt_form__new(void)
+static newtComponent newt_form__new(void)
 {
        newtComponent self = newtForm(NULL, NULL, 0);
        if (self)
index f380fed74359034a843756256d6e7a79b0ff22b5..7562707ddd1c491755dc8ea5121637918ba1b844 100644 (file)
@@ -266,19 +266,6 @@ bool strglobmatch(const char *str, const char *pat);
 bool strlazymatch(const char *str, const char *pat);
 unsigned long convert_unit(unsigned long value, char *unit);
 
-#ifndef ESC
-#define ESC 27
-#endif
-
-static inline bool is_exit_key(int key)
-{
-       char up;
-       if (key == CTRL('c') || key == ESC)
-               return true;
-       up = toupper(key);
-       return up == 'Q';
-}
-
 #define _STR(x) #x
 #define STR(x) _STR(x)
 
index 66cf65b510b11c1c245db3b6a435e040ac3606fc..c1f1e3c6298462f8ed4d672257dac3b4da081b33 100644 (file)
@@ -218,7 +218,6 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi)
        events = file->f_op->poll(file, &irqfd->pt);
 
        list_add_tail(&irqfd->list, &kvm->irqfds.items);
-       spin_unlock_irq(&kvm->irqfds.lock);
 
        /*
         * Check if there was an event already pending on the eventfd
@@ -227,6 +226,8 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi)
        if (events & POLLIN)
                schedule_work(&irqfd->inject);
 
+       spin_unlock_irq(&kvm->irqfds.lock);
+
        /*
         * do not drop the file until the irqfd is fully initialized, otherwise
         * we might race against the POLLHUP
index b78b794c1039df394b6ccfc43ae34fb2ff6fc47a..60e5e4612b0b329fb616564fad02067934e90652 100644 (file)
@@ -1305,6 +1305,7 @@ static struct file_operations kvm_vcpu_fops = {
        .unlocked_ioctl = kvm_vcpu_ioctl,
        .compat_ioctl   = kvm_vcpu_ioctl,
        .mmap           = kvm_vcpu_mmap,
+       .llseek         = noop_llseek,
 };
 
 /*
@@ -1774,6 +1775,7 @@ static struct file_operations kvm_vm_fops = {
        .compat_ioctl   = kvm_vm_compat_ioctl,
 #endif
        .mmap           = kvm_vm_mmap,
+       .llseek         = noop_llseek,
 };
 
 static int kvm_dev_ioctl_create_vm(void)
@@ -1867,6 +1869,7 @@ out:
 static struct file_operations kvm_chardev_ops = {
        .unlocked_ioctl = kvm_dev_ioctl,
        .compat_ioctl   = kvm_dev_ioctl,
+       .llseek         = noop_llseek,
 };
 
 static struct miscdevice kvm_dev = {
@@ -1958,10 +1961,10 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
                       cpu);
                hardware_disable(NULL);
                break;
-       case CPU_ONLINE:
+       case CPU_STARTING:
                printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
                       cpu);
-               smp_call_function_single(cpu, hardware_enable, NULL, 1);
+               hardware_enable(NULL);
                break;
        }
        return NOTIFY_OK;
@@ -1970,10 +1973,12 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
 
 asmlinkage void kvm_handle_fault_on_reboot(void)
 {
-       if (kvm_rebooting)
+       if (kvm_rebooting) {
                /* spin while reset goes on */
+               local_irq_enable();
                while (true)
                        ;
+       }
        /* Fault while not rebooting.  We want the trace. */
        BUG();
 }
@@ -2096,7 +2101,6 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
 
 static struct notifier_block kvm_cpu_notifier = {
        .notifier_call = kvm_cpu_hotplug,
-       .priority = 20, /* must be > scheduler priority */
 };
 
 static int vm_stat_get(void *_offset, u64 *val)